diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index d1822f6b71..a62a7386ab 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -195,7 +195,7 @@ nfp_net_log_device_information(const struct nfp_net_hw *hw)
 			NFD_CFG_MAJOR_VERSION_of(hw->ver),
 			NFD_CFG_MINOR_VERSION_of(hw->ver), hw->max_mtu);
 
-	PMD_INIT_LOG(INFO, "CAP: %#x, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", hw->cap,
+	PMD_INIT_LOG(INFO, "CAP: %#x, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", hw->cap,
 			hw->cap & NFP_NET_CFG_CTRL_PROMISC   ? "PROMISC "   : "",
 			hw->cap & NFP_NET_CFG_CTRL_L2BC      ? "L2BCFILT "  : "",
 			hw->cap & NFP_NET_CFG_CTRL_L2MC      ? "L2MCFILT "  : "",
@@ -203,6 +203,7 @@ nfp_net_log_device_information(const struct nfp_net_hw *hw)
 			hw->cap & NFP_NET_CFG_CTRL_TXCSUM    ? "TXCSUM "    : "",
 			hw->cap & NFP_NET_CFG_CTRL_RXVLAN    ? "RXVLAN "    : "",
 			hw->cap & NFP_NET_CFG_CTRL_TXVLAN    ? "TXVLAN "    : "",
+			hw->cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ? "RXVLANv2 "  : "",
 			hw->cap & NFP_NET_CFG_CTRL_RXQINQ    ? "RXQINQ "    : "",
 			hw->cap & NFP_NET_CFG_CTRL_SCATTER   ? "SCATTER "   : "",
 			hw->cap & NFP_NET_CFG_CTRL_GATHER    ? "GATHER "    : "",
@@ -216,6 +217,15 @@ nfp_net_log_device_information(const struct nfp_net_hw *hw)
 			hw->max_rx_queues, hw->max_tx_queues);
 }
 
+static inline void
+nfp_net_enbable_rxvlan_cap(struct nfp_net_hw *hw, uint32_t *ctrl)
+{
+	if ((hw->cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0)
+		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2;
+	else if ((hw->cap & NFP_NET_CFG_CTRL_RXVLAN) != 0)
+		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
+}
+
 void
 nfp_net_enable_queues(struct rte_eth_dev *dev)
 {
@@ -397,10 +407,8 @@ nfp_check_offloads(struct rte_eth_dev *dev)
 			ctrl |= NFP_NET_CFG_CTRL_RXCSUM;
 	}
 
-	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) {
-		if (hw->cap & NFP_NET_CFG_CTRL_RXVLAN)
-			ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
-	}
+	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
+		nfp_net_enbable_rxvlan_cap(hw, &ctrl);
 
 	if (rxmode->offloads & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) {
 		if (hw->cap & NFP_NET_CFG_CTRL_RXQINQ)
@@ -754,7 +762,7 @@ nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	/* Next should change when PF support is implemented */
 	dev_info->max_mac_addrs = 1;
 
-	if (hw->cap & NFP_NET_CFG_CTRL_RXVLAN)
+	if (hw->cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2))
 		dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
 
 	if (hw->cap & NFP_NET_CFG_CTRL_RXQINQ)
@@ -1034,21 +1042,22 @@ nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	uint32_t new_ctrl, update;
 	struct nfp_net_hw *hw;
 	struct rte_eth_conf *dev_conf;
+	uint32_t rxvlan_ctrl;
 	int ret;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	dev_conf = &dev->data->dev_conf;
 	new_ctrl = hw->ctrl;
+	rxvlan_ctrl = 0;
 
-	/*
-	 * Vlan stripping setting
-	 * Enable or disable VLAN stripping
-	 */
+	nfp_net_enbable_rxvlan_cap(hw, &rxvlan_ctrl);
+
+	/* VLAN stripping setting */
 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
 		if (dev_conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP)
-			new_ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
+			new_ctrl |= rxvlan_ctrl;
 		else
-			new_ctrl &= ~NFP_NET_CFG_CTRL_RXVLAN;
+			new_ctrl &= ~rxvlan_ctrl;
 	}
 
 	/* QinQ stripping setting */
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index 106779c080..c7ebcf43b3 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -94,6 +94,7 @@
 #define   NFP_NET_CFG_CTRL_GATHER         (0x1 <<  9) /* Gather DMA */
 #define   NFP_NET_CFG_CTRL_LSO            (0x1 << 10) /* LSO/TSO */
 #define   NFP_NET_CFG_CTRL_RXQINQ         (0x1 << 13) /* Enable QINQ strip */
+#define   NFP_NET_CFG_CTRL_RXVLAN_V2      (0x1 << 15) /* Enable VLAN strip with metadata */
 #define   NFP_NET_CFG_CTRL_RINGCFG        (0x1 << 16) /* Ring runtime changes */
 #define   NFP_NET_CFG_CTRL_RSS            (0x1 << 17) /* RSS */
 #define   NFP_NET_CFG_CTRL_IRQMOD         (0x1 << 18) /* Interrupt moderation */
diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c
index 40f1702bde..2bc0eb2625 100644
--- a/drivers/net/nfp/nfp_rxtx.c
+++ b/drivers/net/nfp/nfp_rxtx.c
@@ -237,23 +237,30 @@ nfp_net_parse_meta_vlan(const struct nfp_meta_parsed *meta,
 {
 	struct nfp_net_hw *hw = rxq->hw;
 
-	if ((hw->ctrl & NFP_NET_CFG_CTRL_RXVLAN) == 0)
+	/* Skip if hardware don't support setting vlan. */
+	if ((hw->ctrl & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) == 0)
 		return;
 
 	/*
 	 * The nic support the two way to send the VLAN info,
-	 * 1. According the metadata to send the VLAN info
-	 * 2. According the descriptor to sned the VLAN info
+	 * 1. According the metadata to send the VLAN info when NFP_NET_CFG_CTRL_RXVLAN_V2
+	 * is set
+	 * 2. According the descriptor to sned the VLAN info when NFP_NET_CFG_CTRL_RXVLAN
+	 * is set
 	 *
 	 * If the nic doesn't send the VLAN info, it is not necessary
 	 * to do anything.
 	 */
-	if (meta->vlan_layer >= 1 && meta->vlan[0].offload != 0) {
-		mb->vlan_tci = rte_cpu_to_le_32(meta->vlan[0].tci);
-		mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
-	} else if ((rxd->rxd.flags & PCIE_DESC_RX_VLAN) != 0) {
-		mb->vlan_tci = rte_cpu_to_le_32(rxd->rxd.vlan);
-		mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+	if ((hw->ctrl & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0) {
+		if (meta->vlan_layer >= 1 && meta->vlan[0].offload != 0) {
+			mb->vlan_tci = rte_cpu_to_le_32(meta->vlan[0].tci);
+			mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+		}
+	} else if ((hw->ctrl & NFP_NET_CFG_CTRL_RXVLAN) != 0) {
+		if ((rxd->rxd.flags & PCIE_DESC_RX_VLAN) != 0) {
+			mb->vlan_tci = rte_cpu_to_le_32(rxd->rxd.vlan);
+			mb->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+		}
 	}
 }
 
