diff --git a/drivers/net/nfp/nfp_common.c b/drivers/net/nfp/nfp_common.c
index 0644f6f1a8..0bd95d050e 100644
--- a/drivers/net/nfp/nfp_common.c
+++ b/drivers/net/nfp/nfp_common.c
@@ -301,6 +301,48 @@ nfp_net_reconfig(struct nfp_net_hw *hw, uint32_t ctrl, uint32_t update)
 	return 0;
 }
 
+/**
+ * Reconfigure the NIC for the extend ctrl BAR.
+ *
+ * Write the update word to the BAR and ping the reconfig queue. Then poll
+ * until the firmware has acknowledged the update by zeroing the update word.
+ *
+ * @param hw
+ *   Device to reconfigure.
+ * @param ctrl_ext
+ *   The value for the first word of extend ctrl field in the BAR config.
+ * @param update
+ *   The value for the update field in the BAR config.
+ *
+ * @return
+ *   - (0) if OK to reconfigure the device.
+ *   - (EIO) if I/O err and fail to reconfigure the device.
+ */
+int
+nfp_net_ext_reconfig(struct nfp_net_hw *hw, uint32_t ctrl_ext, uint32_t update)
+{
+	int ret;
+
+	rte_spinlock_lock(&hw->reconfig_lock);
+
+	nn_cfg_writel(hw, NFP_NET_CFG_CTRL_WORD1, ctrl_ext);
+	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
+
+	rte_wmb();
+
+	ret = __nfp_net_reconfig(hw, update);
+
+	rte_spinlock_unlock(&hw->reconfig_lock);
+
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Error nft net ext reconfig: ctrl_ext=%#08x update=%#08x",
+				ctrl_ext, update);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 /*
  * Configure an Ethernet device. This function must be invoked first
  * before any other function in the Ethernet API. This function can
diff --git a/drivers/net/nfp/nfp_common.h b/drivers/net/nfp/nfp_common.h
index 47df0510c5..baa6752a44 100644
--- a/drivers/net/nfp/nfp_common.h
+++ b/drivers/net/nfp/nfp_common.h
@@ -423,6 +423,7 @@ nfp_pci_queue(struct rte_pci_device *pdev, uint16_t queue)
 
 /* Prototypes for common NFP functions */
 int nfp_net_reconfig(struct nfp_net_hw *hw, uint32_t ctrl, uint32_t update);
+int nfp_net_ext_reconfig(struct nfp_net_hw *hw, uint32_t ctrl_ext, uint32_t update);
 int nfp_net_configure(struct rte_eth_dev *dev);
 void nfp_net_log_device_information(const struct nfp_net_hw *hw);
 void nfp_net_enable_queues(struct rte_eth_dev *dev);
diff --git a/drivers/net/nfp/nfp_ctrl.h b/drivers/net/nfp/nfp_ctrl.h
index bca31ac311..ce31dea609 100644
--- a/drivers/net/nfp/nfp_ctrl.h
+++ b/drivers/net/nfp/nfp_ctrl.h
@@ -214,11 +214,19 @@
 /* Offload definitions */
 #define NFP_NET_N_VXLAN_PORTS  (NFP_NET_CFG_VXLAN_SZ / sizeof(uint16_t))
 
-/**
- * 64B reserved for future use (0x0080 - 0x00c0)
+/*
+ * 3 words reserved for extended ctrl words (0x0098 - 0x00a4)
+ * 3 words reserved for extended cap words (0x00a4 - 0x00b0)
+ * Currently only one word is used, can be extended in future.
  */
-#define NFP_NET_CFG_RESERVED            0x0080
-#define NFP_NET_CFG_RESERVED_SZ         0x0040
+#define NFP_NET_CFG_CTRL_WORD1          0x0098
+#define NFP_NET_CFG_CTRL_PKT_TYPE         (0x1 << 0)
+
+#define NFP_NET_CFG_CAP_WORD1           0x00a4
+
+/* 16B reserved for future use (0x00b0 - 0x00c0). */
+#define NFP_NET_CFG_RESERVED            0x00b0
+#define NFP_NET_CFG_RESERVED_SZ         0x0010
 
 /*
  * RSS configuration (0x0100 - 0x01ac):
diff --git a/drivers/net/nfp/nfp_ethdev.c b/drivers/net/nfp/nfp_ethdev.c
index 1ddb7a92ee..bd55a54d58 100644
--- a/drivers/net/nfp/nfp_ethdev.c
+++ b/drivers/net/nfp/nfp_ethdev.c
@@ -57,6 +57,8 @@ nfp_net_start(struct rte_eth_dev *dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	struct rte_intr_handle *intr_handle = pci_dev->intr_handle;
 	uint32_t new_ctrl, update = 0;
+	uint32_t cap_extend;
+	uint32_t ctrl_extend = 0;
 	struct nfp_net_hw *hw;
 	struct nfp_pf_dev *pf_dev;
 	struct nfp_app_fw_nic *app_fw_nic;
@@ -147,6 +149,15 @@ nfp_net_start(struct rte_eth_dev *dev)
 	if (nfp_net_reconfig(hw, new_ctrl, update) < 0)
 		return -EIO;
 
+	/* Enable packet type offload by extend ctrl word1. */
+	cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+	if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) != 0)
+		ctrl_extend = NFP_NET_CFG_CTRL_PKT_TYPE;
+
+	update = NFP_NET_CFG_UPDATE_GEN;
+	if (nfp_net_ext_reconfig(hw, ctrl_extend, update) < 0)
+		return -EIO;
+
 	/*
 	 * Allocating rte mbufs for configured rx queues.
 	 * This requires queues being enabled before
diff --git a/drivers/net/nfp/nfp_rxtx.c b/drivers/net/nfp/nfp_rxtx.c
index 26bf1543ac..1bf32c4853 100644
--- a/drivers/net/nfp/nfp_rxtx.c
+++ b/drivers/net/nfp/nfp_rxtx.c
@@ -304,6 +304,138 @@ nfp_net_parse_meta(struct nfp_net_rx_desc *rxds,
 	}
 }
 
+/**
+ * Set packet type to mbuf based on parsed structure.
+ *
+ * @param nfp_ptype
+ *   Packet type structure parsing from Rx descriptor.
+ * @param mb
+ *   Mbuf to set the packet type.
+ */
+static void
+nfp_net_set_ptype(const struct nfp_ptype_parsed *nfp_ptype, struct rte_mbuf *mb)
+{
+	uint32_t mbuf_ptype = RTE_PTYPE_L2_ETHER;
+	uint8_t nfp_tunnel_ptype = nfp_ptype->tunnel_ptype;
+
+	if (nfp_tunnel_ptype != NFP_NET_PTYPE_TUNNEL_NONE)
+		mbuf_ptype |= RTE_PTYPE_INNER_L2_ETHER;
+
+	switch (nfp_tunnel_ptype) {
+	case NFP_NET_PTYPE_TUNNEL_NONE:
+		break;
+	case NFP_NET_PTYPE_TUNNEL_VXLAN:
+		mbuf_ptype |= RTE_PTYPE_TUNNEL_VXLAN;
+		break;
+	case NFP_NET_PTYPE_TUNNEL_NVGRE:
+		mbuf_ptype |= RTE_PTYPE_TUNNEL_NVGRE;
+		break;
+	case NFP_NET_PTYPE_TUNNEL_GENEVE:
+		mbuf_ptype |= RTE_PTYPE_TUNNEL_GENEVE;
+		break;
+	default:
+		PMD_RX_LOG(DEBUG, "Unrecognized nfp tunnel packet type: %u",
+				nfp_tunnel_ptype);
+		break;
+	}
+
+	switch (nfp_ptype->l4_ptype) {
+	case NFP_NET_PTYPE_L4_NONE:
+		break;
+	case NFP_NET_PTYPE_L4_TCP:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_TCP);
+		break;
+	case NFP_NET_PTYPE_L4_UDP:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_UDP);
+		break;
+	case NFP_NET_PTYPE_L4_FRAG:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_FRAG);
+		break;
+	case NFP_NET_PTYPE_L4_NONFRAG:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_NONFRAG);
+		break;
+	case NFP_NET_PTYPE_L4_ICMP:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_ICMP);
+		break;
+	case NFP_NET_PTYPE_L4_SCTP:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L4_SCTP);
+		break;
+	default:
+		PMD_RX_LOG(DEBUG, "Unrecognized nfp layer 4 packet type: %u",
+				nfp_ptype->l4_ptype);
+		break;
+	}
+
+	switch (nfp_ptype->l3_ptype) {
+	case NFP_NET_PTYPE_L3_NONE:
+		break;
+	case NFP_NET_PTYPE_L3_IPV4:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV4);
+		break;
+	case NFP_NET_PTYPE_L3_IPV6:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV6);
+		break;
+	case NFP_NET_PTYPE_L3_IPV4_EXT:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV4_EXT);
+		break;
+	case NFP_NET_PTYPE_L3_IPV6_EXT:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV6_EXT);
+		break;
+	case NFP_NET_PTYPE_L3_IPV4_EXT_UNKNOWN:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV4_EXT_UNKNOWN);
+		break;
+	case NFP_NET_PTYPE_L3_IPV6_EXT_UNKNOWN:
+		mbuf_ptype |= NFP_PTYPE2RTE(nfp_tunnel_ptype, L3_IPV6_EXT_UNKNOWN);
+		break;
+	default:
+		PMD_RX_LOG(DEBUG, "Unrecognized nfp layer 3 packet type: %u",
+				nfp_ptype->l3_ptype);
+		break;
+	}
+
+	mb->packet_type = mbuf_ptype;
+}
+
+/**
+ * Parse the packet type from Rx descriptor and set to mbuf.
+ *
+ * @param rxds
+ *   Rx descriptor including the offloading info of packet type.
+ * @param hw
+ *   Device.
+ * @param mb
+ *   Mbuf to set the packet type.
+ */
+static void
+nfp_net_parse_ptype(struct nfp_net_rx_desc *rxds,
+		struct nfp_net_hw *hw,
+		struct rte_mbuf *mb)
+{
+	uint32_t cap_extend;
+	uint32_t ctrl_extend;
+	struct nfp_ptype_parsed nfp_ptype;
+	uint16_t rxd_ptype = rxds->rxd.offload_info;
+
+	if (rxd_ptype == 0 || (rxds->rxd.flags & PCIE_DESC_RX_VLAN) != 0)
+		return;
+
+	cap_extend = nn_cfg_readl(hw, NFP_NET_CFG_CAP_WORD1);
+	ctrl_extend = nn_cfg_readl(hw, NFP_NET_CFG_CTRL_WORD1);
+
+	if ((cap_extend & NFP_NET_CFG_CTRL_PKT_TYPE) == 0 ||
+			(ctrl_extend & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
+		return;
+
+	nfp_ptype.l4_ptype = (rxd_ptype & NFP_NET_PTYPE_L4_MASK) >>
+			NFP_NET_PTYPE_L4_OFFSET;
+	nfp_ptype.l3_ptype = (rxd_ptype & NFP_NET_PTYPE_L3_MASK) >>
+			NFP_NET_PTYPE_L3_OFFSET;
+	nfp_ptype.tunnel_ptype = (rxd_ptype & NFP_NET_PTYPE_TUNNEL_MASK) >>
+			NFP_NET_PTYPE_TUNNEL_OFFSET;
+
+	nfp_net_set_ptype(&nfp_ptype, mb);
+}
+
 /*
  * RX path design:
  *
@@ -438,6 +570,8 @@ nfp_net_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 		nfp_net_parse_meta(rxds, rxq, hw, mb);
 
+		nfp_net_parse_ptype(rxds, hw, mb);
+
 		/* Checking the checksum flag */
 		nfp_net_rx_cksum(rxq, rxds, mb);
 
diff --git a/drivers/net/nfp/nfp_rxtx.h b/drivers/net/nfp/nfp_rxtx.h
index 73ef0a7c9f..eebe9b3ee2 100644
--- a/drivers/net/nfp/nfp_rxtx.h
+++ b/drivers/net/nfp/nfp_rxtx.h
@@ -170,6 +170,89 @@ struct nfp_net_txq {
 #define PCIE_DESC_RX_L4_CSUM_OK         (PCIE_DESC_RX_TCP_CSUM_OK | \
 					 PCIE_DESC_RX_UDP_CSUM_OK)
 
+/*
+ * The bit format and map of nfp packet type for rxd.offload_info in Rx descriptor.
+ *
+ * Bit format about nfp packet type refers to the following:
+ * ---------------------------------
+ *            1                   0
+ *  5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           |tunnel |  l3 |  l4 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Bit map about nfp packet type refers to the following:
+ *
+ * L4: bit 0~2, used for layer 4 or inner layer 4.
+ * 000: NFP_NET_PTYPE_L4_NONE
+ * 001: NFP_NET_PTYPE_L4_TCP
+ * 010: NFP_NET_PTYPE_L4_UDP
+ * 011: NFP_NET_PTYPE_L4_FRAG
+ * 100: NFP_NET_PTYPE_L4_NONFRAG
+ * 101: NFP_NET_PTYPE_L4_ICMP
+ * 110: NFP_NET_PTYPE_L4_SCTP
+ * 111: reserved
+ *
+ * L3: bit 3~5, used for layer 3 or inner layer 3.
+ * 000: NFP_NET_PTYPE_L3_NONE
+ * 001: NFP_NET_PTYPE_L3_IPV6
+ * 010: NFP_NET_PTYPE_L3_IPV4
+ * 011: NFP_NET_PTYPE_L3_IPV4_EXT
+ * 100: NFP_NET_PTYPE_L3_IPV6_EXT
+ * 101: NFP_NET_PTYPE_L3_IPV4_EXT_UNKNOWN
+ * 110: NFP_NET_PTYPE_L3_IPV6_EXT_UNKNOWN
+ * 111: reserved
+ *
+ * Tunnel: bit 6~9, used for tunnel.
+ * 0000: NFP_NET_PTYPE_TUNNEL_NONE
+ * 0001: NFP_NET_PTYPE_TUNNEL_VXLAN
+ * 0100: NFP_NET_PTYPE_TUNNEL_NVGRE
+ * 0101: NFP_NET_PTYPE_TUNNEL_GENEVE
+ * 0010, 0011, 0110~1111: reserved
+ *
+ * Reserved: bit 10~15, used for extension.
+ */
+
+/* Mask and offset about nfp packet type based on the bit map above. */
+#define NFP_NET_PTYPE_L4_MASK                  0x0007
+#define NFP_NET_PTYPE_L3_MASK                  0x0038
+#define NFP_NET_PTYPE_TUNNEL_MASK              0x03c0
+
+#define NFP_NET_PTYPE_L4_OFFSET                0
+#define NFP_NET_PTYPE_L3_OFFSET                3
+#define NFP_NET_PTYPE_TUNNEL_OFFSET            6
+
+/* Case about nfp packet type based on the bit map above. */
+#define NFP_NET_PTYPE_L4_NONE                  0
+#define NFP_NET_PTYPE_L4_TCP                   1
+#define NFP_NET_PTYPE_L4_UDP                   2
+#define NFP_NET_PTYPE_L4_FRAG                  3
+#define NFP_NET_PTYPE_L4_NONFRAG               4
+#define NFP_NET_PTYPE_L4_ICMP                  5
+#define NFP_NET_PTYPE_L4_SCTP                  6
+
+#define NFP_NET_PTYPE_L3_NONE                  0
+#define NFP_NET_PTYPE_L3_IPV6                  1
+#define NFP_NET_PTYPE_L3_IPV4                  2
+#define NFP_NET_PTYPE_L3_IPV4_EXT              3
+#define NFP_NET_PTYPE_L3_IPV6_EXT              4
+#define NFP_NET_PTYPE_L3_IPV4_EXT_UNKNOWN      5
+#define NFP_NET_PTYPE_L3_IPV6_EXT_UNKNOWN      6
+
+#define NFP_NET_PTYPE_TUNNEL_NONE              0
+#define NFP_NET_PTYPE_TUNNEL_VXLAN             1
+#define NFP_NET_PTYPE_TUNNEL_NVGRE             4
+#define NFP_NET_PTYPE_TUNNEL_GENEVE            5
+
+#define NFP_PTYPE2RTE(tunnel, type) ((tunnel) ? RTE_PTYPE_INNER_##type : RTE_PTYPE_##type)
+
+/* Record NFP packet type parsed from rxd.offload_info. */
+struct nfp_ptype_parsed {
+	uint8_t l4_ptype;     /**< Packet type of layer 4, or inner layer 4. */
+	uint8_t l3_ptype;     /**< Packet type of layer 3, or inner layer 3. */
+	uint8_t tunnel_ptype; /**< Packet type of tunnel. */
+};
+
 struct nfp_net_rx_desc {
 	union {
 		/** Freelist descriptor. */
