DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 1/2] common/cnxk: support NPC flow on cn20k
@ 2024-10-21  4:01 psatheesh
  2024-10-21  4:01 ` [dpdk-dev] [PATCH 2/2] net/cnxk: support rte " psatheesh
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: psatheesh @ 2024-10-21  4:01 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

ROC changes to support NPC flow on cn20k.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 drivers/common/cnxk/roc_mbox.h          | 144 +++++-
 drivers/common/cnxk/roc_nix.h           |  18 +-
 drivers/common/cnxk/roc_nix_mcast.c     |  40 +-
 drivers/common/cnxk/roc_nix_vlan.c      |  66 ++-
 drivers/common/cnxk/roc_npc.c           |  58 ++-
 drivers/common/cnxk/roc_npc.h           |  59 ++-
 drivers/common/cnxk/roc_npc_mcam.c      | 602 +++++++++++++++++++-----
 drivers/common/cnxk/roc_npc_mcam_dump.c | 279 +++++++++--
 drivers/common/cnxk/roc_npc_priv.h      |  86 +++-
 drivers/common/cnxk/roc_npc_utils.c     | 340 ++++++++++---
 drivers/common/cnxk/version.map         |   1 +
 11 files changed, 1321 insertions(+), 372 deletions(-)

diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index dd65946e9e..451589e7e5 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -234,6 +234,22 @@ struct mbox_msghdr {
 	  npc_get_field_hash_info_req, npc_get_field_hash_info_rsp)            \
 	M(NPC_MCAM_GET_HIT_STATUS, 0x6015, npc_mcam_get_hit_status,            \
 	  npc_mcam_get_hit_status_req, npc_mcam_get_hit_status_rsp)            \
+	M(NPC_MCAM_DEFRAG, 0x6016, npc_defrag, msg_req,	msg_rsp)               \
+	M(NPC_CN20K_GET_KEX_CFG, 0x6017, npc_cn20k_get_kex_cfg, msg_req,       \
+	  npc_cn20k_get_kex_cfg_rsp)                                           \
+	M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6018, npc_cn20k_get_free_count,     \
+	  msg_req, npc_cn20k_get_free_count_rsp)                               \
+	M(NPC_CN20K_MCAM_WRITE_ENTRY,	0x6019, npc_cn20k_mcam_write_entry,    \
+	  npc_cn20k_mcam_write_entry_req, msg_rsp)	                       \
+	M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x601a,			       \
+	  npc_cn20k_mcam_alloc_and_write_entry,				       \
+	  npc_cn20k_mcam_alloc_and_write_entry_req,			       \
+	  npc_mcam_alloc_and_write_entry_rsp)				       \
+	M(NPC_CN20K_MCAM_READ_ENTRY,	0x601b, npc_cn20k_mcam_read_entry,     \
+	  npc_mcam_read_entry_req, npc_cn20k_mcam_read_entry_rsp)	       \
+	M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601c,                               \
+	  npc_cn20k_read_base_steer_rule, msg_req,                             \
+	  npc_cn20k_mcam_read_base_rule_rsp)                                   \
 	/* NIX mbox IDs (range 0x8000 - 0xFFFF) */                             \
 	M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, nix_lf_alloc_req,                \
 	  nix_lf_alloc_rsp)                                                    \
@@ -637,7 +653,7 @@ struct cgx_mac_addr_add_req {
  */
 struct cgx_mac_addr_add_rsp {
 	struct mbox_msghdr hdr;
-	uint8_t __io index;
+	uint32_t __io index;
 };
 
 /* Structure for requesting the operation to
@@ -645,7 +661,7 @@ struct cgx_mac_addr_add_rsp {
  */
 struct cgx_mac_addr_del_req {
 	struct mbox_msghdr hdr;
-	uint8_t __io index;
+	uint32_t __io index;
 };
 
 /* Structure for response against the operation to
@@ -653,7 +669,7 @@ struct cgx_mac_addr_del_req {
  */
 struct cgx_max_dmac_entries_get_rsp {
 	struct mbox_msghdr hdr;
-	uint8_t __io max_dmac_filters;
+	uint32_t __io max_dmac_filters;
 };
 
 struct cgx_link_user_info {
@@ -2433,6 +2449,14 @@ enum npc_af_status {
 	NPC_MCAM_ALLOC_FAILED = -703,
 	NPC_MCAM_PERM_DENIED = -704,
 	NPC_AF_ERR_HIGIG_CONFIG_FAIL = -705,
+	NPC_AF_ERR_HIGIG_NOT_SUPPORTED = -706,
+	NPC_FLOW_INTF_INVALID = -707,
+	NPC_FLOW_CHAN_INVALID = -708,
+	NPC_FLOW_NO_NIXLF = -709,
+	NPC_FLOW_NOT_SUPPORTED = -710,
+	NPC_FLOW_VF_PERM_DENIED = -711,
+	NPC_FLOW_VF_NOT_INIT = -712,
+	NPC_FLOW_VF_OVERLAP = -713,
 };
 
 struct npc_mcam_alloc_entry_req {
@@ -2442,9 +2466,12 @@ struct npc_mcam_alloc_entry_req {
 #define NPC_MCAM_ANY_PRIO    0
 #define NPC_MCAM_LOWER_PRIO  1
 #define NPC_MCAM_HIGHER_PRIO 2
-	uint8_t __io priority; /* Lower or higher w.r.t ref_entry */
+	uint8_t __io ref_priority; /* Lower or higher w.r.t ref_entry */
 	uint16_t __io ref_entry;
 	uint16_t __io count; /* Number of entries requested */
+	uint8_t __io kw_type; /* Key type */
+	uint8_t __io virt;    /* Request virtual index */
+	uint16_t __io rsvd[16];	/* Reserved */
 };
 
 struct npc_mcam_alloc_entry_rsp {
@@ -2456,6 +2483,7 @@ struct npc_mcam_alloc_entry_rsp {
 	uint16_t __io count;	  /* Number of entries allocated */
 	uint16_t __io free_count; /* Number of entries available */
 	uint16_t __io entry_list[NPC_MAX_NONCONTIG_ENTRIES];
+	uint16_t __io rsvd[16];	/* Reserved */
 };
 
 struct npc_mcam_free_entry_req {
@@ -2482,6 +2510,26 @@ struct npc_mcam_write_entry_req {
 	uint8_t __io set_cntr;	   /* Set counter for this entry ? */
 };
 
+struct cn20k_mcam_entry {
+#define NPC_CN20K_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */
+	uint64_t __io kw[NPC_CN20K_MAX_KWS_IN_KEY];
+	uint64_t __io kw_mask[NPC_CN20K_MAX_KWS_IN_KEY];
+	uint64_t __io action;
+	uint64_t __io vtag_action;
+};
+
+struct npc_cn20k_mcam_write_entry_req {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint16_t __io entry;	   /* MCAM entry to write this match key */
+	uint16_t __io cntr;	   /* Counter for this MCAM entry */
+	uint8_t __io intf;	   /* Rx or Tx interface */
+	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
+	uint8_t __io hw_prio;	   /* hardware priority, valid for cn20k */
+	uint8_t __io req_kw_type;  /* Type of kw which should be written */
+	uint64_t __io reserved;	   /* reserved for future use */
+};
+
 /* Enable/Disable a given entry */
 struct npc_mcam_ena_dis_entry_req {
 	struct mbox_msghdr hdr;
@@ -2541,12 +2589,25 @@ struct npc_mcam_alloc_and_write_entry_req {
 	struct mbox_msghdr hdr;
 	struct mcam_entry entry_data;
 	uint16_t __io ref_entry;
-	uint8_t __io priority;	   /* Lower or higher w.r.t ref_entry */
+	uint8_t __io ref_priority; /* Lower or higher w.r.t ref_entry */
 	uint8_t __io intf;	   /* Rx or Tx interface */
 	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
 	uint8_t __io alloc_cntr;   /* Allocate counter and map ? */
 };
 
+struct npc_cn20k_mcam_alloc_and_write_entry_req {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint16_t __io ref_entry;
+	uint8_t __io ref_prio;	   /* Lower or higher w.r.t ref_entry */
+	uint8_t __io intf;	   /* Rx or Tx interface */
+	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
+	uint8_t __io hw_prio;	   /* hardware priority, valid for cn20k */
+	uint8_t __io virt;	   /* Allocate virtual index */
+	uint8_t __io req_kw_type;  /* Key type to be written */
+	uint16_t __io reserved[4]; /* reserved for future use */
+};
+
 struct npc_mcam_alloc_and_write_entry_rsp {
 	struct mbox_msghdr hdr;
 	uint16_t __io entry;
@@ -2573,6 +2634,48 @@ struct npc_get_kex_cfg_rsp {
 	uint8_t __io mkex_pfl_name[MKEX_NAME_LEN];
 };
 
+struct npc_delete_flow_rsp {
+	struct mbox_msghdr hdr;
+	uint16_t __io cntr_val;
+};
+
+/* Available entries to use */
+struct npc_cn20k_get_free_count_rsp {
+	struct mbox_msghdr hdr;
+	int __io free_x2;
+	int __io free_x4;
+	int __io free_subbanks;
+};
+
+struct npc_cn20k_get_kex_cfg_rsp {
+	struct mbox_msghdr hdr;
+	uint64_t __io rx_keyx_cfg; /* NPC_AF_INTF(0)_KEX_CFG */
+	uint64_t __io tx_keyx_cfg; /* NPC_AF_INTF(1)_KEX_CFG */
+#define NPC_MAX_EXTRACTOR 24
+	/* MKEX Extractor data */
+	uint64_t __io intf_extr[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
+	/* KEX configuration per extractor */
+	uint64_t __io intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
+#define MKEX_NAME_LEN 128
+	uint8_t __io mkex_pfl_name[MKEX_NAME_LEN];
+};
+
+struct npc_get_field_hash_info_req {
+	struct mbox_msghdr hdr;
+	uint8_t intf;
+};
+
+struct npc_get_field_hash_info_rsp {
+	struct mbox_msghdr hdr;
+	uint64_t __io secret_key[3];
+#define NPC_MAX_HASH	  2
+#define NPC_MAX_HASH_MASK 2
+	/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
+	uint64_t __io hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
+	/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
+	uint64_t __io hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
+};
+
 enum header_fields {
 	NPC_DMAC,
 	NPC_SMAC,
@@ -2662,6 +2765,8 @@ struct npc_install_flow_req {
 	uint8_t __io vtag1_op;
 	/* old counter value */
 	uint16_t __io cntr_val;
+	/* hardware priority, supported for cn20k */
+	uint8_t __io hw_prio;
 };
 
 struct npc_install_flow_rsp {
@@ -2692,11 +2797,24 @@ struct npc_mcam_read_entry_rsp {
 	uint8_t __io enable;
 };
 
+struct npc_cn20k_mcam_read_entry_rsp {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint8_t __io intf;
+	uint8_t __io enable;
+	uint8_t __io hw_prio; /* valid for cn20k */
+};
+
 struct npc_mcam_read_base_rule_rsp {
 	struct mbox_msghdr hdr;
 	struct mcam_entry entry_data;
 };
 
+struct npc_cn20k_mcam_read_base_rule_rsp {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry;
+};
+
 struct npc_mcam_get_stats_req {
 	struct mbox_msghdr hdr;
 	uint16_t __io entry; /* mcam entry */
@@ -2776,22 +2894,6 @@ enum tim_gpio_edge {
 	TIM_GPIO_INVALID,
 };
 
-struct npc_get_field_hash_info_req {
-	struct mbox_msghdr hdr;
-	uint8_t intf;
-};
-
-struct npc_get_field_hash_info_rsp {
-	struct mbox_msghdr hdr;
-	uint64_t __io secret_key[3];
-#define NPC_MAX_HASH	  2
-#define NPC_MAX_HASH_MASK 2
-	/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
-	uint64_t __io hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
-	/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
-	uint64_t __io hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
-};
-
 enum ptp_op {
 	PTP_OP_ADJFINE = 0,   /* adjfine(req.scaled_ppm); */
 	PTP_OP_GET_CLOCK = 1, /* rsp.clk = get_clock() */
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index f213823b9b..15823ab16c 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -983,15 +983,11 @@ bool __roc_api roc_nix_ptp_is_enable(struct roc_nix *roc_nix);
 /* VLAN */
 int __roc_api
 roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
-			     struct npc_mcam_read_entry_rsp **rsp);
-int __roc_api roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix,
-					    uint32_t index,
-					    struct mcam_entry *entry,
+			     void **rsp);
+int __roc_api roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index, void *entry,
 					    uint8_t intf, uint8_t enable);
-int __roc_api roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix,
-						      struct mcam_entry *entry,
-						      uint8_t intf,
-						      uint8_t priority,
+int __roc_api roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix, void *entry,
+						      uint8_t intf, uint8_t priority,
 						      uint8_t ref_entry);
 int __roc_api roc_nix_vlan_mcam_entry_free(struct roc_nix *roc_nix,
 					   uint32_t index);
@@ -1012,10 +1008,8 @@ int __roc_api roc_nix_mcast_mcam_entry_alloc(struct roc_nix *roc_nix,
 					     uint16_t index[]);
 int __roc_api roc_nix_mcast_mcam_entry_free(struct roc_nix *roc_nix,
 					    uint32_t index);
-int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
-					     struct mcam_entry *entry,
-					     uint32_t index, uint8_t intf,
-					     uint64_t action);
+int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix, void *entry, uint32_t index,
+					     uint8_t intf, uint64_t action);
 int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
 					       bool enable);
 int __roc_api roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries,
diff --git a/drivers/common/cnxk/roc_nix_mcast.c b/drivers/common/cnxk/roc_nix_mcast.c
index 615014e820..eab4bde743 100644
--- a/drivers/common/cnxk/roc_nix_mcast.c
+++ b/drivers/common/cnxk/roc_nix_mcast.c
@@ -19,7 +19,7 @@ roc_nix_mcast_mcam_entry_alloc(struct roc_nix *roc_nix, uint16_t nb_entries,
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
 	if (req == NULL)
 		goto exit;
-	req->priority = priority;
+	req->ref_priority = priority;
 	req->count = nb_entries;
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -56,24 +56,38 @@ roc_nix_mcast_mcam_entry_free(struct roc_nix *roc_nix, uint32_t index)
 }
 
 int
-roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
-			       struct mcam_entry *entry, uint32_t index,
-			       uint8_t intf, uint64_t action)
+roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix, void *entry, uint32_t index, uint8_t intf,
+			       uint64_t action)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
-	struct npc_mcam_write_entry_req *req;
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->entry = index;
-	req->intf = intf;
-	req->enable_entry = true;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
-	req->entry_data.action = action;
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+		req->entry_data.action = action;
+
+	} else {
+		struct npc_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+		req->entry_data.action = action;
+	}
 
 	rc = mbox_process(mbox);
 exit:
diff --git a/drivers/common/cnxk/roc_nix_vlan.c b/drivers/common/cnxk/roc_nix_vlan.c
index db218593ad..16100eb5d6 100644
--- a/drivers/common/cnxk/roc_nix_vlan.c
+++ b/drivers/common/cnxk/roc_nix_vlan.c
@@ -7,7 +7,7 @@
 
 int
 roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
-			     struct npc_mcam_read_entry_rsp **rsp)
+			     void **rsp)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
@@ -27,24 +27,34 @@ roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
 }
 
 int
-roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index,
-			      struct mcam_entry *entry, uint8_t intf,
+roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index, void *entry, uint8_t intf,
 			      uint8_t enable)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
 	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
 	struct msghdr *rsp;
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->entry = index;
-	req->intf = intf;
-	req->enable_entry = enable;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (cn20k_req == NULL)
+			goto exit;
+		cn20k_req->entry = index;
+		cn20k_req->intf = intf;
+		cn20k_req->enable_entry = enable;
+		mbox_memcpy(&cn20k_req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+	} else {
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = enable;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 exit:
@@ -53,25 +63,39 @@ roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index,
 }
 
 int
-roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix,
-					struct mcam_entry *entry, uint8_t intf,
+roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix, void *entry, uint8_t intf,
 					uint8_t priority, uint8_t ref_entry)
 {
-	struct npc_mcam_alloc_and_write_entry_req *req;
 	struct npc_mcam_alloc_and_write_entry_rsp *rsp;
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->priority = priority;
-	req->ref_entry = ref_entry;
-	req->intf = intf;
-	req->enable_entry = true;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_alloc_and_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_alloc_and_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->ref_prio = priority;
+		req->ref_entry = ref_entry;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+
+	} else {
+		struct npc_mcam_alloc_and_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->ref_priority = priority;
+		req->ref_entry = ref_entry;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 8a951b6360..922c823186 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -100,6 +100,14 @@ roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, uint64_t *co
 	return npc_mcam_read_counter(npc->mbox, ctr_id, count);
 }
 
+int
+roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow, uint64_t *count)
+{
+	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+	return npc_mcam_get_stats(npc->mbox, flow, count);
+}
+
 int
 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id)
 {
@@ -221,7 +229,9 @@ roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc)
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 
-	if (roc_model_is_cn10k())
+	if (roc_model_is_cn20k())
+		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
+	else if (roc_model_is_cn10k())
 		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
 	else if (roc_model_is_cn98xx())
 		return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1);
@@ -235,7 +245,9 @@ npc_mcam_tot_entries(void)
 	/* FIXME: change to reading in AF from NPC_AF_CONST1/2
 	 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS
 	 */
-	if (roc_model_is_cn10k() || roc_model_is_cn98xx())
+	if (roc_model_is_cn20k())
+		return 2 * 8192; /* MCAM_BANKS = 2, BANK_DEPTH_EXT = 8192 */
+	else if (roc_model_is_cn10k() || roc_model_is_cn98xx())
 		return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */
 	else
 		return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */
@@ -311,6 +323,7 @@ roc_npc_init(struct roc_npc *roc_npc)
 
 	npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX];
 	nix->exact_match_ena = npc->exact_match_ena;
+	roc_npc->max_entries = npc->mcam_entries;
 
 	/* Free, free_rev, live and live_rev entries */
 	bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries);
@@ -1852,9 +1865,7 @@ roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc, int rep_port_id)
 int
 roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 {
-	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
-	struct mcam_entry *base_entry;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int idx, rc;
 
@@ -1864,17 +1875,36 @@ roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_fl
 	}
 
 	(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
-	rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
-	if (rc) {
-		plt_err("Failed to fetch VF's base MCAM entry");
-		goto exit;
-	}
-	base_entry = &base_rule_rsp->entry_data;
-	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		flow->mcam_data[idx] |= base_entry->kw[idx];
-		flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
-	}
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
+		struct cn20k_mcam_entry *base_entry;
 
+		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+		if (rc) {
+			plt_err("Failed to fetch VF's base MCAM entry");
+			goto exit;
+		}
+		base_entry = &base_rule_rsp->entry;
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			flow->mcam_data[idx] |= base_entry->kw[idx];
+			flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+		}
+
+	} else {
+		struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
+		struct mcam_entry *base_entry;
+
+		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+		if (rc) {
+			plt_err("Failed to fetch VF's base MCAM entry");
+			goto exit;
+		}
+		base_entry = &base_rule_rsp->entry_data;
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			flow->mcam_data[idx] |= base_entry->kw[idx];
+			flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+		}
+	}
 	rc = 0;
 exit:
 	mbox_put(mbox);
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index 72aada84a1..a8a803c50a 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -304,52 +304,58 @@ struct roc_npc_spi_to_sa_action_info {
 };
 
 struct mbox;
-
 struct roc_npc_flow {
 	uint8_t nix_intf;
 	uint8_t enable;
-	uint32_t mcam_id;
 	uint8_t use_ctr;
+	bool is_validate;
+	uint32_t mcam_id;
+	uint16_t tx_pf_func;
+	bool has_age_action;
+	bool rep_act_rep;
 	int32_t ctr_id;
 	uint32_t priority;
 	uint32_t mtr_id;
+#if defined(ROC_PLATFORM_CN20K)
+#define ROC_NPC_MAX_MCAM_WIDTH_DWORDS 8
+#define ROC_NPC_MAX_MCAM_PRIORITY     123
+#else
 #define ROC_NPC_MAX_MCAM_WIDTH_DWORDS 7
+#define ROC_NPC_MAX_MCAM_PRIORITY     32
+#endif
 	/* Contiguous match string */
 	uint64_t mcam_data[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t npc_action;
 	uint64_t vtag_action;
 	bool vtag_insert_enabled;
-	uint8_t vtag_insert_count;
+	int8_t vtag_insert_count;
 #define ROC_NPC_MAX_FLOW_PATTERNS 32
 	struct roc_npc_flow_dump_data dump_data[ROC_NPC_MAX_FLOW_PATTERNS];
 	uint16_t num_patterns;
 	struct roc_npc_spi_to_sa_action_info spi_to_sa_info;
-	uint16_t tx_pf_func;
-	bool is_validate;
 	uint16_t match_id;
 	uint8_t is_inline_dev;
 	bool use_pre_alloc;
 	uint64_t timeout_cycles;
 	void *age_context;
-	uint32_t timeout;
-	bool has_age_action;
-	uint16_t rep_pf_func;
 	uint16_t rep_act_pf_func;
-	bool rep_act_rep;
+	bool is_rep_vf;
+	bool has_rep;
+	bool is_sampling_rule;
+	uint16_t rep_pf_func;
+#define ROC_NPC_MIRROR_LIST_SIZE 2
+	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
 	uint16_t rep_channel;
 	struct mbox *rep_mbox;
-	bool has_rep;
-	bool is_rep_vf;
 	struct npc *rep_npc;
 	int port_id;
-	bool is_sampling_rule;
+	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
 	uint32_t recv_queue;
 	uint32_t mcast_grp_index;
 	uint32_t mce_start_index;
-#define ROC_NPC_MIRROR_LIST_SIZE 2
-	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
-	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
+	uint8_t key_type;
+	uint32_t timeout;
 
 	TAILQ_ENTRY(roc_npc_flow) next;
 };
@@ -399,33 +405,34 @@ struct roc_npc {
 	struct roc_nix *roc_nix;
 	uint8_t switch_header_type;
 	uint8_t pre_l2_size_offset;	 /**< Offset with in header that holds
-					   * size of custom header
-					   */
+					  * size of custom header
+					  */
 	uint8_t pre_l2_size_offset_mask; /**< Offset mask with in header
-					   * that holds size of custom header
-					   */
+					  * that holds size of custom header
+					  */
 	uint8_t pre_l2_size_shift_dir;	 /**< Shift direction to calculate size
-					   */
+					  */
 	uint16_t flow_prealloc_size;
 	uint16_t flow_max_priority;
 	uint16_t channel;
 	uint16_t pf_func;
+	bool is_sdp_mask_set;
+	bool rep_act_rep;
+	uint16_t sdp_channel_mask;
 	uint64_t kex_capability;
 	uint64_t rx_parse_nibble;
 	/* Parsed RSS Flowkey cfg for current flow being created */
 	uint32_t flowkey_cfg_state;
-	bool is_sdp_mask_set;
+	uint32_t max_entries;
+	uint16_t rep_act_pf_func;
 	uint16_t sdp_channel;
-	uint16_t sdp_channel_mask;
 	struct roc_npc_flow_age flow_age;
 	struct roc_npc *rep_npc;
 	uint16_t rep_pf_func;
 	uint16_t rep_rx_channel;
-	uint16_t rep_act_pf_func;
-	bool rep_act_rep;
 	int rep_port_id;
 
-#define ROC_NPC_MEM_SZ (6 * 1024)
+#define ROC_NPC_MEM_SZ (20 * 1024)
 	uint8_t reserved[ROC_NPC_MEM_SZ];
 } __plt_cache_aligned;
 
@@ -481,4 +488,6 @@ int __roc_api roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint1
 void *__roc_api roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id);
 void __roc_api roc_npc_sdp_channel_get(struct roc_npc *roc_npc, uint16_t *chan_base,
 				       uint16_t *chan_mask);
+int __roc_api roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+				     uint64_t *count);
 #endif /* _ROC_NPC_H_ */
diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c
index cdb9db1383..e3c0f2e690 100644
--- a/drivers/common/cnxk/roc_npc_mcam.c
+++ b/drivers/common/cnxk/roc_npc_mcam.c
@@ -11,6 +11,10 @@ npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
 	struct npc_mcam_alloc_counter_rsp *rsp;
 	int rc = -ENOSPC;
 
+	/* For CN20K, counters are enabled by default */
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -30,6 +34,9 @@ npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
 	struct npc_mcam_oper_counter_req *req;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -40,6 +47,30 @@ npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
 	return rc;
 }
 
+int
+npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count)
+{
+	struct npc_mcam_get_stats_req *req;
+	struct npc_mcam_get_stats_rsp *rsp;
+	int rc = -ENOSPC;
+
+	/* valid only for cn20k */
+	if (!roc_model_is_cn20k())
+		return 0;
+
+	req = mbox_alloc_msg_npc_mcam_entry_stats(mbox_get(mbox));
+	if (req == NULL)
+		goto exit;
+	req->entry = flow->mcam_id;
+	rc = mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		goto exit;
+	*count = rsp->stat;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
 int
 npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
 {
@@ -47,6 +78,9 @@ npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
 	struct npc_mcam_oper_counter_rsp *rsp;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -66,6 +100,9 @@ npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
 	struct npc_mcam_oper_counter_req *req;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -132,16 +169,53 @@ npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
 	struct npc_xtract_info *x_info;
 	int i;
 
-	for (i = 0; i < NPC_MAX_LD; i++) {
-		x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
-		/* Check for LDATA */
-		if (x_info->enable && x_info->len > 0)
-			return true;
+	if (!roc_model_is_cn20k()) {
+		for (i = 0; i < NPC_MAX_LD; i++) {
+			x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
+			/* Check for LDATA */
+			if (x_info->enable && x_info->len > 0)
+				return true;
+		}
+	} else {
+		for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
+			union npc_kex_ldata_flags_cfg *lid_info = &npc->lid_cfg[NIX_INTF_RX][i];
+
+			if (lid_info->s.lid != lid)
+				continue;
+			x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
+			/* Check for LDATA */
+			if (x_info->enable && x_info->len > 0)
+				return true;
+		}
 	}
 
 	return false;
 }
 
+static void
+npc_construct_ldata_mask_cn20k(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt)
+{
+	struct npc_xtract_info *x_info;
+	int hdr_off, keylen;
+	int i, j;
+
+	for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
+		union npc_kex_ldata_flags_cfg *lid_conf = &npc->lid_cfg[NIX_INTF_RX][i];
+
+		if (lid_conf->s.lid != lid)
+			continue;
+
+		x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
+		if (x_info->enable == 0)
+			continue;
+
+		hdr_off = x_info->hdr_off * 8;
+		keylen = x_info->len * 8;
+		for (j = hdr_off; j < (hdr_off + keylen); j++)
+			plt_bitmap_set(bmap, j);
+	}
+}
+
 static void
 npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt,
 			 uint8_t ld)
@@ -220,8 +294,12 @@ npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset, int len
 		return false;
 	}
 
-	npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
-	npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
+	if (!roc_model_is_cn20k()) {
+		npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
+		npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
+	} else {
+		npc_construct_ldata_mask_cn20k(npc, bmap, lid, lt);
+	}
 
 	for (i = offset; i < (offset + len); i++) {
 		if (plt_bitmap_get(bmap, i) != 0x1) {
@@ -330,7 +408,7 @@ npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int re
 		goto exit;
 	req->contig = is_conti;
 	req->count = req_count;
-	req->priority = prio;
+	req->ref_priority = prio;
 	req->ref_entry = ref_mcam;
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -349,11 +427,11 @@ npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int re
 
 int
 npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
-		     int prio, int *resp_count)
+		     uint8_t prio, int *resp_count)
 {
+	struct mbox *mbox = mbox_get(npc->mbox);
 	struct npc_mcam_alloc_entry_req *req;
 	struct npc_mcam_alloc_entry_rsp *rsp;
-	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = -ENOSPC;
 
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
@@ -361,16 +439,16 @@ npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_
 		goto exit;
 	req->contig = 1;
 	req->count = 1;
-	req->priority = prio;
-	req->ref_entry = ref_mcam->mcam_id;
-
+	req->ref_priority = prio;
+	req->ref_entry = ref_mcam ? ref_mcam->mcam_id : 0;
+	req->kw_type = mcam->key_type;
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		goto exit;
-	memset(mcam, 0, sizeof(struct roc_npc_flow));
 	mcam->mcam_id = rsp->entry;
-	mcam->nix_intf = ref_mcam->nix_intf;
+	mcam->nix_intf = ref_mcam ? ref_mcam->nix_intf : 0;
 	*resp_count = rsp->count;
+
 	rc = 0;
 exit:
 	mbox_put(mbox);
@@ -403,6 +481,7 @@ int
 npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
 {
 	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
 	struct mbox_msghdr *rsp;
 	int rc = -ENOSPC;
 	uint16_t ctr = 0;
@@ -419,33 +498,121 @@ npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
 			return rc;
 	}
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
-	if (req == NULL) {
-		mbox_put(mbox);
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
+		if (cn20k_req == NULL) {
+			mbox_put(mbox);
+			if (mcam->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
+
+			return rc;
+		}
+		cn20k_req->entry = mcam->mcam_id;
+		cn20k_req->intf = mcam->nix_intf;
+		cn20k_req->enable_entry = mcam->enable;
+		cn20k_req->entry_data.action = mcam->npc_action;
+		cn20k_req->entry_data.vtag_action = mcam->vtag_action;
+		cn20k_req->hw_prio = mcam->priority;
 		if (mcam->use_ctr)
-			npc_mcam_free_counter(mbox, ctr);
+			cn20k_req->cntr = mcam->ctr_id;
 
-		return rc;
-	}
-	req->entry = mcam->mcam_id;
-	req->intf = mcam->nix_intf;
-	req->enable_entry = mcam->enable;
-	req->entry_data.action = mcam->npc_action;
-	req->entry_data.vtag_action = mcam->vtag_action;
-	if (mcam->use_ctr) {
-		req->set_cntr = 1;
-		req->cntr = mcam->ctr_id;
-	}
+		for (i = 0; i < NPC_CN20K_MCAM_KEY_X4_WORDS; i++) {
+			cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
+			cn20k_req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+		}
+	} else {
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
+		if (req == NULL) {
+			mbox_put(mbox);
+			if (mcam->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
 
-	for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
-		req->entry_data.kw[i] = mcam->mcam_data[i];
-		req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+			return rc;
+		}
+		req->entry = mcam->mcam_id;
+		req->intf = mcam->nix_intf;
+		req->enable_entry = mcam->enable;
+		req->entry_data.action = mcam->npc_action;
+		req->entry_data.vtag_action = mcam->vtag_action;
+		if (mcam->use_ctr) {
+			req->set_cntr = 1;
+			req->cntr = mcam->ctr_id;
+		}
+
+		for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
+			req->entry_data.kw[i] = mcam->mcam_data[i];
+			req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+		}
 	}
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	mbox_put(mbox);
 	return rc;
 }
 
+static void
+npc_mcam_kex_cfg_dump(struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
+{
+	for (int i = 0; i < NPC_MAX_INTF; i++) {
+		for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+			if (kex_rsp->intf_extr[i][j] == 0)
+				continue;
+			plt_info("Intf %d, Extr %d: 0x%" PRIx64, i, j, kex_rsp->intf_extr[i][j]);
+		}
+	}
+
+	for (int i = 0; i < NPC_MAX_INTF; i++) {
+		for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+			for (int k = 0; k < NPC_MAX_LT; k++) {
+				if (kex_rsp->intf_extr_lt[i][j][k] == 0)
+					continue;
+				plt_info("Intf %d, Extr %d, LT %d: 0x%" PRIx64, i, j, k,
+					 kex_rsp->intf_extr_lt[i][j][k]);
+			}
+		}
+	}
+}
+
+static void
+npc_mcam_process_mkex_cfg_cn20k(struct npc *npc, struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
+{
+	volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
+	volatile uint64_t(*d)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
+	struct npc_xtract_info *x_info = NULL;
+	union npc_kex_ldata_flags_cfg *ld_info = NULL;
+	int ex, lt, ix;
+	npc_dxcfg_cn20k_t *p;
+	npc_lid_cn20k_t *l;
+	uint64_t keyw;
+	uint64_t val;
+
+	npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
+	npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
+	npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
+	npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
+
+	keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
+	npc->keyw[NPC_MCAM_RX] = keyw;
+	keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
+	npc->keyw[NPC_MCAM_TX] = keyw;
+
+	p = &npc->prx_dxcfg_cn20k;
+	l = &npc->lid_cfg;
+	q = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR][NPC_MAX_LT])(&kex_rsp->intf_extr_lt);
+	d = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR])(&kex_rsp->intf_extr);
+	for (ix = 0; ix < NPC_MAX_INTF; ix++) {
+		for (ex = 0; ex < NPC_MAX_EXTRACTOR; ex++) {
+			val = (*d)[ix][ex];
+			ld_info = &(*l)[ix][ex];
+			ld_info->s.lid = (val & 0x7);
+			for (lt = 0; lt < NPC_MAX_LT; lt++) {
+				x_info = &(*p)[ix][ex][lt].xtract;
+				val = (*q)[ix][ex][lt];
+				npc_update_kex_info(x_info, val);
+			}
+		}
+	}
+}
+
 static void
 npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
 {
@@ -522,20 +689,38 @@ int
 npc_mcam_fetch_kex_cfg(struct npc *npc)
 {
 	struct npc_get_kex_cfg_rsp *kex_rsp;
+	struct npc_cn20k_get_kex_cfg_rsp *kex_rsp_20k;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = 0;
 
-	mbox_alloc_msg_npc_get_kex_cfg(mbox);
-	rc = mbox_process_msg(mbox, (void *)&kex_rsp);
-	if (rc) {
-		plt_err("Failed to fetch NPC KEX config");
-		goto done;
-	}
 
-	mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
+	if (!roc_model_is_cn20k()) {
+		mbox_alloc_msg_npc_get_kex_cfg(mbox);
+		rc = mbox_process_msg(mbox, (void *)&kex_rsp);
+		if (rc) {
+			plt_err("Failed to fetch NPC KEX config");
+			goto done;
+		}
 
-	npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
-	npc_mcam_process_mkex_cfg(npc, kex_rsp);
+		mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
+
+		npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
+		npc_mcam_process_mkex_cfg(npc, kex_rsp);
+	} else {
+		mbox_alloc_msg_npc_cn20k_get_kex_cfg(mbox);
+		rc = mbox_process_msg(mbox, (void *)&kex_rsp_20k);
+		if (rc) {
+			plt_err("Failed to fetch NPC KEX config");
+			goto done;
+		}
+
+		mbox_memcpy((char *)npc->profile_name, kex_rsp_20k->mkex_pfl_name, MKEX_NAME_LEN);
+
+		npc->exact_match_ena = (kex_rsp_20k->rx_keyx_cfg >> 40) & 0xF;
+		npc_mcam_process_mkex_cfg_cn20k(npc, kex_rsp_20k);
+		if (npc->enable_debug)
+			npc_mcam_kex_cfg_dump(kex_rsp_20k);
+	}
 
 done:
 	mbox_put(mbox);
@@ -543,7 +728,7 @@ npc_mcam_fetch_kex_cfg(struct npc *npc)
 }
 
 static void
-npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req *req,
+npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_cn20k_mcam_write_entry_req *req,
 		     uint16_t channel, uint16_t chan_mask, bool is_second_pass)
 {
 	uint16_t chan = 0, mask = 0;
@@ -552,6 +737,7 @@ npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req
 	req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
 	flow->mcam_data[0] &= ~(GENMASK(11, 0));
 	flow->mcam_mask[0] &= ~(GENMASK(11, 0));
+
 	chan = channel;
 	mask = chan_mask;
 
@@ -579,11 +765,12 @@ npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req
 	flow->mcam_mask[0] |= (uint64_t)mask;
 }
 
+#define NPC_PF_FUNC_WIDTH    2
+#define NPC_KEX_PF_FUNC_MASK 0xFFFF
+
 static int
 npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
 {
-#define NPC_PF_FUNC_WIDTH    2
-#define NPC_KEX_PF_FUNC_MASK 0xFFFF
 	uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
 	uint8_t *flow_mcam_data, *flow_mcam_mask;
 	struct npc_lid_lt_xtract_info *xinfo;
@@ -618,10 +805,48 @@ npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_fun
 	return 0;
 }
 
+static int
+npc_mcam_set_pf_func_cn20k(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
+{
+	uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
+	struct npc_lid_lt_xtract_info_cn20k *xinfo;
+	uint8_t *flow_mcam_data, *flow_mcam_mask;
+	bool pffunc_found = false;
+	uint16_t mask = 0xFFFF;
+	int i;
+
+	flow_mcam_data = (uint8_t *)flow->mcam_data;
+	flow_mcam_mask = (uint8_t *)flow->mcam_mask;
+
+	xinfo = npc->prx_dxcfg_cn20k[NIX_INTF_TX][NPC_LID_LA];
+
+	for (i = 0; i < NPC_MAX_LT; i++) {
+		nr_bytes = xinfo[i].xtract.len;
+		hdr_offset = xinfo[i].xtract.hdr_off;
+		key_offset = xinfo[i].xtract.key_off;
+
+		if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
+			continue;
+		else
+			pffunc_found = true;
+
+		pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
+		memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
+		       NPC_PF_FUNC_WIDTH);
+		memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
+		       NPC_PF_FUNC_WIDTH);
+	}
+	if (!pffunc_found)
+		return -EINVAL;
+
+	return 0;
+}
+
 int
 npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
 {
-	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
+	struct npc_cn20k_mcam_write_entry_req req;
 	struct nix_inl_dev *inl_dev = NULL;
 	struct mbox *mbox = npc->mbox;
 	struct mbox_msghdr *rsp;
@@ -655,6 +880,12 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 			return rc;
 	}
 
+	if (roc_model_is_cn20k()) {
+		req.hw_prio = flow->priority;
+		flow->key_type = npc_get_key_type(npc, flow);
+		req.req_kw_type = flow->key_type;
+	}
+
 	if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
 	    inl_dev->ipsec_index && inl_dev->is_multi_channel) {
 		if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
@@ -672,14 +903,17 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	}
 
 	if (flow->nix_intf == NIX_INTF_TX) {
-		uint16_t pf_func = flow->tx_pf_func;
+		uint16_t pffunc = flow->tx_pf_func;
 
 		if (flow->has_rep)
-			pf_func = flow->rep_pf_func;
+			pffunc = flow->rep_pf_func;
 
-		pf_func = plt_cpu_to_be_16(pf_func);
+		pffunc = plt_cpu_to_be_16(pffunc);
 
-		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
+		if (roc_model_is_cn20k())
+			rc = npc_mcam_set_pf_func_cn20k(npc, flow, pffunc);
+		else
+			rc = npc_mcam_set_pf_func(npc, flow, pffunc);
 		if (rc)
 			return rc;
 	}
@@ -708,20 +942,14 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		}
 	}
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
-	if (req == NULL) {
-		rc = -ENOSPC;
-		goto exit;
-	}
-	req->set_cntr = flow->use_ctr;
-	req->cntr = flow->ctr_id;
-	req->entry = entry;
+	req.cntr = flow->ctr_id;
+	req.entry = entry;
 
-	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
-	req->enable_entry = 1;
+	req.intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+	req.enable_entry = 1;
 	if (flow->nix_intf == NIX_INTF_RX)
 		flow->npc_action |= (uint64_t)flow->recv_queue << 20;
-	req->entry_data.action = flow->npc_action;
+	req.entry_data.action = flow->npc_action;
 
 	/*
 	 * Driver sets vtag action on per interface basis, not
@@ -735,38 +963,38 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	 *
 	 * Second approach is used now.
 	 */
-	req->entry_data.vtag_action = flow->vtag_action;
+	req.entry_data.vtag_action = flow->vtag_action;
 
 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		req->entry_data.kw[idx] = flow->mcam_data[idx];
-		req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
+		req.entry_data.kw[idx] = flow->mcam_data[idx];
+		req.entry_data.kw_mask[idx] = flow->mcam_mask[idx];
 	}
 
 	if (flow->nix_intf == NIX_INTF_RX) {
 		if (inl_dev && inl_dev->is_multi_channel &&
 		    (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
 			pf_func = nix_inl_dev_pffunc_get();
-			req->entry_data.action &= ~(GENMASK(19, 4));
-			req->entry_data.action |= (uint64_t)pf_func << 4;
+			req.entry_data.action &= ~(GENMASK(19, 4));
+			req.entry_data.action |= (uint64_t)pf_func << 4;
 			flow->npc_action &= ~(GENMASK(19, 4));
 			flow->npc_action |= (uint64_t)pf_func << 4;
 
-			npc_mcam_set_channel(flow, req, inl_dev->channel, inl_dev->chan_mask,
+			npc_mcam_set_channel(flow, &req, inl_dev->channel, inl_dev->chan_mask,
 					     false);
 		} else if (flow->has_rep) {
 			pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
 								 flow->rep_act_pf_func;
-			req->entry_data.action &= ~(GENMASK(19, 4));
-			req->entry_data.action |= (uint64_t)pf_func << 4;
+			req.entry_data.action &= ~(GENMASK(19, 4));
+			req.entry_data.action |= (uint64_t)pf_func << 4;
 			flow->npc_action &= ~(GENMASK(19, 4));
 			flow->npc_action |= (uint64_t)pf_func << 4;
-			npc_mcam_set_channel(flow, req, flow->rep_channel, (BIT_ULL(12) - 1),
+			npc_mcam_set_channel(flow, &req, flow->rep_channel, (BIT_ULL(12) - 1),
 					     false);
 		} else if (npc->is_sdp_link) {
-			npc_mcam_set_channel(flow, req, npc->sdp_channel, npc->sdp_channel_mask,
+			npc_mcam_set_channel(flow, &req, npc->sdp_channel, npc->sdp_channel_mask,
 					     pst->is_second_pass_rule);
 		} else {
-			npc_mcam_set_channel(flow, req, npc->channel, (BIT_ULL(12) - 1),
+			npc_mcam_set_channel(flow, &req, npc->channel, (BIT_ULL(12) - 1),
 					     pst->is_second_pass_rule);
 		}
 		/*
@@ -779,25 +1007,66 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 			la_offset *= 4;
 
 			mask = ~((0xfULL << la_offset));
-			req->entry_data.kw[0] &= mask;
-			req->entry_data.kw_mask[0] &= mask;
+			req.entry_data.kw[0] &= mask;
+			req.entry_data.kw_mask[0] &= mask;
 			flow->mcam_data[0] &= mask;
 			flow->mcam_mask[0] &= mask;
 			if (pst->is_second_pass_rule) {
-				req->entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
-				req->entry_data.kw_mask[0] |= (0xFULL << la_offset);
+				req.entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
+				req.entry_data.kw_mask[0] |= (0xFULL << la_offset);
 				flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
 				flow->mcam_mask[0] |= (0xFULL << la_offset);
 			} else {
 				/* Mask ltype ETHER (0x2) and CPT_HDR (0xa)  */
-				req->entry_data.kw[0] |= (0x2ULL << la_offset);
-				req->entry_data.kw_mask[0] |= (0x7ULL << la_offset);
+				req.entry_data.kw[0] |= (0x2ULL << la_offset);
+				req.entry_data.kw_mask[0] |= (0x7ULL << la_offset);
 				flow->mcam_data[0] |= (0x2ULL << la_offset);
 				flow->mcam_mask[0] |= (0x7ULL << la_offset);
 			}
 		}
 	}
 
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
+		if (cn20k_req == NULL) {
+			mbox_put(mbox);
+			if (flow->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
+
+			return rc;
+		}
+		cn20k_req->entry = req.entry;
+		cn20k_req->intf = req.intf;
+		cn20k_req->enable_entry = req.enable_entry;
+		cn20k_req->entry_data.action = req.entry_data.action;
+		cn20k_req->entry_data.vtag_action = req.entry_data.vtag_action;
+		cn20k_req->hw_prio = req.hw_prio;
+		cn20k_req->req_kw_type = req.req_kw_type;
+		if (flow->use_ctr)
+			cn20k_req->cntr = req.cntr;
+
+		mbox_memcpy(&cn20k_req->entry_data, &req.entry_data,
+			    sizeof(struct cn20k_mcam_entry));
+	} else {
+		struct npc_mcam_write_entry_req *req_leg;
+
+		req_leg = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
+		if (req_leg == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		for (idx = 0; idx < NPC_MAX_KWS_IN_KEY; idx++) {
+			req_leg->entry_data.kw[idx] = req.entry_data.kw[idx];
+			req_leg->entry_data.kw_mask[idx] = req.entry_data.kw_mask[idx];
+		}
+		req_leg->entry = req.entry;
+		req_leg->intf = req.intf;
+		req_leg->enable_entry = req.enable_entry;
+		req_leg->cntr = req.cntr;
+		req_leg->entry_data.action = req.entry_data.action;
+		req_leg->entry_data.vtag_action = req.entry_data.vtag_action;
+		req_leg->set_cntr = flow->use_ctr;
+	}
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc != 0)
 		goto exit;
@@ -810,7 +1079,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 
 exit:
 	mbox_put(mbox);
-	if (rc)
+	if (rc && flow->is_sampling_rule)
 		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 	return rc;
 }
@@ -821,9 +1090,14 @@ npc_set_vlan_ltype(struct npc_parse_state *pst)
 	uint64_t val, mask;
 	uint8_t lb_offset;
 
-	lb_offset =
-		plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-				   ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
+	if (roc_model_is_cn20k()) {
+		lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_CN20K_LTYPE_LB_OFFSET) - 1));
+
+	} else {
+		lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
+	}
 	lb_offset *= 4;
 
 	mask = ~((0xfULL << lb_offset));
@@ -843,9 +1117,14 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	uint8_t lc_offset, lcflag_offset;
 	uint64_t val, mask;
 
-	lc_offset =
-		plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-				   ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
+	if (roc_model_is_cn20k()) {
+		lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_CN20K_LTYPE_LC_OFFSET) - 1));
+
+	} else {
+		lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
+	}
 	lc_offset *= 4;
 
 	mask = ~((0xfULL << lc_offset));
@@ -867,8 +1146,14 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	 * zero in LFLAG.
 	 */
 	if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
-		lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-					       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+		if (roc_model_is_cn20k()) {
+			lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+						       ((1ULL << NPC_CN20K_LFLAG_LC_OFFSET) - 1));
+
+		} else {
+			lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+						       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+		}
 		lcflag_offset *= 4;
 
 		mask = (0xfULL << lcflag_offset);
@@ -881,14 +1166,12 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 int
 npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 {
-	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 	/* This is non-LDATA part in search key */
 	uint64_t key_data[2] = {0ULL, 0ULL};
 	uint64_t key_mask[2] = {0ULL, 0ULL};
 	int key_len, bit = 0, index, rc = 0;
 	struct nix_inl_dev *inl_dev = NULL;
 	int intf = pst->flow->nix_intf;
-	struct mcam_entry *base_entry;
 	bool skip_base_rule = false;
 	int off, idx, data_off = 0;
 	uint8_t lid, mask, data;
@@ -908,40 +1191,79 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 	data_off *= 4;
 
 	index = 0;
-	for (lid = 0; lid < NPC_MAX_LID; lid++) {
-		/* Offset in key */
-		off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
-		lt = pst->lt[lid] & 0xf;
-		flags = pst->flags[lid] & 0xff;
+	if (!roc_model_is_cn20k()) {
+		for (lid = 0; lid < NPC_MAX_LID; lid++) {
+			/* Offset in key */
+			off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
+			lt = pst->lt[lid] & 0xf;
+			flags = pst->flags[lid] & 0xff;
 
-		/* NPC_LAYER_KEX_S */
-		layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
+			/* NPC_LAYER_KEX_S */
+			layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
+			if (!layer_info)
+				continue;
 
-		if (layer_info) {
 			for (idx = 0; idx <= 2; idx++) {
-				if (layer_info & (1 << idx)) {
-					if (idx == 2) {
-						data = lt;
-						mask = 0xf;
-					} else if (idx == 1) {
-						data = ((flags >> 4) & 0xf);
-						mask = ((flags >> 4) & 0xf);
-					} else {
-						data = (flags & 0xf);
-						mask = (flags & 0xf);
-					}
-
-					if (data_off >= 64) {
-						data_off = 0;
-						index++;
-					}
-					key_data[index] |= ((uint64_t)data << data_off);
-
-					if (lt == 0)
-						mask = 0;
-					key_mask[index] |= ((uint64_t)mask << data_off);
-					data_off += 4;
+				if (!(layer_info & (1 << idx)))
+					continue;
+
+				if (idx == 2) {
+					data = lt;
+					mask = 0xf;
+				} else if (idx == 1) {
+					data = ((flags >> 4) & 0xf);
+					mask = ((flags >> 4) & 0xf);
+				} else {
+					data = (flags & 0xf);
+					mask = (flags & 0xf);
+				}
+
+				if (data_off >= 64) {
+					data_off = 0;
+					index++;
 				}
+				key_data[index] |= ((uint64_t)data << data_off);
+
+				if (lt == 0)
+					mask = 0;
+				key_mask[index] |= ((uint64_t)mask << data_off);
+				data_off += 4;
+			}
+		}
+	} else {
+		for (lid = 0; lid < NPC_MAX_LID; lid++) {
+			/* Offset in key */
+			off = NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid);
+			lt = pst->lt[lid] & 0xf;
+			flags = pst->flags[lid] & 0xf;
+
+			/* NPC_LAYER_KEX_S */
+			layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x3);
+			if (!layer_info)
+				continue;
+
+			for (idx = 0; idx <= 1; idx++) {
+				if (!(layer_info & (1 << idx)))
+					continue;
+
+				if (idx == 1) {
+					data = lt;
+					mask = 0xf;
+				} else {
+					data = (flags & 0xf);
+					mask = (flags & 0xf);
+				}
+
+				if (data_off >= 64) {
+					data_off = 0;
+					index++;
+				}
+				key_data[index] |= ((uint64_t)data << data_off);
+
+				if (lt == 0)
+					mask = 0;
+				key_mask[index] |= ((uint64_t)mask << data_off);
+				data_off += 4;
 			}
 		}
 	}
@@ -971,17 +1293,39 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 		else
 			mbox = mbox_get(npc->mbox);
 		(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
-		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
-		if (rc) {
+		if (roc_model_is_cn20k()) {
+			struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
+			struct cn20k_mcam_entry *base_entry;
+
+			rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+			if (rc) {
+				mbox_put(mbox);
+				plt_err("Failed to fetch VF's base MCAM entry");
+				return rc;
+			}
 			mbox_put(mbox);
-			plt_err("Failed to fetch VF's base MCAM entry");
-			return rc;
-		}
-		mbox_put(mbox);
-		base_entry = &base_rule_rsp->entry_data;
-		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-			pst->flow->mcam_data[idx] |= base_entry->kw[idx];
-			pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			base_entry = &base_rule_rsp->entry;
+			for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+				pst->flow->mcam_data[idx] |= base_entry->kw[idx];
+				pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			}
+
+		} else {
+			struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
+			struct mcam_entry *base_entry;
+
+			rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+			if (rc) {
+				mbox_put(mbox);
+				plt_err("Failed to fetch VF's base MCAM entry");
+				return rc;
+			}
+			mbox_put(mbox);
+			base_entry = &base_rule_rsp->entry_data;
+			for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+				pst->flow->mcam_data[idx] |= base_entry->kw[idx];
+				pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			}
 		}
 	}
 
diff --git a/drivers/common/cnxk/roc_npc_mcam_dump.c b/drivers/common/cnxk/roc_npc_mcam_dump.c
index ebd2dd69c2..bedf6db37c 100644
--- a/drivers/common/cnxk/roc_npc_mcam_dump.c
+++ b/drivers/common/cnxk/roc_npc_mcam_dump.c
@@ -35,6 +35,33 @@
 #define NIX_TX_VTAGACT_VTAG1_OP_MASK	 GENMASK(45, 44)
 #define NIX_TX_VTAGACT_VTAG1_DEF_MASK	 GENMASK(57, 48)
 
+union npc_rx_parse_nibble_cn20k_u {
+	struct {
+		uint64_t chan : 3;
+		uint64_t errlev : 1;
+		uint64_t errcode : 2;
+		uint64_t l2l3bm : 1;
+		uint64_t laflags : 1;
+		uint64_t latype : 1;
+		uint64_t lbflags : 1;
+		uint64_t lbtype : 1;
+		uint64_t lcflags : 1;
+		uint64_t lctype : 1;
+		uint64_t ldflags : 1;
+		uint64_t ldtype : 1;
+		uint64_t leflags : 1;
+		uint64_t letype : 1;
+		uint64_t lfflags : 1;
+		uint64_t lftype : 1;
+		uint64_t lgflags : 1;
+		uint64_t lgtype : 1;
+		uint64_t lhflags : 1;
+		uint64_t lhtype : 1;
+		uint64_t reserved : 41;
+	} s __plt_packed;
+	uint64_t u;
+};
+
 struct npc_rx_parse_nibble_s {
 	uint16_t chan : 3;
 	uint16_t errlev : 1;
@@ -181,8 +208,135 @@ npc_get_nibbles(struct roc_npc_flow *flow, uint16_t size, uint32_t bit_offset)
 }
 
 static void
-npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
-			     uint64_t parse_nibbles)
+npc_flow_print_parse_nibbles_cn20k(FILE *file, struct roc_npc_flow *flow, uint64_t parse_nibbles)
+{
+	union npc_rx_parse_nibble_cn20k_u rx_parse;
+	uint32_t data, offset = 0;
+
+	rx_parse.u = parse_nibbles;
+
+	if (rx_parse.s.chan) {
+		data = npc_get_nibbles(flow, 3, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_CHAN:%#03X\n", data);
+		offset += 12;
+	}
+
+	if (rx_parse.s.errlev) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRLEV:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse.s.errcode) {
+		data = npc_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRCODE:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.l2l3bm) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_L2L3_BCAST:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse.s.laflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.latype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n", ltype_str[NPC_LID_LA][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lbflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lbtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n", ltype_str[NPC_LID_LB][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lcflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lctype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n", ltype_str[NPC_LID_LC][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.ldflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.ldtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n", ltype_str[NPC_LID_LD][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.leflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.letype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n", ltype_str[NPC_LID_LE][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lfflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lftype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n", ltype_str[NPC_LID_LF][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lgflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lgtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n", ltype_str[NPC_LID_LG][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lhflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_FLAGS:%#02X\n", data);
+	}
+
+	if (rx_parse.s.lhtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n", ltype_str[NPC_LID_LH][data]);
+		offset += 4;
+	}
+}
+
+static void
+npc_flow_print_parse_nibbles_legacy(FILE *file, struct roc_npc_flow *flow, uint64_t parse_nibbles)
 {
 	struct npc_rx_parse_nibble_s *rx_parse;
 	uint32_t data, offset = 0;
@@ -221,8 +375,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->latype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n",
-			ltype_str[NPC_LID_LA][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n", ltype_str[NPC_LID_LA][data]);
 		offset += 4;
 	}
 
@@ -234,8 +387,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lbtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n",
-			ltype_str[NPC_LID_LB][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n", ltype_str[NPC_LID_LB][data]);
 		offset += 4;
 	}
 
@@ -247,8 +399,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lctype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n",
-			ltype_str[NPC_LID_LC][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n", ltype_str[NPC_LID_LC][data]);
 		offset += 4;
 	}
 
@@ -260,8 +411,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->ldtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n",
-			ltype_str[NPC_LID_LD][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n", ltype_str[NPC_LID_LD][data]);
 		offset += 4;
 	}
 
@@ -273,8 +423,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->letype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n",
-			ltype_str[NPC_LID_LE][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n", ltype_str[NPC_LID_LE][data]);
 		offset += 4;
 	}
 
@@ -286,8 +435,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lftype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n",
-			ltype_str[NPC_LID_LF][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n", ltype_str[NPC_LID_LF][data]);
 		offset += 4;
 	}
 
@@ -299,8 +447,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lgtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n",
-			ltype_str[NPC_LID_LG][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n", ltype_str[NPC_LID_LG][data]);
 		offset += 4;
 	}
 
@@ -311,15 +458,14 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lhtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n",
-			ltype_str[NPC_LID_LH][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n", ltype_str[NPC_LID_LH][data]);
 		offset += 4;
 	}
 }
 
 static void
-npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo,
-			  struct roc_npc_flow *flow, int lid, int lt)
+npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo, struct roc_npc_flow *flow,
+			  int lid, int lt)
 {
 	uint8_t *datastart, *maskstart;
 	int i;
@@ -374,6 +520,7 @@ static void
 npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
 {
 	struct npc_lid_lt_xtract_info *lt_xinfo;
+	struct npc_lid_lt_xtract_info_cn20k *lt_xinfo_cn20k;
 	struct npc_xtract_info *xinfo;
 	uint32_t intf, lid, ld, i;
 	uint64_t parse_nibbles;
@@ -381,19 +528,37 @@ npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
 
 	intf = flow->nix_intf;
 	parse_nibbles = npc->keyx_supp_nmask[intf];
-	npc_flow_print_parse_nibbles(file, flow, parse_nibbles);
-
-	for (i = 0; i < flow->num_patterns; i++) {
-		lid = flow->dump_data[i].lid;
-		ltype = flow->dump_data[i].ltype;
-		lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
-
-		for (ld = 0; ld < NPC_MAX_LD; ld++) {
-			xinfo = &lt_xinfo->xtract[ld];
-			if (!xinfo->enable)
-				continue;
-			npc_flow_print_item(file, npc, xinfo, flow, intf, lid,
-					    ltype, ld);
+	if (roc_model_is_cn20k()) {
+		npc_flow_print_parse_nibbles_cn20k(file, flow, parse_nibbles);
+		for (i = 0; i < flow->num_patterns; i++) {
+			lid = flow->dump_data[i].lid;
+			ltype = flow->dump_data[i].ltype;
+			for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+				union npc_kex_ldata_flags_cfg *lid_info =
+					&npc->lid_cfg[NIX_INTF_RX][j];
+				if (lid_info->s.lid != lid)
+					continue;
+				lt_xinfo_cn20k = &npc->prx_dxcfg_cn20k[intf][j][ltype];
+				xinfo = &lt_xinfo_cn20k->xtract;
+				if (!xinfo->enable)
+					continue;
+				npc_flow_print_item(file, npc, xinfo, flow, intf, lid, ltype, j);
+			}
+		}
+	} else {
+		npc_flow_print_parse_nibbles_legacy(file, flow, parse_nibbles);
+
+		for (i = 0; i < flow->num_patterns; i++) {
+			lid = flow->dump_data[i].lid;
+			ltype = flow->dump_data[i].ltype;
+			lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
+
+			for (ld = 0; ld < NPC_MAX_LD; ld++) {
+				xinfo = &lt_xinfo->xtract[ld];
+				if (!xinfo->enable)
+					continue;
+				npc_flow_print_item(file, npc, xinfo, flow, intf, lid, ltype, ld);
+			}
 		}
 	}
 }
@@ -645,7 +810,6 @@ npc_flow_hw_mcam_entry_dump(FILE *file, struct npc *npc, struct roc_npc_flow *fl
 	uint64_t mcam_data[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	struct npc_mcam_read_entry_req *mcam_read_req;
-	struct npc_mcam_read_entry_rsp *mcam_read_rsp;
 	struct nix_inl_dev *inl_dev = NULL;
 	struct idev_cfg *idev;
 	struct mbox *mbox;
@@ -669,17 +833,34 @@ npc_flow_hw_mcam_entry_dump(FILE *file, struct npc *npc, struct roc_npc_flow *fl
 	}
 
 	mcam_read_req->entry = flow->mcam_id;
-	rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
-	if (rc) {
-		mbox_put(mbox);
-		plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
-		return;
-	}
 
-	mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
-	mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
-	enabled = mcam_read_rsp->enable;
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_read_entry_rsp *mcam_read_rsp;
+
+		rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
+		if (rc) {
+			mbox_put(mbox);
+			plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
+			return;
+		}
+
+		mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
+		mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
+		enabled = mcam_read_rsp->enable;
+	} else {
+		struct npc_mcam_read_entry_rsp *mcam_read_rsp;
 
+		rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
+		if (rc) {
+			mbox_put(mbox);
+			plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
+			return;
+		}
+
+		mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
+		mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
+		enabled = mcam_read_rsp->enable;
+	}
 	fprintf(file, "HW MCAM Data :\n");
 
 	for (i = 0; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
@@ -702,14 +883,18 @@ roc_npc_flow_mcam_dump(FILE *file, struct roc_npc *roc_npc, struct roc_npc_flow
 
 	fprintf(file, "MCAM Index:%d\n", flow->mcam_id);
 	if (flow->ctr_id != NPC_COUNTER_NONE && flow->use_ctr) {
-		if (flow->use_pre_alloc)
+		if (flow->use_pre_alloc) {
 			rc = roc_npc_inl_mcam_read_counter(flow->ctr_id, &count);
-		else
-			rc = roc_npc_mcam_read_counter(roc_npc, flow->ctr_id, &count);
+		} else {
+			if (roc_model_is_cn20k())
+				rc = roc_npc_mcam_get_stats(roc_npc, flow, &count);
+			else
+				rc = roc_npc_mcam_read_counter(roc_npc, flow->ctr_id, &count);
+		}
 
 		if (rc)
 			return;
-		fprintf(file, "Hit count: %" PRIu64 "\n", count);
+		fprintf(file, "Counter_id = 0x%x, Hit count: %" PRIu64 "\n", flow->ctr_id, count);
 	}
 
 	fprintf(file, "Interface :%s (%d)\n", intf_str[flow->nix_intf], flow->nix_intf);
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index 069c625911..971448a7a0 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -30,6 +30,10 @@
 	((((lid) - (NPC_LID_LA)) * NPC_LAYER_KEYX_SZ) +                        \
 	 NPC_PARSE_KEX_S_LA_OFFSET)
 
+#define NPC_LAYER_KEYX_SZ_CN20K (2)
+#define NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid)                                                      \
+	((((lid) - (NPC_LID_LA)) * NPC_LAYER_KEYX_SZ_CN20K) + NPC_PARSE_KEX_S_LA_OFFSET)
+
 /* This mark value indicates flag action */
 #define NPC_FLOW_FLAG_VAL (0xffff)
 
@@ -44,6 +48,7 @@
 #define NPC_MCAM_KEX_FIELD_MAX	  23
 #define NPC_MCAM_MAX_PROTO_FIELDS (NPC_MCAM_KEX_FIELD_MAX + 1)
 #define NPC_MCAM_KEY_X4_WORDS	  7 /* Number of 64-bit words */
+#define NPC_CN20K_MCAM_KEY_X4_WORDS	  8 /* Number of 64-bit words */
 
 #define NPC_RVUPF_MAX_9XXX 0x10 /* HRM: RVU_PRIV_CONST */
 #define NPC_RVUPF_MAX_98XX 0x18 /* HRM: RVU_PRIV_CONST */
@@ -77,6 +82,16 @@
 #define NPC_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 6)
 #define NPC_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 8)
 
+/* LB OFFSET : START + LA (1b flags + 1b ltype) + LB (1b flags) */
+#define NPC_CN20K_LTYPE_LB_OFFSET (NPC_LTYPE_OFFSET_START + 3)
+#define NPC_CN20K_LFLAG_LB_OFFSET (NPC_LTYPE_OFFSET_START + 2)
+
+/* LC OFFSET : START + LA (1b flags + 1b ltype) + LB (1b flags + 1b ltype) + LC
+ * (1b flags)
+ */
+#define NPC_CN20K_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 4)
+#define NPC_CN20K_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 5)
+
 #define CN10K_SDP_CH_START 0x80
 #define CN10K_SDP_CH_MASK  0xF80
 
@@ -176,9 +191,9 @@ struct npc_parse_item_info {
 	const void *def_mask; /* default mask */
 	void *hw_mask;	      /* hardware supported mask */
 	int len;	      /* length of item */
+	uint8_t hw_hdr_len;   /* Extra data len at each layer*/
 	const void *spec;     /* spec to use, NULL implies match any */
 	const void *mask;     /* mask to use */
-	uint8_t hw_hdr_len;   /* Extra data len at each layer*/
 };
 
 struct npc_parse_state {
@@ -192,16 +207,16 @@ struct npc_parse_state {
 	uint8_t layer_mask;
 	uint8_t lt[NPC_MAX_LID];
 	uint8_t flags[NPC_MAX_LID];
+	bool has_eth_type;
+	bool is_second_pass_rule;
+	bool set_ipv6ext_ltype_mask;
+	/* adjust ltype in MCAM to match at least one vlan */
+	bool set_vlan_ltype_mask;
 	uint8_t *mcam_data; /* point to flow->mcam_data + key_len */
 	uint8_t *mcam_mask; /* point to flow->mcam_mask + key_len */
 	bool is_vf;
-	/* adjust ltype in MCAM to match at least one vlan */
-	bool set_vlan_ltype_mask;
-	bool set_ipv6ext_ltype_mask;
-	bool is_second_pass_rule;
-	bool has_eth_type;
-	uint16_t nb_tx_queues;
 	uint16_t dst_pf_func;
+	uint16_t nb_tx_queues;
 };
 
 enum npc_kpu_parser_flag {
@@ -340,6 +355,14 @@ struct npc_lid_lt_xtract_info {
 	struct npc_xtract_info xtract[NPC_MAX_LD];
 };
 
+struct npc_lid_lt_xtract_info_cn20k {
+	/* Info derived from parser configuration */
+	uint16_t npc_proto;	    /* Network protocol identified */
+	uint8_t valid_flags_mask;   /* Flags applicable */
+	uint8_t is_terminating : 1; /* No more parsing */
+	struct npc_xtract_info xtract;
+};
+
 union npc_kex_ldata_flags_cfg {
 	struct {
 		uint64_t lid : 3;
@@ -349,6 +372,11 @@ union npc_kex_ldata_flags_cfg {
 	uint64_t i;
 };
 
+#define NPC_MAX_EXTRACTTORS 24
+typedef struct npc_lid_lt_xtract_info_cn20k npc_dxcfg_cn20k_t[NPC_MAX_INTF][NPC_MAX_EXTRACTTORS]
+							     [NPC_MAX_LT];
+typedef union npc_kex_ldata_flags_cfg npc_lid_cn20k_t[NPC_MAX_INTF][NPC_MAX_EXTRACTTORS];
+
 typedef struct npc_lid_lt_xtract_info npc_dxcfg_t[NPC_MAX_INTF][NPC_MAX_LID]
 						 [NPC_MAX_LT];
 typedef struct npc_lid_lt_xtract_info npc_fxcfg_t[NPC_MAX_INTF][NPC_MAX_LD]
@@ -387,33 +415,36 @@ TAILQ_HEAD(npc_age_flow_list_head, npc_age_flow_entry);
 
 struct npc {
 	struct mbox *mbox;			/* Mbox */
-	uint32_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */
+	uint64_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */
 	uint8_t hash_extract_cap;		/* hash extract support */
 	uint8_t profile_name[MKEX_NAME_LEN];	/* KEX profile name */
-	uint32_t keyx_len[NPC_MAX_INTF];	/* per intf key len in bits */
-	uint32_t datax_len[NPC_MAX_INTF];	/* per intf data len in bits */
-	uint32_t keyw[NPC_MAX_INTF];		/* max key + data len bits */
-	uint32_t mcam_entries;			/* mcam entries supported */
-	uint16_t channel;			/* RX Channel number */
 	bool is_sdp_link;
+	uint16_t channel;		  /* RX Channel number */
+	uint32_t keyx_len[NPC_MAX_INTF];  /* per intf key len in bits */
+	uint32_t datax_len[NPC_MAX_INTF]; /* per intf data len in bits */
+	uint32_t keyw[NPC_MAX_INTF];	  /* max key + data len bits */
+	uint32_t mcam_entries;		  /* mcam entries supported */
+	uint16_t switch_header_type;	  /* Supported switch header type */
+	uint16_t flow_max_priority;	  /* Max priority for flow */
 	uint16_t sdp_channel;
 	uint16_t sdp_channel_mask;
-	uint32_t rss_grps;			/* rss groups supported */
-	uint16_t flow_prealloc_size;		/* Pre allocated mcam size */
-	uint16_t flow_max_priority;		/* Max priority for flow */
-	uint16_t switch_header_type; /* Supported switch header type */
+	uint32_t rss_grps;	     /* rss groups supported */
+	uint16_t flow_prealloc_size; /* Pre allocated mcam size */
+	uint8_t exact_match_ena;
+	uint16_t pf_func; /* pf_func of device */
 	uint32_t mark_actions;
-	uint32_t vtag_strip_actions; /* vtag insert/strip actions */
-	uint16_t pf_func;	     /* pf_func of device */
-	npc_dxcfg_t prx_dxcfg;	     /* intf, lid, lt, extract */
-	npc_fxcfg_t prx_fxcfg;	     /* Flag extract */
-	npc_ld_flags_t prx_lfcfg;    /* KEX LD_Flags CFG */
+	uint32_t vtag_strip_actions;	   /* vtag insert/strip actions */
+	npc_dxcfg_t prx_dxcfg;		   /* intf, lid, lt, extract */
+	npc_dxcfg_cn20k_t prx_dxcfg_cn20k; /* intf, ext, lt, extract */
+	npc_lid_cn20k_t lid_cfg;	   /* KEX LD_Flags CFG */
+	npc_fxcfg_t prx_fxcfg;		   /* Flag extract */
+	npc_ld_flags_t prx_lfcfg;	   /* KEX LD_Flags CFG */
 	struct npc_flow_list *flow_list;
 	struct npc_prio_flow_list_head *prio_flow_list;
 	struct npc_age_flow_list_head age_flow_list;
 	struct plt_bitmap *rss_grp_entries;
 	struct npc_flow_list ipsec_list;
-	uint8_t exact_match_ena;
+	uint8_t enable_debug;
 };
 
 #define NPC_HASH_FIELD_LEN 16
@@ -432,6 +463,7 @@ roc_npc_to_npc_priv(struct roc_npc *npc)
 	return (struct npc *)npc->reserved;
 }
 
+int npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count);
 int npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr);
 int npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id);
 int npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count);
@@ -440,9 +472,10 @@ int npc_mcam_free_entry(struct mbox *mbox, uint32_t entry);
 int npc_mcam_free_all_entries(struct npc *npc);
 int npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow,
 			     struct npc_parse_state *pst);
-int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam,
-			 struct roc_npc_flow *ref_mcam, int prio,
-			 int *resp_count);
+int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
+			 uint8_t prio, int *resp_count);
+int npc_mcam_alloc_entry_cn20k(struct npc *npc, struct roc_npc_flow *mcam, int *resp_count);
+
 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);
 
@@ -453,6 +486,7 @@ int npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_in
 			   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);
+uint8_t npc_get_key_type(struct npc *npc, struct roc_npc_flow *flow);
 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 a507df994f..75d3b0702c 100644
--- a/drivers/common/cnxk/roc_npc_utils.c
+++ b/drivers/common/cnxk/roc_npc_utils.c
@@ -4,6 +4,36 @@
 #include "roc_api.h"
 #include "roc_priv.h"
 
+enum npc_mcam_cn20k_key_width {
+	NPC_CN20K_MCAM_KEY_X1 = 0,
+	NPC_CN20K_MCAM_KEY_DYN = NPC_CN20K_MCAM_KEY_X1,
+	NPC_CN20K_MCAM_KEY_X2,
+	NPC_CN20K_MCAM_KEY_X4,
+	NPC_CN20K_MCAM_KEY_MAX,
+};
+
+uint8_t
+npc_get_key_type(struct npc *npc, struct roc_npc_flow *flow)
+{
+	int i;
+
+	/* KEX is configured just for X2 */
+	if (npc->keyw[ROC_NPC_INTF_RX] == 1)
+		return NPC_CN20K_MCAM_KEY_X2;
+
+	/* KEX is configured just for X4 */
+	if (npc->keyw[ROC_NPC_INTF_RX] == 2)
+		return NPC_CN20K_MCAM_KEY_X4;
+
+	/* KEX is configured for both X2 and X4 */
+	/* Check mask for upper 256 bits. if mask is set, then it is X4 entry */
+	for (i = 4; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
+		if (flow->mcam_mask[i] != 0)
+			return NPC_CN20K_MCAM_KEY_X4;
+	}
+	return NPC_CN20K_MCAM_KEY_X2;
+}
+
 static void
 npc_prep_mcam_ldata(uint8_t *ptr, const uint8_t *data, int len)
 {
@@ -67,8 +97,9 @@ npc_ipv6_hash_mask_get(struct npc_xtract_info *xinfo, struct npc_parse_item_info
 	memset(&hw_mask[offset], 0xFF, NPC_HASH_FIELD_LEN);
 }
 
-void
-npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid, int lt)
+static void
+npc_get_hw_supp_mask_legacy(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			    int lt)
 {
 	struct npc_xtract_info *xinfo, *lfinfo;
 	char *hw_mask = info->hw_mask;
@@ -101,6 +132,40 @@ npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *in
 	}
 }
 
+static void
+npc_get_hw_supp_mask_o20k(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			  int lt)
+{
+	struct npc_xtract_info *xinfo;
+	union npc_kex_ldata_flags_cfg *lid_info;
+	char *hw_mask = info->hw_mask;
+	int ex;
+	int intf;
+
+	intf = pst->nix_intf;
+	memset(hw_mask, 0, info->len);
+	for (ex = 0; ex < NPC_MAX_EXTRACTTORS; ex++) {
+		lid_info = &pst->npc->lid_cfg[intf][ex];
+		if (lid_info->s.lid != lid)
+			continue;
+		xinfo = &pst->npc->prx_dxcfg_cn20k[intf][ex][lt].xtract;
+
+		if (pst->npc->hash_extract_cap && xinfo->use_hash)
+			npc_ipv6_hash_mask_get(xinfo, info);
+		else
+			npc_set_hw_mask(info, xinfo, hw_mask);
+	}
+}
+
+void
+npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid, int lt)
+{
+	if (!roc_model_is_cn20k())
+		return npc_get_hw_supp_mask_legacy(pst, info, lid, lt);
+	else
+		return npc_get_hw_supp_mask_o20k(pst, info, lid, lt);
+}
+
 inline int
 npc_mask_is_supported(const char *mask, const char *hw_mask, int len)
 {
@@ -381,10 +446,10 @@ npc_hash_field_get(struct npc_xtract_info *xinfo, const struct roc_npc_flow_item
 	return 1;
 }
 
-int
-npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
-			    const struct roc_npc_flow_item_ipv6 *ipv6_mask,
-			    struct npc_parse_state *pst, uint8_t ltype)
+static int
+npc_process_ipv6_field_hash_legacy(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+				   const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+				   struct npc_parse_state *pst, uint8_t ltype)
 {
 	struct npc_lid_lt_xtract_info *lid_lt_xinfo;
 	uint8_t hash_field[ROC_IPV6_ADDR_LEN];
@@ -421,9 +486,64 @@ npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
 	return 0;
 }
 
+static int
+npc_process_ipv6_field_hash_o20k(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+				 const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+				 struct npc_parse_state *pst, uint8_t ltype)
+{
+	struct npc_lid_lt_xtract_info_cn20k *lid_lt_xinfo;
+	union npc_kex_ldata_flags_cfg *lid_cfg;
+	uint8_t hash_field[ROC_IPV6_ADDR_LEN];
+	struct npc_xtract_info *xinfo;
+	struct roc_ipv6_hdr ipv6_buf;
+	uint32_t hash = 0, mask;
+	int intf, i, rc = 0;
+
+	memset(&ipv6_buf, 0, sizeof(ipv6_buf));
+	memset(hash_field, 0, sizeof(hash_field));
+
+	intf = pst->nix_intf;
+	for (i = 0; i < NPC_MAX_EXTRACTTORS; i++) {
+		lid_cfg = &pst->npc->lid_cfg[intf][i];
+		if (lid_cfg->s.lid != NPC_LID_LC)
+			continue;
+		lid_lt_xinfo = &pst->npc->prx_dxcfg_cn20k[intf][NPC_LID_LC][ltype];
+
+		xinfo = &lid_lt_xinfo->xtract;
+		if (!xinfo->use_hash)
+			continue;
+
+		rc = npc_hash_field_get(xinfo, ipv6_spec, ipv6_mask, hash_field);
+		if (rc == 0)
+			continue;
+
+		rc = npc_ipv6_field_hash_get(pst->npc, (const uint32_t *)hash_field, intf, i,
+					     &hash);
+		if (rc)
+			return rc;
+
+		mask = GENMASK(31, 0);
+		memcpy(pst->mcam_mask + xinfo->key_off, (uint8_t *)&mask, 4);
+		memcpy(pst->mcam_data + xinfo->key_off, (uint8_t *)&hash, 4);
+	}
+
+	return 0;
+}
+
 int
-npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
-		       int lt, uint8_t flags)
+npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+			    const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+			    struct npc_parse_state *pst, uint8_t ltype)
+{
+	if (!roc_model_is_cn20k())
+		return npc_process_ipv6_field_hash_legacy(ipv6_spec, ipv6_mask, pst, ltype);
+	else
+		return npc_process_ipv6_field_hash_o20k(ipv6_spec, ipv6_mask, pst, ltype);
+}
+
+static int
+npc_update_parse_state_legacy(struct npc_parse_state *pst, struct npc_parse_item_info *info,
+			      int lid, int lt, uint8_t flags)
 {
 	struct npc_lid_lt_xtract_info *xinfo;
 	struct roc_npc_flow_dump_data *dump;
@@ -461,8 +581,7 @@ npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *
 		if (lf_cfg == lid) {
 			for (j = 0; j < NPC_MAX_LFL; j++) {
 				lfinfo = pst->npc->prx_fxcfg[intf][i][j].xtract;
-				rc = npc_update_extraction_data(pst, info,
-								&lfinfo[0]);
+				rc = npc_update_extraction_data(pst, info, &lfinfo[0]);
 				if (rc != 0)
 					return rc;
 
@@ -480,42 +599,127 @@ npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *
 	return 0;
 }
 
+static int
+npc_update_parse_state_o20(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			   int lt, uint8_t flags)
+{
+	struct npc_lid_lt_xtract_info_cn20k *xinfo;
+	union npc_kex_ldata_flags_cfg *lid_cfg;
+	struct roc_npc_flow_dump_data *dump;
+	int intf;
+	int i, rc = 0;
+
+	pst->layer_mask |= lid;
+	pst->lt[lid] = lt;
+	pst->flags[lid] = flags;
+
+	intf = pst->nix_intf;
+	if (info->spec == NULL)
+		goto done;
+
+	for (i = 0; i < NPC_MAX_EXTRACTTORS; i++) {
+		lid_cfg = &pst->npc->lid_cfg[intf][i];
+		if (lid_cfg->s.lid != lid)
+			continue;
+		xinfo = &pst->npc->prx_dxcfg_cn20k[intf][i][lt];
+		if (xinfo->is_terminating)
+			pst->terminate = 1;
+
+		if (xinfo->xtract.use_hash)
+			continue;
+		rc = npc_update_extraction_data(pst, info, &xinfo->xtract);
+		if (rc != 0)
+			return rc;
+	}
+
+done:
+	dump = &pst->flow->dump_data[pst->flow->num_patterns++];
+	dump->lid = lid;
+	dump->ltype = lt;
+	pst->pattern++;
+	return 0;
+}
+
+int
+npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+		       int lt, uint8_t flags)
+{
+	if (roc_model_is_cn20k())
+		return npc_update_parse_state_o20(pst, info, lid, lt, flags);
+	else
+		return npc_update_parse_state_legacy(pst, info, lid, lt, flags);
+}
+
 int
 npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id)
 {
-	struct npc_mcam_write_entry_req *req;
-	struct npc_mcam_write_entry_rsq *rsp;
+	struct msg_rsp *rsp;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = 0, idx;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL) {
-		rc = -ENOSPC;
-		goto exit;
-	}
-	req->set_cntr = 0;
-	req->cntr = 0;
-	req->entry = mcam_id;
-
-	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
-	req->enable_entry = 1;
-	req->entry_data.action = flow->npc_action;
-	req->entry_data.vtag_action = flow->vtag_action;
-
-	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		req->entry_data.kw[idx] = 0x0;
-		req->entry_data.kw_mask[idx] = 0x0;
-	}
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (req == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		req->cntr = 0;
+		req->entry = mcam_id;
+
+		req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+		req->enable_entry = 1;
+		req->entry_data.action = flow->npc_action;
+		req->entry_data.vtag_action = flow->vtag_action;
+
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			req->entry_data.kw[idx] = 0x0;
+			req->entry_data.kw_mask[idx] = 0x0;
+		}
+
+		if (flow->nix_intf == NIX_INTF_RX) {
+			req->entry_data.kw[0] |= (uint64_t)npc->channel;
+			req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+		} else {
+			uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 
-	if (flow->nix_intf == NIX_INTF_RX) {
-		req->entry_data.kw[0] |= (uint64_t)npc->channel;
-		req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+			pf_func = plt_cpu_to_be_16(pf_func);
+			req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
+			req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+		}
 	} else {
-		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
+		struct npc_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		req->set_cntr = 0;
+		req->cntr = 0;
+		req->entry = mcam_id;
+
+		req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+		req->enable_entry = 1;
+		req->entry_data.action = flow->npc_action;
+		req->entry_data.vtag_action = flow->vtag_action;
+
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			req->entry_data.kw[idx] = 0x0;
+			req->entry_data.kw_mask[idx] = 0x0;
+		}
+
+		if (flow->nix_intf == NIX_INTF_RX) {
+			req->entry_data.kw[0] |= (uint64_t)npc->channel;
+			req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+		} else {
+			uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 
-		pf_func = plt_cpu_to_be_16(pf_func);
-		req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
-		req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+			pf_func = plt_cpu_to_be_16(pf_func);
+			req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
+			req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+		}
 	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -783,13 +987,12 @@ npc_insert_into_flow_list(struct npc *npc, struct npc_prio_flow_entry *entry)
 }
 
 static int
-npc_allocate_mcam_entry(struct mbox *mbox, int prio,
-			struct npc_mcam_alloc_entry_rsp *rsp_local,
-			int ref_entry)
+npc_allocate_mcam_entry(struct mbox *mbox, int prio, struct npc_mcam_alloc_entry_rsp *rsp_local,
+			int ref_entry, uint8_t kw_type)
 {
-	struct npc_mcam_alloc_entry_rsp *rsp_cmd;
-	struct npc_mcam_alloc_entry_req *req;
 	struct npc_mcam_alloc_entry_rsp *rsp;
+	struct npc_mcam_alloc_entry_req *req;
+
 	int rc = -ENOSPC;
 
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
@@ -797,20 +1000,20 @@ npc_allocate_mcam_entry(struct mbox *mbox, int prio,
 		goto exit;
 	req->contig = 1;
 	req->count = 1;
-	req->priority = prio;
+	req->ref_priority = prio;
 	req->ref_entry = ref_entry;
+	req->kw_type = kw_type;
 
-	rc = mbox_process_msg(mbox, (void *)&rsp_cmd);
+	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		goto exit;
 
-	if (!rsp_cmd->count) {
+	if (!rsp->count) {
 		rc = -ENOSPC;
 		goto exit;
 	}
 
-	mbox_memcpy(rsp_local, rsp_cmd, sizeof(*rsp));
-
+	mbox_memcpy(rsp_local, rsp, sizeof(*rsp));
 	rc = 0;
 exit:
 	mbox_put(mbox);
@@ -854,8 +1057,7 @@ npc_find_mcam_ref_entry(struct roc_npc_flow *flow, struct npc *npc, int *prio,
 }
 
 static int
-npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
-			    struct npc *npc,
+npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow, struct npc *npc,
 			    struct npc_mcam_alloc_entry_rsp *rsp_local)
 {
 	int prio, ref_entry = 0, rc = 0, dir = NPC_MCAM_LOWER_PRIO;
@@ -863,7 +1065,7 @@ npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
 
 retry:
 	npc_find_mcam_ref_entry(flow, npc, &prio, &ref_entry, dir);
-	rc = npc_allocate_mcam_entry(mbox, prio, rsp_local, ref_entry);
+	rc = npc_allocate_mcam_entry(mbox, prio, rsp_local, ref_entry, flow->key_type);
 	if (rc && !retry_done) {
 		plt_npc_dbg(
 			"npc: Failed to allocate lower priority entry. Retrying for higher priority");
@@ -879,32 +1081,42 @@ npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
 }
 
 int
-npc_get_free_mcam_entry(struct mbox *mbox, struct roc_npc_flow *flow,
-			struct npc *npc)
+npc_get_free_mcam_entry(struct mbox *mbox, struct roc_npc_flow *flow, struct npc *npc)
 {
 	struct npc_mcam_alloc_entry_rsp rsp_local;
 	struct npc_prio_flow_entry *new_entry;
 	int rc = 0;
 
-	rc = npc_alloc_mcam_by_ref_entry(mbox, flow, npc, &rsp_local);
-
-	if (rc)
-		return rc;
-
 	new_entry = plt_zmalloc(sizeof(*new_entry), 0);
 	if (!new_entry)
 		return -ENOSPC;
 
-	new_entry->flow = flow;
+	if (roc_model_is_cn20k()) {
+		rc = npc_allocate_mcam_entry(mbox, NPC_MCAM_ANY_PRIO, &rsp_local, 0,
+					     flow->key_type);
+		if (rc) {
+			plt_npc_dbg("npc: failed to allocate MCAM entry.");
+			return rc;
+		}
+
+		new_entry->flow = flow;
+	} else {
+		rc = npc_alloc_mcam_by_ref_entry(mbox, flow, npc, &rsp_local);
 
-	plt_npc_dbg("kernel allocated MCAM entry %d", rsp_local.entry);
+		if (rc)
+			return rc;
 
-	rc = npc_sort_mcams_by_user_prio_level(mbox, new_entry, npc,
-					       &rsp_local);
-	if (rc)
-		goto err;
+		new_entry->flow = flow;
+
+		plt_npc_dbg("kernel allocated MCAM entry %d", rsp_local.entry);
+
+		rc = npc_sort_mcams_by_user_prio_level(mbox, new_entry, npc, &rsp_local);
+		if (rc)
+			goto err;
+
+		plt_npc_dbg("allocated MCAM entry after sorting %d", rsp_local.entry);
+	}
 
-	plt_npc_dbg("allocated MCAM entry after sorting %d", rsp_local.entry);
 	flow->mcam_id = rsp_local.entry;
 	npc_insert_into_flow_list(npc, new_entry);
 
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 6f8a2e02da..a5a7b1f70f 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -480,6 +480,7 @@ INTERNAL {
 	roc_npc_mcam_free_counter;
 	roc_npc_mcam_free;
 	roc_npc_mcam_free_entry;
+	roc_npc_mcam_get_stats;
 	roc_npc_mcam_init;
 	roc_npc_mcam_move;
 	roc_npc_mcam_merge_base_steering_rule;
-- 
2.39.2


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

* [dpdk-dev] [PATCH 2/2] net/cnxk: support rte flow on cn20k
  2024-10-21  4:01 [dpdk-dev] [PATCH 1/2] common/cnxk: support NPC flow on cn20k psatheesh
@ 2024-10-21  4:01 ` psatheesh
  2024-10-21 17:09   ` Stephen Hemminger
  2024-10-29  7:31 ` [dpdk-dev] [PATCH v2 1/2] common/cnxk: support NPC " psatheesh
  2024-11-12  9:58 ` [dpdk-dev] [PATCH v3 1/2] common/cnxk: support NPC " psatheesh
  2 siblings, 1 reply; 8+ messages in thread
From: psatheesh @ 2024-10-21  4:01 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Support for rte flow in cn20k.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 drivers/net/cnxk/cn10k_ethdev.c        |   8 +-
 drivers/net/cnxk/cn10k_flow.h          |  21 --
 drivers/net/cnxk/cn20k_ethdev.c        |   4 +
 drivers/net/cnxk/cnxk_ethdev_devargs.c |  10 +-
 drivers/net/cnxk/cnxk_flow.c           |  10 +-
 drivers/net/cnxk/cnxk_flow_wrapper.c   | 303 +++++++++++++++++++++++++
 drivers/net/cnxk/cnxk_flow_wrapper.h   |  21 ++
 drivers/net/cnxk/meson.build           |  10 +-
 8 files changed, 355 insertions(+), 32 deletions(-)
 delete mode 100644 drivers/net/cnxk/cn10k_flow.h
 create mode 100644 drivers/net/cnxk/cnxk_flow_wrapper.c
 create mode 100644 drivers/net/cnxk/cnxk_flow_wrapper.h

diff --git a/drivers/net/cnxk/cn10k_ethdev.c b/drivers/net/cnxk/cn10k_ethdev.c
index fbb9b09062..a4b3d56c61 100644
--- a/drivers/net/cnxk/cn10k_ethdev.c
+++ b/drivers/net/cnxk/cn10k_ethdev.c
@@ -2,9 +2,9 @@
  * Copyright(C) 2021 Marvell.
  */
 #include "cn10k_ethdev.h"
-#include "cn10k_flow.h"
 #include "cn10k_rx.h"
 #include "cn10k_tx.h"
+#include "cnxk_flow_wrapper.h"
 
 static uint16_t
 nix_rx_offload_flags(struct rte_eth_dev *eth_dev)
@@ -913,9 +913,9 @@ npc_flow_ops_override(void)
 	init_once = 1;
 
 	/* Update platform specific ops */
-	cnxk_flow_ops.create = cn10k_flow_create;
-	cnxk_flow_ops.destroy = cn10k_flow_destroy;
-	cnxk_flow_ops.info_get = cn10k_flow_info_get;
+	cnxk_flow_ops.create = cnxk_flow_create_wrapper;
+	cnxk_flow_ops.destroy = cnxk_flow_destroy_wrapper;
+	cnxk_flow_ops.info_get = cnxk_flow_info_get_wrapper;
 }
 
 static int
diff --git a/drivers/net/cnxk/cn10k_flow.h b/drivers/net/cnxk/cn10k_flow.h
deleted file mode 100644
index 316b74e6a6..0000000000
--- a/drivers/net/cnxk/cn10k_flow.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(C) 2020 Marvell.
- */
-#ifndef __CN10K_RTE_FLOW_H__
-#define __CN10K_RTE_FLOW_H__
-
-#include <rte_flow_driver.h>
-
-struct rte_flow *cn10k_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
-				   const struct rte_flow_item pattern[],
-				   const struct rte_flow_action actions[],
-				   struct rte_flow_error *error);
-int cn10k_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
-		       struct rte_flow_error *error);
-
-int cn10k_flow_info_get(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
-			struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
-
-#define CN10K_NPC_COUNTERS_MAX 512
-
-#endif /* __CN10K_RTE_FLOW_H__ */
diff --git a/drivers/net/cnxk/cn20k_ethdev.c b/drivers/net/cnxk/cn20k_ethdev.c
index 37c372d80f..e74dd88172 100644
--- a/drivers/net/cnxk/cn20k_ethdev.c
+++ b/drivers/net/cnxk/cn20k_ethdev.c
@@ -4,6 +4,7 @@
 #include "cn20k_ethdev.h"
 #include "cn20k_rx.h"
 #include "cn20k_tx.h"
+#include "cnxk_flow_wrapper.h"
 
 static uint16_t
 nix_rx_offload_flags(struct rte_eth_dev *eth_dev)
@@ -867,6 +868,9 @@ npc_flow_ops_override(void)
 	init_once = 1;
 
 	/* Update platform specific ops */
+	cnxk_flow_ops.create = cnxk_flow_create_wrapper;
+	cnxk_flow_ops.destroy = cnxk_flow_destroy_wrapper;
+	cnxk_flow_ops.info_get = cnxk_flow_info_get_wrapper;
 }
 
 static int
diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c
index 5bd50bb9a1..bdf5d88b92 100644
--- a/drivers/net/cnxk/cnxk_ethdev_devargs.c
+++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c
@@ -88,8 +88,7 @@ parse_flow_max_priority(const char *key, const char *value, void *extra_args)
 
 	val = atoi(value);
 
-	/* Limit the max priority to 32 */
-	if (val < 1 || val > 32)
+	if (val < 1 || val > ROC_NPC_MAX_MCAM_PRIORITY)
 		return -EINVAL;
 
 	*(uint16_t *)extra_args = val;
@@ -390,7 +389,12 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 		dev->nix.meta_buf_sz = meta_buf_sz;
 
 	dev->npc.flow_prealloc_size = flow_prealloc_size;
-	dev->npc.flow_max_priority = flow_max_priority;
+
+	if (roc_model_is_cn20k())
+		dev->npc.flow_max_priority = ROC_NPC_MAX_MCAM_PRIORITY;
+	else
+		dev->npc.flow_max_priority = flow_max_priority;
+
 	dev->npc.switch_header_type = switch_header_type;
 	dev->npc.sdp_channel = sdp_chan.channel;
 	dev->npc.sdp_channel_mask = sdp_chan.mask;
diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c
index d3c20e8315..887dd8f911 100644
--- a/drivers/net/cnxk/cnxk_flow.c
+++ b/drivers/net/cnxk/cnxk_flow.c
@@ -990,10 +990,14 @@ cnxk_flow_query_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
 		npc = &rep_dev->parent_dev->npc;
 	}
 
-	if (in_flow->use_pre_alloc)
+	if (in_flow->use_pre_alloc) {
 		rc = roc_npc_inl_mcam_read_counter(in_flow->ctr_id, &query->hits);
-	else
-		rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	} else {
+		if (roc_model_is_cn20k())
+			rc = roc_npc_mcam_get_stats(npc, in_flow, &query->hits);
+		else
+			rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	}
 	if (rc != 0) {
 		errcode = EIO;
 		errmsg = "Error reading flow counter";
diff --git a/drivers/net/cnxk/cnxk_flow_wrapper.c b/drivers/net/cnxk/cnxk_flow_wrapper.c
new file mode 100644
index 0000000000..af2eee7266
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_flow_wrapper.c
@@ -0,0 +1,303 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+
+#ifdef CNXK_PLATFORM_CN10K
+#include "cn10k_ethdev.h"
+#include "cn10k_rx.h"
+#endif
+#ifdef CNXK_PLATFORM_CN20K
+#include "cn20k_ethdev.h"
+#include "cn20k_rx.h"
+#endif
+#include "cnxk_ethdev_mcs.h"
+#include "cnxk_flow_wrapper.h"
+#include <cnxk_flow.h>
+
+static void
+cnxk_eth_set_rx_function(struct rte_eth_dev *eth_dev)
+{
+	RTE_SET_USED(eth_dev);
+#ifdef CNXK_PLATFORM_CN10K
+	cn10k_eth_set_rx_function(eth_dev);
+#endif
+#ifdef CNXK_PLATFORM_CN20K
+	cn20k_eth_set_rx_function(eth_dev);
+#endif
+}
+
+static int
+cnxk_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
+{
+	return nix_mtr_connect(eth_dev, mtr_id);
+}
+
+static int
+cnxk_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
+{
+	struct rte_mtr_error mtr_error;
+
+	return nix_mtr_destroy(eth_dev, mtr_id, &mtr_error);
+}
+
+static int
+cnxk_mtr_configure(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[])
+{
+	uint32_t mtr_id = 0xffff, prev_mtr_id = 0xffff, next_mtr_id = 0xffff;
+	const struct rte_flow_action_meter *mtr_conf;
+	const struct rte_flow_action_queue *q_conf;
+	const struct rte_flow_action_rss *rss_conf;
+	struct cnxk_mtr_policy_node *policy;
+	bool is_mtr_act = false;
+	int tree_level = 0;
+	int rc = -EINVAL, i;
+
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
+			mtr_conf = (const struct rte_flow_action_meter *)(actions[i].conf);
+			mtr_id = mtr_conf->mtr_id;
+			is_mtr_act = true;
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+			q_conf = (const struct rte_flow_action_queue *)(actions[i].conf);
+			if (is_mtr_act)
+				nix_mtr_rq_update(eth_dev, mtr_id, 1, &q_conf->index);
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
+			rss_conf = (const struct rte_flow_action_rss *)(actions[i].conf);
+			if (is_mtr_act)
+				nix_mtr_rq_update(eth_dev, mtr_id, rss_conf->queue_num,
+						  rss_conf->queue);
+		}
+	}
+
+	if (!is_mtr_act)
+		return rc;
+
+	prev_mtr_id = mtr_id;
+	next_mtr_id = mtr_id;
+	while (next_mtr_id != 0xffff) {
+		rc = nix_mtr_validate(eth_dev, next_mtr_id);
+		if (rc)
+			return rc;
+
+		rc = nix_mtr_policy_act_get(eth_dev, next_mtr_id, &policy);
+		if (rc)
+			return rc;
+
+		rc = nix_mtr_color_action_validate(eth_dev, mtr_id, &prev_mtr_id, &next_mtr_id,
+						   policy, &tree_level);
+		if (rc)
+			return rc;
+	}
+
+	return nix_mtr_configure(eth_dev, mtr_id);
+}
+
+static int
+cnxk_rss_action_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+			 const struct rte_flow_action *act)
+{
+	const struct rte_flow_action_rss *rss;
+
+	if (act == NULL)
+		return -EINVAL;
+
+	rss = (const struct rte_flow_action_rss *)act->conf;
+
+	if (attr->egress) {
+		plt_err("No support of RSS in egress");
+		return -EINVAL;
+	}
+
+	if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
+		plt_err("multi-queue mode is disabled");
+		return -ENOTSUP;
+	}
+
+	if (!rss || !rss->queue_num) {
+		plt_err("no valid queues");
+		return -EINVAL;
+	}
+
+	if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
+		plt_err("non-default RSS hash functions are not supported");
+		return -ENOTSUP;
+	}
+
+	if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
+		plt_err("RSS hash key too large");
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+struct rte_flow *
+cnxk_flow_create_wrapper(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+			 const struct rte_flow_item pattern[],
+			 const struct rte_flow_action actions[], struct rte_flow_error *error)
+{
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	const struct rte_flow_action *action_rss = NULL;
+	const struct rte_flow_action_meter *mtr = NULL;
+	const struct rte_flow_action *act_q = NULL;
+	struct roc_npc *npc = &dev->npc;
+	struct roc_npc_flow *flow;
+	void *mcs_flow = NULL;
+	int vtag_actions = 0;
+	uint32_t req_act = 0;
+	int mark_actions;
+	int i, rc;
+
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER)
+			req_act |= ROC_NPC_ACTION_TYPE_METER;
+
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
+			act_q = &actions[i];
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
+			req_act |= ROC_NPC_ACTION_TYPE_RSS;
+			action_rss = &actions[i];
+		}
+	}
+
+	if (req_act & ROC_NPC_ACTION_TYPE_METER) {
+		if ((req_act & ROC_NPC_ACTION_TYPE_RSS) &&
+		    ((req_act & ROC_NPC_ACTION_TYPE_QUEUE))) {
+			return NULL;
+		}
+		if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
+			rc = cnxk_rss_action_validate(eth_dev, attr, action_rss);
+			if (rc)
+				return NULL;
+		} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
+			const struct rte_flow_action_queue *act_queue;
+			act_queue = (const struct rte_flow_action_queue *)act_q->conf;
+			if (act_queue->index > eth_dev->data->nb_rx_queues)
+				return NULL;
+		} else {
+			return NULL;
+		}
+	}
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
+			mtr = (const struct rte_flow_action_meter *)actions[i].conf;
+			rc = cnxk_mtr_configure(eth_dev, actions);
+			if (rc) {
+				rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+						   "Failed to configure mtr ");
+				return NULL;
+			}
+			break;
+		}
+	}
+
+	if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
+	    cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL) {
+		rc = cnxk_mcs_flow_configure(eth_dev, attr, pattern, actions, error, &mcs_flow);
+		if (rc) {
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					   "Failed to configure mcs flow");
+			return NULL;
+		}
+		return (struct rte_flow *)mcs_flow;
+	}
+
+	flow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);
+	if (!flow) {
+		if (mtr)
+			nix_mtr_chain_reset(eth_dev, mtr->mtr_id);
+
+		return NULL;
+	} else {
+		if (mtr)
+			cnxk_mtr_connect(eth_dev, mtr->mtr_id);
+	}
+
+	mark_actions = roc_npc_mark_actions_get(npc);
+	if (mark_actions) {
+		dev->rx_offload_flags |= NIX_RX_OFFLOAD_MARK_UPDATE_F;
+		cnxk_eth_set_rx_function(eth_dev);
+	}
+
+	vtag_actions = roc_npc_vtag_actions_get(npc);
+
+	if (vtag_actions) {
+		dev->rx_offload_flags |= NIX_RX_OFFLOAD_VLAN_STRIP_F;
+		cnxk_eth_set_rx_function(eth_dev);
+	}
+
+	return (struct rte_flow *)flow;
+}
+
+int
+cnxk_flow_info_get_wrapper(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			   struct rte_flow_queue_info *queue_info, struct rte_flow_error *err)
+{
+	RTE_SET_USED(dev);
+	RTE_SET_USED(err);
+
+	memset(port_info, 0, sizeof(*port_info));
+	memset(queue_info, 0, sizeof(*queue_info));
+
+	port_info->max_nb_counters = CNXK_NPC_COUNTERS_MAX;
+	port_info->max_nb_meters = CNXK_NIX_MTR_COUNT_MAX;
+
+	return 0;
+}
+
+int
+cnxk_flow_destroy_wrapper(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
+			  struct rte_flow_error *error)
+{
+	struct roc_npc_flow *flow = (struct roc_npc_flow *)rte_flow;
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_npc *npc = &dev->npc;
+	int vtag_actions = 0;
+	int mark_actions;
+	uint16_t match_id;
+	uint32_t mtr_id;
+	int rc;
+
+	match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & NPC_RX_ACT_MATCH_MASK;
+	if (match_id) {
+		mark_actions = roc_npc_mark_actions_sub_return(npc, 1);
+		if (mark_actions == 0) {
+			dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_MARK_UPDATE_F;
+			cnxk_eth_set_rx_function(eth_dev);
+		}
+	}
+
+	vtag_actions = roc_npc_vtag_actions_get(npc);
+	if (vtag_actions) {
+		if (flow->nix_intf == ROC_NPC_INTF_RX) {
+			vtag_actions = roc_npc_vtag_actions_sub_return(npc, 1);
+			if (vtag_actions == 0) {
+				dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_VLAN_STRIP_F;
+				cnxk_eth_set_rx_function(eth_dev);
+			}
+		}
+	}
+
+	if (cnxk_eth_macsec_sess_get_by_sess(dev, (void *)flow) != NULL) {
+		rc = cnxk_mcs_flow_destroy(dev, (void *)flow);
+		if (rc < 0)
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Failed to free mcs flow");
+		return rc;
+	}
+
+	mtr_id = flow->mtr_id;
+	rc = cnxk_flow_destroy(eth_dev, flow, error);
+	if (!rc && mtr_id != ROC_NIX_MTR_ID_INVALID) {
+		rc = cnxk_mtr_destroy(eth_dev, mtr_id);
+		if (rc) {
+			rte_flow_error_set(error, ENXIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Meter attached to this flow does not exist");
+		}
+	}
+	return rc;
+}
diff --git a/drivers/net/cnxk/cnxk_flow_wrapper.h b/drivers/net/cnxk/cnxk_flow_wrapper.h
new file mode 100644
index 0000000000..506293dd51
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_flow_wrapper.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell.
+ */
+#ifndef __CNXK_FLOW_WRAPPER_H__
+#define __CNXK_FLOW_WRAPPER_H__
+
+#include <rte_flow_driver.h>
+
+struct rte_flow *cnxk_flow_create_wrapper(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+					  const struct rte_flow_item pattern[],
+					  const struct rte_flow_action actions[],
+					  struct rte_flow_error *error);
+int cnxk_flow_destroy_wrapper(struct rte_eth_dev *dev, struct rte_flow *flow,
+			      struct rte_flow_error *error);
+
+int cnxk_flow_info_get_wrapper(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			       struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
+
+#define CNXK_NPC_COUNTERS_MAX 512
+
+#endif /* __CNXK_FLOW_WRAPPER_H__ */
diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build
index fcf48f600a..5b9e06e535 100644
--- a/drivers/net/cnxk/meson.build
+++ b/drivers/net/cnxk/meson.build
@@ -18,6 +18,13 @@ if soc_type != 'cn9k' and soc_type != 'cn10k' and soc_type != 'cn20k'
         soc_type = 'all'
 endif
 
+if soc_type == 'cn10k' or soc_type == 'all'
+    dpdk_conf.set('CNXK_PLATFORM_CN10K', 1)
+elif soc_type == 'cn20k'
+    dpdk_conf.set('CNXK_PLATFORM_CN20K', 1)
+endif
+
+
 sources = files(
         'cnxk_ethdev.c',
         'cnxk_ethdev_cman.c',
@@ -146,9 +153,9 @@ if soc_type == 'cn10k' or soc_type == 'all'
 sources += files(
         'cn10k_ethdev.c',
         'cn10k_ethdev_sec.c',
-        'cn10k_flow.c',
         'cn10k_rx_select.c',
         'cn10k_tx_select.c',
+        'cnxk_flow_wrapper.c',
 )
 
 if host_machine.cpu_family().startswith('aarch') and not disable_template
@@ -238,6 +245,7 @@ sources += files(
         'cn20k_ethdev.c',
         'cn20k_rx_select.c',
         'cn20k_tx_select.c',
+        'cnxk_flow_wrapper.c',
 )
 
 if host_machine.cpu_family().startswith('aarch') and not disable_template
-- 
2.39.2


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

* Re: [dpdk-dev] [PATCH 2/2] net/cnxk: support rte flow on cn20k
  2024-10-21  4:01 ` [dpdk-dev] [PATCH 2/2] net/cnxk: support rte " psatheesh
@ 2024-10-21 17:09   ` Stephen Hemminger
  0 siblings, 0 replies; 8+ messages in thread
From: Stephen Hemminger @ 2024-10-21 17:09 UTC (permalink / raw)
  To: psatheesh
  Cc: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra, dev

On Mon, 21 Oct 2024 09:31:44 +0530
<psatheesh@marvell.com> wrote:

> From: Satheesh Paul <psatheesh@marvell.com>
> 
> Support for rte flow in cn20k.
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
> ---
>  drivers/net/cnxk/cn10k_ethdev.c        |   8 +-
>  drivers/net/cnxk/cn10k_flow.h          |  21 --
>  drivers/net/cnxk/cn20k_ethdev.c        |   4 +
>  drivers/net/cnxk/cnxk_ethdev_devargs.c |  10 +-
>  drivers/net/cnxk/cnxk_flow.c           |  10 +-
>  drivers/net/cnxk/cnxk_flow_wrapper.c   | 303 +++++++++++++++++++++++++
>  drivers/net/cnxk/cnxk_flow_wrapper.h   |  21 ++
>  drivers/net/cnxk/meson.build           |  10 +-
>  8 files changed, 355 insertions(+), 32 deletions(-)
>  delete mode 100644 drivers/net/cnxk/cn10k_flow.h
>  create mode 100644 drivers/net/cnxk/cnxk_flow_wrapper.c
>  create mode 100644 drivers/net/cnxk/cnxk_flow_wrapper.h

Compiler erorrs.

*Build Failed #2:
OS: RHEL94-64
Target: x86_64-native-linuxapp-gcc
FAILED: drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_npc_mcam.c.o 
gcc -Idrivers/libtmp_rte_common_cnxk.a.p -Idrivers -I../drivers -Idrivers/common/cnxk -I../drivers/common/cnxk -Idrivers/bus/pci -I../drivers/bus/pci -Ilib/net -I../lib/net -Ilib/ethdev -I../lib/ethdev -Ilib/meter -I../lib/meter -I. -I.. -Iconfig -I../config -Ilib/eal/include -I../lib/eal/include -Ilib/eal/linux/include -I../lib/eal/linux/include -Ilib/eal/x86/include -I../lib/eal/x86/include -Ilib/eal/common -I../lib/eal/common -Ilib/eal -I../lib/eal -Ilib/kvargs -I../lib/kvargs -Ilib/log -I../lib/log -Ilib/metrics -I../lib/metrics -Ilib/telemetry -I../lib/telemetry -Ilib/pci -I../lib/pci -I../drivers/bus/pci/linux -Ilib/mbuf -I../lib/mbuf -Ilib/mempool -I../lib/mempool -Ilib/ring -I../lib/ring -Ilib/security -I../lib/security -Ilib/cryptodev -I../lib/cryptodev -Ilib/rcu -I../lib/rcu -fdiagnostics-color=always -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -O3 -include rte_config.h -Wcast-qual -Wdeprecated -Wformat -Wformat-nonliteral -Wformat-security -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wpointer-arith -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings -Wno-address-of-packed-member -Wno-packed-not-aligned -Wno-missing-field-initializers -Wno-zero-length-bounds -D_GNU_SOURCE -fPIC -march=native -mrtm -DALLOW_EXPERIMENTAL_API -DALLOW_INTERNAL_API -Wno-format-truncation -DRTE_LOG_DEFAULT_LOGTYPE=pmd.common.cnxk -MD -MQ drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_npc_mcam.c.o -MF drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_npc_mcam.c.o.d -o drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_npc_mcam.c.o -c ../drivers/common/cnxk/roc_npc_mcam.c
../drivers/common/cnxk/roc_npc_mcam.c: In function ‘npc_mcam_write_entry’:
../drivers/common/cnxk/roc_npc_mcam.c:520:70: error: iteration 7 invokes undefined behavior [-Werror=aggressive-loop-optimizations]
  520 |                         cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
      |                                                       ~~~~~~~~~~~~~~~^~~
../drivers/common/cnxk/roc_npc_mcam.c:519:31: note: within this loop
  519 |                 for (i = 0; i < NPC_CN20K_MCAM_KEY_X4_WORDS; i++) {
cc1: all warnings being treated as errors
[794/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_tim.c.o
[795/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_utils.c.o
[796/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_tim_irq.c.o
[797/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_cnxk_telemetry_bphy.c.o
[798/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_cnxk_telemetry_npa.c.o
[799/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_roc_ree.c.o
[800/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_cnxk_utils.c.o
[801/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_cnxk_security.c.o
[802/3044] Compiling C object drivers/libtmp_rte_common_cnxk.a.p/common_cnxk_cnxk_telemetry_nix.c.o
ninja: build stopped


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

* [dpdk-dev] [PATCH v2 1/2] common/cnxk: support NPC flow on cn20k
  2024-10-21  4:01 [dpdk-dev] [PATCH 1/2] common/cnxk: support NPC flow on cn20k psatheesh
  2024-10-21  4:01 ` [dpdk-dev] [PATCH 2/2] net/cnxk: support rte " psatheesh
@ 2024-10-29  7:31 ` psatheesh
  2024-10-29  7:31   ` [dpdk-dev] [PATCH v2 2/2] net/cnxk: support rte " psatheesh
  2024-11-12  9:58 ` [dpdk-dev] [PATCH v3 1/2] common/cnxk: support NPC " psatheesh
  2 siblings, 1 reply; 8+ messages in thread
From: psatheesh @ 2024-10-29  7:31 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

ROC changes to support NPC flow on cn20k.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
v2:
* Fixed generic platform compiler error.

 drivers/common/cnxk/roc_mbox.h          | 144 +++++-
 drivers/common/cnxk/roc_nix.h           |  18 +-
 drivers/common/cnxk/roc_nix_mcast.c     |  40 +-
 drivers/common/cnxk/roc_nix_vlan.c      |  66 ++-
 drivers/common/cnxk/roc_npc.c           |  58 ++-
 drivers/common/cnxk/roc_npc.h           |  59 ++-
 drivers/common/cnxk/roc_npc_mcam.c      | 602 +++++++++++++++++++-----
 drivers/common/cnxk/roc_npc_mcam_dump.c | 279 +++++++++--
 drivers/common/cnxk/roc_npc_priv.h      |  91 ++--
 drivers/common/cnxk/roc_npc_utils.c     | 340 ++++++++++---
 drivers/common/cnxk/version.map         |   1 +
 11 files changed, 1325 insertions(+), 373 deletions(-)

diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index 0864c0e8c0..cc96ca76a1 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -234,6 +234,22 @@ struct mbox_msghdr {
 	  npc_get_field_hash_info_req, npc_get_field_hash_info_rsp)            \
 	M(NPC_MCAM_GET_HIT_STATUS, 0x6015, npc_mcam_get_hit_status,            \
 	  npc_mcam_get_hit_status_req, npc_mcam_get_hit_status_rsp)            \
+	M(NPC_MCAM_DEFRAG, 0x6016, npc_defrag, msg_req,	msg_rsp)               \
+	M(NPC_CN20K_GET_KEX_CFG, 0x6017, npc_cn20k_get_kex_cfg, msg_req,       \
+	  npc_cn20k_get_kex_cfg_rsp)                                           \
+	M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6018, npc_cn20k_get_free_count,     \
+	  msg_req, npc_cn20k_get_free_count_rsp)                               \
+	M(NPC_CN20K_MCAM_WRITE_ENTRY,	0x6019, npc_cn20k_mcam_write_entry,    \
+	  npc_cn20k_mcam_write_entry_req, msg_rsp)	                       \
+	M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x601a,			       \
+	  npc_cn20k_mcam_alloc_and_write_entry,				       \
+	  npc_cn20k_mcam_alloc_and_write_entry_req,			       \
+	  npc_mcam_alloc_and_write_entry_rsp)				       \
+	M(NPC_CN20K_MCAM_READ_ENTRY,	0x601b, npc_cn20k_mcam_read_entry,     \
+	  npc_mcam_read_entry_req, npc_cn20k_mcam_read_entry_rsp)	       \
+	M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601c,                               \
+	  npc_cn20k_read_base_steer_rule, msg_req,                             \
+	  npc_cn20k_mcam_read_base_rule_rsp)                                   \
 	/* NIX mbox IDs (range 0x8000 - 0xFFFF) */                             \
 	M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, nix_lf_alloc_req,                \
 	  nix_lf_alloc_rsp)                                                    \
@@ -635,7 +651,7 @@ struct cgx_mac_addr_add_req {
  */
 struct cgx_mac_addr_add_rsp {
 	struct mbox_msghdr hdr;
-	uint8_t __io index;
+	uint32_t __io index;
 };
 
 /* Structure for requesting the operation to
@@ -643,7 +659,7 @@ struct cgx_mac_addr_add_rsp {
  */
 struct cgx_mac_addr_del_req {
 	struct mbox_msghdr hdr;
-	uint8_t __io index;
+	uint32_t __io index;
 };
 
 /* Structure for response against the operation to
@@ -651,7 +667,7 @@ struct cgx_mac_addr_del_req {
  */
 struct cgx_max_dmac_entries_get_rsp {
 	struct mbox_msghdr hdr;
-	uint8_t __io max_dmac_filters;
+	uint32_t __io max_dmac_filters;
 };
 
 struct cgx_link_user_info {
@@ -2431,6 +2447,14 @@ enum npc_af_status {
 	NPC_MCAM_ALLOC_FAILED = -703,
 	NPC_MCAM_PERM_DENIED = -704,
 	NPC_AF_ERR_HIGIG_CONFIG_FAIL = -705,
+	NPC_AF_ERR_HIGIG_NOT_SUPPORTED = -706,
+	NPC_FLOW_INTF_INVALID = -707,
+	NPC_FLOW_CHAN_INVALID = -708,
+	NPC_FLOW_NO_NIXLF = -709,
+	NPC_FLOW_NOT_SUPPORTED = -710,
+	NPC_FLOW_VF_PERM_DENIED = -711,
+	NPC_FLOW_VF_NOT_INIT = -712,
+	NPC_FLOW_VF_OVERLAP = -713,
 };
 
 struct npc_mcam_alloc_entry_req {
@@ -2440,9 +2464,12 @@ struct npc_mcam_alloc_entry_req {
 #define NPC_MCAM_ANY_PRIO    0
 #define NPC_MCAM_LOWER_PRIO  1
 #define NPC_MCAM_HIGHER_PRIO 2
-	uint8_t __io priority; /* Lower or higher w.r.t ref_entry */
+	uint8_t __io ref_priority; /* Lower or higher w.r.t ref_entry */
 	uint16_t __io ref_entry;
 	uint16_t __io count; /* Number of entries requested */
+	uint8_t __io kw_type; /* Key type */
+	uint8_t __io virt;    /* Request virtual index */
+	uint16_t __io rsvd[16];	/* Reserved */
 };
 
 struct npc_mcam_alloc_entry_rsp {
@@ -2454,6 +2481,7 @@ struct npc_mcam_alloc_entry_rsp {
 	uint16_t __io count;	  /* Number of entries allocated */
 	uint16_t __io free_count; /* Number of entries available */
 	uint16_t __io entry_list[NPC_MAX_NONCONTIG_ENTRIES];
+	uint16_t __io rsvd[16];	/* Reserved */
 };
 
 struct npc_mcam_free_entry_req {
@@ -2480,6 +2508,26 @@ struct npc_mcam_write_entry_req {
 	uint8_t __io set_cntr;	   /* Set counter for this entry ? */
 };
 
+struct cn20k_mcam_entry {
+#define NPC_CN20K_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */
+	uint64_t __io kw[NPC_CN20K_MAX_KWS_IN_KEY];
+	uint64_t __io kw_mask[NPC_CN20K_MAX_KWS_IN_KEY];
+	uint64_t __io action;
+	uint64_t __io vtag_action;
+};
+
+struct npc_cn20k_mcam_write_entry_req {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint16_t __io entry;	   /* MCAM entry to write this match key */
+	uint16_t __io cntr;	   /* Counter for this MCAM entry */
+	uint8_t __io intf;	   /* Rx or Tx interface */
+	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
+	uint8_t __io hw_prio;	   /* hardware priority, valid for cn20k */
+	uint8_t __io req_kw_type;  /* Type of kw which should be written */
+	uint64_t __io reserved;	   /* reserved for future use */
+};
+
 /* Enable/Disable a given entry */
 struct npc_mcam_ena_dis_entry_req {
 	struct mbox_msghdr hdr;
@@ -2539,12 +2587,25 @@ struct npc_mcam_alloc_and_write_entry_req {
 	struct mbox_msghdr hdr;
 	struct mcam_entry entry_data;
 	uint16_t __io ref_entry;
-	uint8_t __io priority;	   /* Lower or higher w.r.t ref_entry */
+	uint8_t __io ref_priority; /* Lower or higher w.r.t ref_entry */
 	uint8_t __io intf;	   /* Rx or Tx interface */
 	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
 	uint8_t __io alloc_cntr;   /* Allocate counter and map ? */
 };
 
+struct npc_cn20k_mcam_alloc_and_write_entry_req {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint16_t __io ref_entry;
+	uint8_t __io ref_prio;	   /* Lower or higher w.r.t ref_entry */
+	uint8_t __io intf;	   /* Rx or Tx interface */
+	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
+	uint8_t __io hw_prio;	   /* hardware priority, valid for cn20k */
+	uint8_t __io virt;	   /* Allocate virtual index */
+	uint8_t __io req_kw_type;  /* Key type to be written */
+	uint16_t __io reserved[4]; /* reserved for future use */
+};
+
 struct npc_mcam_alloc_and_write_entry_rsp {
 	struct mbox_msghdr hdr;
 	uint16_t __io entry;
@@ -2571,6 +2632,48 @@ struct npc_get_kex_cfg_rsp {
 	uint8_t __io mkex_pfl_name[MKEX_NAME_LEN];
 };
 
+struct npc_delete_flow_rsp {
+	struct mbox_msghdr hdr;
+	uint16_t __io cntr_val;
+};
+
+/* Available entries to use */
+struct npc_cn20k_get_free_count_rsp {
+	struct mbox_msghdr hdr;
+	int __io free_x2;
+	int __io free_x4;
+	int __io free_subbanks;
+};
+
+struct npc_cn20k_get_kex_cfg_rsp {
+	struct mbox_msghdr hdr;
+	uint64_t __io rx_keyx_cfg; /* NPC_AF_INTF(0)_KEX_CFG */
+	uint64_t __io tx_keyx_cfg; /* NPC_AF_INTF(1)_KEX_CFG */
+#define NPC_MAX_EXTRACTOR 24
+	/* MKEX Extractor data */
+	uint64_t __io intf_extr[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
+	/* KEX configuration per extractor */
+	uint64_t __io intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
+#define MKEX_NAME_LEN 128
+	uint8_t __io mkex_pfl_name[MKEX_NAME_LEN];
+};
+
+struct npc_get_field_hash_info_req {
+	struct mbox_msghdr hdr;
+	uint8_t intf;
+};
+
+struct npc_get_field_hash_info_rsp {
+	struct mbox_msghdr hdr;
+	uint64_t __io secret_key[3];
+#define NPC_MAX_HASH	  2
+#define NPC_MAX_HASH_MASK 2
+	/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
+	uint64_t __io hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
+	/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
+	uint64_t __io hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
+};
+
 enum header_fields {
 	NPC_DMAC,
 	NPC_SMAC,
@@ -2660,6 +2763,8 @@ struct npc_install_flow_req {
 	uint8_t __io vtag1_op;
 	/* old counter value */
 	uint16_t __io cntr_val;
+	/* hardware priority, supported for cn20k */
+	uint8_t __io hw_prio;
 };
 
 struct npc_install_flow_rsp {
@@ -2690,11 +2795,24 @@ struct npc_mcam_read_entry_rsp {
 	uint8_t __io enable;
 };
 
+struct npc_cn20k_mcam_read_entry_rsp {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint8_t __io intf;
+	uint8_t __io enable;
+	uint8_t __io hw_prio; /* valid for cn20k */
+};
+
 struct npc_mcam_read_base_rule_rsp {
 	struct mbox_msghdr hdr;
 	struct mcam_entry entry_data;
 };
 
+struct npc_cn20k_mcam_read_base_rule_rsp {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry;
+};
+
 struct npc_mcam_get_stats_req {
 	struct mbox_msghdr hdr;
 	uint16_t __io entry; /* mcam entry */
@@ -2774,22 +2892,6 @@ enum tim_gpio_edge {
 	TIM_GPIO_INVALID,
 };
 
-struct npc_get_field_hash_info_req {
-	struct mbox_msghdr hdr;
-	uint8_t intf;
-};
-
-struct npc_get_field_hash_info_rsp {
-	struct mbox_msghdr hdr;
-	uint64_t __io secret_key[3];
-#define NPC_MAX_HASH	  2
-#define NPC_MAX_HASH_MASK 2
-	/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
-	uint64_t __io hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
-	/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
-	uint64_t __io hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
-};
-
 enum ptp_op {
 	PTP_OP_ADJFINE = 0,   /* adjfine(req.scaled_ppm); */
 	PTP_OP_GET_CLOCK = 1, /* rsp.clk = get_clock() */
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index f213823b9b..15823ab16c 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -983,15 +983,11 @@ bool __roc_api roc_nix_ptp_is_enable(struct roc_nix *roc_nix);
 /* VLAN */
 int __roc_api
 roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
-			     struct npc_mcam_read_entry_rsp **rsp);
-int __roc_api roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix,
-					    uint32_t index,
-					    struct mcam_entry *entry,
+			     void **rsp);
+int __roc_api roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index, void *entry,
 					    uint8_t intf, uint8_t enable);
-int __roc_api roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix,
-						      struct mcam_entry *entry,
-						      uint8_t intf,
-						      uint8_t priority,
+int __roc_api roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix, void *entry,
+						      uint8_t intf, uint8_t priority,
 						      uint8_t ref_entry);
 int __roc_api roc_nix_vlan_mcam_entry_free(struct roc_nix *roc_nix,
 					   uint32_t index);
@@ -1012,10 +1008,8 @@ int __roc_api roc_nix_mcast_mcam_entry_alloc(struct roc_nix *roc_nix,
 					     uint16_t index[]);
 int __roc_api roc_nix_mcast_mcam_entry_free(struct roc_nix *roc_nix,
 					    uint32_t index);
-int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
-					     struct mcam_entry *entry,
-					     uint32_t index, uint8_t intf,
-					     uint64_t action);
+int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix, void *entry, uint32_t index,
+					     uint8_t intf, uint64_t action);
 int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
 					       bool enable);
 int __roc_api roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries,
diff --git a/drivers/common/cnxk/roc_nix_mcast.c b/drivers/common/cnxk/roc_nix_mcast.c
index 615014e820..eab4bde743 100644
--- a/drivers/common/cnxk/roc_nix_mcast.c
+++ b/drivers/common/cnxk/roc_nix_mcast.c
@@ -19,7 +19,7 @@ roc_nix_mcast_mcam_entry_alloc(struct roc_nix *roc_nix, uint16_t nb_entries,
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
 	if (req == NULL)
 		goto exit;
-	req->priority = priority;
+	req->ref_priority = priority;
 	req->count = nb_entries;
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -56,24 +56,38 @@ roc_nix_mcast_mcam_entry_free(struct roc_nix *roc_nix, uint32_t index)
 }
 
 int
-roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
-			       struct mcam_entry *entry, uint32_t index,
-			       uint8_t intf, uint64_t action)
+roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix, void *entry, uint32_t index, uint8_t intf,
+			       uint64_t action)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
-	struct npc_mcam_write_entry_req *req;
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->entry = index;
-	req->intf = intf;
-	req->enable_entry = true;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
-	req->entry_data.action = action;
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+		req->entry_data.action = action;
+
+	} else {
+		struct npc_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+		req->entry_data.action = action;
+	}
 
 	rc = mbox_process(mbox);
 exit:
diff --git a/drivers/common/cnxk/roc_nix_vlan.c b/drivers/common/cnxk/roc_nix_vlan.c
index db218593ad..16100eb5d6 100644
--- a/drivers/common/cnxk/roc_nix_vlan.c
+++ b/drivers/common/cnxk/roc_nix_vlan.c
@@ -7,7 +7,7 @@
 
 int
 roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
-			     struct npc_mcam_read_entry_rsp **rsp)
+			     void **rsp)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
@@ -27,24 +27,34 @@ roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
 }
 
 int
-roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index,
-			      struct mcam_entry *entry, uint8_t intf,
+roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index, void *entry, uint8_t intf,
 			      uint8_t enable)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
 	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
 	struct msghdr *rsp;
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->entry = index;
-	req->intf = intf;
-	req->enable_entry = enable;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (cn20k_req == NULL)
+			goto exit;
+		cn20k_req->entry = index;
+		cn20k_req->intf = intf;
+		cn20k_req->enable_entry = enable;
+		mbox_memcpy(&cn20k_req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+	} else {
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = enable;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 exit:
@@ -53,25 +63,39 @@ roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index,
 }
 
 int
-roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix,
-					struct mcam_entry *entry, uint8_t intf,
+roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix, void *entry, uint8_t intf,
 					uint8_t priority, uint8_t ref_entry)
 {
-	struct npc_mcam_alloc_and_write_entry_req *req;
 	struct npc_mcam_alloc_and_write_entry_rsp *rsp;
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->priority = priority;
-	req->ref_entry = ref_entry;
-	req->intf = intf;
-	req->enable_entry = true;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_alloc_and_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_alloc_and_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->ref_prio = priority;
+		req->ref_entry = ref_entry;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+
+	} else {
+		struct npc_mcam_alloc_and_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->ref_priority = priority;
+		req->ref_entry = ref_entry;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 53f278c764..138f12f6d8 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -100,6 +100,14 @@ roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, uint64_t *co
 	return npc_mcam_read_counter(npc->mbox, ctr_id, count);
 }
 
+int
+roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow, uint64_t *count)
+{
+	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+	return npc_mcam_get_stats(npc->mbox, flow, count);
+}
+
 int
 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id)
 {
@@ -221,7 +229,9 @@ roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc)
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 
-	if (roc_model_is_cn10k())
+	if (roc_model_is_cn20k())
+		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
+	else if (roc_model_is_cn10k())
 		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
 	else if (roc_model_is_cn98xx())
 		return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1);
@@ -235,7 +245,9 @@ npc_mcam_tot_entries(void)
 	/* FIXME: change to reading in AF from NPC_AF_CONST1/2
 	 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS
 	 */
-	if (roc_model_is_cn10k() || roc_model_is_cn98xx())
+	if (roc_model_is_cn20k())
+		return 2 * 8192; /* MCAM_BANKS = 2, BANK_DEPTH_EXT = 8192 */
+	else if (roc_model_is_cn10k() || roc_model_is_cn98xx())
 		return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */
 	else
 		return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */
@@ -311,6 +323,7 @@ roc_npc_init(struct roc_npc *roc_npc)
 
 	npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX];
 	nix->exact_match_ena = npc->exact_match_ena;
+	roc_npc->max_entries = npc->mcam_entries;
 
 	/* Free, free_rev, live and live_rev entries */
 	bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries);
@@ -1856,9 +1869,7 @@ roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc, int rep_port_id)
 int
 roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 {
-	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
-	struct mcam_entry *base_entry;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int idx, rc;
 
@@ -1868,17 +1879,36 @@ roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_fl
 	}
 
 	(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
-	rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
-	if (rc) {
-		plt_err("Failed to fetch VF's base MCAM entry");
-		goto exit;
-	}
-	base_entry = &base_rule_rsp->entry_data;
-	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		flow->mcam_data[idx] |= base_entry->kw[idx];
-		flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
-	}
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
+		struct cn20k_mcam_entry *base_entry;
 
+		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+		if (rc) {
+			plt_err("Failed to fetch VF's base MCAM entry");
+			goto exit;
+		}
+		base_entry = &base_rule_rsp->entry;
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			flow->mcam_data[idx] |= base_entry->kw[idx];
+			flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+		}
+
+	} else {
+		struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
+		struct mcam_entry *base_entry;
+
+		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+		if (rc) {
+			plt_err("Failed to fetch VF's base MCAM entry");
+			goto exit;
+		}
+		base_entry = &base_rule_rsp->entry_data;
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			flow->mcam_data[idx] |= base_entry->kw[idx];
+			flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+		}
+	}
 	rc = 0;
 exit:
 	mbox_put(mbox);
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index bf8c65aa9c..b96862e054 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -305,52 +305,58 @@ struct roc_npc_spi_to_sa_action_info {
 };
 
 struct mbox;
-
 struct roc_npc_flow {
 	uint8_t nix_intf;
 	uint8_t enable;
-	uint32_t mcam_id;
 	uint8_t use_ctr;
+	bool is_validate;
+	uint32_t mcam_id;
+	uint16_t tx_pf_func;
+	bool has_age_action;
+	bool rep_act_rep;
 	int32_t ctr_id;
 	uint32_t priority;
 	uint32_t mtr_id;
+#if defined(ROC_PLATFORM_CN20K)
+#define ROC_NPC_MAX_MCAM_WIDTH_DWORDS 8
+#define ROC_NPC_MAX_MCAM_PRIORITY     123
+#else
 #define ROC_NPC_MAX_MCAM_WIDTH_DWORDS 7
+#define ROC_NPC_MAX_MCAM_PRIORITY     32
+#endif
 	/* Contiguous match string */
 	uint64_t mcam_data[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t npc_action;
 	uint64_t vtag_action;
 	bool vtag_insert_enabled;
-	uint8_t vtag_insert_count;
+	int8_t vtag_insert_count;
 #define ROC_NPC_MAX_FLOW_PATTERNS 32
 	struct roc_npc_flow_dump_data dump_data[ROC_NPC_MAX_FLOW_PATTERNS];
 	uint16_t num_patterns;
 	struct roc_npc_spi_to_sa_action_info spi_to_sa_info;
-	uint16_t tx_pf_func;
-	bool is_validate;
 	uint16_t match_id;
 	uint8_t is_inline_dev;
 	bool use_pre_alloc;
 	uint64_t timeout_cycles;
 	void *age_context;
-	uint32_t timeout;
-	bool has_age_action;
-	uint16_t rep_pf_func;
 	uint16_t rep_act_pf_func;
-	bool rep_act_rep;
+	bool is_rep_vf;
+	bool has_rep;
+	bool is_sampling_rule;
+	uint16_t rep_pf_func;
+#define ROC_NPC_MIRROR_LIST_SIZE 2
+	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
 	uint16_t rep_channel;
 	struct mbox *rep_mbox;
-	bool has_rep;
-	bool is_rep_vf;
 	struct npc *rep_npc;
 	int port_id;
-	bool is_sampling_rule;
+	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
 	uint32_t recv_queue;
 	uint32_t mcast_grp_index;
 	uint32_t mce_start_index;
-#define ROC_NPC_MIRROR_LIST_SIZE 2
-	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
-	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
+	uint8_t key_type;
+	uint32_t timeout;
 
 	TAILQ_ENTRY(roc_npc_flow) next;
 };
@@ -400,33 +406,34 @@ struct roc_npc {
 	struct roc_nix *roc_nix;
 	uint8_t switch_header_type;
 	uint8_t pre_l2_size_offset;	 /**< Offset with in header that holds
-					   * size of custom header
-					   */
+					  * size of custom header
+					  */
 	uint8_t pre_l2_size_offset_mask; /**< Offset mask with in header
-					   * that holds size of custom header
-					   */
+					  * that holds size of custom header
+					  */
 	uint8_t pre_l2_size_shift_dir;	 /**< Shift direction to calculate size
-					   */
+					  */
 	uint16_t flow_prealloc_size;
 	uint16_t flow_max_priority;
 	uint16_t channel;
 	uint16_t pf_func;
+	bool is_sdp_mask_set;
+	bool rep_act_rep;
+	uint16_t sdp_channel_mask;
 	uint64_t kex_capability;
 	uint64_t rx_parse_nibble;
 	/* Parsed RSS Flowkey cfg for current flow being created */
 	uint32_t flowkey_cfg_state;
-	bool is_sdp_mask_set;
+	uint32_t max_entries;
+	uint16_t rep_act_pf_func;
 	uint16_t sdp_channel;
-	uint16_t sdp_channel_mask;
 	struct roc_npc_flow_age flow_age;
 	struct roc_npc *rep_npc;
 	uint16_t rep_pf_func;
 	uint16_t rep_rx_channel;
-	uint16_t rep_act_pf_func;
-	bool rep_act_rep;
 	int rep_port_id;
 
-#define ROC_NPC_MEM_SZ (6 * 1024)
+#define ROC_NPC_MEM_SZ (20 * 1024)
 	uint8_t reserved[ROC_NPC_MEM_SZ];
 } __plt_cache_aligned;
 
@@ -482,4 +489,6 @@ int __roc_api roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint1
 void *__roc_api roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id);
 void __roc_api roc_npc_sdp_channel_get(struct roc_npc *roc_npc, uint16_t *chan_base,
 				       uint16_t *chan_mask);
+int __roc_api roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+				     uint64_t *count);
 #endif /* _ROC_NPC_H_ */
diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c
index cdb9db1383..412b2611b7 100644
--- a/drivers/common/cnxk/roc_npc_mcam.c
+++ b/drivers/common/cnxk/roc_npc_mcam.c
@@ -11,6 +11,10 @@ npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
 	struct npc_mcam_alloc_counter_rsp *rsp;
 	int rc = -ENOSPC;
 
+	/* For CN20K, counters are enabled by default */
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -30,6 +34,9 @@ npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
 	struct npc_mcam_oper_counter_req *req;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -40,6 +47,30 @@ npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
 	return rc;
 }
 
+int
+npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count)
+{
+	struct npc_mcam_get_stats_req *req;
+	struct npc_mcam_get_stats_rsp *rsp;
+	int rc = -ENOSPC;
+
+	/* valid only for cn20k */
+	if (!roc_model_is_cn20k())
+		return 0;
+
+	req = mbox_alloc_msg_npc_mcam_entry_stats(mbox_get(mbox));
+	if (req == NULL)
+		goto exit;
+	req->entry = flow->mcam_id;
+	rc = mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		goto exit;
+	*count = rsp->stat;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
 int
 npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
 {
@@ -47,6 +78,9 @@ npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
 	struct npc_mcam_oper_counter_rsp *rsp;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -66,6 +100,9 @@ npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
 	struct npc_mcam_oper_counter_req *req;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -132,16 +169,53 @@ npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
 	struct npc_xtract_info *x_info;
 	int i;
 
-	for (i = 0; i < NPC_MAX_LD; i++) {
-		x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
-		/* Check for LDATA */
-		if (x_info->enable && x_info->len > 0)
-			return true;
+	if (!roc_model_is_cn20k()) {
+		for (i = 0; i < NPC_MAX_LD; i++) {
+			x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
+			/* Check for LDATA */
+			if (x_info->enable && x_info->len > 0)
+				return true;
+		}
+	} else {
+		for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
+			union npc_kex_ldata_flags_cfg *lid_info = &npc->lid_cfg[NIX_INTF_RX][i];
+
+			if (lid_info->s.lid != lid)
+				continue;
+			x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
+			/* Check for LDATA */
+			if (x_info->enable && x_info->len > 0)
+				return true;
+		}
 	}
 
 	return false;
 }
 
+static void
+npc_construct_ldata_mask_cn20k(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt)
+{
+	struct npc_xtract_info *x_info;
+	int hdr_off, keylen;
+	int i, j;
+
+	for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
+		union npc_kex_ldata_flags_cfg *lid_conf = &npc->lid_cfg[NIX_INTF_RX][i];
+
+		if (lid_conf->s.lid != lid)
+			continue;
+
+		x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
+		if (x_info->enable == 0)
+			continue;
+
+		hdr_off = x_info->hdr_off * 8;
+		keylen = x_info->len * 8;
+		for (j = hdr_off; j < (hdr_off + keylen); j++)
+			plt_bitmap_set(bmap, j);
+	}
+}
+
 static void
 npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt,
 			 uint8_t ld)
@@ -220,8 +294,12 @@ npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset, int len
 		return false;
 	}
 
-	npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
-	npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
+	if (!roc_model_is_cn20k()) {
+		npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
+		npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
+	} else {
+		npc_construct_ldata_mask_cn20k(npc, bmap, lid, lt);
+	}
 
 	for (i = offset; i < (offset + len); i++) {
 		if (plt_bitmap_get(bmap, i) != 0x1) {
@@ -330,7 +408,7 @@ npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int re
 		goto exit;
 	req->contig = is_conti;
 	req->count = req_count;
-	req->priority = prio;
+	req->ref_priority = prio;
 	req->ref_entry = ref_mcam;
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -349,11 +427,11 @@ npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int re
 
 int
 npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
-		     int prio, int *resp_count)
+		     uint8_t prio, int *resp_count)
 {
+	struct mbox *mbox = mbox_get(npc->mbox);
 	struct npc_mcam_alloc_entry_req *req;
 	struct npc_mcam_alloc_entry_rsp *rsp;
-	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = -ENOSPC;
 
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
@@ -361,16 +439,16 @@ npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_
 		goto exit;
 	req->contig = 1;
 	req->count = 1;
-	req->priority = prio;
-	req->ref_entry = ref_mcam->mcam_id;
-
+	req->ref_priority = prio;
+	req->ref_entry = ref_mcam ? ref_mcam->mcam_id : 0;
+	req->kw_type = mcam->key_type;
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		goto exit;
-	memset(mcam, 0, sizeof(struct roc_npc_flow));
 	mcam->mcam_id = rsp->entry;
-	mcam->nix_intf = ref_mcam->nix_intf;
+	mcam->nix_intf = ref_mcam ? ref_mcam->nix_intf : 0;
 	*resp_count = rsp->count;
+
 	rc = 0;
 exit:
 	mbox_put(mbox);
@@ -403,6 +481,7 @@ int
 npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
 {
 	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
 	struct mbox_msghdr *rsp;
 	int rc = -ENOSPC;
 	uint16_t ctr = 0;
@@ -419,33 +498,121 @@ npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
 			return rc;
 	}
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
-	if (req == NULL) {
-		mbox_put(mbox);
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
+		if (cn20k_req == NULL) {
+			mbox_put(mbox);
+			if (mcam->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
+
+			return rc;
+		}
+		cn20k_req->entry = mcam->mcam_id;
+		cn20k_req->intf = mcam->nix_intf;
+		cn20k_req->enable_entry = mcam->enable;
+		cn20k_req->entry_data.action = mcam->npc_action;
+		cn20k_req->entry_data.vtag_action = mcam->vtag_action;
+		cn20k_req->hw_prio = mcam->priority;
 		if (mcam->use_ctr)
-			npc_mcam_free_counter(mbox, ctr);
+			cn20k_req->cntr = mcam->ctr_id;
 
-		return rc;
-	}
-	req->entry = mcam->mcam_id;
-	req->intf = mcam->nix_intf;
-	req->enable_entry = mcam->enable;
-	req->entry_data.action = mcam->npc_action;
-	req->entry_data.vtag_action = mcam->vtag_action;
-	if (mcam->use_ctr) {
-		req->set_cntr = 1;
-		req->cntr = mcam->ctr_id;
-	}
+		for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
+			cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
+			cn20k_req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+		}
+	} else {
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
+		if (req == NULL) {
+			mbox_put(mbox);
+			if (mcam->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
 
-	for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
-		req->entry_data.kw[i] = mcam->mcam_data[i];
-		req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+			return rc;
+		}
+		req->entry = mcam->mcam_id;
+		req->intf = mcam->nix_intf;
+		req->enable_entry = mcam->enable;
+		req->entry_data.action = mcam->npc_action;
+		req->entry_data.vtag_action = mcam->vtag_action;
+		if (mcam->use_ctr) {
+			req->set_cntr = 1;
+			req->cntr = mcam->ctr_id;
+		}
+
+		for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
+			req->entry_data.kw[i] = mcam->mcam_data[i];
+			req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+		}
 	}
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	mbox_put(mbox);
 	return rc;
 }
 
+static void
+npc_mcam_kex_cfg_dump(struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
+{
+	for (int i = 0; i < NPC_MAX_INTF; i++) {
+		for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+			if (kex_rsp->intf_extr[i][j] == 0)
+				continue;
+			plt_info("Intf %d, Extr %d: 0x%" PRIx64, i, j, kex_rsp->intf_extr[i][j]);
+		}
+	}
+
+	for (int i = 0; i < NPC_MAX_INTF; i++) {
+		for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+			for (int k = 0; k < NPC_MAX_LT; k++) {
+				if (kex_rsp->intf_extr_lt[i][j][k] == 0)
+					continue;
+				plt_info("Intf %d, Extr %d, LT %d: 0x%" PRIx64, i, j, k,
+					 kex_rsp->intf_extr_lt[i][j][k]);
+			}
+		}
+	}
+}
+
+static void
+npc_mcam_process_mkex_cfg_cn20k(struct npc *npc, struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
+{
+	volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
+	volatile uint64_t(*d)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
+	struct npc_xtract_info *x_info = NULL;
+	union npc_kex_ldata_flags_cfg *ld_info = NULL;
+	int ex, lt, ix;
+	npc_dxcfg_cn20k_t *p;
+	npc_lid_cn20k_t *l;
+	uint64_t keyw;
+	uint64_t val;
+
+	npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
+	npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
+	npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
+	npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
+
+	keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
+	npc->keyw[NPC_MCAM_RX] = keyw;
+	keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
+	npc->keyw[NPC_MCAM_TX] = keyw;
+
+	p = &npc->prx_dxcfg_cn20k;
+	l = &npc->lid_cfg;
+	q = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR][NPC_MAX_LT])(&kex_rsp->intf_extr_lt);
+	d = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR])(&kex_rsp->intf_extr);
+	for (ix = 0; ix < NPC_MAX_INTF; ix++) {
+		for (ex = 0; ex < NPC_MAX_EXTRACTOR; ex++) {
+			val = (*d)[ix][ex];
+			ld_info = &(*l)[ix][ex];
+			ld_info->s.lid = (val & 0x7);
+			for (lt = 0; lt < NPC_MAX_LT; lt++) {
+				x_info = &(*p)[ix][ex][lt].xtract;
+				val = (*q)[ix][ex][lt];
+				npc_update_kex_info(x_info, val);
+			}
+		}
+	}
+}
+
 static void
 npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
 {
@@ -522,20 +689,38 @@ int
 npc_mcam_fetch_kex_cfg(struct npc *npc)
 {
 	struct npc_get_kex_cfg_rsp *kex_rsp;
+	struct npc_cn20k_get_kex_cfg_rsp *kex_rsp_20k;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = 0;
 
-	mbox_alloc_msg_npc_get_kex_cfg(mbox);
-	rc = mbox_process_msg(mbox, (void *)&kex_rsp);
-	if (rc) {
-		plt_err("Failed to fetch NPC KEX config");
-		goto done;
-	}
 
-	mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
+	if (!roc_model_is_cn20k()) {
+		mbox_alloc_msg_npc_get_kex_cfg(mbox);
+		rc = mbox_process_msg(mbox, (void *)&kex_rsp);
+		if (rc) {
+			plt_err("Failed to fetch NPC KEX config");
+			goto done;
+		}
 
-	npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
-	npc_mcam_process_mkex_cfg(npc, kex_rsp);
+		mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
+
+		npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
+		npc_mcam_process_mkex_cfg(npc, kex_rsp);
+	} else {
+		mbox_alloc_msg_npc_cn20k_get_kex_cfg(mbox);
+		rc = mbox_process_msg(mbox, (void *)&kex_rsp_20k);
+		if (rc) {
+			plt_err("Failed to fetch NPC KEX config");
+			goto done;
+		}
+
+		mbox_memcpy((char *)npc->profile_name, kex_rsp_20k->mkex_pfl_name, MKEX_NAME_LEN);
+
+		npc->exact_match_ena = (kex_rsp_20k->rx_keyx_cfg >> 40) & 0xF;
+		npc_mcam_process_mkex_cfg_cn20k(npc, kex_rsp_20k);
+		if (npc->enable_debug)
+			npc_mcam_kex_cfg_dump(kex_rsp_20k);
+	}
 
 done:
 	mbox_put(mbox);
@@ -543,7 +728,7 @@ npc_mcam_fetch_kex_cfg(struct npc *npc)
 }
 
 static void
-npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req *req,
+npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_cn20k_mcam_write_entry_req *req,
 		     uint16_t channel, uint16_t chan_mask, bool is_second_pass)
 {
 	uint16_t chan = 0, mask = 0;
@@ -552,6 +737,7 @@ npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req
 	req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
 	flow->mcam_data[0] &= ~(GENMASK(11, 0));
 	flow->mcam_mask[0] &= ~(GENMASK(11, 0));
+
 	chan = channel;
 	mask = chan_mask;
 
@@ -579,11 +765,12 @@ npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req
 	flow->mcam_mask[0] |= (uint64_t)mask;
 }
 
+#define NPC_PF_FUNC_WIDTH    2
+#define NPC_KEX_PF_FUNC_MASK 0xFFFF
+
 static int
 npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
 {
-#define NPC_PF_FUNC_WIDTH    2
-#define NPC_KEX_PF_FUNC_MASK 0xFFFF
 	uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
 	uint8_t *flow_mcam_data, *flow_mcam_mask;
 	struct npc_lid_lt_xtract_info *xinfo;
@@ -618,10 +805,48 @@ npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_fun
 	return 0;
 }
 
+static int
+npc_mcam_set_pf_func_cn20k(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
+{
+	uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
+	struct npc_lid_lt_xtract_info_cn20k *xinfo;
+	uint8_t *flow_mcam_data, *flow_mcam_mask;
+	bool pffunc_found = false;
+	uint16_t mask = 0xFFFF;
+	int i;
+
+	flow_mcam_data = (uint8_t *)flow->mcam_data;
+	flow_mcam_mask = (uint8_t *)flow->mcam_mask;
+
+	xinfo = npc->prx_dxcfg_cn20k[NIX_INTF_TX][NPC_LID_LA];
+
+	for (i = 0; i < NPC_MAX_LT; i++) {
+		nr_bytes = xinfo[i].xtract.len;
+		hdr_offset = xinfo[i].xtract.hdr_off;
+		key_offset = xinfo[i].xtract.key_off;
+
+		if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
+			continue;
+		else
+			pffunc_found = true;
+
+		pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
+		memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
+		       NPC_PF_FUNC_WIDTH);
+		memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
+		       NPC_PF_FUNC_WIDTH);
+	}
+	if (!pffunc_found)
+		return -EINVAL;
+
+	return 0;
+}
+
 int
 npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
 {
-	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
+	struct npc_cn20k_mcam_write_entry_req req;
 	struct nix_inl_dev *inl_dev = NULL;
 	struct mbox *mbox = npc->mbox;
 	struct mbox_msghdr *rsp;
@@ -655,6 +880,12 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 			return rc;
 	}
 
+	if (roc_model_is_cn20k()) {
+		req.hw_prio = flow->priority;
+		flow->key_type = npc_get_key_type(npc, flow);
+		req.req_kw_type = flow->key_type;
+	}
+
 	if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
 	    inl_dev->ipsec_index && inl_dev->is_multi_channel) {
 		if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
@@ -672,14 +903,17 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	}
 
 	if (flow->nix_intf == NIX_INTF_TX) {
-		uint16_t pf_func = flow->tx_pf_func;
+		uint16_t pffunc = flow->tx_pf_func;
 
 		if (flow->has_rep)
-			pf_func = flow->rep_pf_func;
+			pffunc = flow->rep_pf_func;
 
-		pf_func = plt_cpu_to_be_16(pf_func);
+		pffunc = plt_cpu_to_be_16(pffunc);
 
-		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
+		if (roc_model_is_cn20k())
+			rc = npc_mcam_set_pf_func_cn20k(npc, flow, pffunc);
+		else
+			rc = npc_mcam_set_pf_func(npc, flow, pffunc);
 		if (rc)
 			return rc;
 	}
@@ -708,20 +942,14 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		}
 	}
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
-	if (req == NULL) {
-		rc = -ENOSPC;
-		goto exit;
-	}
-	req->set_cntr = flow->use_ctr;
-	req->cntr = flow->ctr_id;
-	req->entry = entry;
+	req.cntr = flow->ctr_id;
+	req.entry = entry;
 
-	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
-	req->enable_entry = 1;
+	req.intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+	req.enable_entry = 1;
 	if (flow->nix_intf == NIX_INTF_RX)
 		flow->npc_action |= (uint64_t)flow->recv_queue << 20;
-	req->entry_data.action = flow->npc_action;
+	req.entry_data.action = flow->npc_action;
 
 	/*
 	 * Driver sets vtag action on per interface basis, not
@@ -735,38 +963,38 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	 *
 	 * Second approach is used now.
 	 */
-	req->entry_data.vtag_action = flow->vtag_action;
+	req.entry_data.vtag_action = flow->vtag_action;
 
 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		req->entry_data.kw[idx] = flow->mcam_data[idx];
-		req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
+		req.entry_data.kw[idx] = flow->mcam_data[idx];
+		req.entry_data.kw_mask[idx] = flow->mcam_mask[idx];
 	}
 
 	if (flow->nix_intf == NIX_INTF_RX) {
 		if (inl_dev && inl_dev->is_multi_channel &&
 		    (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
 			pf_func = nix_inl_dev_pffunc_get();
-			req->entry_data.action &= ~(GENMASK(19, 4));
-			req->entry_data.action |= (uint64_t)pf_func << 4;
+			req.entry_data.action &= ~(GENMASK(19, 4));
+			req.entry_data.action |= (uint64_t)pf_func << 4;
 			flow->npc_action &= ~(GENMASK(19, 4));
 			flow->npc_action |= (uint64_t)pf_func << 4;
 
-			npc_mcam_set_channel(flow, req, inl_dev->channel, inl_dev->chan_mask,
+			npc_mcam_set_channel(flow, &req, inl_dev->channel, inl_dev->chan_mask,
 					     false);
 		} else if (flow->has_rep) {
 			pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
 								 flow->rep_act_pf_func;
-			req->entry_data.action &= ~(GENMASK(19, 4));
-			req->entry_data.action |= (uint64_t)pf_func << 4;
+			req.entry_data.action &= ~(GENMASK(19, 4));
+			req.entry_data.action |= (uint64_t)pf_func << 4;
 			flow->npc_action &= ~(GENMASK(19, 4));
 			flow->npc_action |= (uint64_t)pf_func << 4;
-			npc_mcam_set_channel(flow, req, flow->rep_channel, (BIT_ULL(12) - 1),
+			npc_mcam_set_channel(flow, &req, flow->rep_channel, (BIT_ULL(12) - 1),
 					     false);
 		} else if (npc->is_sdp_link) {
-			npc_mcam_set_channel(flow, req, npc->sdp_channel, npc->sdp_channel_mask,
+			npc_mcam_set_channel(flow, &req, npc->sdp_channel, npc->sdp_channel_mask,
 					     pst->is_second_pass_rule);
 		} else {
-			npc_mcam_set_channel(flow, req, npc->channel, (BIT_ULL(12) - 1),
+			npc_mcam_set_channel(flow, &req, npc->channel, (BIT_ULL(12) - 1),
 					     pst->is_second_pass_rule);
 		}
 		/*
@@ -779,25 +1007,66 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 			la_offset *= 4;
 
 			mask = ~((0xfULL << la_offset));
-			req->entry_data.kw[0] &= mask;
-			req->entry_data.kw_mask[0] &= mask;
+			req.entry_data.kw[0] &= mask;
+			req.entry_data.kw_mask[0] &= mask;
 			flow->mcam_data[0] &= mask;
 			flow->mcam_mask[0] &= mask;
 			if (pst->is_second_pass_rule) {
-				req->entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
-				req->entry_data.kw_mask[0] |= (0xFULL << la_offset);
+				req.entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
+				req.entry_data.kw_mask[0] |= (0xFULL << la_offset);
 				flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
 				flow->mcam_mask[0] |= (0xFULL << la_offset);
 			} else {
 				/* Mask ltype ETHER (0x2) and CPT_HDR (0xa)  */
-				req->entry_data.kw[0] |= (0x2ULL << la_offset);
-				req->entry_data.kw_mask[0] |= (0x7ULL << la_offset);
+				req.entry_data.kw[0] |= (0x2ULL << la_offset);
+				req.entry_data.kw_mask[0] |= (0x7ULL << la_offset);
 				flow->mcam_data[0] |= (0x2ULL << la_offset);
 				flow->mcam_mask[0] |= (0x7ULL << la_offset);
 			}
 		}
 	}
 
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
+		if (cn20k_req == NULL) {
+			mbox_put(mbox);
+			if (flow->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
+
+			return rc;
+		}
+		cn20k_req->entry = req.entry;
+		cn20k_req->intf = req.intf;
+		cn20k_req->enable_entry = req.enable_entry;
+		cn20k_req->entry_data.action = req.entry_data.action;
+		cn20k_req->entry_data.vtag_action = req.entry_data.vtag_action;
+		cn20k_req->hw_prio = req.hw_prio;
+		cn20k_req->req_kw_type = req.req_kw_type;
+		if (flow->use_ctr)
+			cn20k_req->cntr = req.cntr;
+
+		mbox_memcpy(&cn20k_req->entry_data, &req.entry_data,
+			    sizeof(struct cn20k_mcam_entry));
+	} else {
+		struct npc_mcam_write_entry_req *req_leg;
+
+		req_leg = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
+		if (req_leg == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		for (idx = 0; idx < NPC_MAX_KWS_IN_KEY; idx++) {
+			req_leg->entry_data.kw[idx] = req.entry_data.kw[idx];
+			req_leg->entry_data.kw_mask[idx] = req.entry_data.kw_mask[idx];
+		}
+		req_leg->entry = req.entry;
+		req_leg->intf = req.intf;
+		req_leg->enable_entry = req.enable_entry;
+		req_leg->cntr = req.cntr;
+		req_leg->entry_data.action = req.entry_data.action;
+		req_leg->entry_data.vtag_action = req.entry_data.vtag_action;
+		req_leg->set_cntr = flow->use_ctr;
+	}
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc != 0)
 		goto exit;
@@ -810,7 +1079,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 
 exit:
 	mbox_put(mbox);
-	if (rc)
+	if (rc && flow->is_sampling_rule)
 		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 	return rc;
 }
@@ -821,9 +1090,14 @@ npc_set_vlan_ltype(struct npc_parse_state *pst)
 	uint64_t val, mask;
 	uint8_t lb_offset;
 
-	lb_offset =
-		plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-				   ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
+	if (roc_model_is_cn20k()) {
+		lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_CN20K_LTYPE_LB_OFFSET) - 1));
+
+	} else {
+		lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
+	}
 	lb_offset *= 4;
 
 	mask = ~((0xfULL << lb_offset));
@@ -843,9 +1117,14 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	uint8_t lc_offset, lcflag_offset;
 	uint64_t val, mask;
 
-	lc_offset =
-		plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-				   ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
+	if (roc_model_is_cn20k()) {
+		lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_CN20K_LTYPE_LC_OFFSET) - 1));
+
+	} else {
+		lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
+	}
 	lc_offset *= 4;
 
 	mask = ~((0xfULL << lc_offset));
@@ -867,8 +1146,14 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	 * zero in LFLAG.
 	 */
 	if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
-		lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-					       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+		if (roc_model_is_cn20k()) {
+			lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+						       ((1ULL << NPC_CN20K_LFLAG_LC_OFFSET) - 1));
+
+		} else {
+			lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+						       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+		}
 		lcflag_offset *= 4;
 
 		mask = (0xfULL << lcflag_offset);
@@ -881,14 +1166,12 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 int
 npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 {
-	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 	/* This is non-LDATA part in search key */
 	uint64_t key_data[2] = {0ULL, 0ULL};
 	uint64_t key_mask[2] = {0ULL, 0ULL};
 	int key_len, bit = 0, index, rc = 0;
 	struct nix_inl_dev *inl_dev = NULL;
 	int intf = pst->flow->nix_intf;
-	struct mcam_entry *base_entry;
 	bool skip_base_rule = false;
 	int off, idx, data_off = 0;
 	uint8_t lid, mask, data;
@@ -908,40 +1191,79 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 	data_off *= 4;
 
 	index = 0;
-	for (lid = 0; lid < NPC_MAX_LID; lid++) {
-		/* Offset in key */
-		off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
-		lt = pst->lt[lid] & 0xf;
-		flags = pst->flags[lid] & 0xff;
+	if (!roc_model_is_cn20k()) {
+		for (lid = 0; lid < NPC_MAX_LID; lid++) {
+			/* Offset in key */
+			off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
+			lt = pst->lt[lid] & 0xf;
+			flags = pst->flags[lid] & 0xff;
 
-		/* NPC_LAYER_KEX_S */
-		layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
+			/* NPC_LAYER_KEX_S */
+			layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
+			if (!layer_info)
+				continue;
 
-		if (layer_info) {
 			for (idx = 0; idx <= 2; idx++) {
-				if (layer_info & (1 << idx)) {
-					if (idx == 2) {
-						data = lt;
-						mask = 0xf;
-					} else if (idx == 1) {
-						data = ((flags >> 4) & 0xf);
-						mask = ((flags >> 4) & 0xf);
-					} else {
-						data = (flags & 0xf);
-						mask = (flags & 0xf);
-					}
-
-					if (data_off >= 64) {
-						data_off = 0;
-						index++;
-					}
-					key_data[index] |= ((uint64_t)data << data_off);
-
-					if (lt == 0)
-						mask = 0;
-					key_mask[index] |= ((uint64_t)mask << data_off);
-					data_off += 4;
+				if (!(layer_info & (1 << idx)))
+					continue;
+
+				if (idx == 2) {
+					data = lt;
+					mask = 0xf;
+				} else if (idx == 1) {
+					data = ((flags >> 4) & 0xf);
+					mask = ((flags >> 4) & 0xf);
+				} else {
+					data = (flags & 0xf);
+					mask = (flags & 0xf);
+				}
+
+				if (data_off >= 64) {
+					data_off = 0;
+					index++;
 				}
+				key_data[index] |= ((uint64_t)data << data_off);
+
+				if (lt == 0)
+					mask = 0;
+				key_mask[index] |= ((uint64_t)mask << data_off);
+				data_off += 4;
+			}
+		}
+	} else {
+		for (lid = 0; lid < NPC_MAX_LID; lid++) {
+			/* Offset in key */
+			off = NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid);
+			lt = pst->lt[lid] & 0xf;
+			flags = pst->flags[lid] & 0xf;
+
+			/* NPC_LAYER_KEX_S */
+			layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x3);
+			if (!layer_info)
+				continue;
+
+			for (idx = 0; idx <= 1; idx++) {
+				if (!(layer_info & (1 << idx)))
+					continue;
+
+				if (idx == 1) {
+					data = lt;
+					mask = 0xf;
+				} else {
+					data = (flags & 0xf);
+					mask = (flags & 0xf);
+				}
+
+				if (data_off >= 64) {
+					data_off = 0;
+					index++;
+				}
+				key_data[index] |= ((uint64_t)data << data_off);
+
+				if (lt == 0)
+					mask = 0;
+				key_mask[index] |= ((uint64_t)mask << data_off);
+				data_off += 4;
 			}
 		}
 	}
@@ -971,17 +1293,39 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 		else
 			mbox = mbox_get(npc->mbox);
 		(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
-		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
-		if (rc) {
+		if (roc_model_is_cn20k()) {
+			struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
+			struct cn20k_mcam_entry *base_entry;
+
+			rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+			if (rc) {
+				mbox_put(mbox);
+				plt_err("Failed to fetch VF's base MCAM entry");
+				return rc;
+			}
 			mbox_put(mbox);
-			plt_err("Failed to fetch VF's base MCAM entry");
-			return rc;
-		}
-		mbox_put(mbox);
-		base_entry = &base_rule_rsp->entry_data;
-		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-			pst->flow->mcam_data[idx] |= base_entry->kw[idx];
-			pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			base_entry = &base_rule_rsp->entry;
+			for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+				pst->flow->mcam_data[idx] |= base_entry->kw[idx];
+				pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			}
+
+		} else {
+			struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
+			struct mcam_entry *base_entry;
+
+			rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+			if (rc) {
+				mbox_put(mbox);
+				plt_err("Failed to fetch VF's base MCAM entry");
+				return rc;
+			}
+			mbox_put(mbox);
+			base_entry = &base_rule_rsp->entry_data;
+			for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+				pst->flow->mcam_data[idx] |= base_entry->kw[idx];
+				pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			}
 		}
 	}
 
diff --git a/drivers/common/cnxk/roc_npc_mcam_dump.c b/drivers/common/cnxk/roc_npc_mcam_dump.c
index ebd2dd69c2..bedf6db37c 100644
--- a/drivers/common/cnxk/roc_npc_mcam_dump.c
+++ b/drivers/common/cnxk/roc_npc_mcam_dump.c
@@ -35,6 +35,33 @@
 #define NIX_TX_VTAGACT_VTAG1_OP_MASK	 GENMASK(45, 44)
 #define NIX_TX_VTAGACT_VTAG1_DEF_MASK	 GENMASK(57, 48)
 
+union npc_rx_parse_nibble_cn20k_u {
+	struct {
+		uint64_t chan : 3;
+		uint64_t errlev : 1;
+		uint64_t errcode : 2;
+		uint64_t l2l3bm : 1;
+		uint64_t laflags : 1;
+		uint64_t latype : 1;
+		uint64_t lbflags : 1;
+		uint64_t lbtype : 1;
+		uint64_t lcflags : 1;
+		uint64_t lctype : 1;
+		uint64_t ldflags : 1;
+		uint64_t ldtype : 1;
+		uint64_t leflags : 1;
+		uint64_t letype : 1;
+		uint64_t lfflags : 1;
+		uint64_t lftype : 1;
+		uint64_t lgflags : 1;
+		uint64_t lgtype : 1;
+		uint64_t lhflags : 1;
+		uint64_t lhtype : 1;
+		uint64_t reserved : 41;
+	} s __plt_packed;
+	uint64_t u;
+};
+
 struct npc_rx_parse_nibble_s {
 	uint16_t chan : 3;
 	uint16_t errlev : 1;
@@ -181,8 +208,135 @@ npc_get_nibbles(struct roc_npc_flow *flow, uint16_t size, uint32_t bit_offset)
 }
 
 static void
-npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
-			     uint64_t parse_nibbles)
+npc_flow_print_parse_nibbles_cn20k(FILE *file, struct roc_npc_flow *flow, uint64_t parse_nibbles)
+{
+	union npc_rx_parse_nibble_cn20k_u rx_parse;
+	uint32_t data, offset = 0;
+
+	rx_parse.u = parse_nibbles;
+
+	if (rx_parse.s.chan) {
+		data = npc_get_nibbles(flow, 3, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_CHAN:%#03X\n", data);
+		offset += 12;
+	}
+
+	if (rx_parse.s.errlev) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRLEV:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse.s.errcode) {
+		data = npc_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRCODE:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.l2l3bm) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_L2L3_BCAST:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse.s.laflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.latype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n", ltype_str[NPC_LID_LA][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lbflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lbtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n", ltype_str[NPC_LID_LB][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lcflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lctype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n", ltype_str[NPC_LID_LC][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.ldflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.ldtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n", ltype_str[NPC_LID_LD][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.leflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.letype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n", ltype_str[NPC_LID_LE][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lfflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lftype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n", ltype_str[NPC_LID_LF][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lgflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lgtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n", ltype_str[NPC_LID_LG][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lhflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_FLAGS:%#02X\n", data);
+	}
+
+	if (rx_parse.s.lhtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n", ltype_str[NPC_LID_LH][data]);
+		offset += 4;
+	}
+}
+
+static void
+npc_flow_print_parse_nibbles_legacy(FILE *file, struct roc_npc_flow *flow, uint64_t parse_nibbles)
 {
 	struct npc_rx_parse_nibble_s *rx_parse;
 	uint32_t data, offset = 0;
@@ -221,8 +375,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->latype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n",
-			ltype_str[NPC_LID_LA][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n", ltype_str[NPC_LID_LA][data]);
 		offset += 4;
 	}
 
@@ -234,8 +387,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lbtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n",
-			ltype_str[NPC_LID_LB][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n", ltype_str[NPC_LID_LB][data]);
 		offset += 4;
 	}
 
@@ -247,8 +399,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lctype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n",
-			ltype_str[NPC_LID_LC][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n", ltype_str[NPC_LID_LC][data]);
 		offset += 4;
 	}
 
@@ -260,8 +411,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->ldtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n",
-			ltype_str[NPC_LID_LD][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n", ltype_str[NPC_LID_LD][data]);
 		offset += 4;
 	}
 
@@ -273,8 +423,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->letype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n",
-			ltype_str[NPC_LID_LE][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n", ltype_str[NPC_LID_LE][data]);
 		offset += 4;
 	}
 
@@ -286,8 +435,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lftype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n",
-			ltype_str[NPC_LID_LF][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n", ltype_str[NPC_LID_LF][data]);
 		offset += 4;
 	}
 
@@ -299,8 +447,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lgtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n",
-			ltype_str[NPC_LID_LG][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n", ltype_str[NPC_LID_LG][data]);
 		offset += 4;
 	}
 
@@ -311,15 +458,14 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lhtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n",
-			ltype_str[NPC_LID_LH][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n", ltype_str[NPC_LID_LH][data]);
 		offset += 4;
 	}
 }
 
 static void
-npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo,
-			  struct roc_npc_flow *flow, int lid, int lt)
+npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo, struct roc_npc_flow *flow,
+			  int lid, int lt)
 {
 	uint8_t *datastart, *maskstart;
 	int i;
@@ -374,6 +520,7 @@ static void
 npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
 {
 	struct npc_lid_lt_xtract_info *lt_xinfo;
+	struct npc_lid_lt_xtract_info_cn20k *lt_xinfo_cn20k;
 	struct npc_xtract_info *xinfo;
 	uint32_t intf, lid, ld, i;
 	uint64_t parse_nibbles;
@@ -381,19 +528,37 @@ npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
 
 	intf = flow->nix_intf;
 	parse_nibbles = npc->keyx_supp_nmask[intf];
-	npc_flow_print_parse_nibbles(file, flow, parse_nibbles);
-
-	for (i = 0; i < flow->num_patterns; i++) {
-		lid = flow->dump_data[i].lid;
-		ltype = flow->dump_data[i].ltype;
-		lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
-
-		for (ld = 0; ld < NPC_MAX_LD; ld++) {
-			xinfo = &lt_xinfo->xtract[ld];
-			if (!xinfo->enable)
-				continue;
-			npc_flow_print_item(file, npc, xinfo, flow, intf, lid,
-					    ltype, ld);
+	if (roc_model_is_cn20k()) {
+		npc_flow_print_parse_nibbles_cn20k(file, flow, parse_nibbles);
+		for (i = 0; i < flow->num_patterns; i++) {
+			lid = flow->dump_data[i].lid;
+			ltype = flow->dump_data[i].ltype;
+			for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+				union npc_kex_ldata_flags_cfg *lid_info =
+					&npc->lid_cfg[NIX_INTF_RX][j];
+				if (lid_info->s.lid != lid)
+					continue;
+				lt_xinfo_cn20k = &npc->prx_dxcfg_cn20k[intf][j][ltype];
+				xinfo = &lt_xinfo_cn20k->xtract;
+				if (!xinfo->enable)
+					continue;
+				npc_flow_print_item(file, npc, xinfo, flow, intf, lid, ltype, j);
+			}
+		}
+	} else {
+		npc_flow_print_parse_nibbles_legacy(file, flow, parse_nibbles);
+
+		for (i = 0; i < flow->num_patterns; i++) {
+			lid = flow->dump_data[i].lid;
+			ltype = flow->dump_data[i].ltype;
+			lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
+
+			for (ld = 0; ld < NPC_MAX_LD; ld++) {
+				xinfo = &lt_xinfo->xtract[ld];
+				if (!xinfo->enable)
+					continue;
+				npc_flow_print_item(file, npc, xinfo, flow, intf, lid, ltype, ld);
+			}
 		}
 	}
 }
@@ -645,7 +810,6 @@ npc_flow_hw_mcam_entry_dump(FILE *file, struct npc *npc, struct roc_npc_flow *fl
 	uint64_t mcam_data[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	struct npc_mcam_read_entry_req *mcam_read_req;
-	struct npc_mcam_read_entry_rsp *mcam_read_rsp;
 	struct nix_inl_dev *inl_dev = NULL;
 	struct idev_cfg *idev;
 	struct mbox *mbox;
@@ -669,17 +833,34 @@ npc_flow_hw_mcam_entry_dump(FILE *file, struct npc *npc, struct roc_npc_flow *fl
 	}
 
 	mcam_read_req->entry = flow->mcam_id;
-	rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
-	if (rc) {
-		mbox_put(mbox);
-		plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
-		return;
-	}
 
-	mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
-	mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
-	enabled = mcam_read_rsp->enable;
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_read_entry_rsp *mcam_read_rsp;
+
+		rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
+		if (rc) {
+			mbox_put(mbox);
+			plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
+			return;
+		}
+
+		mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
+		mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
+		enabled = mcam_read_rsp->enable;
+	} else {
+		struct npc_mcam_read_entry_rsp *mcam_read_rsp;
 
+		rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
+		if (rc) {
+			mbox_put(mbox);
+			plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
+			return;
+		}
+
+		mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
+		mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
+		enabled = mcam_read_rsp->enable;
+	}
 	fprintf(file, "HW MCAM Data :\n");
 
 	for (i = 0; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
@@ -702,14 +883,18 @@ roc_npc_flow_mcam_dump(FILE *file, struct roc_npc *roc_npc, struct roc_npc_flow
 
 	fprintf(file, "MCAM Index:%d\n", flow->mcam_id);
 	if (flow->ctr_id != NPC_COUNTER_NONE && flow->use_ctr) {
-		if (flow->use_pre_alloc)
+		if (flow->use_pre_alloc) {
 			rc = roc_npc_inl_mcam_read_counter(flow->ctr_id, &count);
-		else
-			rc = roc_npc_mcam_read_counter(roc_npc, flow->ctr_id, &count);
+		} else {
+			if (roc_model_is_cn20k())
+				rc = roc_npc_mcam_get_stats(roc_npc, flow, &count);
+			else
+				rc = roc_npc_mcam_read_counter(roc_npc, flow->ctr_id, &count);
+		}
 
 		if (rc)
 			return;
-		fprintf(file, "Hit count: %" PRIu64 "\n", count);
+		fprintf(file, "Counter_id = 0x%x, Hit count: %" PRIu64 "\n", flow->ctr_id, count);
 	}
 
 	fprintf(file, "Interface :%s (%d)\n", intf_str[flow->nix_intf], flow->nix_intf);
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index e08a34d146..b7d726caa1 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -30,6 +30,10 @@
 	((((lid) - (NPC_LID_LA)) * NPC_LAYER_KEYX_SZ) +                        \
 	 NPC_PARSE_KEX_S_LA_OFFSET)
 
+#define NPC_LAYER_KEYX_SZ_CN20K (2)
+#define NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid)                                                      \
+	((((lid) - (NPC_LID_LA)) * NPC_LAYER_KEYX_SZ_CN20K) + NPC_PARSE_KEX_S_LA_OFFSET)
+
 /* This mark value indicates flag action */
 #define NPC_FLOW_FLAG_VAL (0xffff)
 
@@ -43,7 +47,11 @@
 
 #define NPC_MCAM_KEX_FIELD_MAX	  23
 #define NPC_MCAM_MAX_PROTO_FIELDS (NPC_MCAM_KEX_FIELD_MAX + 1)
-#define NPC_MCAM_KEY_X4_WORDS	  7 /* Number of 64-bit words */
+#if defined(ROC_PLATFORM_CN20K)
+#define NPC_MCAM_KEY_X4_WORDS 8 /* Number of 64-bit words */
+#else
+#define NPC_MCAM_KEY_X4_WORDS 7 /* Number of 64-bit words */
+#endif
 
 #define NPC_RVUPF_MAX_9XXX 0x10 /* HRM: RVU_PRIV_CONST */
 #define NPC_RVUPF_MAX_98XX 0x18 /* HRM: RVU_PRIV_CONST */
@@ -77,6 +85,16 @@
 #define NPC_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 6)
 #define NPC_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 8)
 
+/* LB OFFSET : START + LA (1b flags + 1b ltype) + LB (1b flags) */
+#define NPC_CN20K_LTYPE_LB_OFFSET (NPC_LTYPE_OFFSET_START + 3)
+#define NPC_CN20K_LFLAG_LB_OFFSET (NPC_LTYPE_OFFSET_START + 2)
+
+/* LC OFFSET : START + LA (1b flags + 1b ltype) + LB (1b flags + 1b ltype) + LC
+ * (1b flags)
+ */
+#define NPC_CN20K_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 4)
+#define NPC_CN20K_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 5)
+
 #define CN10K_SDP_CH_START 0x80
 #define CN10K_SDP_CH_MASK  0xF80
 
@@ -176,9 +194,9 @@ struct npc_parse_item_info {
 	const void *def_mask; /* default mask */
 	void *hw_mask;	      /* hardware supported mask */
 	int len;	      /* length of item */
+	uint8_t hw_hdr_len;   /* Extra data len at each layer*/
 	const void *spec;     /* spec to use, NULL implies match any */
 	const void *mask;     /* mask to use */
-	uint8_t hw_hdr_len;   /* Extra data len at each layer*/
 };
 
 struct npc_parse_state {
@@ -192,16 +210,16 @@ struct npc_parse_state {
 	uint8_t layer_mask;
 	uint8_t lt[NPC_MAX_LID];
 	uint8_t flags[NPC_MAX_LID];
+	bool has_eth_type;
+	bool is_second_pass_rule;
+	bool set_ipv6ext_ltype_mask;
+	/* adjust ltype in MCAM to match at least one vlan */
+	bool set_vlan_ltype_mask;
 	uint8_t *mcam_data; /* point to flow->mcam_data + key_len */
 	uint8_t *mcam_mask; /* point to flow->mcam_mask + key_len */
 	bool is_vf;
-	/* adjust ltype in MCAM to match at least one vlan */
-	bool set_vlan_ltype_mask;
-	bool set_ipv6ext_ltype_mask;
-	bool is_second_pass_rule;
-	bool has_eth_type;
-	uint16_t nb_tx_queues;
 	uint16_t dst_pf_func;
+	uint16_t nb_tx_queues;
 };
 
 enum npc_kpu_parser_flag {
@@ -340,6 +358,14 @@ struct npc_lid_lt_xtract_info {
 	struct npc_xtract_info xtract[NPC_MAX_LD];
 };
 
+struct npc_lid_lt_xtract_info_cn20k {
+	/* Info derived from parser configuration */
+	uint16_t npc_proto;	    /* Network protocol identified */
+	uint8_t valid_flags_mask;   /* Flags applicable */
+	uint8_t is_terminating : 1; /* No more parsing */
+	struct npc_xtract_info xtract;
+};
+
 union npc_kex_ldata_flags_cfg {
 	struct {
 		uint64_t lid : 3;
@@ -349,6 +375,11 @@ union npc_kex_ldata_flags_cfg {
 	uint64_t i;
 };
 
+#define NPC_MAX_EXTRACTTORS 24
+typedef struct npc_lid_lt_xtract_info_cn20k npc_dxcfg_cn20k_t[NPC_MAX_INTF][NPC_MAX_EXTRACTTORS]
+							     [NPC_MAX_LT];
+typedef union npc_kex_ldata_flags_cfg npc_lid_cn20k_t[NPC_MAX_INTF][NPC_MAX_EXTRACTTORS];
+
 typedef struct npc_lid_lt_xtract_info npc_dxcfg_t[NPC_MAX_INTF][NPC_MAX_LID]
 						 [NPC_MAX_LT];
 typedef struct npc_lid_lt_xtract_info npc_fxcfg_t[NPC_MAX_INTF][NPC_MAX_LD]
@@ -387,33 +418,36 @@ TAILQ_HEAD(npc_age_flow_list_head, npc_age_flow_entry);
 
 struct npc {
 	struct mbox *mbox;			/* Mbox */
-	uint32_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */
+	uint64_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */
 	uint8_t hash_extract_cap;		/* hash extract support */
 	uint8_t profile_name[MKEX_NAME_LEN];	/* KEX profile name */
-	uint32_t keyx_len[NPC_MAX_INTF];	/* per intf key len in bits */
-	uint32_t datax_len[NPC_MAX_INTF];	/* per intf data len in bits */
-	uint32_t keyw[NPC_MAX_INTF];		/* max key + data len bits */
-	uint32_t mcam_entries;			/* mcam entries supported */
-	uint16_t channel;			/* RX Channel number */
 	bool is_sdp_link;
+	uint16_t channel;		  /* RX Channel number */
+	uint32_t keyx_len[NPC_MAX_INTF];  /* per intf key len in bits */
+	uint32_t datax_len[NPC_MAX_INTF]; /* per intf data len in bits */
+	uint32_t keyw[NPC_MAX_INTF];	  /* max key + data len bits */
+	uint32_t mcam_entries;		  /* mcam entries supported */
+	uint16_t switch_header_type;	  /* Supported switch header type */
+	uint16_t flow_max_priority;	  /* Max priority for flow */
 	uint16_t sdp_channel;
 	uint16_t sdp_channel_mask;
-	uint32_t rss_grps;			/* rss groups supported */
-	uint16_t flow_prealloc_size;		/* Pre allocated mcam size */
-	uint16_t flow_max_priority;		/* Max priority for flow */
-	uint16_t switch_header_type; /* Supported switch header type */
+	uint32_t rss_grps;	     /* rss groups supported */
+	uint16_t flow_prealloc_size; /* Pre allocated mcam size */
+	uint8_t exact_match_ena;
+	uint16_t pf_func; /* pf_func of device */
 	uint32_t mark_actions;
-	uint32_t vtag_strip_actions; /* vtag insert/strip actions */
-	uint16_t pf_func;	     /* pf_func of device */
-	npc_dxcfg_t prx_dxcfg;	     /* intf, lid, lt, extract */
-	npc_fxcfg_t prx_fxcfg;	     /* Flag extract */
-	npc_ld_flags_t prx_lfcfg;    /* KEX LD_Flags CFG */
+	uint32_t vtag_strip_actions;	   /* vtag insert/strip actions */
+	npc_dxcfg_t prx_dxcfg;		   /* intf, lid, lt, extract */
+	npc_dxcfg_cn20k_t prx_dxcfg_cn20k; /* intf, ext, lt, extract */
+	npc_lid_cn20k_t lid_cfg;	   /* KEX LD_Flags CFG */
+	npc_fxcfg_t prx_fxcfg;		   /* Flag extract */
+	npc_ld_flags_t prx_lfcfg;	   /* KEX LD_Flags CFG */
 	struct npc_flow_list *flow_list;
 	struct npc_prio_flow_list_head *prio_flow_list;
 	struct npc_age_flow_list_head age_flow_list;
 	struct plt_bitmap *rss_grp_entries;
 	struct npc_flow_list ipsec_list;
-	uint8_t exact_match_ena;
+	uint8_t enable_debug;
 };
 
 #define NPC_HASH_FIELD_LEN 16
@@ -432,6 +466,7 @@ roc_npc_to_npc_priv(struct roc_npc *npc)
 	return (struct npc *)npc->reserved;
 }
 
+int npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count);
 int npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr);
 int npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id);
 int npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count);
@@ -440,9 +475,10 @@ int npc_mcam_free_entry(struct mbox *mbox, uint32_t entry);
 int npc_mcam_free_all_entries(struct npc *npc);
 int npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow,
 			     struct npc_parse_state *pst);
-int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam,
-			 struct roc_npc_flow *ref_mcam, int prio,
-			 int *resp_count);
+int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
+			 uint8_t prio, int *resp_count);
+int npc_mcam_alloc_entry_cn20k(struct npc *npc, struct roc_npc_flow *mcam, int *resp_count);
+
 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);
 
@@ -453,6 +489,7 @@ int npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_in
 			   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);
+uint8_t npc_get_key_type(struct npc *npc, struct roc_npc_flow *flow);
 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 a507df994f..75d3b0702c 100644
--- a/drivers/common/cnxk/roc_npc_utils.c
+++ b/drivers/common/cnxk/roc_npc_utils.c
@@ -4,6 +4,36 @@
 #include "roc_api.h"
 #include "roc_priv.h"
 
+enum npc_mcam_cn20k_key_width {
+	NPC_CN20K_MCAM_KEY_X1 = 0,
+	NPC_CN20K_MCAM_KEY_DYN = NPC_CN20K_MCAM_KEY_X1,
+	NPC_CN20K_MCAM_KEY_X2,
+	NPC_CN20K_MCAM_KEY_X4,
+	NPC_CN20K_MCAM_KEY_MAX,
+};
+
+uint8_t
+npc_get_key_type(struct npc *npc, struct roc_npc_flow *flow)
+{
+	int i;
+
+	/* KEX is configured just for X2 */
+	if (npc->keyw[ROC_NPC_INTF_RX] == 1)
+		return NPC_CN20K_MCAM_KEY_X2;
+
+	/* KEX is configured just for X4 */
+	if (npc->keyw[ROC_NPC_INTF_RX] == 2)
+		return NPC_CN20K_MCAM_KEY_X4;
+
+	/* KEX is configured for both X2 and X4 */
+	/* Check mask for upper 256 bits. if mask is set, then it is X4 entry */
+	for (i = 4; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
+		if (flow->mcam_mask[i] != 0)
+			return NPC_CN20K_MCAM_KEY_X4;
+	}
+	return NPC_CN20K_MCAM_KEY_X2;
+}
+
 static void
 npc_prep_mcam_ldata(uint8_t *ptr, const uint8_t *data, int len)
 {
@@ -67,8 +97,9 @@ npc_ipv6_hash_mask_get(struct npc_xtract_info *xinfo, struct npc_parse_item_info
 	memset(&hw_mask[offset], 0xFF, NPC_HASH_FIELD_LEN);
 }
 
-void
-npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid, int lt)
+static void
+npc_get_hw_supp_mask_legacy(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			    int lt)
 {
 	struct npc_xtract_info *xinfo, *lfinfo;
 	char *hw_mask = info->hw_mask;
@@ -101,6 +132,40 @@ npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *in
 	}
 }
 
+static void
+npc_get_hw_supp_mask_o20k(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			  int lt)
+{
+	struct npc_xtract_info *xinfo;
+	union npc_kex_ldata_flags_cfg *lid_info;
+	char *hw_mask = info->hw_mask;
+	int ex;
+	int intf;
+
+	intf = pst->nix_intf;
+	memset(hw_mask, 0, info->len);
+	for (ex = 0; ex < NPC_MAX_EXTRACTTORS; ex++) {
+		lid_info = &pst->npc->lid_cfg[intf][ex];
+		if (lid_info->s.lid != lid)
+			continue;
+		xinfo = &pst->npc->prx_dxcfg_cn20k[intf][ex][lt].xtract;
+
+		if (pst->npc->hash_extract_cap && xinfo->use_hash)
+			npc_ipv6_hash_mask_get(xinfo, info);
+		else
+			npc_set_hw_mask(info, xinfo, hw_mask);
+	}
+}
+
+void
+npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid, int lt)
+{
+	if (!roc_model_is_cn20k())
+		return npc_get_hw_supp_mask_legacy(pst, info, lid, lt);
+	else
+		return npc_get_hw_supp_mask_o20k(pst, info, lid, lt);
+}
+
 inline int
 npc_mask_is_supported(const char *mask, const char *hw_mask, int len)
 {
@@ -381,10 +446,10 @@ npc_hash_field_get(struct npc_xtract_info *xinfo, const struct roc_npc_flow_item
 	return 1;
 }
 
-int
-npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
-			    const struct roc_npc_flow_item_ipv6 *ipv6_mask,
-			    struct npc_parse_state *pst, uint8_t ltype)
+static int
+npc_process_ipv6_field_hash_legacy(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+				   const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+				   struct npc_parse_state *pst, uint8_t ltype)
 {
 	struct npc_lid_lt_xtract_info *lid_lt_xinfo;
 	uint8_t hash_field[ROC_IPV6_ADDR_LEN];
@@ -421,9 +486,64 @@ npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
 	return 0;
 }
 
+static int
+npc_process_ipv6_field_hash_o20k(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+				 const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+				 struct npc_parse_state *pst, uint8_t ltype)
+{
+	struct npc_lid_lt_xtract_info_cn20k *lid_lt_xinfo;
+	union npc_kex_ldata_flags_cfg *lid_cfg;
+	uint8_t hash_field[ROC_IPV6_ADDR_LEN];
+	struct npc_xtract_info *xinfo;
+	struct roc_ipv6_hdr ipv6_buf;
+	uint32_t hash = 0, mask;
+	int intf, i, rc = 0;
+
+	memset(&ipv6_buf, 0, sizeof(ipv6_buf));
+	memset(hash_field, 0, sizeof(hash_field));
+
+	intf = pst->nix_intf;
+	for (i = 0; i < NPC_MAX_EXTRACTTORS; i++) {
+		lid_cfg = &pst->npc->lid_cfg[intf][i];
+		if (lid_cfg->s.lid != NPC_LID_LC)
+			continue;
+		lid_lt_xinfo = &pst->npc->prx_dxcfg_cn20k[intf][NPC_LID_LC][ltype];
+
+		xinfo = &lid_lt_xinfo->xtract;
+		if (!xinfo->use_hash)
+			continue;
+
+		rc = npc_hash_field_get(xinfo, ipv6_spec, ipv6_mask, hash_field);
+		if (rc == 0)
+			continue;
+
+		rc = npc_ipv6_field_hash_get(pst->npc, (const uint32_t *)hash_field, intf, i,
+					     &hash);
+		if (rc)
+			return rc;
+
+		mask = GENMASK(31, 0);
+		memcpy(pst->mcam_mask + xinfo->key_off, (uint8_t *)&mask, 4);
+		memcpy(pst->mcam_data + xinfo->key_off, (uint8_t *)&hash, 4);
+	}
+
+	return 0;
+}
+
 int
-npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
-		       int lt, uint8_t flags)
+npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+			    const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+			    struct npc_parse_state *pst, uint8_t ltype)
+{
+	if (!roc_model_is_cn20k())
+		return npc_process_ipv6_field_hash_legacy(ipv6_spec, ipv6_mask, pst, ltype);
+	else
+		return npc_process_ipv6_field_hash_o20k(ipv6_spec, ipv6_mask, pst, ltype);
+}
+
+static int
+npc_update_parse_state_legacy(struct npc_parse_state *pst, struct npc_parse_item_info *info,
+			      int lid, int lt, uint8_t flags)
 {
 	struct npc_lid_lt_xtract_info *xinfo;
 	struct roc_npc_flow_dump_data *dump;
@@ -461,8 +581,7 @@ npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *
 		if (lf_cfg == lid) {
 			for (j = 0; j < NPC_MAX_LFL; j++) {
 				lfinfo = pst->npc->prx_fxcfg[intf][i][j].xtract;
-				rc = npc_update_extraction_data(pst, info,
-								&lfinfo[0]);
+				rc = npc_update_extraction_data(pst, info, &lfinfo[0]);
 				if (rc != 0)
 					return rc;
 
@@ -480,42 +599,127 @@ npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *
 	return 0;
 }
 
+static int
+npc_update_parse_state_o20(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			   int lt, uint8_t flags)
+{
+	struct npc_lid_lt_xtract_info_cn20k *xinfo;
+	union npc_kex_ldata_flags_cfg *lid_cfg;
+	struct roc_npc_flow_dump_data *dump;
+	int intf;
+	int i, rc = 0;
+
+	pst->layer_mask |= lid;
+	pst->lt[lid] = lt;
+	pst->flags[lid] = flags;
+
+	intf = pst->nix_intf;
+	if (info->spec == NULL)
+		goto done;
+
+	for (i = 0; i < NPC_MAX_EXTRACTTORS; i++) {
+		lid_cfg = &pst->npc->lid_cfg[intf][i];
+		if (lid_cfg->s.lid != lid)
+			continue;
+		xinfo = &pst->npc->prx_dxcfg_cn20k[intf][i][lt];
+		if (xinfo->is_terminating)
+			pst->terminate = 1;
+
+		if (xinfo->xtract.use_hash)
+			continue;
+		rc = npc_update_extraction_data(pst, info, &xinfo->xtract);
+		if (rc != 0)
+			return rc;
+	}
+
+done:
+	dump = &pst->flow->dump_data[pst->flow->num_patterns++];
+	dump->lid = lid;
+	dump->ltype = lt;
+	pst->pattern++;
+	return 0;
+}
+
+int
+npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+		       int lt, uint8_t flags)
+{
+	if (roc_model_is_cn20k())
+		return npc_update_parse_state_o20(pst, info, lid, lt, flags);
+	else
+		return npc_update_parse_state_legacy(pst, info, lid, lt, flags);
+}
+
 int
 npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id)
 {
-	struct npc_mcam_write_entry_req *req;
-	struct npc_mcam_write_entry_rsq *rsp;
+	struct msg_rsp *rsp;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = 0, idx;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL) {
-		rc = -ENOSPC;
-		goto exit;
-	}
-	req->set_cntr = 0;
-	req->cntr = 0;
-	req->entry = mcam_id;
-
-	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
-	req->enable_entry = 1;
-	req->entry_data.action = flow->npc_action;
-	req->entry_data.vtag_action = flow->vtag_action;
-
-	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		req->entry_data.kw[idx] = 0x0;
-		req->entry_data.kw_mask[idx] = 0x0;
-	}
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (req == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		req->cntr = 0;
+		req->entry = mcam_id;
+
+		req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+		req->enable_entry = 1;
+		req->entry_data.action = flow->npc_action;
+		req->entry_data.vtag_action = flow->vtag_action;
+
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			req->entry_data.kw[idx] = 0x0;
+			req->entry_data.kw_mask[idx] = 0x0;
+		}
+
+		if (flow->nix_intf == NIX_INTF_RX) {
+			req->entry_data.kw[0] |= (uint64_t)npc->channel;
+			req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+		} else {
+			uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 
-	if (flow->nix_intf == NIX_INTF_RX) {
-		req->entry_data.kw[0] |= (uint64_t)npc->channel;
-		req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+			pf_func = plt_cpu_to_be_16(pf_func);
+			req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
+			req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+		}
 	} else {
-		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
+		struct npc_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		req->set_cntr = 0;
+		req->cntr = 0;
+		req->entry = mcam_id;
+
+		req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+		req->enable_entry = 1;
+		req->entry_data.action = flow->npc_action;
+		req->entry_data.vtag_action = flow->vtag_action;
+
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			req->entry_data.kw[idx] = 0x0;
+			req->entry_data.kw_mask[idx] = 0x0;
+		}
+
+		if (flow->nix_intf == NIX_INTF_RX) {
+			req->entry_data.kw[0] |= (uint64_t)npc->channel;
+			req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+		} else {
+			uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 
-		pf_func = plt_cpu_to_be_16(pf_func);
-		req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
-		req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+			pf_func = plt_cpu_to_be_16(pf_func);
+			req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
+			req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+		}
 	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -783,13 +987,12 @@ npc_insert_into_flow_list(struct npc *npc, struct npc_prio_flow_entry *entry)
 }
 
 static int
-npc_allocate_mcam_entry(struct mbox *mbox, int prio,
-			struct npc_mcam_alloc_entry_rsp *rsp_local,
-			int ref_entry)
+npc_allocate_mcam_entry(struct mbox *mbox, int prio, struct npc_mcam_alloc_entry_rsp *rsp_local,
+			int ref_entry, uint8_t kw_type)
 {
-	struct npc_mcam_alloc_entry_rsp *rsp_cmd;
-	struct npc_mcam_alloc_entry_req *req;
 	struct npc_mcam_alloc_entry_rsp *rsp;
+	struct npc_mcam_alloc_entry_req *req;
+
 	int rc = -ENOSPC;
 
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
@@ -797,20 +1000,20 @@ npc_allocate_mcam_entry(struct mbox *mbox, int prio,
 		goto exit;
 	req->contig = 1;
 	req->count = 1;
-	req->priority = prio;
+	req->ref_priority = prio;
 	req->ref_entry = ref_entry;
+	req->kw_type = kw_type;
 
-	rc = mbox_process_msg(mbox, (void *)&rsp_cmd);
+	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		goto exit;
 
-	if (!rsp_cmd->count) {
+	if (!rsp->count) {
 		rc = -ENOSPC;
 		goto exit;
 	}
 
-	mbox_memcpy(rsp_local, rsp_cmd, sizeof(*rsp));
-
+	mbox_memcpy(rsp_local, rsp, sizeof(*rsp));
 	rc = 0;
 exit:
 	mbox_put(mbox);
@@ -854,8 +1057,7 @@ npc_find_mcam_ref_entry(struct roc_npc_flow *flow, struct npc *npc, int *prio,
 }
 
 static int
-npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
-			    struct npc *npc,
+npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow, struct npc *npc,
 			    struct npc_mcam_alloc_entry_rsp *rsp_local)
 {
 	int prio, ref_entry = 0, rc = 0, dir = NPC_MCAM_LOWER_PRIO;
@@ -863,7 +1065,7 @@ npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
 
 retry:
 	npc_find_mcam_ref_entry(flow, npc, &prio, &ref_entry, dir);
-	rc = npc_allocate_mcam_entry(mbox, prio, rsp_local, ref_entry);
+	rc = npc_allocate_mcam_entry(mbox, prio, rsp_local, ref_entry, flow->key_type);
 	if (rc && !retry_done) {
 		plt_npc_dbg(
 			"npc: Failed to allocate lower priority entry. Retrying for higher priority");
@@ -879,32 +1081,42 @@ npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
 }
 
 int
-npc_get_free_mcam_entry(struct mbox *mbox, struct roc_npc_flow *flow,
-			struct npc *npc)
+npc_get_free_mcam_entry(struct mbox *mbox, struct roc_npc_flow *flow, struct npc *npc)
 {
 	struct npc_mcam_alloc_entry_rsp rsp_local;
 	struct npc_prio_flow_entry *new_entry;
 	int rc = 0;
 
-	rc = npc_alloc_mcam_by_ref_entry(mbox, flow, npc, &rsp_local);
-
-	if (rc)
-		return rc;
-
 	new_entry = plt_zmalloc(sizeof(*new_entry), 0);
 	if (!new_entry)
 		return -ENOSPC;
 
-	new_entry->flow = flow;
+	if (roc_model_is_cn20k()) {
+		rc = npc_allocate_mcam_entry(mbox, NPC_MCAM_ANY_PRIO, &rsp_local, 0,
+					     flow->key_type);
+		if (rc) {
+			plt_npc_dbg("npc: failed to allocate MCAM entry.");
+			return rc;
+		}
+
+		new_entry->flow = flow;
+	} else {
+		rc = npc_alloc_mcam_by_ref_entry(mbox, flow, npc, &rsp_local);
 
-	plt_npc_dbg("kernel allocated MCAM entry %d", rsp_local.entry);
+		if (rc)
+			return rc;
 
-	rc = npc_sort_mcams_by_user_prio_level(mbox, new_entry, npc,
-					       &rsp_local);
-	if (rc)
-		goto err;
+		new_entry->flow = flow;
+
+		plt_npc_dbg("kernel allocated MCAM entry %d", rsp_local.entry);
+
+		rc = npc_sort_mcams_by_user_prio_level(mbox, new_entry, npc, &rsp_local);
+		if (rc)
+			goto err;
+
+		plt_npc_dbg("allocated MCAM entry after sorting %d", rsp_local.entry);
+	}
 
-	plt_npc_dbg("allocated MCAM entry after sorting %d", rsp_local.entry);
 	flow->mcam_id = rsp_local.entry;
 	npc_insert_into_flow_list(npc, new_entry);
 
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 935be3584c..27c6e8ed0e 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -482,6 +482,7 @@ INTERNAL {
 	roc_npc_mcam_free_counter;
 	roc_npc_mcam_free;
 	roc_npc_mcam_free_entry;
+	roc_npc_mcam_get_stats;
 	roc_npc_mcam_init;
 	roc_npc_mcam_move;
 	roc_npc_mcam_merge_base_steering_rule;
-- 
2.39.2


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

* [dpdk-dev] [PATCH v2 2/2] net/cnxk: support rte flow on cn20k
  2024-10-29  7:31 ` [dpdk-dev] [PATCH v2 1/2] common/cnxk: support NPC " psatheesh
@ 2024-10-29  7:31   ` psatheesh
  2024-11-04 11:29     ` Jerin Jacob
  0 siblings, 1 reply; 8+ messages in thread
From: psatheesh @ 2024-10-29  7:31 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Support for rte flow in cn20k.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 drivers/net/cnxk/cn10k_ethdev.c        |   8 +-
 drivers/net/cnxk/cn10k_flow.h          |  21 --
 drivers/net/cnxk/cn20k_ethdev.c        |   4 +
 drivers/net/cnxk/cnxk_ethdev_devargs.c |  10 +-
 drivers/net/cnxk/cnxk_flow.c           |  10 +-
 drivers/net/cnxk/cnxk_flow_wrapper.c   | 303 +++++++++++++++++++++++++
 drivers/net/cnxk/cnxk_flow_wrapper.h   |  21 ++
 drivers/net/cnxk/meson.build           |  10 +-
 8 files changed, 355 insertions(+), 32 deletions(-)
 delete mode 100644 drivers/net/cnxk/cn10k_flow.h
 create mode 100644 drivers/net/cnxk/cnxk_flow_wrapper.c
 create mode 100644 drivers/net/cnxk/cnxk_flow_wrapper.h

diff --git a/drivers/net/cnxk/cn10k_ethdev.c b/drivers/net/cnxk/cn10k_ethdev.c
index fbb9b09062..a4b3d56c61 100644
--- a/drivers/net/cnxk/cn10k_ethdev.c
+++ b/drivers/net/cnxk/cn10k_ethdev.c
@@ -2,9 +2,9 @@
  * Copyright(C) 2021 Marvell.
  */
 #include "cn10k_ethdev.h"
-#include "cn10k_flow.h"
 #include "cn10k_rx.h"
 #include "cn10k_tx.h"
+#include "cnxk_flow_wrapper.h"
 
 static uint16_t
 nix_rx_offload_flags(struct rte_eth_dev *eth_dev)
@@ -913,9 +913,9 @@ npc_flow_ops_override(void)
 	init_once = 1;
 
 	/* Update platform specific ops */
-	cnxk_flow_ops.create = cn10k_flow_create;
-	cnxk_flow_ops.destroy = cn10k_flow_destroy;
-	cnxk_flow_ops.info_get = cn10k_flow_info_get;
+	cnxk_flow_ops.create = cnxk_flow_create_wrapper;
+	cnxk_flow_ops.destroy = cnxk_flow_destroy_wrapper;
+	cnxk_flow_ops.info_get = cnxk_flow_info_get_wrapper;
 }
 
 static int
diff --git a/drivers/net/cnxk/cn10k_flow.h b/drivers/net/cnxk/cn10k_flow.h
deleted file mode 100644
index 316b74e6a6..0000000000
--- a/drivers/net/cnxk/cn10k_flow.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(C) 2020 Marvell.
- */
-#ifndef __CN10K_RTE_FLOW_H__
-#define __CN10K_RTE_FLOW_H__
-
-#include <rte_flow_driver.h>
-
-struct rte_flow *cn10k_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
-				   const struct rte_flow_item pattern[],
-				   const struct rte_flow_action actions[],
-				   struct rte_flow_error *error);
-int cn10k_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
-		       struct rte_flow_error *error);
-
-int cn10k_flow_info_get(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
-			struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
-
-#define CN10K_NPC_COUNTERS_MAX 512
-
-#endif /* __CN10K_RTE_FLOW_H__ */
diff --git a/drivers/net/cnxk/cn20k_ethdev.c b/drivers/net/cnxk/cn20k_ethdev.c
index 37c372d80f..e74dd88172 100644
--- a/drivers/net/cnxk/cn20k_ethdev.c
+++ b/drivers/net/cnxk/cn20k_ethdev.c
@@ -4,6 +4,7 @@
 #include "cn20k_ethdev.h"
 #include "cn20k_rx.h"
 #include "cn20k_tx.h"
+#include "cnxk_flow_wrapper.h"
 
 static uint16_t
 nix_rx_offload_flags(struct rte_eth_dev *eth_dev)
@@ -867,6 +868,9 @@ npc_flow_ops_override(void)
 	init_once = 1;
 
 	/* Update platform specific ops */
+	cnxk_flow_ops.create = cnxk_flow_create_wrapper;
+	cnxk_flow_ops.destroy = cnxk_flow_destroy_wrapper;
+	cnxk_flow_ops.info_get = cnxk_flow_info_get_wrapper;
 }
 
 static int
diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c
index 5bd50bb9a1..bdf5d88b92 100644
--- a/drivers/net/cnxk/cnxk_ethdev_devargs.c
+++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c
@@ -88,8 +88,7 @@ parse_flow_max_priority(const char *key, const char *value, void *extra_args)
 
 	val = atoi(value);
 
-	/* Limit the max priority to 32 */
-	if (val < 1 || val > 32)
+	if (val < 1 || val > ROC_NPC_MAX_MCAM_PRIORITY)
 		return -EINVAL;
 
 	*(uint16_t *)extra_args = val;
@@ -390,7 +389,12 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 		dev->nix.meta_buf_sz = meta_buf_sz;
 
 	dev->npc.flow_prealloc_size = flow_prealloc_size;
-	dev->npc.flow_max_priority = flow_max_priority;
+
+	if (roc_model_is_cn20k())
+		dev->npc.flow_max_priority = ROC_NPC_MAX_MCAM_PRIORITY;
+	else
+		dev->npc.flow_max_priority = flow_max_priority;
+
 	dev->npc.switch_header_type = switch_header_type;
 	dev->npc.sdp_channel = sdp_chan.channel;
 	dev->npc.sdp_channel_mask = sdp_chan.mask;
diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c
index e42e2f8deb..4a32c11765 100644
--- a/drivers/net/cnxk/cnxk_flow.c
+++ b/drivers/net/cnxk/cnxk_flow.c
@@ -1083,10 +1083,14 @@ cnxk_flow_query_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
 		npc = &rep_dev->parent_dev->npc;
 	}
 
-	if (in_flow->use_pre_alloc)
+	if (in_flow->use_pre_alloc) {
 		rc = roc_npc_inl_mcam_read_counter(in_flow->ctr_id, &query->hits);
-	else
-		rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	} else {
+		if (roc_model_is_cn20k())
+			rc = roc_npc_mcam_get_stats(npc, in_flow, &query->hits);
+		else
+			rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	}
 	if (rc != 0) {
 		errcode = EIO;
 		errmsg = "Error reading flow counter";
diff --git a/drivers/net/cnxk/cnxk_flow_wrapper.c b/drivers/net/cnxk/cnxk_flow_wrapper.c
new file mode 100644
index 0000000000..af2eee7266
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_flow_wrapper.c
@@ -0,0 +1,303 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+
+#ifdef CNXK_PLATFORM_CN10K
+#include "cn10k_ethdev.h"
+#include "cn10k_rx.h"
+#endif
+#ifdef CNXK_PLATFORM_CN20K
+#include "cn20k_ethdev.h"
+#include "cn20k_rx.h"
+#endif
+#include "cnxk_ethdev_mcs.h"
+#include "cnxk_flow_wrapper.h"
+#include <cnxk_flow.h>
+
+static void
+cnxk_eth_set_rx_function(struct rte_eth_dev *eth_dev)
+{
+	RTE_SET_USED(eth_dev);
+#ifdef CNXK_PLATFORM_CN10K
+	cn10k_eth_set_rx_function(eth_dev);
+#endif
+#ifdef CNXK_PLATFORM_CN20K
+	cn20k_eth_set_rx_function(eth_dev);
+#endif
+}
+
+static int
+cnxk_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
+{
+	return nix_mtr_connect(eth_dev, mtr_id);
+}
+
+static int
+cnxk_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
+{
+	struct rte_mtr_error mtr_error;
+
+	return nix_mtr_destroy(eth_dev, mtr_id, &mtr_error);
+}
+
+static int
+cnxk_mtr_configure(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[])
+{
+	uint32_t mtr_id = 0xffff, prev_mtr_id = 0xffff, next_mtr_id = 0xffff;
+	const struct rte_flow_action_meter *mtr_conf;
+	const struct rte_flow_action_queue *q_conf;
+	const struct rte_flow_action_rss *rss_conf;
+	struct cnxk_mtr_policy_node *policy;
+	bool is_mtr_act = false;
+	int tree_level = 0;
+	int rc = -EINVAL, i;
+
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
+			mtr_conf = (const struct rte_flow_action_meter *)(actions[i].conf);
+			mtr_id = mtr_conf->mtr_id;
+			is_mtr_act = true;
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+			q_conf = (const struct rte_flow_action_queue *)(actions[i].conf);
+			if (is_mtr_act)
+				nix_mtr_rq_update(eth_dev, mtr_id, 1, &q_conf->index);
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
+			rss_conf = (const struct rte_flow_action_rss *)(actions[i].conf);
+			if (is_mtr_act)
+				nix_mtr_rq_update(eth_dev, mtr_id, rss_conf->queue_num,
+						  rss_conf->queue);
+		}
+	}
+
+	if (!is_mtr_act)
+		return rc;
+
+	prev_mtr_id = mtr_id;
+	next_mtr_id = mtr_id;
+	while (next_mtr_id != 0xffff) {
+		rc = nix_mtr_validate(eth_dev, next_mtr_id);
+		if (rc)
+			return rc;
+
+		rc = nix_mtr_policy_act_get(eth_dev, next_mtr_id, &policy);
+		if (rc)
+			return rc;
+
+		rc = nix_mtr_color_action_validate(eth_dev, mtr_id, &prev_mtr_id, &next_mtr_id,
+						   policy, &tree_level);
+		if (rc)
+			return rc;
+	}
+
+	return nix_mtr_configure(eth_dev, mtr_id);
+}
+
+static int
+cnxk_rss_action_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+			 const struct rte_flow_action *act)
+{
+	const struct rte_flow_action_rss *rss;
+
+	if (act == NULL)
+		return -EINVAL;
+
+	rss = (const struct rte_flow_action_rss *)act->conf;
+
+	if (attr->egress) {
+		plt_err("No support of RSS in egress");
+		return -EINVAL;
+	}
+
+	if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
+		plt_err("multi-queue mode is disabled");
+		return -ENOTSUP;
+	}
+
+	if (!rss || !rss->queue_num) {
+		plt_err("no valid queues");
+		return -EINVAL;
+	}
+
+	if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
+		plt_err("non-default RSS hash functions are not supported");
+		return -ENOTSUP;
+	}
+
+	if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
+		plt_err("RSS hash key too large");
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+struct rte_flow *
+cnxk_flow_create_wrapper(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+			 const struct rte_flow_item pattern[],
+			 const struct rte_flow_action actions[], struct rte_flow_error *error)
+{
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	const struct rte_flow_action *action_rss = NULL;
+	const struct rte_flow_action_meter *mtr = NULL;
+	const struct rte_flow_action *act_q = NULL;
+	struct roc_npc *npc = &dev->npc;
+	struct roc_npc_flow *flow;
+	void *mcs_flow = NULL;
+	int vtag_actions = 0;
+	uint32_t req_act = 0;
+	int mark_actions;
+	int i, rc;
+
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER)
+			req_act |= ROC_NPC_ACTION_TYPE_METER;
+
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
+			act_q = &actions[i];
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
+			req_act |= ROC_NPC_ACTION_TYPE_RSS;
+			action_rss = &actions[i];
+		}
+	}
+
+	if (req_act & ROC_NPC_ACTION_TYPE_METER) {
+		if ((req_act & ROC_NPC_ACTION_TYPE_RSS) &&
+		    ((req_act & ROC_NPC_ACTION_TYPE_QUEUE))) {
+			return NULL;
+		}
+		if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
+			rc = cnxk_rss_action_validate(eth_dev, attr, action_rss);
+			if (rc)
+				return NULL;
+		} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
+			const struct rte_flow_action_queue *act_queue;
+			act_queue = (const struct rte_flow_action_queue *)act_q->conf;
+			if (act_queue->index > eth_dev->data->nb_rx_queues)
+				return NULL;
+		} else {
+			return NULL;
+		}
+	}
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
+			mtr = (const struct rte_flow_action_meter *)actions[i].conf;
+			rc = cnxk_mtr_configure(eth_dev, actions);
+			if (rc) {
+				rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+						   "Failed to configure mtr ");
+				return NULL;
+			}
+			break;
+		}
+	}
+
+	if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
+	    cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL) {
+		rc = cnxk_mcs_flow_configure(eth_dev, attr, pattern, actions, error, &mcs_flow);
+		if (rc) {
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					   "Failed to configure mcs flow");
+			return NULL;
+		}
+		return (struct rte_flow *)mcs_flow;
+	}
+
+	flow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);
+	if (!flow) {
+		if (mtr)
+			nix_mtr_chain_reset(eth_dev, mtr->mtr_id);
+
+		return NULL;
+	} else {
+		if (mtr)
+			cnxk_mtr_connect(eth_dev, mtr->mtr_id);
+	}
+
+	mark_actions = roc_npc_mark_actions_get(npc);
+	if (mark_actions) {
+		dev->rx_offload_flags |= NIX_RX_OFFLOAD_MARK_UPDATE_F;
+		cnxk_eth_set_rx_function(eth_dev);
+	}
+
+	vtag_actions = roc_npc_vtag_actions_get(npc);
+
+	if (vtag_actions) {
+		dev->rx_offload_flags |= NIX_RX_OFFLOAD_VLAN_STRIP_F;
+		cnxk_eth_set_rx_function(eth_dev);
+	}
+
+	return (struct rte_flow *)flow;
+}
+
+int
+cnxk_flow_info_get_wrapper(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			   struct rte_flow_queue_info *queue_info, struct rte_flow_error *err)
+{
+	RTE_SET_USED(dev);
+	RTE_SET_USED(err);
+
+	memset(port_info, 0, sizeof(*port_info));
+	memset(queue_info, 0, sizeof(*queue_info));
+
+	port_info->max_nb_counters = CNXK_NPC_COUNTERS_MAX;
+	port_info->max_nb_meters = CNXK_NIX_MTR_COUNT_MAX;
+
+	return 0;
+}
+
+int
+cnxk_flow_destroy_wrapper(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
+			  struct rte_flow_error *error)
+{
+	struct roc_npc_flow *flow = (struct roc_npc_flow *)rte_flow;
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_npc *npc = &dev->npc;
+	int vtag_actions = 0;
+	int mark_actions;
+	uint16_t match_id;
+	uint32_t mtr_id;
+	int rc;
+
+	match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & NPC_RX_ACT_MATCH_MASK;
+	if (match_id) {
+		mark_actions = roc_npc_mark_actions_sub_return(npc, 1);
+		if (mark_actions == 0) {
+			dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_MARK_UPDATE_F;
+			cnxk_eth_set_rx_function(eth_dev);
+		}
+	}
+
+	vtag_actions = roc_npc_vtag_actions_get(npc);
+	if (vtag_actions) {
+		if (flow->nix_intf == ROC_NPC_INTF_RX) {
+			vtag_actions = roc_npc_vtag_actions_sub_return(npc, 1);
+			if (vtag_actions == 0) {
+				dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_VLAN_STRIP_F;
+				cnxk_eth_set_rx_function(eth_dev);
+			}
+		}
+	}
+
+	if (cnxk_eth_macsec_sess_get_by_sess(dev, (void *)flow) != NULL) {
+		rc = cnxk_mcs_flow_destroy(dev, (void *)flow);
+		if (rc < 0)
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Failed to free mcs flow");
+		return rc;
+	}
+
+	mtr_id = flow->mtr_id;
+	rc = cnxk_flow_destroy(eth_dev, flow, error);
+	if (!rc && mtr_id != ROC_NIX_MTR_ID_INVALID) {
+		rc = cnxk_mtr_destroy(eth_dev, mtr_id);
+		if (rc) {
+			rte_flow_error_set(error, ENXIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Meter attached to this flow does not exist");
+		}
+	}
+	return rc;
+}
diff --git a/drivers/net/cnxk/cnxk_flow_wrapper.h b/drivers/net/cnxk/cnxk_flow_wrapper.h
new file mode 100644
index 0000000000..506293dd51
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_flow_wrapper.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell.
+ */
+#ifndef __CNXK_FLOW_WRAPPER_H__
+#define __CNXK_FLOW_WRAPPER_H__
+
+#include <rte_flow_driver.h>
+
+struct rte_flow *cnxk_flow_create_wrapper(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+					  const struct rte_flow_item pattern[],
+					  const struct rte_flow_action actions[],
+					  struct rte_flow_error *error);
+int cnxk_flow_destroy_wrapper(struct rte_eth_dev *dev, struct rte_flow *flow,
+			      struct rte_flow_error *error);
+
+int cnxk_flow_info_get_wrapper(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			       struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
+
+#define CNXK_NPC_COUNTERS_MAX 512
+
+#endif /* __CNXK_FLOW_WRAPPER_H__ */
diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build
index 32ff8aadc0..e77ceb8efc 100644
--- a/drivers/net/cnxk/meson.build
+++ b/drivers/net/cnxk/meson.build
@@ -18,6 +18,13 @@ if soc_type != 'cn9k' and soc_type != 'cn10k' and soc_type != 'cn20k'
         soc_type = 'all'
 endif
 
+if soc_type == 'cn10k' or soc_type == 'all'
+    dpdk_conf.set('CNXK_PLATFORM_CN10K', 1)
+elif soc_type == 'cn20k'
+    dpdk_conf.set('CNXK_PLATFORM_CN20K', 1)
+endif
+
+
 sources = files(
         'cnxk_ethdev.c',
         'cnxk_ethdev_cman.c',
@@ -146,9 +153,9 @@ if soc_type == 'cn10k' or soc_type == 'all'
 sources += files(
         'cn10k_ethdev.c',
         'cn10k_ethdev_sec.c',
-        'cn10k_flow.c',
         'cn10k_rx_select.c',
         'cn10k_tx_select.c',
+        'cnxk_flow_wrapper.c',
 )
 
 if host_machine.cpu_family().startswith('aarch') and not disable_template
@@ -238,6 +245,7 @@ sources += files(
         'cn20k_ethdev.c',
         'cn20k_rx_select.c',
         'cn20k_tx_select.c',
+        'cnxk_flow_wrapper.c',
 )
 
 if host_machine.cpu_family().startswith('aarch') and not disable_template
-- 
2.39.2


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

* Re: [dpdk-dev] [PATCH v2 2/2] net/cnxk: support rte flow on cn20k
  2024-10-29  7:31   ` [dpdk-dev] [PATCH v2 2/2] net/cnxk: support rte " psatheesh
@ 2024-11-04 11:29     ` Jerin Jacob
  0 siblings, 0 replies; 8+ messages in thread
From: Jerin Jacob @ 2024-11-04 11:29 UTC (permalink / raw)
  To: psatheesh
  Cc: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra, dev

On Tue, Oct 29, 2024 at 1:01 PM <psatheesh@marvell.com> wrote:
>
> From: Satheesh Paul <psatheesh@marvell.com>
>
> Support for rte flow in cn20k.
>
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>

> index 0000000000..af2eee7266
> --- /dev/null
> +++ b/drivers/net/cnxk/cnxk_flow_wrapper.c
> @@ -0,0 +1,303 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2024 Marvell.
> + */
> +
> +#ifdef CNXK_PLATFORM_CN10K
> +#include "cn10k_ethdev.h"
> +#include "cn10k_rx.h"
> +#endif
> +#ifdef CNXK_PLATFORM_CN20K
> +#include "cn20k_ethdev.h"
> +#include "cn20k_rx.h"
> +#endif
> +#include "cnxk_ethdev_mcs.h"
> +#include "cnxk_flow_wrapper.h"
> +#include <cnxk_flow.h>
> +
> +static void
> +cnxk_eth_set_rx_function(struct rte_eth_dev *eth_dev)
> +{
> +       RTE_SET_USED(eth_dev);
> +#ifdef CNXK_PLATFORM_CN10K
> +       cn10k_eth_set_rx_function(eth_dev);
> +#endif
> +#ifdef CNXK_PLATFORM_CN20K
> +       cn20k_eth_set_rx_function(eth_dev);
> +#endif

Please work to remove compile time macros

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

* [dpdk-dev] [PATCH v3 1/2] common/cnxk: support NPC flow on cn20k
  2024-10-21  4:01 [dpdk-dev] [PATCH 1/2] common/cnxk: support NPC flow on cn20k psatheesh
  2024-10-21  4:01 ` [dpdk-dev] [PATCH 2/2] net/cnxk: support rte " psatheesh
  2024-10-29  7:31 ` [dpdk-dev] [PATCH v2 1/2] common/cnxk: support NPC " psatheesh
@ 2024-11-12  9:58 ` psatheesh
  2024-11-12  9:58   ` [dpdk-dev] [PATCH v3 2/2] net/cnxk: support rte " psatheesh
  2 siblings, 1 reply; 8+ messages in thread
From: psatheesh @ 2024-11-12  9:58 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

ROC changes to support NPC flow on cn20k.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
v2:
* Fixed generic platform compiler error.
v3:
* Removed compile time macros.

 drivers/common/cnxk/roc_mbox.h          | 144 +++++-
 drivers/common/cnxk/roc_nix.h           |  18 +-
 drivers/common/cnxk/roc_nix_mcast.c     |  40 +-
 drivers/common/cnxk/roc_nix_vlan.c      |  66 ++-
 drivers/common/cnxk/roc_npc.c           |  58 ++-
 drivers/common/cnxk/roc_npc.h           |  59 ++-
 drivers/common/cnxk/roc_npc_mcam.c      | 602 +++++++++++++++++++-----
 drivers/common/cnxk/roc_npc_mcam_dump.c | 279 +++++++++--
 drivers/common/cnxk/roc_npc_priv.h      |  91 ++--
 drivers/common/cnxk/roc_npc_utils.c     | 340 ++++++++++---
 drivers/common/cnxk/version.map         |   1 +
 11 files changed, 1325 insertions(+), 373 deletions(-)

diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index e7a916d61c..5328fd768e 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -236,6 +236,22 @@ struct mbox_msghdr {
 	  npc_get_field_hash_info_req, npc_get_field_hash_info_rsp)            \
 	M(NPC_MCAM_GET_HIT_STATUS, 0x6015, npc_mcam_get_hit_status,            \
 	  npc_mcam_get_hit_status_req, npc_mcam_get_hit_status_rsp)            \
+	M(NPC_MCAM_DEFRAG, 0x6016, npc_defrag, msg_req,	msg_rsp)               \
+	M(NPC_CN20K_GET_KEX_CFG, 0x6017, npc_cn20k_get_kex_cfg, msg_req,       \
+	  npc_cn20k_get_kex_cfg_rsp)                                           \
+	M(NPC_CN20K_MCAM_GET_FREE_COUNT, 0x6018, npc_cn20k_get_free_count,     \
+	  msg_req, npc_cn20k_get_free_count_rsp)                               \
+	M(NPC_CN20K_MCAM_WRITE_ENTRY,	0x6019, npc_cn20k_mcam_write_entry,    \
+	  npc_cn20k_mcam_write_entry_req, msg_rsp)	                       \
+	M(NPC_CN20K_MCAM_ALLOC_AND_WRITE_ENTRY, 0x601a,			       \
+	  npc_cn20k_mcam_alloc_and_write_entry,				       \
+	  npc_cn20k_mcam_alloc_and_write_entry_req,			       \
+	  npc_mcam_alloc_and_write_entry_rsp)				       \
+	M(NPC_CN20K_MCAM_READ_ENTRY,	0x601b, npc_cn20k_mcam_read_entry,     \
+	  npc_mcam_read_entry_req, npc_cn20k_mcam_read_entry_rsp)	       \
+	M(NPC_CN20K_MCAM_READ_BASE_RULE, 0x601c,                               \
+	  npc_cn20k_read_base_steer_rule, msg_req,                             \
+	  npc_cn20k_mcam_read_base_rule_rsp)                                   \
 	/* NIX mbox IDs (range 0x8000 - 0xFFFF) */                             \
 	M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, nix_lf_alloc_req,                \
 	  nix_lf_alloc_rsp)                                                    \
@@ -637,7 +653,7 @@ struct cgx_mac_addr_add_req {
  */
 struct cgx_mac_addr_add_rsp {
 	struct mbox_msghdr hdr;
-	uint8_t __io index;
+	uint32_t __io index;
 };
 
 /* Structure for requesting the operation to
@@ -645,7 +661,7 @@ struct cgx_mac_addr_add_rsp {
  */
 struct cgx_mac_addr_del_req {
 	struct mbox_msghdr hdr;
-	uint8_t __io index;
+	uint32_t __io index;
 };
 
 /* Structure for response against the operation to
@@ -653,7 +669,7 @@ struct cgx_mac_addr_del_req {
  */
 struct cgx_max_dmac_entries_get_rsp {
 	struct mbox_msghdr hdr;
-	uint8_t __io max_dmac_filters;
+	uint32_t __io max_dmac_filters;
 };
 
 struct cgx_link_user_info {
@@ -2433,6 +2449,14 @@ enum npc_af_status {
 	NPC_MCAM_ALLOC_FAILED = -703,
 	NPC_MCAM_PERM_DENIED = -704,
 	NPC_AF_ERR_HIGIG_CONFIG_FAIL = -705,
+	NPC_AF_ERR_HIGIG_NOT_SUPPORTED = -706,
+	NPC_FLOW_INTF_INVALID = -707,
+	NPC_FLOW_CHAN_INVALID = -708,
+	NPC_FLOW_NO_NIXLF = -709,
+	NPC_FLOW_NOT_SUPPORTED = -710,
+	NPC_FLOW_VF_PERM_DENIED = -711,
+	NPC_FLOW_VF_NOT_INIT = -712,
+	NPC_FLOW_VF_OVERLAP = -713,
 };
 
 struct npc_mcam_alloc_entry_req {
@@ -2442,9 +2466,12 @@ struct npc_mcam_alloc_entry_req {
 #define NPC_MCAM_ANY_PRIO    0
 #define NPC_MCAM_LOWER_PRIO  1
 #define NPC_MCAM_HIGHER_PRIO 2
-	uint8_t __io priority; /* Lower or higher w.r.t ref_entry */
+	uint8_t __io ref_priority; /* Lower or higher w.r.t ref_entry */
 	uint16_t __io ref_entry;
 	uint16_t __io count; /* Number of entries requested */
+	uint8_t __io kw_type; /* Key type */
+	uint8_t __io virt;    /* Request virtual index */
+	uint16_t __io rsvd[16];	/* Reserved */
 };
 
 struct npc_mcam_alloc_entry_rsp {
@@ -2456,6 +2483,7 @@ struct npc_mcam_alloc_entry_rsp {
 	uint16_t __io count;	  /* Number of entries allocated */
 	uint16_t __io free_count; /* Number of entries available */
 	uint16_t __io entry_list[NPC_MAX_NONCONTIG_ENTRIES];
+	uint16_t __io rsvd[16];	/* Reserved */
 };
 
 struct npc_mcam_free_entry_req {
@@ -2482,6 +2510,26 @@ struct npc_mcam_write_entry_req {
 	uint8_t __io set_cntr;	   /* Set counter for this entry ? */
 };
 
+struct cn20k_mcam_entry {
+#define NPC_CN20K_MAX_KWS_IN_KEY 8 /* Number of keywords in max keywidth */
+	uint64_t __io kw[NPC_CN20K_MAX_KWS_IN_KEY];
+	uint64_t __io kw_mask[NPC_CN20K_MAX_KWS_IN_KEY];
+	uint64_t __io action;
+	uint64_t __io vtag_action;
+};
+
+struct npc_cn20k_mcam_write_entry_req {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint16_t __io entry;	   /* MCAM entry to write this match key */
+	uint16_t __io cntr;	   /* Counter for this MCAM entry */
+	uint8_t __io intf;	   /* Rx or Tx interface */
+	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
+	uint8_t __io hw_prio;	   /* hardware priority, valid for cn20k */
+	uint8_t __io req_kw_type;  /* Type of kw which should be written */
+	uint64_t __io reserved;	   /* reserved for future use */
+};
+
 /* Enable/Disable a given entry */
 struct npc_mcam_ena_dis_entry_req {
 	struct mbox_msghdr hdr;
@@ -2541,12 +2589,25 @@ struct npc_mcam_alloc_and_write_entry_req {
 	struct mbox_msghdr hdr;
 	struct mcam_entry entry_data;
 	uint16_t __io ref_entry;
-	uint8_t __io priority;	   /* Lower or higher w.r.t ref_entry */
+	uint8_t __io ref_priority; /* Lower or higher w.r.t ref_entry */
 	uint8_t __io intf;	   /* Rx or Tx interface */
 	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
 	uint8_t __io alloc_cntr;   /* Allocate counter and map ? */
 };
 
+struct npc_cn20k_mcam_alloc_and_write_entry_req {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint16_t __io ref_entry;
+	uint8_t __io ref_prio;	   /* Lower or higher w.r.t ref_entry */
+	uint8_t __io intf;	   /* Rx or Tx interface */
+	uint8_t __io enable_entry; /* Enable this MCAM entry ? */
+	uint8_t __io hw_prio;	   /* hardware priority, valid for cn20k */
+	uint8_t __io virt;	   /* Allocate virtual index */
+	uint8_t __io req_kw_type;  /* Key type to be written */
+	uint16_t __io reserved[4]; /* reserved for future use */
+};
+
 struct npc_mcam_alloc_and_write_entry_rsp {
 	struct mbox_msghdr hdr;
 	uint16_t __io entry;
@@ -2573,6 +2634,48 @@ struct npc_get_kex_cfg_rsp {
 	uint8_t __io mkex_pfl_name[MKEX_NAME_LEN];
 };
 
+struct npc_delete_flow_rsp {
+	struct mbox_msghdr hdr;
+	uint16_t __io cntr_val;
+};
+
+/* Available entries to use */
+struct npc_cn20k_get_free_count_rsp {
+	struct mbox_msghdr hdr;
+	int __io free_x2;
+	int __io free_x4;
+	int __io free_subbanks;
+};
+
+struct npc_cn20k_get_kex_cfg_rsp {
+	struct mbox_msghdr hdr;
+	uint64_t __io rx_keyx_cfg; /* NPC_AF_INTF(0)_KEX_CFG */
+	uint64_t __io tx_keyx_cfg; /* NPC_AF_INTF(1)_KEX_CFG */
+#define NPC_MAX_EXTRACTOR 24
+	/* MKEX Extractor data */
+	uint64_t __io intf_extr[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
+	/* KEX configuration per extractor */
+	uint64_t __io intf_extr_lt[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
+#define MKEX_NAME_LEN 128
+	uint8_t __io mkex_pfl_name[MKEX_NAME_LEN];
+};
+
+struct npc_get_field_hash_info_req {
+	struct mbox_msghdr hdr;
+	uint8_t intf;
+};
+
+struct npc_get_field_hash_info_rsp {
+	struct mbox_msghdr hdr;
+	uint64_t __io secret_key[3];
+#define NPC_MAX_HASH	  2
+#define NPC_MAX_HASH_MASK 2
+	/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
+	uint64_t __io hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
+	/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
+	uint64_t __io hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
+};
+
 enum header_fields {
 	NPC_DMAC,
 	NPC_SMAC,
@@ -2662,6 +2765,8 @@ struct npc_install_flow_req {
 	uint8_t __io vtag1_op;
 	/* old counter value */
 	uint16_t __io cntr_val;
+	/* hardware priority, supported for cn20k */
+	uint8_t __io hw_prio;
 };
 
 struct npc_install_flow_rsp {
@@ -2692,11 +2797,24 @@ struct npc_mcam_read_entry_rsp {
 	uint8_t __io enable;
 };
 
+struct npc_cn20k_mcam_read_entry_rsp {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry_data;
+	uint8_t __io intf;
+	uint8_t __io enable;
+	uint8_t __io hw_prio; /* valid for cn20k */
+};
+
 struct npc_mcam_read_base_rule_rsp {
 	struct mbox_msghdr hdr;
 	struct mcam_entry entry_data;
 };
 
+struct npc_cn20k_mcam_read_base_rule_rsp {
+	struct mbox_msghdr hdr;
+	struct cn20k_mcam_entry entry;
+};
+
 struct npc_mcam_get_stats_req {
 	struct mbox_msghdr hdr;
 	uint16_t __io entry; /* mcam entry */
@@ -2776,22 +2894,6 @@ enum tim_gpio_edge {
 	TIM_GPIO_INVALID,
 };
 
-struct npc_get_field_hash_info_req {
-	struct mbox_msghdr hdr;
-	uint8_t intf;
-};
-
-struct npc_get_field_hash_info_rsp {
-	struct mbox_msghdr hdr;
-	uint64_t __io secret_key[3];
-#define NPC_MAX_HASH	  2
-#define NPC_MAX_HASH_MASK 2
-	/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
-	uint64_t __io hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
-	/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
-	uint64_t __io hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
-};
-
 enum ptp_op {
 	PTP_OP_ADJFINE = 0,   /* adjfine(req.scaled_ppm); */
 	PTP_OP_GET_CLOCK = 1, /* rsp.clk = get_clock() */
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index f213823b9b..15823ab16c 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -983,15 +983,11 @@ bool __roc_api roc_nix_ptp_is_enable(struct roc_nix *roc_nix);
 /* VLAN */
 int __roc_api
 roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
-			     struct npc_mcam_read_entry_rsp **rsp);
-int __roc_api roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix,
-					    uint32_t index,
-					    struct mcam_entry *entry,
+			     void **rsp);
+int __roc_api roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index, void *entry,
 					    uint8_t intf, uint8_t enable);
-int __roc_api roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix,
-						      struct mcam_entry *entry,
-						      uint8_t intf,
-						      uint8_t priority,
+int __roc_api roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix, void *entry,
+						      uint8_t intf, uint8_t priority,
 						      uint8_t ref_entry);
 int __roc_api roc_nix_vlan_mcam_entry_free(struct roc_nix *roc_nix,
 					   uint32_t index);
@@ -1012,10 +1008,8 @@ int __roc_api roc_nix_mcast_mcam_entry_alloc(struct roc_nix *roc_nix,
 					     uint16_t index[]);
 int __roc_api roc_nix_mcast_mcam_entry_free(struct roc_nix *roc_nix,
 					    uint32_t index);
-int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
-					     struct mcam_entry *entry,
-					     uint32_t index, uint8_t intf,
-					     uint64_t action);
+int __roc_api roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix, void *entry, uint32_t index,
+					     uint8_t intf, uint64_t action);
 int __roc_api roc_nix_mcast_mcam_entry_ena_dis(struct roc_nix *roc_nix, uint32_t index,
 					       bool enable);
 int __roc_api roc_nix_mcast_list_setup(struct mbox *mbox, uint8_t intf, int nb_entries,
diff --git a/drivers/common/cnxk/roc_nix_mcast.c b/drivers/common/cnxk/roc_nix_mcast.c
index 615014e820..eab4bde743 100644
--- a/drivers/common/cnxk/roc_nix_mcast.c
+++ b/drivers/common/cnxk/roc_nix_mcast.c
@@ -19,7 +19,7 @@ roc_nix_mcast_mcam_entry_alloc(struct roc_nix *roc_nix, uint16_t nb_entries,
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
 	if (req == NULL)
 		goto exit;
-	req->priority = priority;
+	req->ref_priority = priority;
 	req->count = nb_entries;
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -56,24 +56,38 @@ roc_nix_mcast_mcam_entry_free(struct roc_nix *roc_nix, uint32_t index)
 }
 
 int
-roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix,
-			       struct mcam_entry *entry, uint32_t index,
-			       uint8_t intf, uint64_t action)
+roc_nix_mcast_mcam_entry_write(struct roc_nix *roc_nix, void *entry, uint32_t index, uint8_t intf,
+			       uint64_t action)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
-	struct npc_mcam_write_entry_req *req;
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->entry = index;
-	req->intf = intf;
-	req->enable_entry = true;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
-	req->entry_data.action = action;
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+		req->entry_data.action = action;
+
+	} else {
+		struct npc_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+		req->entry_data.action = action;
+	}
 
 	rc = mbox_process(mbox);
 exit:
diff --git a/drivers/common/cnxk/roc_nix_vlan.c b/drivers/common/cnxk/roc_nix_vlan.c
index db218593ad..16100eb5d6 100644
--- a/drivers/common/cnxk/roc_nix_vlan.c
+++ b/drivers/common/cnxk/roc_nix_vlan.c
@@ -7,7 +7,7 @@
 
 int
 roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
-			     struct npc_mcam_read_entry_rsp **rsp)
+			     void **rsp)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
@@ -27,24 +27,34 @@ roc_nix_vlan_mcam_entry_read(struct roc_nix *roc_nix, uint32_t index,
 }
 
 int
-roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index,
-			      struct mcam_entry *entry, uint8_t intf,
+roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index, void *entry, uint8_t intf,
 			      uint8_t enable)
 {
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
 	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
 	struct msghdr *rsp;
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->entry = index;
-	req->intf = intf;
-	req->enable_entry = enable;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (cn20k_req == NULL)
+			goto exit;
+		cn20k_req->entry = index;
+		cn20k_req->intf = intf;
+		cn20k_req->enable_entry = enable;
+		mbox_memcpy(&cn20k_req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+	} else {
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->entry = index;
+		req->intf = intf;
+		req->enable_entry = enable;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 exit:
@@ -53,25 +63,39 @@ roc_nix_vlan_mcam_entry_write(struct roc_nix *roc_nix, uint32_t index,
 }
 
 int
-roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix,
-					struct mcam_entry *entry, uint8_t intf,
+roc_nix_vlan_mcam_entry_alloc_and_write(struct roc_nix *roc_nix, void *entry, uint8_t intf,
 					uint8_t priority, uint8_t ref_entry)
 {
-	struct npc_mcam_alloc_and_write_entry_req *req;
 	struct npc_mcam_alloc_and_write_entry_rsp *rsp;
 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
 	struct dev *dev = &nix->dev;
 	struct mbox *mbox = mbox_get(dev->mbox);
 	int rc = -ENOSPC;
 
-	req = mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
-	if (req == NULL)
-		goto exit;
-	req->priority = priority;
-	req->ref_entry = ref_entry;
-	req->intf = intf;
-	req->enable_entry = true;
-	mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_alloc_and_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_alloc_and_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->ref_prio = priority;
+		req->ref_entry = ref_entry;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct cn20k_mcam_entry));
+
+	} else {
+		struct npc_mcam_alloc_and_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_alloc_and_write_entry(mbox);
+		if (req == NULL)
+			goto exit;
+		req->ref_priority = priority;
+		req->ref_entry = ref_entry;
+		req->intf = intf;
+		req->enable_entry = true;
+		mbox_memcpy(&req->entry_data, entry, sizeof(struct mcam_entry));
+	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c
index 53f278c764..138f12f6d8 100644
--- a/drivers/common/cnxk/roc_npc.c
+++ b/drivers/common/cnxk/roc_npc.c
@@ -100,6 +100,14 @@ roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, uint64_t *co
 	return npc_mcam_read_counter(npc->mbox, ctr_id, count);
 }
 
+int
+roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow, uint64_t *count)
+{
+	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
+
+	return npc_mcam_get_stats(npc->mbox, flow, count);
+}
+
 int
 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id)
 {
@@ -221,7 +229,9 @@ roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc)
 {
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
 
-	if (roc_model_is_cn10k())
+	if (roc_model_is_cn20k())
+		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
+	else if (roc_model_is_cn10k())
 		return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1);
 	else if (roc_model_is_cn98xx())
 		return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1);
@@ -235,7 +245,9 @@ npc_mcam_tot_entries(void)
 	/* FIXME: change to reading in AF from NPC_AF_CONST1/2
 	 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS
 	 */
-	if (roc_model_is_cn10k() || roc_model_is_cn98xx())
+	if (roc_model_is_cn20k())
+		return 2 * 8192; /* MCAM_BANKS = 2, BANK_DEPTH_EXT = 8192 */
+	else if (roc_model_is_cn10k() || roc_model_is_cn98xx())
 		return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */
 	else
 		return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */
@@ -311,6 +323,7 @@ roc_npc_init(struct roc_npc *roc_npc)
 
 	npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX];
 	nix->exact_match_ena = npc->exact_match_ena;
+	roc_npc->max_entries = npc->mcam_entries;
 
 	/* Free, free_rev, live and live_rev entries */
 	bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries);
@@ -1856,9 +1869,7 @@ roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc, int rep_port_id)
 int
 roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_flow *flow)
 {
-	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 	struct npc *npc = roc_npc_to_npc_priv(roc_npc);
-	struct mcam_entry *base_entry;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int idx, rc;
 
@@ -1868,17 +1879,36 @@ roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, struct roc_npc_fl
 	}
 
 	(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
-	rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
-	if (rc) {
-		plt_err("Failed to fetch VF's base MCAM entry");
-		goto exit;
-	}
-	base_entry = &base_rule_rsp->entry_data;
-	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		flow->mcam_data[idx] |= base_entry->kw[idx];
-		flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
-	}
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
+		struct cn20k_mcam_entry *base_entry;
 
+		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+		if (rc) {
+			plt_err("Failed to fetch VF's base MCAM entry");
+			goto exit;
+		}
+		base_entry = &base_rule_rsp->entry;
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			flow->mcam_data[idx] |= base_entry->kw[idx];
+			flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+		}
+
+	} else {
+		struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
+		struct mcam_entry *base_entry;
+
+		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+		if (rc) {
+			plt_err("Failed to fetch VF's base MCAM entry");
+			goto exit;
+		}
+		base_entry = &base_rule_rsp->entry_data;
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			flow->mcam_data[idx] |= base_entry->kw[idx];
+			flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+		}
+	}
 	rc = 0;
 exit:
 	mbox_put(mbox);
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index bf8c65aa9c..b96862e054 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -305,52 +305,58 @@ struct roc_npc_spi_to_sa_action_info {
 };
 
 struct mbox;
-
 struct roc_npc_flow {
 	uint8_t nix_intf;
 	uint8_t enable;
-	uint32_t mcam_id;
 	uint8_t use_ctr;
+	bool is_validate;
+	uint32_t mcam_id;
+	uint16_t tx_pf_func;
+	bool has_age_action;
+	bool rep_act_rep;
 	int32_t ctr_id;
 	uint32_t priority;
 	uint32_t mtr_id;
+#if defined(ROC_PLATFORM_CN20K)
+#define ROC_NPC_MAX_MCAM_WIDTH_DWORDS 8
+#define ROC_NPC_MAX_MCAM_PRIORITY     123
+#else
 #define ROC_NPC_MAX_MCAM_WIDTH_DWORDS 7
+#define ROC_NPC_MAX_MCAM_PRIORITY     32
+#endif
 	/* Contiguous match string */
 	uint64_t mcam_data[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t npc_action;
 	uint64_t vtag_action;
 	bool vtag_insert_enabled;
-	uint8_t vtag_insert_count;
+	int8_t vtag_insert_count;
 #define ROC_NPC_MAX_FLOW_PATTERNS 32
 	struct roc_npc_flow_dump_data dump_data[ROC_NPC_MAX_FLOW_PATTERNS];
 	uint16_t num_patterns;
 	struct roc_npc_spi_to_sa_action_info spi_to_sa_info;
-	uint16_t tx_pf_func;
-	bool is_validate;
 	uint16_t match_id;
 	uint8_t is_inline_dev;
 	bool use_pre_alloc;
 	uint64_t timeout_cycles;
 	void *age_context;
-	uint32_t timeout;
-	bool has_age_action;
-	uint16_t rep_pf_func;
 	uint16_t rep_act_pf_func;
-	bool rep_act_rep;
+	bool is_rep_vf;
+	bool has_rep;
+	bool is_sampling_rule;
+	uint16_t rep_pf_func;
+#define ROC_NPC_MIRROR_LIST_SIZE 2
+	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
 	uint16_t rep_channel;
 	struct mbox *rep_mbox;
-	bool has_rep;
-	bool is_rep_vf;
 	struct npc *rep_npc;
 	int port_id;
-	bool is_sampling_rule;
+	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
 	uint32_t recv_queue;
 	uint32_t mcast_grp_index;
 	uint32_t mce_start_index;
-#define ROC_NPC_MIRROR_LIST_SIZE 2
-	uint16_t mcast_pf_funcs[ROC_NPC_MIRROR_LIST_SIZE];
-	uint16_t mcast_channels[ROC_NPC_MIRROR_LIST_SIZE];
+	uint8_t key_type;
+	uint32_t timeout;
 
 	TAILQ_ENTRY(roc_npc_flow) next;
 };
@@ -400,33 +406,34 @@ struct roc_npc {
 	struct roc_nix *roc_nix;
 	uint8_t switch_header_type;
 	uint8_t pre_l2_size_offset;	 /**< Offset with in header that holds
-					   * size of custom header
-					   */
+					  * size of custom header
+					  */
 	uint8_t pre_l2_size_offset_mask; /**< Offset mask with in header
-					   * that holds size of custom header
-					   */
+					  * that holds size of custom header
+					  */
 	uint8_t pre_l2_size_shift_dir;	 /**< Shift direction to calculate size
-					   */
+					  */
 	uint16_t flow_prealloc_size;
 	uint16_t flow_max_priority;
 	uint16_t channel;
 	uint16_t pf_func;
+	bool is_sdp_mask_set;
+	bool rep_act_rep;
+	uint16_t sdp_channel_mask;
 	uint64_t kex_capability;
 	uint64_t rx_parse_nibble;
 	/* Parsed RSS Flowkey cfg for current flow being created */
 	uint32_t flowkey_cfg_state;
-	bool is_sdp_mask_set;
+	uint32_t max_entries;
+	uint16_t rep_act_pf_func;
 	uint16_t sdp_channel;
-	uint16_t sdp_channel_mask;
 	struct roc_npc_flow_age flow_age;
 	struct roc_npc *rep_npc;
 	uint16_t rep_pf_func;
 	uint16_t rep_rx_channel;
-	uint16_t rep_act_pf_func;
-	bool rep_act_rep;
 	int rep_port_id;
 
-#define ROC_NPC_MEM_SZ (6 * 1024)
+#define ROC_NPC_MEM_SZ (20 * 1024)
 	uint8_t reserved[ROC_NPC_MEM_SZ];
 } __plt_cache_aligned;
 
@@ -482,4 +489,6 @@ int __roc_api roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint1
 void *__roc_api roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id);
 void __roc_api roc_npc_sdp_channel_get(struct roc_npc *roc_npc, uint16_t *chan_base,
 				       uint16_t *chan_mask);
+int __roc_api roc_npc_mcam_get_stats(struct roc_npc *roc_npc, struct roc_npc_flow *flow,
+				     uint64_t *count);
 #endif /* _ROC_NPC_H_ */
diff --git a/drivers/common/cnxk/roc_npc_mcam.c b/drivers/common/cnxk/roc_npc_mcam.c
index cdb9db1383..412b2611b7 100644
--- a/drivers/common/cnxk/roc_npc_mcam.c
+++ b/drivers/common/cnxk/roc_npc_mcam.c
@@ -11,6 +11,10 @@ npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr)
 	struct npc_mcam_alloc_counter_rsp *rsp;
 	int rc = -ENOSPC;
 
+	/* For CN20K, counters are enabled by default */
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_alloc_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -30,6 +34,9 @@ npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
 	struct npc_mcam_oper_counter_req *req;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_free_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -40,6 +47,30 @@ npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id)
 	return rc;
 }
 
+int
+npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count)
+{
+	struct npc_mcam_get_stats_req *req;
+	struct npc_mcam_get_stats_rsp *rsp;
+	int rc = -ENOSPC;
+
+	/* valid only for cn20k */
+	if (!roc_model_is_cn20k())
+		return 0;
+
+	req = mbox_alloc_msg_npc_mcam_entry_stats(mbox_get(mbox));
+	if (req == NULL)
+		goto exit;
+	req->entry = flow->mcam_id;
+	rc = mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		goto exit;
+	*count = rsp->stat;
+exit:
+	mbox_put(mbox);
+	return rc;
+}
+
 int
 npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
 {
@@ -47,6 +78,9 @@ npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count)
 	struct npc_mcam_oper_counter_rsp *rsp;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_counter_stats(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -66,6 +100,9 @@ npc_mcam_clear_counter(struct mbox *mbox, uint32_t ctr_id)
 	struct npc_mcam_oper_counter_req *req;
 	int rc = -ENOSPC;
 
+	if (roc_model_is_cn20k())
+		return 0;
+
 	req = mbox_alloc_msg_npc_mcam_clear_counter(mbox_get(mbox));
 	if (req == NULL)
 		goto exit;
@@ -132,16 +169,53 @@ npc_lid_lt_in_kex(struct npc *npc, uint8_t lid, uint8_t lt)
 	struct npc_xtract_info *x_info;
 	int i;
 
-	for (i = 0; i < NPC_MAX_LD; i++) {
-		x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
-		/* Check for LDATA */
-		if (x_info->enable && x_info->len > 0)
-			return true;
+	if (!roc_model_is_cn20k()) {
+		for (i = 0; i < NPC_MAX_LD; i++) {
+			x_info = &npc->prx_dxcfg[NIX_INTF_RX][lid][lt].xtract[i];
+			/* Check for LDATA */
+			if (x_info->enable && x_info->len > 0)
+				return true;
+		}
+	} else {
+		for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
+			union npc_kex_ldata_flags_cfg *lid_info = &npc->lid_cfg[NIX_INTF_RX][i];
+
+			if (lid_info->s.lid != lid)
+				continue;
+			x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
+			/* Check for LDATA */
+			if (x_info->enable && x_info->len > 0)
+				return true;
+		}
 	}
 
 	return false;
 }
 
+static void
+npc_construct_ldata_mask_cn20k(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt)
+{
+	struct npc_xtract_info *x_info;
+	int hdr_off, keylen;
+	int i, j;
+
+	for (i = 0; i < NPC_MAX_EXTRACTOR; i++) {
+		union npc_kex_ldata_flags_cfg *lid_conf = &npc->lid_cfg[NIX_INTF_RX][i];
+
+		if (lid_conf->s.lid != lid)
+			continue;
+
+		x_info = &npc->prx_dxcfg_cn20k[NIX_INTF_RX][i][lt].xtract;
+		if (x_info->enable == 0)
+			continue;
+
+		hdr_off = x_info->hdr_off * 8;
+		keylen = x_info->len * 8;
+		for (j = hdr_off; j < (hdr_off + keylen); j++)
+			plt_bitmap_set(bmap, j);
+	}
+}
+
 static void
 npc_construct_ldata_mask(struct npc *npc, struct plt_bitmap *bmap, uint8_t lid, uint8_t lt,
 			 uint8_t ld)
@@ -220,8 +294,12 @@ npc_is_kex_enabled(struct npc *npc, uint8_t lid, uint8_t lt, int offset, int len
 		return false;
 	}
 
-	npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
-	npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
+	if (!roc_model_is_cn20k()) {
+		npc_construct_ldata_mask(npc, bmap, lid, lt, 0);
+		npc_construct_ldata_mask(npc, bmap, lid, lt, 1);
+	} else {
+		npc_construct_ldata_mask_cn20k(npc, bmap, lid, lt);
+	}
 
 	for (i = offset; i < (offset + len); i++) {
 		if (plt_bitmap_get(bmap, i) != 0x1) {
@@ -330,7 +408,7 @@ npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int re
 		goto exit;
 	req->contig = is_conti;
 	req->count = req_count;
-	req->priority = prio;
+	req->ref_priority = prio;
 	req->ref_entry = ref_mcam;
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -349,11 +427,11 @@ npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int re
 
 int
 npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
-		     int prio, int *resp_count)
+		     uint8_t prio, int *resp_count)
 {
+	struct mbox *mbox = mbox_get(npc->mbox);
 	struct npc_mcam_alloc_entry_req *req;
 	struct npc_mcam_alloc_entry_rsp *rsp;
-	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = -ENOSPC;
 
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox);
@@ -361,16 +439,16 @@ npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_
 		goto exit;
 	req->contig = 1;
 	req->count = 1;
-	req->priority = prio;
-	req->ref_entry = ref_mcam->mcam_id;
-
+	req->ref_priority = prio;
+	req->ref_entry = ref_mcam ? ref_mcam->mcam_id : 0;
+	req->kw_type = mcam->key_type;
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		goto exit;
-	memset(mcam, 0, sizeof(struct roc_npc_flow));
 	mcam->mcam_id = rsp->entry;
-	mcam->nix_intf = ref_mcam->nix_intf;
+	mcam->nix_intf = ref_mcam ? ref_mcam->nix_intf : 0;
 	*resp_count = rsp->count;
+
 	rc = 0;
 exit:
 	mbox_put(mbox);
@@ -403,6 +481,7 @@ int
 npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
 {
 	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
 	struct mbox_msghdr *rsp;
 	int rc = -ENOSPC;
 	uint16_t ctr = 0;
@@ -419,33 +498,121 @@ npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam)
 			return rc;
 	}
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
-	if (req == NULL) {
-		mbox_put(mbox);
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
+		if (cn20k_req == NULL) {
+			mbox_put(mbox);
+			if (mcam->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
+
+			return rc;
+		}
+		cn20k_req->entry = mcam->mcam_id;
+		cn20k_req->intf = mcam->nix_intf;
+		cn20k_req->enable_entry = mcam->enable;
+		cn20k_req->entry_data.action = mcam->npc_action;
+		cn20k_req->entry_data.vtag_action = mcam->vtag_action;
+		cn20k_req->hw_prio = mcam->priority;
 		if (mcam->use_ctr)
-			npc_mcam_free_counter(mbox, ctr);
+			cn20k_req->cntr = mcam->ctr_id;
 
-		return rc;
-	}
-	req->entry = mcam->mcam_id;
-	req->intf = mcam->nix_intf;
-	req->enable_entry = mcam->enable;
-	req->entry_data.action = mcam->npc_action;
-	req->entry_data.vtag_action = mcam->vtag_action;
-	if (mcam->use_ctr) {
-		req->set_cntr = 1;
-		req->cntr = mcam->ctr_id;
-	}
+		for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
+			cn20k_req->entry_data.kw[i] = mcam->mcam_data[i];
+			cn20k_req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+		}
+	} else {
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
+		if (req == NULL) {
+			mbox_put(mbox);
+			if (mcam->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
 
-	for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
-		req->entry_data.kw[i] = mcam->mcam_data[i];
-		req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+			return rc;
+		}
+		req->entry = mcam->mcam_id;
+		req->intf = mcam->nix_intf;
+		req->enable_entry = mcam->enable;
+		req->entry_data.action = mcam->npc_action;
+		req->entry_data.vtag_action = mcam->vtag_action;
+		if (mcam->use_ctr) {
+			req->set_cntr = 1;
+			req->cntr = mcam->ctr_id;
+		}
+
+		for (i = 0; i < NPC_MCAM_KEY_X4_WORDS; i++) {
+			req->entry_data.kw[i] = mcam->mcam_data[i];
+			req->entry_data.kw_mask[i] = mcam->mcam_mask[i];
+		}
 	}
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	mbox_put(mbox);
 	return rc;
 }
 
+static void
+npc_mcam_kex_cfg_dump(struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
+{
+	for (int i = 0; i < NPC_MAX_INTF; i++) {
+		for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+			if (kex_rsp->intf_extr[i][j] == 0)
+				continue;
+			plt_info("Intf %d, Extr %d: 0x%" PRIx64, i, j, kex_rsp->intf_extr[i][j]);
+		}
+	}
+
+	for (int i = 0; i < NPC_MAX_INTF; i++) {
+		for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+			for (int k = 0; k < NPC_MAX_LT; k++) {
+				if (kex_rsp->intf_extr_lt[i][j][k] == 0)
+					continue;
+				plt_info("Intf %d, Extr %d, LT %d: 0x%" PRIx64, i, j, k,
+					 kex_rsp->intf_extr_lt[i][j][k]);
+			}
+		}
+	}
+}
+
+static void
+npc_mcam_process_mkex_cfg_cn20k(struct npc *npc, struct npc_cn20k_get_kex_cfg_rsp *kex_rsp)
+{
+	volatile uint64_t(*q)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR][NPC_MAX_LT];
+	volatile uint64_t(*d)[NPC_MAX_INTF][NPC_MAX_EXTRACTOR];
+	struct npc_xtract_info *x_info = NULL;
+	union npc_kex_ldata_flags_cfg *ld_info = NULL;
+	int ex, lt, ix;
+	npc_dxcfg_cn20k_t *p;
+	npc_lid_cn20k_t *l;
+	uint64_t keyw;
+	uint64_t val;
+
+	npc->keyx_supp_nmask[NPC_MCAM_RX] = kex_rsp->rx_keyx_cfg & 0x7fffffffULL;
+	npc->keyx_supp_nmask[NPC_MCAM_TX] = kex_rsp->tx_keyx_cfg & 0x7fffffffULL;
+	npc->keyx_len[NPC_MCAM_RX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_RX]);
+	npc->keyx_len[NPC_MCAM_TX] = npc_supp_key_len(npc->keyx_supp_nmask[NPC_MCAM_TX]);
+
+	keyw = (kex_rsp->rx_keyx_cfg >> 32) & 0x7ULL;
+	npc->keyw[NPC_MCAM_RX] = keyw;
+	keyw = (kex_rsp->tx_keyx_cfg >> 32) & 0x7ULL;
+	npc->keyw[NPC_MCAM_TX] = keyw;
+
+	p = &npc->prx_dxcfg_cn20k;
+	l = &npc->lid_cfg;
+	q = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR][NPC_MAX_LT])(&kex_rsp->intf_extr_lt);
+	d = (volatile uint64_t(*)[][NPC_MAX_EXTRACTOR])(&kex_rsp->intf_extr);
+	for (ix = 0; ix < NPC_MAX_INTF; ix++) {
+		for (ex = 0; ex < NPC_MAX_EXTRACTOR; ex++) {
+			val = (*d)[ix][ex];
+			ld_info = &(*l)[ix][ex];
+			ld_info->s.lid = (val & 0x7);
+			for (lt = 0; lt < NPC_MAX_LT; lt++) {
+				x_info = &(*p)[ix][ex][lt].xtract;
+				val = (*q)[ix][ex][lt];
+				npc_update_kex_info(x_info, val);
+			}
+		}
+	}
+}
+
 static void
 npc_mcam_process_mkex_cfg(struct npc *npc, struct npc_get_kex_cfg_rsp *kex_rsp)
 {
@@ -522,20 +689,38 @@ int
 npc_mcam_fetch_kex_cfg(struct npc *npc)
 {
 	struct npc_get_kex_cfg_rsp *kex_rsp;
+	struct npc_cn20k_get_kex_cfg_rsp *kex_rsp_20k;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = 0;
 
-	mbox_alloc_msg_npc_get_kex_cfg(mbox);
-	rc = mbox_process_msg(mbox, (void *)&kex_rsp);
-	if (rc) {
-		plt_err("Failed to fetch NPC KEX config");
-		goto done;
-	}
 
-	mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
+	if (!roc_model_is_cn20k()) {
+		mbox_alloc_msg_npc_get_kex_cfg(mbox);
+		rc = mbox_process_msg(mbox, (void *)&kex_rsp);
+		if (rc) {
+			plt_err("Failed to fetch NPC KEX config");
+			goto done;
+		}
 
-	npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
-	npc_mcam_process_mkex_cfg(npc, kex_rsp);
+		mbox_memcpy((char *)npc->profile_name, kex_rsp->mkex_pfl_name, MKEX_NAME_LEN);
+
+		npc->exact_match_ena = (kex_rsp->rx_keyx_cfg >> 40) & 0xF;
+		npc_mcam_process_mkex_cfg(npc, kex_rsp);
+	} else {
+		mbox_alloc_msg_npc_cn20k_get_kex_cfg(mbox);
+		rc = mbox_process_msg(mbox, (void *)&kex_rsp_20k);
+		if (rc) {
+			plt_err("Failed to fetch NPC KEX config");
+			goto done;
+		}
+
+		mbox_memcpy((char *)npc->profile_name, kex_rsp_20k->mkex_pfl_name, MKEX_NAME_LEN);
+
+		npc->exact_match_ena = (kex_rsp_20k->rx_keyx_cfg >> 40) & 0xF;
+		npc_mcam_process_mkex_cfg_cn20k(npc, kex_rsp_20k);
+		if (npc->enable_debug)
+			npc_mcam_kex_cfg_dump(kex_rsp_20k);
+	}
 
 done:
 	mbox_put(mbox);
@@ -543,7 +728,7 @@ npc_mcam_fetch_kex_cfg(struct npc *npc)
 }
 
 static void
-npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req *req,
+npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_cn20k_mcam_write_entry_req *req,
 		     uint16_t channel, uint16_t chan_mask, bool is_second_pass)
 {
 	uint16_t chan = 0, mask = 0;
@@ -552,6 +737,7 @@ npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req
 	req->entry_data.kw_mask[0] &= ~(GENMASK(11, 0));
 	flow->mcam_data[0] &= ~(GENMASK(11, 0));
 	flow->mcam_mask[0] &= ~(GENMASK(11, 0));
+
 	chan = channel;
 	mask = chan_mask;
 
@@ -579,11 +765,12 @@ npc_mcam_set_channel(struct roc_npc_flow *flow, struct npc_mcam_write_entry_req
 	flow->mcam_mask[0] |= (uint64_t)mask;
 }
 
+#define NPC_PF_FUNC_WIDTH    2
+#define NPC_KEX_PF_FUNC_MASK 0xFFFF
+
 static int
 npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
 {
-#define NPC_PF_FUNC_WIDTH    2
-#define NPC_KEX_PF_FUNC_MASK 0xFFFF
 	uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
 	uint8_t *flow_mcam_data, *flow_mcam_mask;
 	struct npc_lid_lt_xtract_info *xinfo;
@@ -618,10 +805,48 @@ npc_mcam_set_pf_func(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_fun
 	return 0;
 }
 
+static int
+npc_mcam_set_pf_func_cn20k(struct npc *npc, struct roc_npc_flow *flow, uint16_t pf_func)
+{
+	uint16_t nr_bytes, hdr_offset, key_offset, pf_func_offset;
+	struct npc_lid_lt_xtract_info_cn20k *xinfo;
+	uint8_t *flow_mcam_data, *flow_mcam_mask;
+	bool pffunc_found = false;
+	uint16_t mask = 0xFFFF;
+	int i;
+
+	flow_mcam_data = (uint8_t *)flow->mcam_data;
+	flow_mcam_mask = (uint8_t *)flow->mcam_mask;
+
+	xinfo = npc->prx_dxcfg_cn20k[NIX_INTF_TX][NPC_LID_LA];
+
+	for (i = 0; i < NPC_MAX_LT; i++) {
+		nr_bytes = xinfo[i].xtract.len;
+		hdr_offset = xinfo[i].xtract.hdr_off;
+		key_offset = xinfo[i].xtract.key_off;
+
+		if (hdr_offset > 0 || nr_bytes < NPC_PF_FUNC_WIDTH)
+			continue;
+		else
+			pffunc_found = true;
+
+		pf_func_offset = key_offset + nr_bytes - NPC_PF_FUNC_WIDTH;
+		memcpy((void *)&flow_mcam_data[pf_func_offset], (uint8_t *)&pf_func,
+		       NPC_PF_FUNC_WIDTH);
+		memcpy((void *)&flow_mcam_mask[pf_func_offset], (uint8_t *)&mask,
+		       NPC_PF_FUNC_WIDTH);
+	}
+	if (!pffunc_found)
+		return -EINVAL;
+
+	return 0;
+}
+
 int
 npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_parse_state *pst)
 {
-	struct npc_mcam_write_entry_req *req;
+	struct npc_cn20k_mcam_write_entry_req *cn20k_req;
+	struct npc_cn20k_mcam_write_entry_req req;
 	struct nix_inl_dev *inl_dev = NULL;
 	struct mbox *mbox = npc->mbox;
 	struct mbox_msghdr *rsp;
@@ -655,6 +880,12 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 			return rc;
 	}
 
+	if (roc_model_is_cn20k()) {
+		req.hw_prio = flow->priority;
+		flow->key_type = npc_get_key_type(npc, flow);
+		req.req_kw_type = flow->key_type;
+	}
+
 	if (flow->nix_intf == NIX_INTF_RX && flow->is_inline_dev && inl_dev &&
 	    inl_dev->ipsec_index && inl_dev->is_multi_channel) {
 		if (inl_dev->curr_ipsec_idx >= inl_dev->alloc_ipsec_rules)
@@ -672,14 +903,17 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	}
 
 	if (flow->nix_intf == NIX_INTF_TX) {
-		uint16_t pf_func = flow->tx_pf_func;
+		uint16_t pffunc = flow->tx_pf_func;
 
 		if (flow->has_rep)
-			pf_func = flow->rep_pf_func;
+			pffunc = flow->rep_pf_func;
 
-		pf_func = plt_cpu_to_be_16(pf_func);
+		pffunc = plt_cpu_to_be_16(pffunc);
 
-		rc = npc_mcam_set_pf_func(npc, flow, pf_func);
+		if (roc_model_is_cn20k())
+			rc = npc_mcam_set_pf_func_cn20k(npc, flow, pffunc);
+		else
+			rc = npc_mcam_set_pf_func(npc, flow, pffunc);
 		if (rc)
 			return rc;
 	}
@@ -708,20 +942,14 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 		}
 	}
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
-	if (req == NULL) {
-		rc = -ENOSPC;
-		goto exit;
-	}
-	req->set_cntr = flow->use_ctr;
-	req->cntr = flow->ctr_id;
-	req->entry = entry;
+	req.cntr = flow->ctr_id;
+	req.entry = entry;
 
-	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
-	req->enable_entry = 1;
+	req.intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+	req.enable_entry = 1;
 	if (flow->nix_intf == NIX_INTF_RX)
 		flow->npc_action |= (uint64_t)flow->recv_queue << 20;
-	req->entry_data.action = flow->npc_action;
+	req.entry_data.action = flow->npc_action;
 
 	/*
 	 * Driver sets vtag action on per interface basis, not
@@ -735,38 +963,38 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 	 *
 	 * Second approach is used now.
 	 */
-	req->entry_data.vtag_action = flow->vtag_action;
+	req.entry_data.vtag_action = flow->vtag_action;
 
 	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		req->entry_data.kw[idx] = flow->mcam_data[idx];
-		req->entry_data.kw_mask[idx] = flow->mcam_mask[idx];
+		req.entry_data.kw[idx] = flow->mcam_data[idx];
+		req.entry_data.kw_mask[idx] = flow->mcam_mask[idx];
 	}
 
 	if (flow->nix_intf == NIX_INTF_RX) {
 		if (inl_dev && inl_dev->is_multi_channel &&
 		    (flow->npc_action & NIX_RX_ACTIONOP_UCAST_IPSEC)) {
 			pf_func = nix_inl_dev_pffunc_get();
-			req->entry_data.action &= ~(GENMASK(19, 4));
-			req->entry_data.action |= (uint64_t)pf_func << 4;
+			req.entry_data.action &= ~(GENMASK(19, 4));
+			req.entry_data.action |= (uint64_t)pf_func << 4;
 			flow->npc_action &= ~(GENMASK(19, 4));
 			flow->npc_action |= (uint64_t)pf_func << 4;
 
-			npc_mcam_set_channel(flow, req, inl_dev->channel, inl_dev->chan_mask,
+			npc_mcam_set_channel(flow, &req, inl_dev->channel, inl_dev->chan_mask,
 					     false);
 		} else if (flow->has_rep) {
 			pf_func = (flow->rep_act_pf_func == 0) ? flow->rep_pf_func :
 								 flow->rep_act_pf_func;
-			req->entry_data.action &= ~(GENMASK(19, 4));
-			req->entry_data.action |= (uint64_t)pf_func << 4;
+			req.entry_data.action &= ~(GENMASK(19, 4));
+			req.entry_data.action |= (uint64_t)pf_func << 4;
 			flow->npc_action &= ~(GENMASK(19, 4));
 			flow->npc_action |= (uint64_t)pf_func << 4;
-			npc_mcam_set_channel(flow, req, flow->rep_channel, (BIT_ULL(12) - 1),
+			npc_mcam_set_channel(flow, &req, flow->rep_channel, (BIT_ULL(12) - 1),
 					     false);
 		} else if (npc->is_sdp_link) {
-			npc_mcam_set_channel(flow, req, npc->sdp_channel, npc->sdp_channel_mask,
+			npc_mcam_set_channel(flow, &req, npc->sdp_channel, npc->sdp_channel_mask,
 					     pst->is_second_pass_rule);
 		} else {
-			npc_mcam_set_channel(flow, req, npc->channel, (BIT_ULL(12) - 1),
+			npc_mcam_set_channel(flow, &req, npc->channel, (BIT_ULL(12) - 1),
 					     pst->is_second_pass_rule);
 		}
 		/*
@@ -779,25 +1007,66 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 			la_offset *= 4;
 
 			mask = ~((0xfULL << la_offset));
-			req->entry_data.kw[0] &= mask;
-			req->entry_data.kw_mask[0] &= mask;
+			req.entry_data.kw[0] &= mask;
+			req.entry_data.kw_mask[0] &= mask;
 			flow->mcam_data[0] &= mask;
 			flow->mcam_mask[0] &= mask;
 			if (pst->is_second_pass_rule) {
-				req->entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
-				req->entry_data.kw_mask[0] |= (0xFULL << la_offset);
+				req.entry_data.kw[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
+				req.entry_data.kw_mask[0] |= (0xFULL << la_offset);
 				flow->mcam_data[0] |= ((uint64_t)NPC_LT_LA_CPT_HDR) << la_offset;
 				flow->mcam_mask[0] |= (0xFULL << la_offset);
 			} else {
 				/* Mask ltype ETHER (0x2) and CPT_HDR (0xa)  */
-				req->entry_data.kw[0] |= (0x2ULL << la_offset);
-				req->entry_data.kw_mask[0] |= (0x7ULL << la_offset);
+				req.entry_data.kw[0] |= (0x2ULL << la_offset);
+				req.entry_data.kw_mask[0] |= (0x7ULL << la_offset);
 				flow->mcam_data[0] |= (0x2ULL << la_offset);
 				flow->mcam_mask[0] |= (0x7ULL << la_offset);
 			}
 		}
 	}
 
+	if (roc_model_is_cn20k()) {
+		cn20k_req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox_get(mbox));
+		if (cn20k_req == NULL) {
+			mbox_put(mbox);
+			if (flow->use_ctr)
+				npc_mcam_free_counter(mbox, ctr);
+
+			return rc;
+		}
+		cn20k_req->entry = req.entry;
+		cn20k_req->intf = req.intf;
+		cn20k_req->enable_entry = req.enable_entry;
+		cn20k_req->entry_data.action = req.entry_data.action;
+		cn20k_req->entry_data.vtag_action = req.entry_data.vtag_action;
+		cn20k_req->hw_prio = req.hw_prio;
+		cn20k_req->req_kw_type = req.req_kw_type;
+		if (flow->use_ctr)
+			cn20k_req->cntr = req.cntr;
+
+		mbox_memcpy(&cn20k_req->entry_data, &req.entry_data,
+			    sizeof(struct cn20k_mcam_entry));
+	} else {
+		struct npc_mcam_write_entry_req *req_leg;
+
+		req_leg = mbox_alloc_msg_npc_mcam_write_entry(mbox_get(mbox));
+		if (req_leg == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		for (idx = 0; idx < NPC_MAX_KWS_IN_KEY; idx++) {
+			req_leg->entry_data.kw[idx] = req.entry_data.kw[idx];
+			req_leg->entry_data.kw_mask[idx] = req.entry_data.kw_mask[idx];
+		}
+		req_leg->entry = req.entry;
+		req_leg->intf = req.intf;
+		req_leg->enable_entry = req.enable_entry;
+		req_leg->cntr = req.cntr;
+		req_leg->entry_data.action = req.entry_data.action;
+		req_leg->entry_data.vtag_action = req.entry_data.vtag_action;
+		req_leg->set_cntr = flow->use_ctr;
+	}
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc != 0)
 		goto exit;
@@ -810,7 +1079,7 @@ npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow, struct npc_
 
 exit:
 	mbox_put(mbox);
-	if (rc)
+	if (rc && flow->is_sampling_rule)
 		roc_nix_mcast_list_free(npc->mbox, flow->mcast_grp_index);
 	return rc;
 }
@@ -821,9 +1090,14 @@ npc_set_vlan_ltype(struct npc_parse_state *pst)
 	uint64_t val, mask;
 	uint8_t lb_offset;
 
-	lb_offset =
-		plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-				   ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
+	if (roc_model_is_cn20k()) {
+		lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_CN20K_LTYPE_LB_OFFSET) - 1));
+
+	} else {
+		lb_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_LTYPE_LB_OFFSET) - 1));
+	}
 	lb_offset *= 4;
 
 	mask = ~((0xfULL << lb_offset));
@@ -843,9 +1117,14 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	uint8_t lc_offset, lcflag_offset;
 	uint64_t val, mask;
 
-	lc_offset =
-		plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-				   ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
+	if (roc_model_is_cn20k()) {
+		lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_CN20K_LTYPE_LC_OFFSET) - 1));
+
+	} else {
+		lc_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+					   ((1ULL << NPC_LTYPE_LC_OFFSET) - 1));
+	}
 	lc_offset *= 4;
 
 	mask = ~((0xfULL << lc_offset));
@@ -867,8 +1146,14 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 	 * zero in LFLAG.
 	 */
 	if (pst->npc->keyx_supp_nmask[pst->nix_intf] & (1ULL << NPC_LFLAG_LC_OFFSET)) {
-		lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
-					       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+		if (roc_model_is_cn20k()) {
+			lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+						       ((1ULL << NPC_CN20K_LFLAG_LC_OFFSET) - 1));
+
+		} else {
+			lcflag_offset = plt_popcount32(pst->npc->keyx_supp_nmask[pst->nix_intf] &
+						       ((1ULL << NPC_LFLAG_LC_OFFSET) - 1));
+		}
 		lcflag_offset *= 4;
 
 		mask = (0xfULL << lcflag_offset);
@@ -881,14 +1166,12 @@ npc_set_ipv6ext_ltype_mask(struct npc_parse_state *pst)
 int
 npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 {
-	struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
 	/* This is non-LDATA part in search key */
 	uint64_t key_data[2] = {0ULL, 0ULL};
 	uint64_t key_mask[2] = {0ULL, 0ULL};
 	int key_len, bit = 0, index, rc = 0;
 	struct nix_inl_dev *inl_dev = NULL;
 	int intf = pst->flow->nix_intf;
-	struct mcam_entry *base_entry;
 	bool skip_base_rule = false;
 	int off, idx, data_off = 0;
 	uint8_t lid, mask, data;
@@ -908,40 +1191,79 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 	data_off *= 4;
 
 	index = 0;
-	for (lid = 0; lid < NPC_MAX_LID; lid++) {
-		/* Offset in key */
-		off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
-		lt = pst->lt[lid] & 0xf;
-		flags = pst->flags[lid] & 0xff;
+	if (!roc_model_is_cn20k()) {
+		for (lid = 0; lid < NPC_MAX_LID; lid++) {
+			/* Offset in key */
+			off = NPC_PARSE_KEX_S_LID_OFFSET(lid);
+			lt = pst->lt[lid] & 0xf;
+			flags = pst->flags[lid] & 0xff;
 
-		/* NPC_LAYER_KEX_S */
-		layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
+			/* NPC_LAYER_KEX_S */
+			layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x7);
+			if (!layer_info)
+				continue;
 
-		if (layer_info) {
 			for (idx = 0; idx <= 2; idx++) {
-				if (layer_info & (1 << idx)) {
-					if (idx == 2) {
-						data = lt;
-						mask = 0xf;
-					} else if (idx == 1) {
-						data = ((flags >> 4) & 0xf);
-						mask = ((flags >> 4) & 0xf);
-					} else {
-						data = (flags & 0xf);
-						mask = (flags & 0xf);
-					}
-
-					if (data_off >= 64) {
-						data_off = 0;
-						index++;
-					}
-					key_data[index] |= ((uint64_t)data << data_off);
-
-					if (lt == 0)
-						mask = 0;
-					key_mask[index] |= ((uint64_t)mask << data_off);
-					data_off += 4;
+				if (!(layer_info & (1 << idx)))
+					continue;
+
+				if (idx == 2) {
+					data = lt;
+					mask = 0xf;
+				} else if (idx == 1) {
+					data = ((flags >> 4) & 0xf);
+					mask = ((flags >> 4) & 0xf);
+				} else {
+					data = (flags & 0xf);
+					mask = (flags & 0xf);
+				}
+
+				if (data_off >= 64) {
+					data_off = 0;
+					index++;
 				}
+				key_data[index] |= ((uint64_t)data << data_off);
+
+				if (lt == 0)
+					mask = 0;
+				key_mask[index] |= ((uint64_t)mask << data_off);
+				data_off += 4;
+			}
+		}
+	} else {
+		for (lid = 0; lid < NPC_MAX_LID; lid++) {
+			/* Offset in key */
+			off = NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid);
+			lt = pst->lt[lid] & 0xf;
+			flags = pst->flags[lid] & 0xf;
+
+			/* NPC_LAYER_KEX_S */
+			layer_info = ((npc->keyx_supp_nmask[intf] >> off) & 0x3);
+			if (!layer_info)
+				continue;
+
+			for (idx = 0; idx <= 1; idx++) {
+				if (!(layer_info & (1 << idx)))
+					continue;
+
+				if (idx == 1) {
+					data = lt;
+					mask = 0xf;
+				} else {
+					data = (flags & 0xf);
+					mask = (flags & 0xf);
+				}
+
+				if (data_off >= 64) {
+					data_off = 0;
+					index++;
+				}
+				key_data[index] |= ((uint64_t)data << data_off);
+
+				if (lt == 0)
+					mask = 0;
+				key_mask[index] |= ((uint64_t)mask << data_off);
+				data_off += 4;
 			}
 		}
 	}
@@ -971,17 +1293,39 @@ npc_program_mcam(struct npc *npc, struct npc_parse_state *pst, bool mcam_alloc)
 		else
 			mbox = mbox_get(npc->mbox);
 		(void)mbox_alloc_msg_npc_read_base_steer_rule(mbox);
-		rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
-		if (rc) {
+		if (roc_model_is_cn20k()) {
+			struct npc_cn20k_mcam_read_base_rule_rsp *base_rule_rsp;
+			struct cn20k_mcam_entry *base_entry;
+
+			rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+			if (rc) {
+				mbox_put(mbox);
+				plt_err("Failed to fetch VF's base MCAM entry");
+				return rc;
+			}
 			mbox_put(mbox);
-			plt_err("Failed to fetch VF's base MCAM entry");
-			return rc;
-		}
-		mbox_put(mbox);
-		base_entry = &base_rule_rsp->entry_data;
-		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-			pst->flow->mcam_data[idx] |= base_entry->kw[idx];
-			pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			base_entry = &base_rule_rsp->entry;
+			for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+				pst->flow->mcam_data[idx] |= base_entry->kw[idx];
+				pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			}
+
+		} else {
+			struct npc_mcam_read_base_rule_rsp *base_rule_rsp;
+			struct mcam_entry *base_entry;
+
+			rc = mbox_process_msg(mbox, (void *)&base_rule_rsp);
+			if (rc) {
+				mbox_put(mbox);
+				plt_err("Failed to fetch VF's base MCAM entry");
+				return rc;
+			}
+			mbox_put(mbox);
+			base_entry = &base_rule_rsp->entry_data;
+			for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+				pst->flow->mcam_data[idx] |= base_entry->kw[idx];
+				pst->flow->mcam_mask[idx] |= base_entry->kw_mask[idx];
+			}
 		}
 	}
 
diff --git a/drivers/common/cnxk/roc_npc_mcam_dump.c b/drivers/common/cnxk/roc_npc_mcam_dump.c
index ebd2dd69c2..bedf6db37c 100644
--- a/drivers/common/cnxk/roc_npc_mcam_dump.c
+++ b/drivers/common/cnxk/roc_npc_mcam_dump.c
@@ -35,6 +35,33 @@
 #define NIX_TX_VTAGACT_VTAG1_OP_MASK	 GENMASK(45, 44)
 #define NIX_TX_VTAGACT_VTAG1_DEF_MASK	 GENMASK(57, 48)
 
+union npc_rx_parse_nibble_cn20k_u {
+	struct {
+		uint64_t chan : 3;
+		uint64_t errlev : 1;
+		uint64_t errcode : 2;
+		uint64_t l2l3bm : 1;
+		uint64_t laflags : 1;
+		uint64_t latype : 1;
+		uint64_t lbflags : 1;
+		uint64_t lbtype : 1;
+		uint64_t lcflags : 1;
+		uint64_t lctype : 1;
+		uint64_t ldflags : 1;
+		uint64_t ldtype : 1;
+		uint64_t leflags : 1;
+		uint64_t letype : 1;
+		uint64_t lfflags : 1;
+		uint64_t lftype : 1;
+		uint64_t lgflags : 1;
+		uint64_t lgtype : 1;
+		uint64_t lhflags : 1;
+		uint64_t lhtype : 1;
+		uint64_t reserved : 41;
+	} s __plt_packed;
+	uint64_t u;
+};
+
 struct npc_rx_parse_nibble_s {
 	uint16_t chan : 3;
 	uint16_t errlev : 1;
@@ -181,8 +208,135 @@ npc_get_nibbles(struct roc_npc_flow *flow, uint16_t size, uint32_t bit_offset)
 }
 
 static void
-npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
-			     uint64_t parse_nibbles)
+npc_flow_print_parse_nibbles_cn20k(FILE *file, struct roc_npc_flow *flow, uint64_t parse_nibbles)
+{
+	union npc_rx_parse_nibble_cn20k_u rx_parse;
+	uint32_t data, offset = 0;
+
+	rx_parse.u = parse_nibbles;
+
+	if (rx_parse.s.chan) {
+		data = npc_get_nibbles(flow, 3, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_CHAN:%#03X\n", data);
+		offset += 12;
+	}
+
+	if (rx_parse.s.errlev) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRLEV:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse.s.errcode) {
+		data = npc_get_nibbles(flow, 2, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_ERRCODE:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.l2l3bm) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_L2L3_BCAST:%#X\n", data);
+		offset += 4;
+	}
+
+	if (rx_parse.s.laflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.latype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n", ltype_str[NPC_LID_LA][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lbflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lbtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n", ltype_str[NPC_LID_LB][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lcflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lctype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n", ltype_str[NPC_LID_LC][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.ldflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.ldtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n", ltype_str[NPC_LID_LD][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.leflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.letype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n", ltype_str[NPC_LID_LE][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lfflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lftype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n", ltype_str[NPC_LID_LF][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lgflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_FLAGS:%#02X\n", data);
+		offset += 8;
+	}
+
+	if (rx_parse.s.lgtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n", ltype_str[NPC_LID_LG][data]);
+		offset += 4;
+	}
+
+	if (rx_parse.s.lhflags) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_FLAGS:%#02X\n", data);
+	}
+
+	if (rx_parse.s.lhtype) {
+		data = npc_get_nibbles(flow, 1, offset);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n", ltype_str[NPC_LID_LH][data]);
+		offset += 4;
+	}
+}
+
+static void
+npc_flow_print_parse_nibbles_legacy(FILE *file, struct roc_npc_flow *flow, uint64_t parse_nibbles)
 {
 	struct npc_rx_parse_nibble_s *rx_parse;
 	uint32_t data, offset = 0;
@@ -221,8 +375,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->latype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n",
-			ltype_str[NPC_LID_LA][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LA_LTYPE:%s\n", ltype_str[NPC_LID_LA][data]);
 		offset += 4;
 	}
 
@@ -234,8 +387,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lbtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n",
-			ltype_str[NPC_LID_LB][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LB_LTYPE:%s\n", ltype_str[NPC_LID_LB][data]);
 		offset += 4;
 	}
 
@@ -247,8 +399,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lctype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n",
-			ltype_str[NPC_LID_LC][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LC_LTYPE:%s\n", ltype_str[NPC_LID_LC][data]);
 		offset += 4;
 	}
 
@@ -260,8 +411,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->ldtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n",
-			ltype_str[NPC_LID_LD][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LD_LTYPE:%s\n", ltype_str[NPC_LID_LD][data]);
 		offset += 4;
 	}
 
@@ -273,8 +423,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->letype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n",
-			ltype_str[NPC_LID_LE][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LE_LTYPE:%s\n", ltype_str[NPC_LID_LE][data]);
 		offset += 4;
 	}
 
@@ -286,8 +435,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lftype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n",
-			ltype_str[NPC_LID_LF][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LF_LTYPE:%s\n", ltype_str[NPC_LID_LF][data]);
 		offset += 4;
 	}
 
@@ -299,8 +447,7 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lgtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n",
-			ltype_str[NPC_LID_LG][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LG_LTYPE:%s\n", ltype_str[NPC_LID_LG][data]);
 		offset += 4;
 	}
 
@@ -311,15 +458,14 @@ npc_flow_print_parse_nibbles(FILE *file, struct roc_npc_flow *flow,
 
 	if (rx_parse->lhtype) {
 		data = npc_get_nibbles(flow, 1, offset);
-		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n",
-			ltype_str[NPC_LID_LH][data]);
+		fprintf(file, "\tNPC_PARSE_NIBBLE_LH_LTYPE:%s\n", ltype_str[NPC_LID_LH][data]);
 		offset += 4;
 	}
 }
 
 static void
-npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo,
-			  struct roc_npc_flow *flow, int lid, int lt)
+npc_flow_print_xtractinfo(FILE *file, struct npc_xtract_info *lfinfo, struct roc_npc_flow *flow,
+			  int lid, int lt)
 {
 	uint8_t *datastart, *maskstart;
 	int i;
@@ -374,6 +520,7 @@ static void
 npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
 {
 	struct npc_lid_lt_xtract_info *lt_xinfo;
+	struct npc_lid_lt_xtract_info_cn20k *lt_xinfo_cn20k;
 	struct npc_xtract_info *xinfo;
 	uint32_t intf, lid, ld, i;
 	uint64_t parse_nibbles;
@@ -381,19 +528,37 @@ npc_flow_dump_patterns(FILE *file, struct npc *npc, struct roc_npc_flow *flow)
 
 	intf = flow->nix_intf;
 	parse_nibbles = npc->keyx_supp_nmask[intf];
-	npc_flow_print_parse_nibbles(file, flow, parse_nibbles);
-
-	for (i = 0; i < flow->num_patterns; i++) {
-		lid = flow->dump_data[i].lid;
-		ltype = flow->dump_data[i].ltype;
-		lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
-
-		for (ld = 0; ld < NPC_MAX_LD; ld++) {
-			xinfo = &lt_xinfo->xtract[ld];
-			if (!xinfo->enable)
-				continue;
-			npc_flow_print_item(file, npc, xinfo, flow, intf, lid,
-					    ltype, ld);
+	if (roc_model_is_cn20k()) {
+		npc_flow_print_parse_nibbles_cn20k(file, flow, parse_nibbles);
+		for (i = 0; i < flow->num_patterns; i++) {
+			lid = flow->dump_data[i].lid;
+			ltype = flow->dump_data[i].ltype;
+			for (int j = 0; j < NPC_MAX_EXTRACTOR; j++) {
+				union npc_kex_ldata_flags_cfg *lid_info =
+					&npc->lid_cfg[NIX_INTF_RX][j];
+				if (lid_info->s.lid != lid)
+					continue;
+				lt_xinfo_cn20k = &npc->prx_dxcfg_cn20k[intf][j][ltype];
+				xinfo = &lt_xinfo_cn20k->xtract;
+				if (!xinfo->enable)
+					continue;
+				npc_flow_print_item(file, npc, xinfo, flow, intf, lid, ltype, j);
+			}
+		}
+	} else {
+		npc_flow_print_parse_nibbles_legacy(file, flow, parse_nibbles);
+
+		for (i = 0; i < flow->num_patterns; i++) {
+			lid = flow->dump_data[i].lid;
+			ltype = flow->dump_data[i].ltype;
+			lt_xinfo = &npc->prx_dxcfg[intf][lid][ltype];
+
+			for (ld = 0; ld < NPC_MAX_LD; ld++) {
+				xinfo = &lt_xinfo->xtract[ld];
+				if (!xinfo->enable)
+					continue;
+				npc_flow_print_item(file, npc, xinfo, flow, intf, lid, ltype, ld);
+			}
 		}
 	}
 }
@@ -645,7 +810,6 @@ npc_flow_hw_mcam_entry_dump(FILE *file, struct npc *npc, struct roc_npc_flow *fl
 	uint64_t mcam_data[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	uint64_t mcam_mask[ROC_NPC_MAX_MCAM_WIDTH_DWORDS];
 	struct npc_mcam_read_entry_req *mcam_read_req;
-	struct npc_mcam_read_entry_rsp *mcam_read_rsp;
 	struct nix_inl_dev *inl_dev = NULL;
 	struct idev_cfg *idev;
 	struct mbox *mbox;
@@ -669,17 +833,34 @@ npc_flow_hw_mcam_entry_dump(FILE *file, struct npc *npc, struct roc_npc_flow *fl
 	}
 
 	mcam_read_req->entry = flow->mcam_id;
-	rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
-	if (rc) {
-		mbox_put(mbox);
-		plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
-		return;
-	}
 
-	mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
-	mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
-	enabled = mcam_read_rsp->enable;
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_read_entry_rsp *mcam_read_rsp;
+
+		rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
+		if (rc) {
+			mbox_put(mbox);
+			plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
+			return;
+		}
+
+		mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
+		mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
+		enabled = mcam_read_rsp->enable;
+	} else {
+		struct npc_mcam_read_entry_rsp *mcam_read_rsp;
 
+		rc = mbox_process_msg(mbox, (void *)&mcam_read_rsp);
+		if (rc) {
+			mbox_put(mbox);
+			plt_err("Failed to fetch MCAM entry:%d", flow->mcam_id);
+			return;
+		}
+
+		mbox_memcpy(mcam_data, mcam_read_rsp->entry_data.kw, sizeof(mcam_data));
+		mbox_memcpy(mcam_mask, mcam_read_rsp->entry_data.kw_mask, sizeof(mcam_data));
+		enabled = mcam_read_rsp->enable;
+	}
 	fprintf(file, "HW MCAM Data :\n");
 
 	for (i = 0; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
@@ -702,14 +883,18 @@ roc_npc_flow_mcam_dump(FILE *file, struct roc_npc *roc_npc, struct roc_npc_flow
 
 	fprintf(file, "MCAM Index:%d\n", flow->mcam_id);
 	if (flow->ctr_id != NPC_COUNTER_NONE && flow->use_ctr) {
-		if (flow->use_pre_alloc)
+		if (flow->use_pre_alloc) {
 			rc = roc_npc_inl_mcam_read_counter(flow->ctr_id, &count);
-		else
-			rc = roc_npc_mcam_read_counter(roc_npc, flow->ctr_id, &count);
+		} else {
+			if (roc_model_is_cn20k())
+				rc = roc_npc_mcam_get_stats(roc_npc, flow, &count);
+			else
+				rc = roc_npc_mcam_read_counter(roc_npc, flow->ctr_id, &count);
+		}
 
 		if (rc)
 			return;
-		fprintf(file, "Hit count: %" PRIu64 "\n", count);
+		fprintf(file, "Counter_id = 0x%x, Hit count: %" PRIu64 "\n", flow->ctr_id, count);
 	}
 
 	fprintf(file, "Interface :%s (%d)\n", intf_str[flow->nix_intf], flow->nix_intf);
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index e08a34d146..b7d726caa1 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -30,6 +30,10 @@
 	((((lid) - (NPC_LID_LA)) * NPC_LAYER_KEYX_SZ) +                        \
 	 NPC_PARSE_KEX_S_LA_OFFSET)
 
+#define NPC_LAYER_KEYX_SZ_CN20K (2)
+#define NPC_PARSE_KEX_S_LID_OFFSET_CN20K(lid)                                                      \
+	((((lid) - (NPC_LID_LA)) * NPC_LAYER_KEYX_SZ_CN20K) + NPC_PARSE_KEX_S_LA_OFFSET)
+
 /* This mark value indicates flag action */
 #define NPC_FLOW_FLAG_VAL (0xffff)
 
@@ -43,7 +47,11 @@
 
 #define NPC_MCAM_KEX_FIELD_MAX	  23
 #define NPC_MCAM_MAX_PROTO_FIELDS (NPC_MCAM_KEX_FIELD_MAX + 1)
-#define NPC_MCAM_KEY_X4_WORDS	  7 /* Number of 64-bit words */
+#if defined(ROC_PLATFORM_CN20K)
+#define NPC_MCAM_KEY_X4_WORDS 8 /* Number of 64-bit words */
+#else
+#define NPC_MCAM_KEY_X4_WORDS 7 /* Number of 64-bit words */
+#endif
 
 #define NPC_RVUPF_MAX_9XXX 0x10 /* HRM: RVU_PRIV_CONST */
 #define NPC_RVUPF_MAX_98XX 0x18 /* HRM: RVU_PRIV_CONST */
@@ -77,6 +85,16 @@
 #define NPC_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 6)
 #define NPC_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 8)
 
+/* LB OFFSET : START + LA (1b flags + 1b ltype) + LB (1b flags) */
+#define NPC_CN20K_LTYPE_LB_OFFSET (NPC_LTYPE_OFFSET_START + 3)
+#define NPC_CN20K_LFLAG_LB_OFFSET (NPC_LTYPE_OFFSET_START + 2)
+
+/* LC OFFSET : START + LA (1b flags + 1b ltype) + LB (1b flags + 1b ltype) + LC
+ * (1b flags)
+ */
+#define NPC_CN20K_LFLAG_LC_OFFSET (NPC_LTYPE_OFFSET_START + 4)
+#define NPC_CN20K_LTYPE_LC_OFFSET (NPC_LTYPE_OFFSET_START + 5)
+
 #define CN10K_SDP_CH_START 0x80
 #define CN10K_SDP_CH_MASK  0xF80
 
@@ -176,9 +194,9 @@ struct npc_parse_item_info {
 	const void *def_mask; /* default mask */
 	void *hw_mask;	      /* hardware supported mask */
 	int len;	      /* length of item */
+	uint8_t hw_hdr_len;   /* Extra data len at each layer*/
 	const void *spec;     /* spec to use, NULL implies match any */
 	const void *mask;     /* mask to use */
-	uint8_t hw_hdr_len;   /* Extra data len at each layer*/
 };
 
 struct npc_parse_state {
@@ -192,16 +210,16 @@ struct npc_parse_state {
 	uint8_t layer_mask;
 	uint8_t lt[NPC_MAX_LID];
 	uint8_t flags[NPC_MAX_LID];
+	bool has_eth_type;
+	bool is_second_pass_rule;
+	bool set_ipv6ext_ltype_mask;
+	/* adjust ltype in MCAM to match at least one vlan */
+	bool set_vlan_ltype_mask;
 	uint8_t *mcam_data; /* point to flow->mcam_data + key_len */
 	uint8_t *mcam_mask; /* point to flow->mcam_mask + key_len */
 	bool is_vf;
-	/* adjust ltype in MCAM to match at least one vlan */
-	bool set_vlan_ltype_mask;
-	bool set_ipv6ext_ltype_mask;
-	bool is_second_pass_rule;
-	bool has_eth_type;
-	uint16_t nb_tx_queues;
 	uint16_t dst_pf_func;
+	uint16_t nb_tx_queues;
 };
 
 enum npc_kpu_parser_flag {
@@ -340,6 +358,14 @@ struct npc_lid_lt_xtract_info {
 	struct npc_xtract_info xtract[NPC_MAX_LD];
 };
 
+struct npc_lid_lt_xtract_info_cn20k {
+	/* Info derived from parser configuration */
+	uint16_t npc_proto;	    /* Network protocol identified */
+	uint8_t valid_flags_mask;   /* Flags applicable */
+	uint8_t is_terminating : 1; /* No more parsing */
+	struct npc_xtract_info xtract;
+};
+
 union npc_kex_ldata_flags_cfg {
 	struct {
 		uint64_t lid : 3;
@@ -349,6 +375,11 @@ union npc_kex_ldata_flags_cfg {
 	uint64_t i;
 };
 
+#define NPC_MAX_EXTRACTTORS 24
+typedef struct npc_lid_lt_xtract_info_cn20k npc_dxcfg_cn20k_t[NPC_MAX_INTF][NPC_MAX_EXTRACTTORS]
+							     [NPC_MAX_LT];
+typedef union npc_kex_ldata_flags_cfg npc_lid_cn20k_t[NPC_MAX_INTF][NPC_MAX_EXTRACTTORS];
+
 typedef struct npc_lid_lt_xtract_info npc_dxcfg_t[NPC_MAX_INTF][NPC_MAX_LID]
 						 [NPC_MAX_LT];
 typedef struct npc_lid_lt_xtract_info npc_fxcfg_t[NPC_MAX_INTF][NPC_MAX_LD]
@@ -387,33 +418,36 @@ TAILQ_HEAD(npc_age_flow_list_head, npc_age_flow_entry);
 
 struct npc {
 	struct mbox *mbox;			/* Mbox */
-	uint32_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */
+	uint64_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */
 	uint8_t hash_extract_cap;		/* hash extract support */
 	uint8_t profile_name[MKEX_NAME_LEN];	/* KEX profile name */
-	uint32_t keyx_len[NPC_MAX_INTF];	/* per intf key len in bits */
-	uint32_t datax_len[NPC_MAX_INTF];	/* per intf data len in bits */
-	uint32_t keyw[NPC_MAX_INTF];		/* max key + data len bits */
-	uint32_t mcam_entries;			/* mcam entries supported */
-	uint16_t channel;			/* RX Channel number */
 	bool is_sdp_link;
+	uint16_t channel;		  /* RX Channel number */
+	uint32_t keyx_len[NPC_MAX_INTF];  /* per intf key len in bits */
+	uint32_t datax_len[NPC_MAX_INTF]; /* per intf data len in bits */
+	uint32_t keyw[NPC_MAX_INTF];	  /* max key + data len bits */
+	uint32_t mcam_entries;		  /* mcam entries supported */
+	uint16_t switch_header_type;	  /* Supported switch header type */
+	uint16_t flow_max_priority;	  /* Max priority for flow */
 	uint16_t sdp_channel;
 	uint16_t sdp_channel_mask;
-	uint32_t rss_grps;			/* rss groups supported */
-	uint16_t flow_prealloc_size;		/* Pre allocated mcam size */
-	uint16_t flow_max_priority;		/* Max priority for flow */
-	uint16_t switch_header_type; /* Supported switch header type */
+	uint32_t rss_grps;	     /* rss groups supported */
+	uint16_t flow_prealloc_size; /* Pre allocated mcam size */
+	uint8_t exact_match_ena;
+	uint16_t pf_func; /* pf_func of device */
 	uint32_t mark_actions;
-	uint32_t vtag_strip_actions; /* vtag insert/strip actions */
-	uint16_t pf_func;	     /* pf_func of device */
-	npc_dxcfg_t prx_dxcfg;	     /* intf, lid, lt, extract */
-	npc_fxcfg_t prx_fxcfg;	     /* Flag extract */
-	npc_ld_flags_t prx_lfcfg;    /* KEX LD_Flags CFG */
+	uint32_t vtag_strip_actions;	   /* vtag insert/strip actions */
+	npc_dxcfg_t prx_dxcfg;		   /* intf, lid, lt, extract */
+	npc_dxcfg_cn20k_t prx_dxcfg_cn20k; /* intf, ext, lt, extract */
+	npc_lid_cn20k_t lid_cfg;	   /* KEX LD_Flags CFG */
+	npc_fxcfg_t prx_fxcfg;		   /* Flag extract */
+	npc_ld_flags_t prx_lfcfg;	   /* KEX LD_Flags CFG */
 	struct npc_flow_list *flow_list;
 	struct npc_prio_flow_list_head *prio_flow_list;
 	struct npc_age_flow_list_head age_flow_list;
 	struct plt_bitmap *rss_grp_entries;
 	struct npc_flow_list ipsec_list;
-	uint8_t exact_match_ena;
+	uint8_t enable_debug;
 };
 
 #define NPC_HASH_FIELD_LEN 16
@@ -432,6 +466,7 @@ roc_npc_to_npc_priv(struct roc_npc *npc)
 	return (struct npc *)npc->reserved;
 }
 
+int npc_mcam_get_stats(struct mbox *mbox, struct roc_npc_flow *flow, uint64_t *count);
 int npc_mcam_alloc_counter(struct mbox *mbox, uint16_t *ctr);
 int npc_mcam_free_counter(struct mbox *mbox, uint16_t ctr_id);
 int npc_mcam_read_counter(struct mbox *mbox, uint32_t ctr_id, uint64_t *count);
@@ -440,9 +475,10 @@ int npc_mcam_free_entry(struct mbox *mbox, uint32_t entry);
 int npc_mcam_free_all_entries(struct npc *npc);
 int npc_mcam_alloc_and_write(struct npc *npc, struct roc_npc_flow *flow,
 			     struct npc_parse_state *pst);
-int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam,
-			 struct roc_npc_flow *ref_mcam, int prio,
-			 int *resp_count);
+int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam, struct roc_npc_flow *ref_mcam,
+			 uint8_t prio, int *resp_count);
+int npc_mcam_alloc_entry_cn20k(struct npc *npc, struct roc_npc_flow *mcam, int *resp_count);
+
 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);
 
@@ -453,6 +489,7 @@ int npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_in
 			   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);
+uint8_t npc_get_key_type(struct npc *npc, struct roc_npc_flow *flow);
 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 a507df994f..75d3b0702c 100644
--- a/drivers/common/cnxk/roc_npc_utils.c
+++ b/drivers/common/cnxk/roc_npc_utils.c
@@ -4,6 +4,36 @@
 #include "roc_api.h"
 #include "roc_priv.h"
 
+enum npc_mcam_cn20k_key_width {
+	NPC_CN20K_MCAM_KEY_X1 = 0,
+	NPC_CN20K_MCAM_KEY_DYN = NPC_CN20K_MCAM_KEY_X1,
+	NPC_CN20K_MCAM_KEY_X2,
+	NPC_CN20K_MCAM_KEY_X4,
+	NPC_CN20K_MCAM_KEY_MAX,
+};
+
+uint8_t
+npc_get_key_type(struct npc *npc, struct roc_npc_flow *flow)
+{
+	int i;
+
+	/* KEX is configured just for X2 */
+	if (npc->keyw[ROC_NPC_INTF_RX] == 1)
+		return NPC_CN20K_MCAM_KEY_X2;
+
+	/* KEX is configured just for X4 */
+	if (npc->keyw[ROC_NPC_INTF_RX] == 2)
+		return NPC_CN20K_MCAM_KEY_X4;
+
+	/* KEX is configured for both X2 and X4 */
+	/* Check mask for upper 256 bits. if mask is set, then it is X4 entry */
+	for (i = 4; i < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; i++) {
+		if (flow->mcam_mask[i] != 0)
+			return NPC_CN20K_MCAM_KEY_X4;
+	}
+	return NPC_CN20K_MCAM_KEY_X2;
+}
+
 static void
 npc_prep_mcam_ldata(uint8_t *ptr, const uint8_t *data, int len)
 {
@@ -67,8 +97,9 @@ npc_ipv6_hash_mask_get(struct npc_xtract_info *xinfo, struct npc_parse_item_info
 	memset(&hw_mask[offset], 0xFF, NPC_HASH_FIELD_LEN);
 }
 
-void
-npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid, int lt)
+static void
+npc_get_hw_supp_mask_legacy(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			    int lt)
 {
 	struct npc_xtract_info *xinfo, *lfinfo;
 	char *hw_mask = info->hw_mask;
@@ -101,6 +132,40 @@ npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *in
 	}
 }
 
+static void
+npc_get_hw_supp_mask_o20k(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			  int lt)
+{
+	struct npc_xtract_info *xinfo;
+	union npc_kex_ldata_flags_cfg *lid_info;
+	char *hw_mask = info->hw_mask;
+	int ex;
+	int intf;
+
+	intf = pst->nix_intf;
+	memset(hw_mask, 0, info->len);
+	for (ex = 0; ex < NPC_MAX_EXTRACTTORS; ex++) {
+		lid_info = &pst->npc->lid_cfg[intf][ex];
+		if (lid_info->s.lid != lid)
+			continue;
+		xinfo = &pst->npc->prx_dxcfg_cn20k[intf][ex][lt].xtract;
+
+		if (pst->npc->hash_extract_cap && xinfo->use_hash)
+			npc_ipv6_hash_mask_get(xinfo, info);
+		else
+			npc_set_hw_mask(info, xinfo, hw_mask);
+	}
+}
+
+void
+npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid, int lt)
+{
+	if (!roc_model_is_cn20k())
+		return npc_get_hw_supp_mask_legacy(pst, info, lid, lt);
+	else
+		return npc_get_hw_supp_mask_o20k(pst, info, lid, lt);
+}
+
 inline int
 npc_mask_is_supported(const char *mask, const char *hw_mask, int len)
 {
@@ -381,10 +446,10 @@ npc_hash_field_get(struct npc_xtract_info *xinfo, const struct roc_npc_flow_item
 	return 1;
 }
 
-int
-npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
-			    const struct roc_npc_flow_item_ipv6 *ipv6_mask,
-			    struct npc_parse_state *pst, uint8_t ltype)
+static int
+npc_process_ipv6_field_hash_legacy(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+				   const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+				   struct npc_parse_state *pst, uint8_t ltype)
 {
 	struct npc_lid_lt_xtract_info *lid_lt_xinfo;
 	uint8_t hash_field[ROC_IPV6_ADDR_LEN];
@@ -421,9 +486,64 @@ npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
 	return 0;
 }
 
+static int
+npc_process_ipv6_field_hash_o20k(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+				 const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+				 struct npc_parse_state *pst, uint8_t ltype)
+{
+	struct npc_lid_lt_xtract_info_cn20k *lid_lt_xinfo;
+	union npc_kex_ldata_flags_cfg *lid_cfg;
+	uint8_t hash_field[ROC_IPV6_ADDR_LEN];
+	struct npc_xtract_info *xinfo;
+	struct roc_ipv6_hdr ipv6_buf;
+	uint32_t hash = 0, mask;
+	int intf, i, rc = 0;
+
+	memset(&ipv6_buf, 0, sizeof(ipv6_buf));
+	memset(hash_field, 0, sizeof(hash_field));
+
+	intf = pst->nix_intf;
+	for (i = 0; i < NPC_MAX_EXTRACTTORS; i++) {
+		lid_cfg = &pst->npc->lid_cfg[intf][i];
+		if (lid_cfg->s.lid != NPC_LID_LC)
+			continue;
+		lid_lt_xinfo = &pst->npc->prx_dxcfg_cn20k[intf][NPC_LID_LC][ltype];
+
+		xinfo = &lid_lt_xinfo->xtract;
+		if (!xinfo->use_hash)
+			continue;
+
+		rc = npc_hash_field_get(xinfo, ipv6_spec, ipv6_mask, hash_field);
+		if (rc == 0)
+			continue;
+
+		rc = npc_ipv6_field_hash_get(pst->npc, (const uint32_t *)hash_field, intf, i,
+					     &hash);
+		if (rc)
+			return rc;
+
+		mask = GENMASK(31, 0);
+		memcpy(pst->mcam_mask + xinfo->key_off, (uint8_t *)&mask, 4);
+		memcpy(pst->mcam_data + xinfo->key_off, (uint8_t *)&hash, 4);
+	}
+
+	return 0;
+}
+
 int
-npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
-		       int lt, uint8_t flags)
+npc_process_ipv6_field_hash(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
+			    const struct roc_npc_flow_item_ipv6 *ipv6_mask,
+			    struct npc_parse_state *pst, uint8_t ltype)
+{
+	if (!roc_model_is_cn20k())
+		return npc_process_ipv6_field_hash_legacy(ipv6_spec, ipv6_mask, pst, ltype);
+	else
+		return npc_process_ipv6_field_hash_o20k(ipv6_spec, ipv6_mask, pst, ltype);
+}
+
+static int
+npc_update_parse_state_legacy(struct npc_parse_state *pst, struct npc_parse_item_info *info,
+			      int lid, int lt, uint8_t flags)
 {
 	struct npc_lid_lt_xtract_info *xinfo;
 	struct roc_npc_flow_dump_data *dump;
@@ -461,8 +581,7 @@ npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *
 		if (lf_cfg == lid) {
 			for (j = 0; j < NPC_MAX_LFL; j++) {
 				lfinfo = pst->npc->prx_fxcfg[intf][i][j].xtract;
-				rc = npc_update_extraction_data(pst, info,
-								&lfinfo[0]);
+				rc = npc_update_extraction_data(pst, info, &lfinfo[0]);
 				if (rc != 0)
 					return rc;
 
@@ -480,42 +599,127 @@ npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *
 	return 0;
 }
 
+static int
+npc_update_parse_state_o20(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+			   int lt, uint8_t flags)
+{
+	struct npc_lid_lt_xtract_info_cn20k *xinfo;
+	union npc_kex_ldata_flags_cfg *lid_cfg;
+	struct roc_npc_flow_dump_data *dump;
+	int intf;
+	int i, rc = 0;
+
+	pst->layer_mask |= lid;
+	pst->lt[lid] = lt;
+	pst->flags[lid] = flags;
+
+	intf = pst->nix_intf;
+	if (info->spec == NULL)
+		goto done;
+
+	for (i = 0; i < NPC_MAX_EXTRACTTORS; i++) {
+		lid_cfg = &pst->npc->lid_cfg[intf][i];
+		if (lid_cfg->s.lid != lid)
+			continue;
+		xinfo = &pst->npc->prx_dxcfg_cn20k[intf][i][lt];
+		if (xinfo->is_terminating)
+			pst->terminate = 1;
+
+		if (xinfo->xtract.use_hash)
+			continue;
+		rc = npc_update_extraction_data(pst, info, &xinfo->xtract);
+		if (rc != 0)
+			return rc;
+	}
+
+done:
+	dump = &pst->flow->dump_data[pst->flow->num_patterns++];
+	dump->lid = lid;
+	dump->ltype = lt;
+	pst->pattern++;
+	return 0;
+}
+
+int
+npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
+		       int lt, uint8_t flags)
+{
+	if (roc_model_is_cn20k())
+		return npc_update_parse_state_o20(pst, info, lid, lt, flags);
+	else
+		return npc_update_parse_state_legacy(pst, info, lid, lt, flags);
+}
+
 int
 npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id)
 {
-	struct npc_mcam_write_entry_req *req;
-	struct npc_mcam_write_entry_rsq *rsp;
+	struct msg_rsp *rsp;
 	struct mbox *mbox = mbox_get(npc->mbox);
 	int rc = 0, idx;
 
-	req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
-	if (req == NULL) {
-		rc = -ENOSPC;
-		goto exit;
-	}
-	req->set_cntr = 0;
-	req->cntr = 0;
-	req->entry = mcam_id;
-
-	req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
-	req->enable_entry = 1;
-	req->entry_data.action = flow->npc_action;
-	req->entry_data.vtag_action = flow->vtag_action;
-
-	for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
-		req->entry_data.kw[idx] = 0x0;
-		req->entry_data.kw_mask[idx] = 0x0;
-	}
+	if (roc_model_is_cn20k()) {
+		struct npc_cn20k_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_cn20k_mcam_write_entry(mbox);
+		if (req == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		req->cntr = 0;
+		req->entry = mcam_id;
+
+		req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+		req->enable_entry = 1;
+		req->entry_data.action = flow->npc_action;
+		req->entry_data.vtag_action = flow->vtag_action;
+
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			req->entry_data.kw[idx] = 0x0;
+			req->entry_data.kw_mask[idx] = 0x0;
+		}
+
+		if (flow->nix_intf == NIX_INTF_RX) {
+			req->entry_data.kw[0] |= (uint64_t)npc->channel;
+			req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+		} else {
+			uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 
-	if (flow->nix_intf == NIX_INTF_RX) {
-		req->entry_data.kw[0] |= (uint64_t)npc->channel;
-		req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+			pf_func = plt_cpu_to_be_16(pf_func);
+			req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
+			req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+		}
 	} else {
-		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
+		struct npc_mcam_write_entry_req *req;
+
+		req = mbox_alloc_msg_npc_mcam_write_entry(mbox);
+		if (req == NULL) {
+			rc = -ENOSPC;
+			goto exit;
+		}
+		req->set_cntr = 0;
+		req->cntr = 0;
+		req->entry = mcam_id;
+
+		req->intf = (flow->nix_intf == NIX_INTF_RX) ? NPC_MCAM_RX : NPC_MCAM_TX;
+		req->enable_entry = 1;
+		req->entry_data.action = flow->npc_action;
+		req->entry_data.vtag_action = flow->vtag_action;
+
+		for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) {
+			req->entry_data.kw[idx] = 0x0;
+			req->entry_data.kw_mask[idx] = 0x0;
+		}
+
+		if (flow->nix_intf == NIX_INTF_RX) {
+			req->entry_data.kw[0] |= (uint64_t)npc->channel;
+			req->entry_data.kw_mask[0] |= (BIT_ULL(12) - 1);
+		} else {
+			uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
 
-		pf_func = plt_cpu_to_be_16(pf_func);
-		req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
-		req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+			pf_func = plt_cpu_to_be_16(pf_func);
+			req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
+			req->entry_data.kw_mask[0] |= ((uint64_t)0xffff << 32);
+		}
 	}
 
 	rc = mbox_process_msg(mbox, (void *)&rsp);
@@ -783,13 +987,12 @@ npc_insert_into_flow_list(struct npc *npc, struct npc_prio_flow_entry *entry)
 }
 
 static int
-npc_allocate_mcam_entry(struct mbox *mbox, int prio,
-			struct npc_mcam_alloc_entry_rsp *rsp_local,
-			int ref_entry)
+npc_allocate_mcam_entry(struct mbox *mbox, int prio, struct npc_mcam_alloc_entry_rsp *rsp_local,
+			int ref_entry, uint8_t kw_type)
 {
-	struct npc_mcam_alloc_entry_rsp *rsp_cmd;
-	struct npc_mcam_alloc_entry_req *req;
 	struct npc_mcam_alloc_entry_rsp *rsp;
+	struct npc_mcam_alloc_entry_req *req;
+
 	int rc = -ENOSPC;
 
 	req = mbox_alloc_msg_npc_mcam_alloc_entry(mbox_get(mbox));
@@ -797,20 +1000,20 @@ npc_allocate_mcam_entry(struct mbox *mbox, int prio,
 		goto exit;
 	req->contig = 1;
 	req->count = 1;
-	req->priority = prio;
+	req->ref_priority = prio;
 	req->ref_entry = ref_entry;
+	req->kw_type = kw_type;
 
-	rc = mbox_process_msg(mbox, (void *)&rsp_cmd);
+	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
 		goto exit;
 
-	if (!rsp_cmd->count) {
+	if (!rsp->count) {
 		rc = -ENOSPC;
 		goto exit;
 	}
 
-	mbox_memcpy(rsp_local, rsp_cmd, sizeof(*rsp));
-
+	mbox_memcpy(rsp_local, rsp, sizeof(*rsp));
 	rc = 0;
 exit:
 	mbox_put(mbox);
@@ -854,8 +1057,7 @@ npc_find_mcam_ref_entry(struct roc_npc_flow *flow, struct npc *npc, int *prio,
 }
 
 static int
-npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
-			    struct npc *npc,
+npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow, struct npc *npc,
 			    struct npc_mcam_alloc_entry_rsp *rsp_local)
 {
 	int prio, ref_entry = 0, rc = 0, dir = NPC_MCAM_LOWER_PRIO;
@@ -863,7 +1065,7 @@ npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
 
 retry:
 	npc_find_mcam_ref_entry(flow, npc, &prio, &ref_entry, dir);
-	rc = npc_allocate_mcam_entry(mbox, prio, rsp_local, ref_entry);
+	rc = npc_allocate_mcam_entry(mbox, prio, rsp_local, ref_entry, flow->key_type);
 	if (rc && !retry_done) {
 		plt_npc_dbg(
 			"npc: Failed to allocate lower priority entry. Retrying for higher priority");
@@ -879,32 +1081,42 @@ npc_alloc_mcam_by_ref_entry(struct mbox *mbox, struct roc_npc_flow *flow,
 }
 
 int
-npc_get_free_mcam_entry(struct mbox *mbox, struct roc_npc_flow *flow,
-			struct npc *npc)
+npc_get_free_mcam_entry(struct mbox *mbox, struct roc_npc_flow *flow, struct npc *npc)
 {
 	struct npc_mcam_alloc_entry_rsp rsp_local;
 	struct npc_prio_flow_entry *new_entry;
 	int rc = 0;
 
-	rc = npc_alloc_mcam_by_ref_entry(mbox, flow, npc, &rsp_local);
-
-	if (rc)
-		return rc;
-
 	new_entry = plt_zmalloc(sizeof(*new_entry), 0);
 	if (!new_entry)
 		return -ENOSPC;
 
-	new_entry->flow = flow;
+	if (roc_model_is_cn20k()) {
+		rc = npc_allocate_mcam_entry(mbox, NPC_MCAM_ANY_PRIO, &rsp_local, 0,
+					     flow->key_type);
+		if (rc) {
+			plt_npc_dbg("npc: failed to allocate MCAM entry.");
+			return rc;
+		}
+
+		new_entry->flow = flow;
+	} else {
+		rc = npc_alloc_mcam_by_ref_entry(mbox, flow, npc, &rsp_local);
 
-	plt_npc_dbg("kernel allocated MCAM entry %d", rsp_local.entry);
+		if (rc)
+			return rc;
 
-	rc = npc_sort_mcams_by_user_prio_level(mbox, new_entry, npc,
-					       &rsp_local);
-	if (rc)
-		goto err;
+		new_entry->flow = flow;
+
+		plt_npc_dbg("kernel allocated MCAM entry %d", rsp_local.entry);
+
+		rc = npc_sort_mcams_by_user_prio_level(mbox, new_entry, npc, &rsp_local);
+		if (rc)
+			goto err;
+
+		plt_npc_dbg("allocated MCAM entry after sorting %d", rsp_local.entry);
+	}
 
-	plt_npc_dbg("allocated MCAM entry after sorting %d", rsp_local.entry);
 	flow->mcam_id = rsp_local.entry;
 	npc_insert_into_flow_list(npc, new_entry);
 
diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map
index 42e9375706..4f8da55da5 100644
--- a/drivers/common/cnxk/version.map
+++ b/drivers/common/cnxk/version.map
@@ -486,6 +486,7 @@ INTERNAL {
 	roc_npc_mcam_free_counter;
 	roc_npc_mcam_free;
 	roc_npc_mcam_free_entry;
+	roc_npc_mcam_get_stats;
 	roc_npc_mcam_init;
 	roc_npc_mcam_move;
 	roc_npc_mcam_merge_base_steering_rule;
-- 
2.39.2


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

* [dpdk-dev] [PATCH v3 2/2] net/cnxk: support rte flow on cn20k
  2024-11-12  9:58 ` [dpdk-dev] [PATCH v3 1/2] common/cnxk: support NPC " psatheesh
@ 2024-11-12  9:58   ` psatheesh
  0 siblings, 0 replies; 8+ messages in thread
From: psatheesh @ 2024-11-12  9:58 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
	Harman Kalra
  Cc: dev, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

Support for rte flow in cn20k.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar K <kirankumark@marvell.com>
---
 drivers/net/cnxk/cn10k_flow.c          | 227 ++-----------------------
 drivers/net/cnxk/cn10k_flow.h          |  10 +-
 drivers/net/cnxk/cn20k_ethdev.c        |   4 +
 drivers/net/cnxk/cn20k_flow.c          | 101 +++++++++++
 drivers/net/cnxk/cn20k_flow.h          |  21 +++
 drivers/net/cnxk/cn9k_flow.c           |   2 +-
 drivers/net/cnxk/cnxk_ethdev_devargs.c |  10 +-
 drivers/net/cnxk/cnxk_flow.c           |  18 +-
 drivers/net/cnxk/cnxk_flow.h           |   5 +-
 drivers/net/cnxk/cnxk_flow_common.c    | 214 +++++++++++++++++++++++
 drivers/net/cnxk/cnxk_flow_common.h    |  19 +++
 drivers/net/cnxk/meson.build           |   2 +
 12 files changed, 396 insertions(+), 237 deletions(-)
 create mode 100644 drivers/net/cnxk/cn20k_flow.c
 create mode 100644 drivers/net/cnxk/cn20k_flow.h
 create mode 100644 drivers/net/cnxk/cnxk_flow_common.c
 create mode 100644 drivers/net/cnxk/cnxk_flow_common.h

diff --git a/drivers/net/cnxk/cn10k_flow.c b/drivers/net/cnxk/cn10k_flow.c
index db5e427362..b95fb83f08 100644
--- a/drivers/net/cnxk/cn10k_flow.c
+++ b/drivers/net/cnxk/cn10k_flow.c
@@ -1,215 +1,29 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(C) 2020 Marvell.
  */
-#include "cn10k_flow.h"
+
 #include "cn10k_ethdev.h"
 #include "cn10k_rx.h"
 #include "cnxk_ethdev_mcs.h"
+#include "cnxk_flow_common.h"
+#include <cn10k_flow.h>
 #include <cnxk_flow.h>
 
-static int
-cn10k_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
-{
-	return nix_mtr_connect(eth_dev, mtr_id);
-}
-
-static int
-cn10k_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
-{
-	struct rte_mtr_error mtr_error;
-
-	return nix_mtr_destroy(eth_dev, mtr_id, &mtr_error);
-}
-
-static int
-cn10k_mtr_configure(struct rte_eth_dev *eth_dev,
-		    const struct rte_flow_action actions[])
-{
-	uint32_t mtr_id = 0xffff, prev_mtr_id = 0xffff, next_mtr_id = 0xffff;
-	const struct rte_flow_action_meter *mtr_conf;
-	const struct rte_flow_action_queue *q_conf;
-	const struct rte_flow_action_rss *rss_conf;
-	struct cnxk_mtr_policy_node *policy;
-	bool is_mtr_act = false;
-	int tree_level = 0;
-	int rc = -EINVAL, i;
-
-	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
-			mtr_conf = (const struct rte_flow_action_meter
-					    *)(actions[i].conf);
-			mtr_id = mtr_conf->mtr_id;
-			is_mtr_act = true;
-		}
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
-			q_conf = (const struct rte_flow_action_queue
-					  *)(actions[i].conf);
-			if (is_mtr_act)
-				nix_mtr_rq_update(eth_dev, mtr_id, 1,
-						  &q_conf->index);
-		}
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
-			rss_conf = (const struct rte_flow_action_rss
-					    *)(actions[i].conf);
-			if (is_mtr_act)
-				nix_mtr_rq_update(eth_dev, mtr_id,
-						  rss_conf->queue_num,
-						  rss_conf->queue);
-		}
-	}
-
-	if (!is_mtr_act)
-		return rc;
-
-	prev_mtr_id = mtr_id;
-	next_mtr_id = mtr_id;
-	while (next_mtr_id != 0xffff) {
-		rc = nix_mtr_validate(eth_dev, next_mtr_id);
-		if (rc)
-			return rc;
-
-		rc = nix_mtr_policy_act_get(eth_dev, next_mtr_id, &policy);
-		if (rc)
-			return rc;
-
-		rc = nix_mtr_color_action_validate(eth_dev, mtr_id,
-						   &prev_mtr_id, &next_mtr_id,
-						   policy, &tree_level);
-		if (rc)
-			return rc;
-	}
-
-	return nix_mtr_configure(eth_dev, mtr_id);
-}
-
-static int
-cn10k_rss_action_validate(struct rte_eth_dev *eth_dev,
-			  const struct rte_flow_attr *attr,
-			  const struct rte_flow_action *act)
-{
-	const struct rte_flow_action_rss *rss;
-
-	if (act == NULL)
-		return -EINVAL;
-
-	rss = (const struct rte_flow_action_rss *)act->conf;
-
-	if (attr->egress) {
-		plt_err("No support of RSS in egress");
-		return -EINVAL;
-	}
-
-	if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
-		plt_err("multi-queue mode is disabled");
-		return -ENOTSUP;
-	}
-
-	if (!rss || !rss->queue_num) {
-		plt_err("no valid queues");
-		return -EINVAL;
-	}
-
-	if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
-		plt_err("non-default RSS hash functions are not supported");
-		return -ENOTSUP;
-	}
-
-	if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
-		plt_err("RSS hash key too large");
-		return -ENOTSUP;
-	}
-
-	return 0;
-}
-
 struct rte_flow *
 cn10k_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
-		  const struct rte_flow_item pattern[],
-		  const struct rte_flow_action actions[],
+		  const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
 		  struct rte_flow_error *error)
 {
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
-	const struct rte_flow_action *action_rss = NULL;
-	const struct rte_flow_action_meter *mtr = NULL;
-	const struct rte_flow_action *act_q = NULL;
 	struct roc_npc *npc = &dev->npc;
 	struct roc_npc_flow *flow;
-	void *mcs_flow = NULL;
 	int vtag_actions = 0;
-	uint32_t req_act = 0;
 	int mark_actions;
-	int i, rc;
-
-	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER)
-			req_act |= ROC_NPC_ACTION_TYPE_METER;
-
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
-			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
-			act_q = &actions[i];
-		}
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
-			req_act |= ROC_NPC_ACTION_TYPE_RSS;
-			action_rss = &actions[i];
-		}
-	}
-
-	if (req_act & ROC_NPC_ACTION_TYPE_METER) {
-		if ((req_act & ROC_NPC_ACTION_TYPE_RSS) &&
-		    ((req_act & ROC_NPC_ACTION_TYPE_QUEUE))) {
-			return NULL;
-		}
-		if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
-			rc = cn10k_rss_action_validate(eth_dev, attr,
-						       action_rss);
-			if (rc)
-				return NULL;
-		} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
-			const struct rte_flow_action_queue *act_queue;
-			act_queue = (const struct rte_flow_action_queue *)
-					    act_q->conf;
-			if (act_queue->index > eth_dev->data->nb_rx_queues)
-				return NULL;
-		} else {
-			return NULL;
-		}
-	}
-	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
-		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
-			mtr = (const struct rte_flow_action_meter *)actions[i]
-				      .conf;
-			rc = cn10k_mtr_configure(eth_dev, actions);
-			if (rc) {
-				rte_flow_error_set(error, rc,
-					RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					"Failed to configure mtr ");
-				return NULL;
-			}
-			break;
-		}
-	}
-
-	if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
-	    cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL) {
-		rc = cnxk_mcs_flow_configure(eth_dev, attr, pattern, actions, error, &mcs_flow);
-		if (rc) {
-			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					   "Failed to configure mcs flow");
-			return NULL;
-		}
-		return (struct rte_flow *)mcs_flow;
-	}
 
 	flow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);
-	if (!flow) {
-		if (mtr)
-			nix_mtr_chain_reset(eth_dev, mtr->mtr_id);
 
+	if (!flow)
 		return NULL;
-	} else {
-		if (mtr)
-			cn10k_mtr_connect(eth_dev, mtr->mtr_id);
-	}
 
 	mark_actions = roc_npc_mark_actions_get(npc);
 	if (mark_actions) {
@@ -231,16 +45,7 @@ int
 cn10k_flow_info_get(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
 		    struct rte_flow_queue_info *queue_info, struct rte_flow_error *err)
 {
-	RTE_SET_USED(dev);
-	RTE_SET_USED(err);
-
-	memset(port_info, 0, sizeof(*port_info));
-	memset(queue_info, 0, sizeof(*queue_info));
-
-	port_info->max_nb_counters = CN10K_NPC_COUNTERS_MAX;
-	port_info->max_nb_meters = CNXK_NIX_MTR_COUNT_MAX;
-
-	return 0;
+	return cnxk_flow_info_get_common(dev, port_info, queue_info, err);
 }
 
 int
@@ -250,14 +55,12 @@ cn10k_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
 	struct roc_npc_flow *flow = (struct roc_npc_flow *)rte_flow;
 	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
 	struct roc_npc *npc = &dev->npc;
-	int vtag_actions = 0;
+	int vtag_actions = 0, rc = 0;
 	int mark_actions;
 	uint16_t match_id;
 	uint32_t mtr_id;
-	int rc;
 
-	match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) &
-		   NPC_RX_ACT_MATCH_MASK;
+	match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & NPC_RX_ACT_MATCH_MASK;
 	if (match_id) {
 		mark_actions = roc_npc_mark_actions_sub_return(npc, 1);
 		if (mark_actions == 0) {
@@ -271,8 +74,7 @@ cn10k_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
 		if (flow->nix_intf == ROC_NPC_INTF_RX) {
 			vtag_actions = roc_npc_vtag_actions_sub_return(npc, 1);
 			if (vtag_actions == 0) {
-				dev->rx_offload_flags &=
-					~NIX_RX_OFFLOAD_VLAN_STRIP_F;
+				dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_VLAN_STRIP_F;
 				cn10k_eth_set_rx_function(eth_dev);
 			}
 		}
@@ -281,19 +83,18 @@ cn10k_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
 	if (cnxk_eth_macsec_sess_get_by_sess(dev, (void *)flow) != NULL) {
 		rc = cnxk_mcs_flow_destroy(dev, (void *)flow);
 		if (rc < 0)
-			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL, "Failed to free mcs flow");
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Failed to free mcs flow");
 		return rc;
 	}
 
 	mtr_id = flow->mtr_id;
 	rc = cnxk_flow_destroy(eth_dev, flow, error);
 	if (!rc && mtr_id != ROC_NIX_MTR_ID_INVALID) {
-		rc = cn10k_mtr_destroy(eth_dev, mtr_id);
+		rc = cnxk_mtr_destroy(eth_dev, mtr_id);
 		if (rc) {
-			rte_flow_error_set(error, ENXIO,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
-				"Meter attached to this flow does not exist");
+			rte_flow_error_set(error, ENXIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Meter attached to this flow does not exist");
 		}
 	}
 	return rc;
diff --git a/drivers/net/cnxk/cn10k_flow.h b/drivers/net/cnxk/cn10k_flow.h
index 316b74e6a6..c9e8c86e96 100644
--- a/drivers/net/cnxk/cn10k_flow.h
+++ b/drivers/net/cnxk/cn10k_flow.h
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(C) 2020 Marvell.
+ * Copyright(C) 2024 Marvell.
  */
-#ifndef __CN10K_RTE_FLOW_H__
-#define __CN10K_RTE_FLOW_H__
+#ifndef __CN10K_FLOW_H__
+#define __CN10K_FLOW_H__
 
 #include <rte_flow_driver.h>
 
@@ -16,6 +16,6 @@ int cn10k_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
 int cn10k_flow_info_get(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
 			struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
 
-#define CN10K_NPC_COUNTERS_MAX 512
+#define CNXK_NPC_COUNTERS_MAX 512
 
-#endif /* __CN10K_RTE_FLOW_H__ */
+#endif /* __CN10K_FLOW_H__ */
diff --git a/drivers/net/cnxk/cn20k_ethdev.c b/drivers/net/cnxk/cn20k_ethdev.c
index 37c372d80f..4e4337a6e5 100644
--- a/drivers/net/cnxk/cn20k_ethdev.c
+++ b/drivers/net/cnxk/cn20k_ethdev.c
@@ -2,6 +2,7 @@
  * Copyright(C) 2024 Marvell.
  */
 #include "cn20k_ethdev.h"
+#include "cn20k_flow.h"
 #include "cn20k_rx.h"
 #include "cn20k_tx.h"
 
@@ -867,6 +868,9 @@ npc_flow_ops_override(void)
 	init_once = 1;
 
 	/* Update platform specific ops */
+	cnxk_flow_ops.create = cn20k_flow_create;
+	cnxk_flow_ops.destroy = cn20k_flow_destroy;
+	cnxk_flow_ops.info_get = cn20k_flow_info_get;
 }
 
 static int
diff --git a/drivers/net/cnxk/cn20k_flow.c b/drivers/net/cnxk/cn20k_flow.c
new file mode 100644
index 0000000000..fd50f516ee
--- /dev/null
+++ b/drivers/net/cnxk/cn20k_flow.c
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+
+#include "cn20k_ethdev.h"
+#include "cn20k_rx.h"
+#include "cnxk_ethdev_mcs.h"
+#include "cnxk_flow_common.h"
+#include <cn20k_flow.h>
+#include <cnxk_flow.h>
+
+struct rte_flow *
+cn20k_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+		  const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
+		  struct rte_flow_error *error)
+{
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_npc *npc = &dev->npc;
+	struct roc_npc_flow *flow;
+	int vtag_actions = 0;
+	int mark_actions;
+
+	flow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);
+
+	if (!flow)
+		return NULL;
+
+	mark_actions = roc_npc_mark_actions_get(npc);
+	if (mark_actions) {
+		dev->rx_offload_flags |= NIX_RX_OFFLOAD_MARK_UPDATE_F;
+		cn20k_eth_set_rx_function(eth_dev);
+	}
+
+	vtag_actions = roc_npc_vtag_actions_get(npc);
+
+	if (vtag_actions) {
+		dev->rx_offload_flags |= NIX_RX_OFFLOAD_VLAN_STRIP_F;
+		cn20k_eth_set_rx_function(eth_dev);
+	}
+
+	return (struct rte_flow *)flow;
+}
+
+int
+cn20k_flow_info_get(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+		    struct rte_flow_queue_info *queue_info, struct rte_flow_error *err)
+{
+	return cnxk_flow_info_get_common(dev, port_info, queue_info, err);
+}
+
+int
+cn20k_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *rte_flow,
+		   struct rte_flow_error *error)
+{
+	struct roc_npc_flow *flow = (struct roc_npc_flow *)rte_flow;
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	struct roc_npc *npc = &dev->npc;
+	int vtag_actions = 0, rc = 0;
+	int mark_actions;
+	uint16_t match_id;
+	uint32_t mtr_id;
+
+	match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & NPC_RX_ACT_MATCH_MASK;
+	if (match_id) {
+		mark_actions = roc_npc_mark_actions_sub_return(npc, 1);
+		if (mark_actions == 0) {
+			dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_MARK_UPDATE_F;
+			cn20k_eth_set_rx_function(eth_dev);
+		}
+	}
+
+	vtag_actions = roc_npc_vtag_actions_get(npc);
+	if (vtag_actions) {
+		if (flow->nix_intf == ROC_NPC_INTF_RX) {
+			vtag_actions = roc_npc_vtag_actions_sub_return(npc, 1);
+			if (vtag_actions == 0) {
+				dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_VLAN_STRIP_F;
+				cn20k_eth_set_rx_function(eth_dev);
+			}
+		}
+	}
+
+	if (cnxk_eth_macsec_sess_get_by_sess(dev, (void *)flow) != NULL) {
+		rc = cnxk_mcs_flow_destroy(dev, (void *)flow);
+		if (rc < 0)
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Failed to free mcs flow");
+		return rc;
+	}
+
+	mtr_id = flow->mtr_id;
+	rc = cnxk_flow_destroy(eth_dev, flow, error);
+	if (!rc && mtr_id != ROC_NIX_MTR_ID_INVALID) {
+		rc = cnxk_mtr_destroy(eth_dev, mtr_id);
+		if (rc) {
+			rte_flow_error_set(error, ENXIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					   "Meter attached to this flow does not exist");
+		}
+	}
+	return rc;
+}
diff --git a/drivers/net/cnxk/cn20k_flow.h b/drivers/net/cnxk/cn20k_flow.h
new file mode 100644
index 0000000000..1e4bd6214a
--- /dev/null
+++ b/drivers/net/cnxk/cn20k_flow.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+#ifndef __CN20K_FLOW_H__
+#define __CN20K_FLOW_H__
+
+#include <rte_flow_driver.h>
+
+struct rte_flow *cn20k_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+				   const struct rte_flow_item pattern[],
+				   const struct rte_flow_action actions[],
+				   struct rte_flow_error *error);
+int cn20k_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
+		       struct rte_flow_error *error);
+
+int cn20k_flow_info_get(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
+
+#define CNXK_NPC_COUNTERS_MAX 512
+
+#endif /* __CN20K_FLOW_H__ */
diff --git a/drivers/net/cnxk/cn9k_flow.c b/drivers/net/cnxk/cn9k_flow.c
index dc5476a189..ae4629ea69 100644
--- a/drivers/net/cnxk/cn9k_flow.c
+++ b/drivers/net/cnxk/cn9k_flow.c
@@ -18,7 +18,7 @@ cn9k_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
 	int vtag_actions = 0;
 	int mark_actions;
 
-	flow = cnxk_flow_create(eth_dev, attr, pattern, actions, error);
+	flow = cnxk_flow_create_common(eth_dev, attr, pattern, actions, error, false);
 	if (!flow)
 		return NULL;
 
diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c
index 5bd50bb9a1..bdf5d88b92 100644
--- a/drivers/net/cnxk/cnxk_ethdev_devargs.c
+++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c
@@ -88,8 +88,7 @@ parse_flow_max_priority(const char *key, const char *value, void *extra_args)
 
 	val = atoi(value);
 
-	/* Limit the max priority to 32 */
-	if (val < 1 || val > 32)
+	if (val < 1 || val > ROC_NPC_MAX_MCAM_PRIORITY)
 		return -EINVAL;
 
 	*(uint16_t *)extra_args = val;
@@ -390,7 +389,12 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 		dev->nix.meta_buf_sz = meta_buf_sz;
 
 	dev->npc.flow_prealloc_size = flow_prealloc_size;
-	dev->npc.flow_max_priority = flow_max_priority;
+
+	if (roc_model_is_cn20k())
+		dev->npc.flow_max_priority = ROC_NPC_MAX_MCAM_PRIORITY;
+	else
+		dev->npc.flow_max_priority = flow_max_priority;
+
 	dev->npc.switch_header_type = switch_header_type;
 	dev->npc.sdp_channel = sdp_chan.channel;
 	dev->npc.sdp_channel_mask = sdp_chan.mask;
diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c
index e42e2f8deb..fcc60cd4f0 100644
--- a/drivers/net/cnxk/cnxk_flow.c
+++ b/drivers/net/cnxk/cnxk_flow.c
@@ -977,14 +977,6 @@ cnxk_flow_create_common(struct rte_eth_dev *eth_dev, const struct rte_flow_attr
 	return flow;
 }
 
-struct roc_npc_flow *
-cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
-		 const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
-		 struct rte_flow_error *error)
-{
-	return cnxk_flow_create_common(eth_dev, attr, pattern, actions, error, false);
-}
-
 int
 cnxk_flow_destroy_common(struct rte_eth_dev *eth_dev, struct roc_npc_flow *flow,
 			 struct rte_flow_error *error, bool is_rep)
@@ -1083,10 +1075,14 @@ cnxk_flow_query_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
 		npc = &rep_dev->parent_dev->npc;
 	}
 
-	if (in_flow->use_pre_alloc)
+	if (in_flow->use_pre_alloc) {
 		rc = roc_npc_inl_mcam_read_counter(in_flow->ctr_id, &query->hits);
-	else
-		rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	} else {
+		if (roc_model_is_cn20k())
+			rc = roc_npc_mcam_get_stats(npc, in_flow, &query->hits);
+		else
+			rc = roc_npc_mcam_read_counter(npc, in_flow->ctr_id, &query->hits);
+	}
 	if (rc != 0) {
 		errcode = EIO;
 		errmsg = "Error reading flow counter";
diff --git a/drivers/net/cnxk/cnxk_flow.h b/drivers/net/cnxk/cnxk_flow.h
index e51d04b2c9..80b8d2c36a 100644
--- a/drivers/net/cnxk/cnxk_flow.h
+++ b/drivers/net/cnxk/cnxk_flow.h
@@ -22,10 +22,6 @@ struct cnxk_rte_flow_action_info {
 
 extern const struct cnxk_rte_flow_term_info term[];
 
-struct roc_npc_flow *cnxk_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
-				      const struct rte_flow_item pattern[],
-				      const struct rte_flow_action actions[],
-				      struct rte_flow_error *error);
 int cnxk_flow_destroy(struct rte_eth_dev *dev, struct roc_npc_flow *flow,
 		      struct rte_flow_error *error);
 
@@ -46,5 +42,6 @@ int cnxk_flow_query_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
 			   struct rte_flow_error *error, bool is_rep);
 int cnxk_flow_dev_dump_common(struct rte_eth_dev *eth_dev, struct rte_flow *flow, FILE *file,
 			      struct rte_flow_error *error, bool is_rep);
+int cnxk_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id);
 
 #endif /* __CNXK_RTE_FLOW_H__ */
diff --git a/drivers/net/cnxk/cnxk_flow_common.c b/drivers/net/cnxk/cnxk_flow_common.c
new file mode 100644
index 0000000000..c2a173ac8c
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_flow_common.c
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+
+#include "cnxk_flow_common.h"
+#include "cnxk_ethdev_mcs.h"
+#include <cnxk_flow.h>
+
+static int
+cnxk_mtr_connect(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
+{
+	return nix_mtr_connect(eth_dev, mtr_id);
+}
+
+int
+cnxk_mtr_destroy(struct rte_eth_dev *eth_dev, uint32_t mtr_id)
+{
+	struct rte_mtr_error mtr_error;
+
+	return nix_mtr_destroy(eth_dev, mtr_id, &mtr_error);
+}
+
+static int
+cnxk_mtr_configure(struct rte_eth_dev *eth_dev, const struct rte_flow_action actions[])
+{
+	uint32_t mtr_id = 0xffff, prev_mtr_id = 0xffff, next_mtr_id = 0xffff;
+	const struct rte_flow_action_meter *mtr_conf;
+	const struct rte_flow_action_queue *q_conf;
+	const struct rte_flow_action_rss *rss_conf;
+	struct cnxk_mtr_policy_node *policy;
+	bool is_mtr_act = false;
+	int tree_level = 0;
+	int rc = -EINVAL, i;
+
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
+			mtr_conf = (const struct rte_flow_action_meter *)(actions[i].conf);
+			mtr_id = mtr_conf->mtr_id;
+			is_mtr_act = true;
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+			q_conf = (const struct rte_flow_action_queue *)(actions[i].conf);
+			if (is_mtr_act)
+				nix_mtr_rq_update(eth_dev, mtr_id, 1, &q_conf->index);
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
+			rss_conf = (const struct rte_flow_action_rss *)(actions[i].conf);
+			if (is_mtr_act)
+				nix_mtr_rq_update(eth_dev, mtr_id, rss_conf->queue_num,
+						  rss_conf->queue);
+		}
+	}
+
+	if (!is_mtr_act)
+		return rc;
+
+	prev_mtr_id = mtr_id;
+	next_mtr_id = mtr_id;
+	while (next_mtr_id != 0xffff) {
+		rc = nix_mtr_validate(eth_dev, next_mtr_id);
+		if (rc)
+			return rc;
+
+		rc = nix_mtr_policy_act_get(eth_dev, next_mtr_id, &policy);
+		if (rc)
+			return rc;
+
+		rc = nix_mtr_color_action_validate(eth_dev, mtr_id, &prev_mtr_id, &next_mtr_id,
+						   policy, &tree_level);
+		if (rc)
+			return rc;
+	}
+
+	return nix_mtr_configure(eth_dev, mtr_id);
+}
+
+static int
+cnxk_rss_action_validate(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+			 const struct rte_flow_action *act)
+{
+	const struct rte_flow_action_rss *rss;
+
+	if (act == NULL)
+		return -EINVAL;
+
+	rss = (const struct rte_flow_action_rss *)act->conf;
+
+	if (attr->egress) {
+		plt_err("No support of RSS in egress");
+		return -EINVAL;
+	}
+
+	if (eth_dev->data->dev_conf.rxmode.mq_mode != RTE_ETH_MQ_RX_RSS) {
+		plt_err("multi-queue mode is disabled");
+		return -ENOTSUP;
+	}
+
+	if (!rss || !rss->queue_num) {
+		plt_err("no valid queues");
+		return -EINVAL;
+	}
+
+	if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
+		plt_err("non-default RSS hash functions are not supported");
+		return -ENOTSUP;
+	}
+
+	if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
+		plt_err("RSS hash key too large");
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+struct roc_npc_flow *
+cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
+		 const struct rte_flow_item pattern[], const struct rte_flow_action actions[],
+		 struct rte_flow_error *error)
+{
+	struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+	const struct rte_flow_action *action_rss = NULL;
+	const struct rte_flow_action_meter *mtr = NULL;
+	const struct rte_flow_action *act_q = NULL;
+	struct roc_npc_flow *flow;
+	void *mcs_flow = NULL;
+	uint32_t req_act = 0;
+	int i, rc;
+
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER)
+			req_act |= ROC_NPC_ACTION_TYPE_METER;
+
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+			req_act |= ROC_NPC_ACTION_TYPE_QUEUE;
+			act_q = &actions[i];
+		}
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_RSS) {
+			req_act |= ROC_NPC_ACTION_TYPE_RSS;
+			action_rss = &actions[i];
+		}
+	}
+
+	if (req_act & ROC_NPC_ACTION_TYPE_METER) {
+		if ((req_act & ROC_NPC_ACTION_TYPE_RSS) &&
+		    ((req_act & ROC_NPC_ACTION_TYPE_QUEUE))) {
+			return NULL;
+		}
+		if (req_act & ROC_NPC_ACTION_TYPE_RSS) {
+			rc = cnxk_rss_action_validate(eth_dev, attr, action_rss);
+			if (rc)
+				return NULL;
+		} else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) {
+			const struct rte_flow_action_queue *act_queue;
+			act_queue = (const struct rte_flow_action_queue *)act_q->conf;
+			if (act_queue->index > eth_dev->data->nb_rx_queues)
+				return NULL;
+		} else {
+			return NULL;
+		}
+	}
+	for (i = 0; actions[i].type != RTE_FLOW_ACTION_TYPE_END; i++) {
+		if (actions[i].type == RTE_FLOW_ACTION_TYPE_METER) {
+			mtr = (const struct rte_flow_action_meter *)actions[i].conf;
+			rc = cnxk_mtr_configure(eth_dev, actions);
+			if (rc) {
+				rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+						   "Failed to configure mtr ");
+				return NULL;
+			}
+			break;
+		}
+	}
+
+	if (actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY &&
+	    cnxk_eth_macsec_sess_get_by_sess(dev, actions[0].conf) != NULL) {
+		rc = cnxk_mcs_flow_configure(eth_dev, attr, pattern, actions, error, &mcs_flow);
+		if (rc) {
+			rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					   "Failed to configure mcs flow");
+			return NULL;
+		}
+		return mcs_flow;
+	}
+
+	flow = cnxk_flow_create_common(eth_dev, attr, pattern, actions, error, false);
+	if (!flow) {
+		if (mtr)
+			nix_mtr_chain_reset(eth_dev, mtr->mtr_id);
+
+		return NULL;
+	} else {
+		if (mtr)
+			cnxk_mtr_connect(eth_dev, mtr->mtr_id);
+	}
+
+	return flow;
+}
+
+int
+cnxk_flow_info_get_common(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			  struct rte_flow_queue_info *queue_info, struct rte_flow_error *err)
+{
+	RTE_SET_USED(dev);
+	RTE_SET_USED(err);
+
+	memset(port_info, 0, sizeof(*port_info));
+	memset(queue_info, 0, sizeof(*queue_info));
+
+	port_info->max_nb_counters = CNXK_NPC_COUNTERS_MAX;
+	port_info->max_nb_meters = CNXK_NIX_MTR_COUNT_MAX;
+
+	return 0;
+}
diff --git a/drivers/net/cnxk/cnxk_flow_common.h b/drivers/net/cnxk/cnxk_flow_common.h
new file mode 100644
index 0000000000..21289d9daf
--- /dev/null
+++ b/drivers/net/cnxk/cnxk_flow_common.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2024 Marvell.
+ */
+#ifndef __CNXK_FLOW_COMMON_H__
+#define __CNXK_FLOW_COMMON_H__
+
+#include <rte_flow_driver.h>
+
+struct roc_npc_flow *cnxk_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+				      const struct rte_flow_item pattern[],
+				      const struct rte_flow_action actions[],
+				      struct rte_flow_error *error);
+
+int cnxk_flow_info_get_common(struct rte_eth_dev *dev, struct rte_flow_port_info *port_info,
+			      struct rte_flow_queue_info *queue_info, struct rte_flow_error *err);
+
+#define CNXK_NPC_COUNTERS_MAX 512
+
+#endif /* __CNXK_FLOW_COMMON_H__ */
diff --git a/drivers/net/cnxk/meson.build b/drivers/net/cnxk/meson.build
index 32ff8aadc0..733ee61c0a 100644
--- a/drivers/net/cnxk/meson.build
+++ b/drivers/net/cnxk/meson.build
@@ -32,6 +32,7 @@ sources = files(
         'cnxk_eswitch_devargs.c',
         'cnxk_eswitch_flow.c',
         'cnxk_eswitch_rxtx.c',
+        'cnxk_flow_common.c',
         'cnxk_link.c',
         'cnxk_lookup.c',
         'cnxk_ptp.c',
@@ -236,6 +237,7 @@ if soc_type == 'cn20k' or soc_type == 'all'
 # CN20K
 sources += files(
         'cn20k_ethdev.c',
+        'cn20k_flow.c',
         'cn20k_rx_select.c',
         'cn20k_tx_select.c',
 )
-- 
2.39.2


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

end of thread, other threads:[~2024-11-12  9:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-10-21  4:01 [dpdk-dev] [PATCH 1/2] common/cnxk: support NPC flow on cn20k psatheesh
2024-10-21  4:01 ` [dpdk-dev] [PATCH 2/2] net/cnxk: support rte " psatheesh
2024-10-21 17:09   ` Stephen Hemminger
2024-10-29  7:31 ` [dpdk-dev] [PATCH v2 1/2] common/cnxk: support NPC " psatheesh
2024-10-29  7:31   ` [dpdk-dev] [PATCH v2 2/2] net/cnxk: support rte " psatheesh
2024-11-04 11:29     ` Jerin Jacob
2024-11-12  9:58 ` [dpdk-dev] [PATCH v3 1/2] common/cnxk: support NPC " psatheesh
2024-11-12  9:58   ` [dpdk-dev] [PATCH v3 2/2] net/cnxk: support rte " psatheesh

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).