diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index ec1aad9..405d94d 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -97,9 +97,16 @@ struct bnxt_vlan_table_entry {
 	uint16_t		vid;
 } __attribute__((packed));
 
+struct bnxt_vlan_antispoof_table_entry {
+	uint16_t		tpid;
+	uint16_t		vid;
+	uint16_t		mask;
+} __attribute__((packed));
+
 struct bnxt_child_vf_info {
 	void			*req_buf;
 	struct bnxt_vlan_table_entry	*vlan_table;
+	struct bnxt_vlan_antispoof_table_entry	*vlan_as_table;
 	STAILQ_HEAD(, bnxt_filter_info)	filter;
 	uint32_t		func_cfg_flags;
 	uint32_t		l2_rx_mask;
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 231f06b..a82cc81 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -282,6 +282,44 @@ int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp,
 	return rc;
 }
 
+int bnxt_hwrm_cfa_vlan_antispoof_cfg(struct bnxt *bp, uint16_t fid,
+			uint16_t vlan_count,
+			struct bnxt_vlan_antispoof_table_entry *vlan_table)
+{
+	int rc = 0;
+	struct hwrm_cfa_vlan_antispoof_cfg_input req = {.req_type = 0 };
+	struct hwrm_cfa_vlan_antispoof_cfg_output *resp =
+						bp->hwrm_cmd_resp_addr;
+
+	/*
+	 * Older HWRM versions did not support this command, and the set_rx_mask
+	 * list was used for anti-spoof. In 1.8.0, the TX path configuration was
+	 * removed from set_rx_mask call, and this command was added.
+	 *
+	 * This command is also present from 1.7.8.11 and higher,
+	 * as well as 1.7.8.0
+	 */
+	if (bp->fw_ver < ((1 << 24) | (8 << 16))) {
+		if (bp->fw_ver != ((1 << 24) | (7 << 16) | (8 << 8))) {
+			if (bp->fw_ver < ((1 << 24) | (7 << 16) | (8 << 8) |
+					(11)))
+				return 0;
+		}
+	}
+	HWRM_PREP(req, CFA_VLAN_ANTISPOOF_CFG, -1, resp);
+	req.fid = rte_cpu_to_le_16(fid);
+
+	req.vlan_tag_mask_tbl_addr =
+		rte_cpu_to_le_64(rte_mem_virt2phy(vlan_table));
+	req.num_vlan_entries = rte_cpu_to_le_32((uint32_t)vlan_count);
+
+	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+	HWRM_CHECK_RESULT;
+
+	return rc;
+}
+
 int bnxt_hwrm_clear_filter(struct bnxt *bp,
 			   struct bnxt_filter_info *filter)
 {
@@ -389,6 +427,17 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 				else
 					rte_mem_lock_page(
 						bp->pf.vf_info[i].vlan_table);
+				bp->pf.vf_info[i].vlan_as_table =
+					rte_zmalloc("VF VLAN AS table",
+						    getpagesize(),
+						    getpagesize());
+				if (bp->pf.vf_info[i].vlan_as_table == NULL)
+					RTE_LOG(ERR, PMD,
+					"Alloc VLAN AS table for VF %d fail\n",
+					i);
+				else
+					rte_mem_lock_page(
+					       bp->pf.vf_info[i].vlan_as_table);
 				STAILQ_INIT(&bp->pf.vf_info[i].filter);
 			}
 		}
diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h
index dd0999a..51cd0dd 100644
--- a/drivers/net/bnxt/bnxt_hwrm.h
+++ b/drivers/net/bnxt/bnxt_hwrm.h
@@ -48,6 +48,9 @@ int bnxt_hwrm_cfa_l2_clear_rx_mask(struct bnxt *bp,
 int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, struct bnxt_vnic_info *vnic,
 				 uint16_t vlan_count,
 				 struct bnxt_vlan_table_entry *vlan_table);
+int bnxt_hwrm_cfa_vlan_antispoof_cfg(struct bnxt *bp, uint16_t fid,
+			uint16_t vlan_count,
+			struct bnxt_vlan_antispoof_table_entry *vlan_table);
 int bnxt_hwrm_clear_filter(struct bnxt *bp,
 			   struct bnxt_filter_info *filter);
 int bnxt_hwrm_set_filter(struct bnxt *bp,
diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h
index 1eb8d33..cb8660a 100644
--- a/drivers/net/bnxt/hsi_struct_def_dpdk.h
+++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h
@@ -123,7 +123,7 @@
 #define HWRM_CFA_L2_FILTER_CFG		(UINT32_C(0x92))
 #define HWRM_CFA_L2_SET_RX_MASK		(UINT32_C(0x93))
     /* Reserved for future use */
-#define RESERVED4			(UINT32_C(0x94))
+#define HWRM_CFA_VLAN_ANTISPOOF_CFG	(UINT32_C(0x94))
 #define HWRM_CFA_TUNNEL_FILTER_ALLOC	(UINT32_C(0x95))
 #define HWRM_CFA_TUNNEL_FILTER_FREE	(UINT32_C(0x96))
 #define HWRM_CFA_NTUPLE_FILTER_ALLOC	(UINT32_C(0x99))
@@ -9471,6 +9471,85 @@ struct hwrm_cfa_l2_set_rx_mask_output {
 	 */
 } __attribute__((packed));
 
+/* hwrm_cfa_vlan_antispoof_cfg */
+/* Description: Configures vlan anti-spoof filters for VF. */
+/* Input (32 bytes) */
+struct hwrm_cfa_vlan_antispoof_cfg_input {
+	uint16_t req_type;
+	/*
+	 * This value indicates what type of request this is. The format for the
+	 * rest of the command is determined by this field.
+	 */
+	uint16_t cmpl_ring;
+	/*
+	 * This value indicates the what completion ring the request will be
+	 * optionally completed on. If the value is -1, then no CR completion
+	 * will be generated. Any other value must be a valid CR ring_id value
+	 * for this function.
+	 */
+	uint16_t seq_id;
+	/* This value indicates the command sequence number. */
+	uint16_t target_id;
+	/*
+	 * Target ID of this command. 0x0 - 0xFFF8 - Used for function ids
+	 * 0xFFF8 - 0xFFFE - Reserved for internal processors 0xFFFF - HWRM
+	 */
+	uint64_t resp_addr;
+	/*
+	 * This is the host address where the response will be written when the
+	 * request is complete. This area must be 16B aligned and must be
+	 * cleared to zero before the request is made.
+	 */
+	uint16_t fid;
+	/*
+	 * Function ID of the function that is being configured. Only valid for
+	 * a VF FID configured by the PF.
+	 */
+	uint8_t unused_0;
+	uint8_t unused_1;
+	uint32_t num_vlan_entries;
+	/* Number of VLAN entries in the vlan_tag_mask_tbl. */
+	uint64_t vlan_tag_mask_tbl_addr;
+	/*
+	 * The vlan_tag_mask_tbl_addr is the DMA address of the VLAN antispoof
+	 * table. Each table entry contains the 16-bit TPID (0x8100 or 0x88a8
+	 * only), 16-bit VLAN ID, and a 16-bit mask, all in network order to
+	 * match hwrm_cfa_l2_set_rx_mask. For an individual VLAN entry, the mask
+	 * value should be 0xfff for the 12-bit VLAN ID.
+	 */
+};
+
+/* Output (16 bytes) */
+struct hwrm_cfa_vlan_antispoof_cfg_output {
+	uint16_t error_code;
+	/*
+	 * Pass/Fail or error type Note: receiver to verify the in parameters,
+	 * and fail the call with an error when appropriate
+	 */
+	uint16_t req_type;
+	/* This field returns the type of original request. */
+	uint16_t seq_id;
+	/* This field provides original sequence number of the command. */
+	uint16_t resp_len;
+	/*
+	 * This field is the length of the response in bytes. The last byte of
+	 * the response is a valid flag that will read as '1' when the command
+	 * has been completely written to memory.
+	 */
+	uint32_t unused_0;
+	uint8_t unused_1;
+	uint8_t unused_2;
+	uint8_t unused_3;
+	uint8_t valid;
+	/*
+	 * This field is used in Output records to indicate that the output is
+	 * completely written to RAM. This field should be read as '1' to
+	 * indicate that the output has been completely written. When writing a
+	 * command completion or response to an internal processor, the order of
+	 * writes has to be such that this field is written last.
+	 */
+};
+
 /* hwrm_tunnel_dst_port_query */
 /*
  * Description: This function is called by a driver to query tunnel type
diff --git a/drivers/net/bnxt/rte_pmd_bnxt.c b/drivers/net/bnxt/rte_pmd_bnxt.c
index 0d48873..b43ef9c 100644
--- a/drivers/net/bnxt/rte_pmd_bnxt.c
+++ b/drivers/net/bnxt/rte_pmd_bnxt.c
@@ -299,8 +299,6 @@ int rte_pmd_bnxt_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
 	struct rte_eth_dev *dev;
 	struct bnxt *bp;
 	int rc;
-	int dflt_vnic;
-	struct bnxt_vnic_info vnic;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
 
@@ -327,25 +325,11 @@ int rte_pmd_bnxt_set_vf_vlan_anti_spoof(uint8_t port, uint16_t vf, uint8_t on)
 	if (!rc) {
 		bp->pf.vf_info[vf].vlan_spoof_en = on;
 		if (on) {
-			dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf);
-			if (dflt_vnic < 0) {
-				/*
-				 * This simply indicates there's no driver
-				 * loaded.  This is not an error.
-				 */
-				RTE_LOG(INFO, PMD,
-				      "Unable to get default VNIC for VF %d\n",
-					vf);
-			} else {
-				vnic.fw_vnic_id = dflt_vnic;
-				if (bnxt_hwrm_vnic_qcfg(bp,
-					&vnic, bp->pf.first_vf_id + vf) == 0) {
-					if (bnxt_hwrm_cfa_l2_set_rx_mask(bp,
-					   &vnic, bp->pf.vf_info[vf].vlan_count,
-					   bp->pf.vf_info[vf].vlan_table))
-						rc = -1;
-				}
-			}
+			if (bnxt_hwrm_cfa_vlan_antispoof_cfg(bp,
+				bp->pf.first_vf_id + vf,
+				bp->pf.vf_info[vf].vlan_count,
+				bp->pf.vf_info[vf].vlan_as_table))
+				rc = -1;
 		}
 	} else {
 		RTE_LOG(ERR, PMD, "Failed to update VF VNIC %d.\n", vf);
@@ -451,10 +435,47 @@ int rte_pmd_bnxt_set_vf_rxmode(uint8_t port, uint16_t vf,
 	return rc;
 }
 
+static int bnxt_set_vf_table(struct bnxt *bp, uint16_t vf)
+{
+	int rc;
+	int dflt_vnic;
+	struct bnxt_vnic_info vnic;
+
+	if (!BNXT_PF(bp)) {
+		RTE_LOG(ERR, PMD,
+			"Attempt to set VLAN table on non-PF port!\n");
+		return -EINVAL;
+	}
+
+	if (vf >= bp->pdev->max_vfs)
+		return -EINVAL;
+
+	dflt_vnic = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf);
+	if (dflt_vnic < 0) {
+		/* This simply indicates there's no driver loaded.
+		 * This is not an error.
+		 */
+		RTE_LOG(ERR, PMD, "Unable to get default VNIC for VF %d\n", vf);
+	} else {
+		memset(&vnic, 0, sizeof(vnic));
+		vnic.fw_vnic_id = dflt_vnic;
+		if (bnxt_hwrm_vnic_qcfg(bp, &vnic,
+					bp->pf.first_vf_id + vf) == 0) {
+			if (bnxt_hwrm_cfa_l2_set_rx_mask(bp, &vnic,
+						bp->pf.vf_info[vf].vlan_count,
+						bp->pf.vf_info[vf].vlan_table))
+				rc = -1;
+		}
+	}
+
+	return rc;
+}
+
 int rte_pmd_bnxt_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
 				    uint64_t vf_mask, uint8_t vlan_on)
 {
 	struct bnxt_vlan_table_entry *ve;
+	struct bnxt_vlan_antispoof_table_entry *vase;
 	struct rte_eth_dev *dev;
 	struct bnxt *bp;
 	uint16_t cnt;
@@ -478,6 +499,10 @@ int rte_pmd_bnxt_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
 				rc = -1;
 				continue;
 			}
+			if (bp->pf.vf_info[i].vlan_as_table == NULL) {
+				rc = -1;
+				continue;
+			}
 			if (vlan_on) {
 				/* First, search for a duplicate... */
 				for (j = 0; j < cnt; j++) {
@@ -488,14 +513,13 @@ int rte_pmd_bnxt_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
 				}
 				if (j == cnt) {
 					/* Now check that there's space */
-					if (cnt == getpagesize() /
-					 sizeof(struct bnxt_vlan_table_entry)) {
+					if (cnt == getpagesize() / sizeof(struct
+					    bnxt_vlan_antispoof_table_entry)) {
 						RTE_LOG(ERR, PMD,
-						  "VF %d VLAN table is full\n",
-						  i);
+					    "VLAN anti-spoof table is full\n");
 						RTE_LOG(ERR, PMD,
-							"cannot add VLAN %u\n",
-							vlan);
+						   "VF %d cannot add VLAN %u\n",
+							i, vlan);
 						rc = -1;
 						continue;
 					}
@@ -506,6 +530,12 @@ int rte_pmd_bnxt_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
 					 * And finally, add to the
 					 * end of the table
 					 */
+					vase =
+					&bp->pf.vf_info[i].vlan_as_table[cnt];
+					// TODO: Hardcoded TPID
+					vase->tpid = rte_cpu_to_be_16(0x8100);
+					vase->vid = rte_cpu_to_be_16(vlan);
+					vase->mask = rte_cpu_to_be_16(0xfff);
 					ve = &bp->pf.vf_info[i].vlan_table[cnt];
 					/* TODO: Hardcoded TPID */
 					ve->tpid = rte_cpu_to_be_16(0x8100);
@@ -523,12 +553,17 @@ int rte_pmd_bnxt_set_vf_vlan_filter(uint8_t port, uint16_t vlan,
 					    getpagesize() -
 					    ((j + 1) *
 					 sizeof(struct bnxt_vlan_table_entry)));
+					memmove(
+					    &bp->pf.vf_info[i].vlan_as_table[j],
+					&bp->pf.vf_info[i].vlan_as_table[j + 1],
+					    getpagesize() -
+					    ((j + 1) * sizeof(struct
+					    bnxt_vlan_antispoof_table_entry)));
 					j--;
 					cnt = --bp->pf.vf_info[i].vlan_count;
 				}
 			}
-			rte_pmd_bnxt_set_vf_vlan_anti_spoof(dev->data->port_id,
-					 i, bp->pf.vf_info[i].vlan_spoof_en);
+			bnxt_set_vf_table(bp, i);
 		}
 	}
 
