diff --git a/doc/guides/nics/cnxk.rst b/doc/guides/nics/cnxk.rst
index 2927c6cb7e..7c82cb55e1 100644
--- a/doc/guides/nics/cnxk.rst
+++ b/doc/guides/nics/cnxk.rst
@@ -167,7 +167,30 @@ Runtime Config Options
 
    With the above configuration, higig2 will be enabled on that port and the
    traffic on this port should be higig2 traffic only. Supported switch header
-   types are "chlen24b", "chlen90b", "dsa", "exdsa", "higig2" and "vlan_exdsa".
+   types are "chlen24b", "chlen90b", "dsa", "exdsa", "higig2", "vlan_exdsa" and "pre_l2".
+
+- ``Flow pre l2 info`` (default ``0x0/0x0/0x0``)
+
+   In case of custom pre l2 headers, an offset, mask with in the offset and shift direction
+   has to be provided within the custom header that holds the size of the custom header.
+   This is valid only with switch header pre l2. Maximum supported offset range is 0 to 255
+   and mask range is 1 to 255 and shift direction, 0: left shift, 1: right shift.
+   Info format will be "offset/mask/shift direction". All parameters has to be in hexadecimal
+   format and mask should be contiguous. Info can be configured using
+   ``flow_pre_l2_info`` ``devargs`` parameter.
+
+   For example::
+
+      -a 0002:02:00.0,switch_header="pre_l2",flow_pre_l2_info=0x2/0x7e/0x1
+
+   With the above configuration, custom pre l2 header will be enabled on that port and size
+   of the header is placed at byte offset 0x2 in the packet with mask 0x7e and right shift will
+   be used to get the size. i.e size will be (pkt[0x2] & 0x7e) >> shift count.
+   Shift count will be calculated based on mask and shift direction. For example if mask is 0x7c
+   and shift direction is 1, i.e right shift, then the shift count will be 2 i.e absolute
+   position of the right most set bit. If the mask is 0x7c and shift direction is 0, i.e left
+   shift, then the shift count will be 1, i.e 8-n, where n is the absolute position of
+   left most set bit.
 
 - ``RSS tag as XOR`` (default ``0``)
 
diff --git a/drivers/common/cnxk/hw/npc.h b/drivers/common/cnxk/hw/npc.h
index 68c5037e1c..6f896de9f0 100644
--- a/drivers/common/cnxk/hw/npc.h
+++ b/drivers/common/cnxk/hw/npc.h
@@ -169,13 +169,12 @@ enum npc_kpu_la_ltype {
 	NPC_LT_LA_8023 = 1,
 	NPC_LT_LA_ETHER,
 	NPC_LT_LA_IH_NIX_ETHER,
-	NPC_LT_LA_IH_8_ETHER,
-	NPC_LT_LA_IH_4_ETHER,
-	NPC_LT_LA_IH_2_ETHER,
-	NPC_LT_LA_HIGIG2_ETHER,
+	NPC_LT_LA_HIGIG2_ETHER = 7,
 	NPC_LT_LA_IH_NIX_HIGIG2_ETHER,
-	NPC_LT_LA_CH_LEN_90B_ETHER,
+	NPC_LT_LA_CUSTOM_L2_90B_ETHER,
 	NPC_LT_LA_CPT_HDR,
+	NPC_LT_LA_CUSTOM_L2_24B_ETHER,
+	NPC_LT_LA_CUSTOM_PRE_L2_ETHER,
 	NPC_LT_LA_CUSTOM0 = 0xE,
 	NPC_LT_LA_CUSTOM1 = 0xF,
 };
@@ -185,7 +184,7 @@ enum npc_kpu_lb_ltype {
 	NPC_LT_LB_CTAG,
 	NPC_LT_LB_STAG_QINQ,
 	NPC_LT_LB_BTAG,
-	NPC_LT_LB_ITAG,
+	NPC_LT_LB_PPPOE,
 	NPC_LT_LB_DSA,
 	NPC_LT_LB_DSA_VLAN,
 	NPC_LT_LB_EDSA,
diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index b63fe108c9..4cffe9b182 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -313,6 +313,7 @@ struct npc_set_pkind {
 #define ROC_PRIV_FLAGS_LEN_90B	  BIT_ULL(3)
 #define ROC_PRIV_FLAGS_EXDSA	  BIT_ULL(4)
 #define ROC_PRIV_FLAGS_VLAN_EXDSA BIT_ULL(5)
+#define ROC_PRIV_FLAGS_PRE_L2	  BIT_ULL(6)
 #define ROC_PRIV_FLAGS_CUSTOM	  BIT_ULL(63)
 	uint64_t __io mode;
 #define PKIND_TX BIT_ULL(0)
diff --git a/drivers/common/cnxk/roc_nix.h b/drivers/common/cnxk/roc_nix.h
index 69a5e8e7b4..3f195f191a 100644
--- a/drivers/common/cnxk/roc_nix.h
+++ b/drivers/common/cnxk/roc_nix.h
@@ -714,7 +714,10 @@ void __roc_api roc_nix_mac_link_info_get_cb_unregister(struct roc_nix *roc_nix);
 
 /* Ops */
 int __roc_api roc_nix_switch_hdr_set(struct roc_nix *roc_nix,
-				     uint64_t switch_header_type);
+				     uint64_t switch_header_type,
+				     uint8_t pre_l2_size_offset,
+				     uint8_t pre_l2_size_offset_mask,
+				     uint8_t pre_l2_size_shift_dir);
 int __roc_api roc_nix_lso_fmt_setup(struct roc_nix *roc_nix);
 int __roc_api roc_nix_lso_fmt_get(struct roc_nix *roc_nix,
 				  uint8_t udp_tun[ROC_NIX_LSO_TUN_MAX],
diff --git a/drivers/common/cnxk/roc_nix_ops.c b/drivers/common/cnxk/roc_nix_ops.c
index 04a78cf4ca..8d3cddf2a6 100644
--- a/drivers/common/cnxk/roc_nix_ops.c
+++ b/drivers/common/cnxk/roc_nix_ops.c
@@ -364,7 +364,10 @@ roc_nix_lso_fmt_get(struct roc_nix *roc_nix,
 }
 
 int
-roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
+roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type,
+		       uint8_t pre_l2_size_offset,
+		       uint8_t pre_l2_size_offset_mask,
+		       uint8_t pre_l2_size_shift_dir)
 {
 	struct mbox *mbox = get_mbox(roc_nix);
 	struct npc_set_pkind *req;
@@ -380,6 +383,7 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
 	    switch_header_type != ROC_PRIV_FLAGS_LEN_90B &&
 	    switch_header_type != ROC_PRIV_FLAGS_EXDSA &&
 	    switch_header_type != ROC_PRIV_FLAGS_VLAN_EXDSA &&
+	    switch_header_type != ROC_PRIV_FLAGS_PRE_L2 &&
 	    switch_header_type != ROC_PRIV_FLAGS_CUSTOM) {
 		plt_err("switch header type is not supported");
 		return NIX_ERR_PARAM;
@@ -411,6 +415,12 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
 	} else if (switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
 		req->mode = ROC_PRIV_FLAGS_CUSTOM;
 		req->pkind = NPC_RX_VLAN_EXDSA_PKIND;
+	} else if (switch_header_type == ROC_PRIV_FLAGS_PRE_L2) {
+		req->mode = ROC_PRIV_FLAGS_CUSTOM;
+		req->pkind = NPC_RX_CUSTOM_PRE_L2_PKIND;
+		req->var_len_off = pre_l2_size_offset;
+		req->var_len_off_mask = pre_l2_size_offset_mask;
+		req->shift_dir = pre_l2_size_shift_dir;
 	}
 
 	req->dir = PKIND_RX;
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index 8c24126ae8..8b57678863 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -187,6 +187,14 @@ enum flow_vtag_cfg_dir { VTAG_TX, VTAG_RX };
 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
+					   */
+	uint8_t pre_l2_size_offset_mask; /**< Offset mask with in 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;
diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index 74f625553d..cacc117e50 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -1164,7 +1164,10 @@ cnxk_nix_configure(struct rte_eth_dev *eth_dev)
 		goto free_nix_lf;
 	}
 
-	rc = roc_nix_switch_hdr_set(nix, dev->npc.switch_header_type);
+	rc = roc_nix_switch_hdr_set(nix, dev->npc.switch_header_type,
+				    dev->npc.pre_l2_size_offset,
+				    dev->npc.pre_l2_size_offset_mask,
+				    dev->npc.pre_l2_size_shift_dir);
 	if (rc) {
 		plt_err("Failed to enable switch type nix_lf rc=%d", rc);
 		goto free_nix_lf;
@@ -1405,7 +1408,7 @@ cnxk_nix_dev_stop(struct rte_eth_dev *eth_dev)
 	void *rxq;
 
 	/* Disable switch hdr pkind */
-	roc_nix_switch_hdr_set(&dev->nix, 0);
+	roc_nix_switch_hdr_set(&dev->nix, 0, 0, 0, 0);
 
 	/* Stop link change events */
 	if (!roc_nix_is_vf_or_sdp(&dev->nix))
diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c
index ad7babdf52..157b27d9cb 100644
--- a/drivers/net/cnxk/cnxk_ethdev_devargs.c
+++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c
@@ -13,6 +13,12 @@ struct sdp_channel {
 	uint16_t mask;
 };
 
+struct flow_pre_l2_size_info {
+	uint8_t pre_l2_size_off;
+	uint8_t pre_l2_size_off_mask;
+	uint8_t pre_l2_size_shift_dir;
+};
+
 static int
 parse_outb_nb_desc(const char *key, const char *value, void *extra_args)
 {
@@ -124,6 +130,29 @@ parse_reta_size(const char *key, const char *value, void *extra_args)
 	return 0;
 }
 
+static int
+parse_pre_l2_hdr_info(const char *key, const char *value, void *extra_args)
+{
+	struct flow_pre_l2_size_info *info =
+		(struct flow_pre_l2_size_info *)extra_args;
+	char *tok1 = NULL, *tok2 = NULL;
+	uint16_t off, off_mask, dir;
+
+	RTE_SET_USED(key);
+	off = strtol(value, &tok1, 16);
+	tok1++;
+	off_mask = strtol(tok1, &tok2, 16);
+	tok2++;
+	dir = strtol(tok2, 0, 16);
+	if (off >= 256 || off_mask < 1 || off_mask >= 256 || dir > 1)
+		return -EINVAL;
+	info->pre_l2_size_off = off;
+	info->pre_l2_size_off_mask = off_mask;
+	info->pre_l2_size_shift_dir = dir;
+
+	return 0;
+}
+
 static int
 parse_flag(const char *key, const char *value, void *extra_args)
 {
@@ -167,6 +196,9 @@ parse_switch_header_type(const char *key, const char *value, void *extra_args)
 	if (strcmp(value, "vlan_exdsa") == 0)
 		*(uint16_t *)extra_args = ROC_PRIV_FLAGS_VLAN_EXDSA;
 
+	if (strcmp(value, "pre_l2") == 0)
+		*(uint16_t *)extra_args = ROC_PRIV_FLAGS_PRE_L2;
+
 	return 0;
 }
 
@@ -205,12 +237,14 @@ parse_sdp_channel_mask(const char *key, const char *value, void *extra_args)
 #define CNXK_FORCE_INB_INL_DEV	"force_inb_inl_dev"
 #define CNXK_OUTB_NB_CRYPTO_QS	"outb_nb_crypto_qs"
 #define CNXK_SDP_CHANNEL_MASK	"sdp_channel_mask"
+#define CNXK_FLOW_PRE_L2_INFO	"flow_pre_l2_info"
 
 int
 cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 {
 	uint16_t reta_sz = ROC_NIX_RSS_RETA_SZ_64;
 	uint16_t sqb_count = CNXK_NIX_TX_MAX_SQB;
+	struct flow_pre_l2_size_info pre_l2_info;
 	uint16_t ipsec_in_max_spi = BIT(8) - 1;
 	uint16_t ipsec_out_max_sa = BIT(12);
 	uint16_t flow_prealloc_size = 1;
@@ -226,6 +260,7 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 	struct rte_kvargs *kvlist;
 
 	memset(&sdp_chan, 0, sizeof(sdp_chan));
+	memset(&pre_l2_info, 0, sizeof(struct flow_pre_l2_size_info));
 
 	if (devargs == NULL)
 		goto null_devargs;
@@ -261,6 +296,8 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 			   &force_inb_inl_dev);
 	rte_kvargs_process(kvlist, CNXK_SDP_CHANNEL_MASK,
 			   &parse_sdp_channel_mask, &sdp_chan);
+	rte_kvargs_process(kvlist, CNXK_FLOW_PRE_L2_INFO,
+			   &parse_pre_l2_hdr_info, &pre_l2_info);
 	rte_kvargs_free(kvlist);
 
 null_devargs:
@@ -282,6 +319,9 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev)
 	dev->npc.sdp_channel = sdp_chan.channel;
 	dev->npc.sdp_channel_mask = sdp_chan.mask;
 	dev->npc.is_sdp_mask_set = sdp_chan.is_sdp_mask_set;
+	dev->npc.pre_l2_size_offset = pre_l2_info.pre_l2_size_off;
+	dev->npc.pre_l2_size_offset_mask = pre_l2_info.pre_l2_size_off_mask;
+	dev->npc.pre_l2_size_shift_dir = pre_l2_info.pre_l2_size_shift_dir;
 	return 0;
 exit:
 	return -EINVAL;
@@ -297,6 +337,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_cnxk,
 			      CNXK_RSS_TAG_AS_XOR "=1"
 			      CNXK_IPSEC_IN_MAX_SPI "=<1-65535>"
 			      CNXK_OUTB_NB_DESC "=<1-65535>"
+			      CNXK_FLOW_PRE_L2_INFO "=<0-255>/<1-255>/<0-1>"
 			      CNXK_OUTB_NB_CRYPTO_QS "=<1-64>"
 			      CNXK_FORCE_INB_INL_DEV "=1"
 			      CNXK_SDP_CHANNEL_MASK "=<1-4095>/<1-4095>");
