diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 089f86fec7..f8a550ba54 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -521,6 +521,10 @@ struct bnxt {
 	uint16_t		max_stat_ctx;
 	uint16_t		first_vf_id;
 	uint16_t		vlan;
+#define BNXT_OUTER_TPID_MASK	0x0000ffff
+#define BNXT_OUTER_TPID_BD_MASK	0xffff0000
+#define BNXT_OUTER_TPID_BD_SHFT	16
+	uint32_t		outer_tpid_bd;
 	struct bnxt_pf_info	pf;
 	uint8_t			port_partition_type;
 	uint8_t			dev_stopped;
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 5985963bf7..b3a37e1554 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -151,6 +151,7 @@ static const struct rte_pci_id bnxt_pci_id_map[] = {
 				     DEV_TX_OFFLOAD_GRE_TNL_TSO | \
 				     DEV_TX_OFFLOAD_IPIP_TNL_TSO | \
 				     DEV_TX_OFFLOAD_GENEVE_TNL_TSO | \
+				     DEV_TX_OFFLOAD_QINQ_INSERT | \
 				     DEV_TX_OFFLOAD_MULTI_SEGS)
 
 #define BNXT_DEV_RX_OFFLOAD_SUPPORT (DEV_RX_OFFLOAD_VLAN_FILTER | \
@@ -161,6 +162,7 @@ static const struct rte_pci_id bnxt_pci_id_map[] = {
 				     DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | \
 				     DEV_RX_OFFLOAD_JUMBO_FRAME | \
 				     DEV_RX_OFFLOAD_KEEP_CRC | \
+				     DEV_RX_OFFLOAD_VLAN_EXTEND | \
 				     DEV_RX_OFFLOAD_TCP_LRO)
 
 static int bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask);
@@ -1831,15 +1833,77 @@ bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
 			!!(rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP));
 	}
 
-	if (mask & ETH_VLAN_EXTEND_MASK)
-		PMD_DRV_LOG(ERR, "Extend VLAN Not supported\n");
+	if (mask & ETH_VLAN_EXTEND_MASK) {
+		if (rx_offloads & DEV_RX_OFFLOAD_VLAN_EXTEND)
+			PMD_DRV_LOG(DEBUG, "Extend VLAN supported\n");
+		else
+			PMD_DRV_LOG(INFO, "Extend VLAN unsupported\n");
+	}
+
+	return 0;
+}
+
+static int
+bnxt_vlan_tpid_set_op(struct rte_eth_dev *dev, enum rte_vlan_type vlan_type,
+		      uint16_t tpid)
+{
+	struct bnxt *bp = dev->data->dev_private;
+	int qinq = dev->data->dev_conf.rxmode.offloads &
+		   DEV_RX_OFFLOAD_VLAN_EXTEND;
+
+	if (vlan_type != ETH_VLAN_TYPE_INNER &&
+	    vlan_type != ETH_VLAN_TYPE_OUTER) {
+		PMD_DRV_LOG(ERR,
+			    "Unsupported vlan type.");
+		return -EINVAL;
+	}
+	if (!qinq) {
+		PMD_DRV_LOG(ERR,
+			    "QinQ not enabled. Needs to be ON as we can "
+			    "accelerate only outer vlan\n");
+		return -EINVAL;
+	}
+
+	if (vlan_type == ETH_VLAN_TYPE_OUTER) {
+		switch (tpid) {
+		case RTE_ETHER_TYPE_QINQ:
+			bp->outer_tpid_bd =
+				TX_BD_LONG_CFA_META_VLAN_TPID_TPID88A8;
+				break;
+		case RTE_ETHER_TYPE_VLAN:
+			bp->outer_tpid_bd =
+				TX_BD_LONG_CFA_META_VLAN_TPID_TPID8100;
+				break;
+		case 0x9100:
+			bp->outer_tpid_bd =
+				TX_BD_LONG_CFA_META_VLAN_TPID_TPID9100;
+				break;
+		case 0x9200:
+			bp->outer_tpid_bd =
+				TX_BD_LONG_CFA_META_VLAN_TPID_TPID9200;
+				break;
+		case 0x9300:
+			bp->outer_tpid_bd =
+				 TX_BD_LONG_CFA_META_VLAN_TPID_TPID9300;
+				break;
+		default:
+			PMD_DRV_LOG(ERR, "Invalid TPID: %x\n", tpid);
+			return -EINVAL;
+		}
+		bp->outer_tpid_bd |= tpid;
+		PMD_DRV_LOG(INFO, "outer_tpid_bd = %x\n", bp->outer_tpid_bd);
+	} else if (vlan_type == ETH_VLAN_TYPE_INNER) {
+		PMD_DRV_LOG(ERR,
+			    "Can accelerate only outer vlan in QinQ\n");
+		return -EINVAL;
+	}
 
 	return 0;
 }
 
 static int
 bnxt_set_default_mac_addr_op(struct rte_eth_dev *dev,
-			struct rte_ether_addr *addr)
+			     struct rte_ether_addr *addr)
 {
 	struct bnxt *bp = dev->data->dev_private;
 	/* Default Filter is tied to VNIC 0 */
@@ -3534,6 +3598,7 @@ static const struct eth_dev_ops bnxt_dev_ops = {
 	.udp_tunnel_port_del  = bnxt_udp_tunnel_port_del_op,
 	.vlan_filter_set = bnxt_vlan_filter_set_op,
 	.vlan_offload_set = bnxt_vlan_offload_set_op,
+	.vlan_tpid_set = bnxt_vlan_tpid_set_op,
 	.vlan_pvid_set = bnxt_vlan_pvid_set_op,
 	.mtu_set = bnxt_mtu_set_op,
 	.mac_addr_set = bnxt_set_default_mac_addr_op,
diff --git a/drivers/net/bnxt/bnxt_txr.c b/drivers/net/bnxt/bnxt_txr.c
index 99d2009055..0ed6581bed 100644
--- a/drivers/net/bnxt/bnxt_txr.c
+++ b/drivers/net/bnxt/bnxt_txr.c
@@ -134,6 +134,7 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
 				struct tx_bd_long **last_txbd)
 {
 	struct bnxt_tx_ring_info *txr = txq->tx_ring;
+	uint32_t outer_tpid_bd = 0;
 	struct tx_bd_long *txbd;
 	struct tx_bd_long_hi *txbd1 = NULL;
 	uint32_t vlan_tag_flags, cfa_action;
@@ -155,7 +156,8 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
 				PKT_TX_UDP_CKSUM | PKT_TX_IP_CKSUM |
 				PKT_TX_VLAN_PKT | PKT_TX_OUTER_IP_CKSUM |
 				PKT_TX_TUNNEL_GRE | PKT_TX_TUNNEL_VXLAN |
-				PKT_TX_TUNNEL_GENEVE | PKT_TX_IEEE1588_TMST))
+				PKT_TX_TUNNEL_GENEVE | PKT_TX_IEEE1588_TMST |
+				PKT_TX_QINQ_PKT))
 		long_bd = true;
 
 	nr_bds = long_bd + tx_pkt->nb_segs;
@@ -209,7 +211,14 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
 		txbd->flags_type |= TX_BD_LONG_TYPE_TX_BD_LONG;
 		vlan_tag_flags = 0;
 		cfa_action = 0;
-		if (tx_buf->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
+		/* HW can accelerate only outer vlan in QinQ mode */
+		if (tx_buf->mbuf->ol_flags & PKT_TX_QINQ_PKT) {
+			vlan_tag_flags = TX_BD_LONG_CFA_META_KEY_VLAN_TAG |
+				tx_buf->mbuf->vlan_tci_outer;
+			outer_tpid_bd = txq->bp->outer_tpid_bd &
+				BNXT_OUTER_TPID_BD_MASK;
+			vlan_tag_flags |= outer_tpid_bd;
+		} else if (tx_buf->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
 			/* shurd: Should this mask at
 			 * TX_BD_LONG_CFA_META_VLAN_VID_MASK?
 			 */
