diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c
index 0afde86..e9aac27 100644
--- a/drivers/net/bnxt/bnxt_filter.c
+++ b/drivers/net/bnxt/bnxt_filter.c
@@ -68,6 +68,22 @@ struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp)
 	return filter;
 }
 
+struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf)
+{
+	struct bnxt_filter_info *filter;
+
+	filter = rte_zmalloc("bnxt_vf_filter_info", sizeof(*filter), 0);
+	if (!filter) {
+		RTE_LOG(ERR, PMD, "Failed to alloc memory for VF %hu filters\n",
+			vf);
+		return NULL;
+	}
+
+	filter->fw_l2_filter_id = UINT64_MAX;
+	STAILQ_INSERT_TAIL(&bp->pf.vf_info[vf].filter, filter, next);
+	return filter;
+}
+
 void bnxt_init_filters(struct bnxt *bp)
 {
 	struct bnxt_filter_info *filter;
@@ -102,6 +118,12 @@ void bnxt_free_all_filters(struct bnxt *bp)
 			STAILQ_INIT(&vnic->filter);
 		}
 	}
+
+	for (i = 0; i < bp->pf.max_vfs; i++) {
+		STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) {
+			bnxt_hwrm_clear_filter(bp, filter);
+		}
+	}
 }
 
 void bnxt_free_filter_mem(struct bnxt *bp)
diff --git a/drivers/net/bnxt/bnxt_filter.h b/drivers/net/bnxt/bnxt_filter.h
index 353b7f7..613b2ee 100644
--- a/drivers/net/bnxt/bnxt_filter.h
+++ b/drivers/net/bnxt/bnxt_filter.h
@@ -68,6 +68,7 @@ struct bnxt_filter_info {
 };
 
 struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp);
+struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf);
 void bnxt_init_filters(struct bnxt *bp);
 void bnxt_free_all_filters(struct bnxt *bp);
 void bnxt_free_filter_mem(struct bnxt *bp);
diff --git a/drivers/net/bnxt/rte_pmd_bnxt.c b/drivers/net/bnxt/rte_pmd_bnxt.c
index 82fe313..a2bd39e 100644
--- a/drivers/net/bnxt/rte_pmd_bnxt.c
+++ b/drivers/net/bnxt/rte_pmd_bnxt.c
@@ -540,3 +540,76 @@ int rte_pmd_bnxt_get_vf_tx_drop_count(uint8_t port, uint16_t vf_id,
 	return bnxt_hwrm_func_qstats_tx_drop(bp, bp->pf.first_vf_id + vf_id,
 					     count);
 }
+
+int rte_pmd_bnxt_mac_addr_add(uint8_t port, struct ether_addr *addr,
+				uint32_t vf_id)
+{
+	struct rte_eth_dev *dev;
+	struct rte_eth_dev_info dev_info;
+	struct bnxt *bp;
+	struct bnxt_filter_info *filter;
+	struct bnxt_vnic_info vnic;
+	struct ether_addr dflt_mac;
+	int rc;
+
+	dev = &rte_eth_devices[port];
+	rte_eth_dev_info_get(port, &dev_info);
+	bp = (struct bnxt *)dev->data->dev_private;
+
+	if (vf_id >= dev_info.max_vfs)
+		return -EINVAL;
+
+	if (!BNXT_PF(bp)) {
+		RTE_LOG(ERR, PMD,
+			"Attempt to config VF %d MAC on non-PF port %d!\n",
+			vf_id, port);
+		return -ENOTSUP;
+	}
+
+	/* If the VF currently uses a random MAC, update default to this one */
+	if (bp->pf.vf_info[vf_id].random_mac) {
+		if (rte_pmd_bnxt_get_vf_rx_status(port, vf_id) <= 0)
+			rc = bnxt_hwrm_func_vf_mac(bp, vf_id, (uint8_t *)addr);
+	}
+
+	/* query the default VNIC id used by the function */
+	rc = bnxt_hwrm_func_qcfg_vf_dflt_vnic_id(bp, vf_id);
+	if (rc < 0)
+		goto exit;
+
+	memset(&vnic, 0, sizeof(struct bnxt_vnic_info));
+	vnic.fw_vnic_id = rte_le_to_cpu_16(rc);
+	rc = bnxt_hwrm_vnic_qcfg(bp, &vnic, bp->pf.first_vf_id + vf_id);
+	if (rc < 0)
+		goto exit;
+
+	STAILQ_FOREACH(filter, &bp->pf.vf_info[vf_id].filter, next) {
+		if (filter->flags ==
+		    HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX &&
+		    filter->enables ==
+		    (HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
+		     HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK) &&
+		    memcmp(addr, filter->l2_addr, ETHER_ADDR_LEN) == 0) {
+			bnxt_hwrm_clear_filter(bp, filter);
+			break;
+		}
+	}
+
+	if (filter == NULL)
+		filter = bnxt_alloc_vf_filter(bp, vf_id);
+
+	filter->fw_l2_filter_id = UINT64_MAX;
+	filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX;
+	filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
+			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK;
+	memcpy(filter->l2_addr, addr, ETHER_ADDR_LEN);
+	memset(filter->l2_addr_mask, 0xff, ETHER_ADDR_LEN);
+
+	/* Do not add a filter for the default MAC */
+	if (bnxt_hwrm_func_qcfg_vf_default_mac(bp, vf_id, &dflt_mac) ||
+	    memcmp(filter->l2_addr, dflt_mac.addr_bytes, ETHER_ADDR_LEN))
+		rc = bnxt_hwrm_set_filter(bp, vnic.fw_vnic_id, filter);
+
+exit:
+	return rc;
+}
diff --git a/drivers/net/bnxt/rte_pmd_bnxt.h b/drivers/net/bnxt/rte_pmd_bnxt.h
index a35e577..9b1777c 100644
--- a/drivers/net/bnxt/rte_pmd_bnxt.h
+++ b/drivers/net/bnxt/rte_pmd_bnxt.h
@@ -262,4 +262,22 @@ int rte_pmd_bnxt_get_tx_drop_count(uint8_t port, uint64_t *count);
  */
 int rte_pmd_bnxt_get_vf_tx_drop_count(uint8_t port, uint16_t vf_id,
 				      uint64_t *count);
+
+/**
+ * Programs the MAC address for the function specified
+ *
+ * @param port
+ *    The port identifier of the Ethernet device.
+ * @param mac_addr
+ *    The MAC address to be programmed in the filter.
+ * @param vf_id
+ *    VF on which to get.
+ * @return
+ *   - Positive Non-zero value - Error code from HWRM
+ *   - (-EINVAL) invalid vf_id specified.
+ *   - (-ENOTSUP) Ethernet device is not a PF
+ *   - (-ENOMEM) on an allocation failure
+ */
+int rte_pmd_bnxt_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
+				uint32_t vf_id);
 #endif /* _PMD_BNXT_H_ */
diff --git a/drivers/net/bnxt/rte_pmd_bnxt_version.map b/drivers/net/bnxt/rte_pmd_bnxt_version.map
index 7fb9a28..17c8bd9 100644
--- a/drivers/net/bnxt/rte_pmd_bnxt_version.map
+++ b/drivers/net/bnxt/rte_pmd_bnxt_version.map
@@ -14,6 +14,7 @@ DPDK_17.08 {
 	rte_pmd_bnxt_get_vf_rx_status;
 	rte_pmd_bnxt_get_vf_tx_drop_count;
 	rte_pmd_bnxt_get_tx_drop_count;
+	rte_pmd_bnxt_mac_addr_add;
 	rte_pmd_bnxt_set_vf_mac_addr;
 	rte_pmd_bnxt_set_vf_mac_anti_spoof;
 	rte_pmd_bnxt_set_vf_rate_limit;
