diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 0c9b8fc..88683df 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -325,6 +325,15 @@ enum HNS3_CAPS_BITS {
 	HNS3_CAPS_TM_B = 17,
 };
 
+/* Capabilities of VF dependent on the PF */
+enum HNS3VF_CAPS_BITS {
+	/*
+	 * The following capability index definitions must be the same as those
+	 * in kernel side PF.
+	 */
+	HNS3VF_CAPS_VLAN_FLT_MOD_B = 0,
+};
+
 enum HNS3_API_CAP_BITS {
 	HNS3_API_CAP_FLEX_RSS_TBL_B,
 };
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index a9a199a..729e1c3 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -870,6 +870,7 @@ enum {
 	HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B,
 	HNS3_DEV_SUPPORT_RAS_IMP_B,
 	HNS3_DEV_SUPPORT_TM_B,
+	HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B,
 };
 
 #define hns3_dev_dcb_supported(hw) \
@@ -909,6 +910,9 @@ enum {
 #define hns3_dev_tm_supported(hw) \
 	hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_TM_B)
 
+#define hns3_dev_vf_vlan_flt_supported(hw) \
+	hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B)
+
 #define HNS3_DEV_PRIVATE_TO_HW(adapter) \
 	(&((struct hns3_adapter *)adapter)->hw)
 #define HNS3_DEV_PRIVATE_TO_PF(adapter) \
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index dc95e71..8f3be64 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1408,6 +1408,14 @@ hns3vf_get_queue_depth(struct hns3_hw *hw)
 	return 0;
 }
 
+static void
+hns3vf_update_caps(struct hns3_hw *hw, uint32_t caps)
+{
+	if (hns3_get_bit(caps, HNS3VF_CAPS_VLAN_FLT_MOD_B))
+		hns3_set_bit(hw->capability,
+				HNS3_DEV_SUPPORT_VF_VLAN_FLT_MOD_B, 1);
+}
+
 static int
 hns3vf_get_num_tc(struct hns3_hw *hw)
 {
@@ -1440,7 +1448,7 @@ hns3vf_get_basic_info(struct hns3_hw *hw)
 	hw->hw_tc_map = basic_info->hw_tc_map;
 	hw->num_tc = hns3vf_get_num_tc(hw);
 	hw->pf_vf_if_version = basic_info->pf_vf_if_version;
-
+	hns3vf_update_caps(hw, basic_info->caps);
 
 	return 0;
 }
@@ -1611,6 +1619,26 @@ hns3vf_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 }
 
 static int
+hns3vf_en_vlan_filter(struct hns3_hw *hw, bool enable)
+{
+	uint8_t msg_data;
+	int ret;
+
+	if (!hns3_dev_vf_vlan_flt_supported(hw))
+		return 0;
+
+	msg_data = enable ? 1 : 0;
+	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_VLAN,
+			HNS3_MBX_ENABLE_VLAN_FILTER, &msg_data,
+			sizeof(msg_data), true, NULL, 0);
+	if (ret)
+		hns3_err(hw, "%s vlan filter failed, ret = %d.",
+				enable ? "enable" : "disable", ret);
+
+	return ret;
+}
+
+static int
 hns3vf_en_hw_strip_rxvtag(struct hns3_hw *hw, bool enable)
 {
 	uint8_t msg_data;
@@ -1641,6 +1669,19 @@ hns3vf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	}
 
 	tmp_mask = (unsigned int)mask;
+
+	if (tmp_mask & ETH_VLAN_FILTER_MASK) {
+		rte_spinlock_lock(&hw->lock);
+		/* Enable or disable VLAN filter */
+		if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
+			ret = hns3vf_en_vlan_filter(hw, true);
+		else
+			ret = hns3vf_en_vlan_filter(hw, false);
+		rte_spinlock_unlock(&hw->lock);
+		if (ret)
+			return ret;
+	}
+
 	/* Vlan stripping setting */
 	if (tmp_mask & ETH_VLAN_STRIP_MASK) {
 		rte_spinlock_lock(&hw->lock);
@@ -1738,9 +1779,10 @@ hns3vf_dev_configure_vlan(struct rte_eth_dev *dev)
 	}
 
 	/* Apply vlan offload setting */
-	ret = hns3vf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	ret = hns3vf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK |
+					ETH_VLAN_FILTER_MASK);
 	if (ret)
-		hns3_err(hw, "dev config vlan offload failed, ret =%d", ret);
+		hns3_err(hw, "dev config vlan offload failed, ret = %d.", ret);
 
 	return ret;
 }
diff --git a/drivers/net/hns3/hns3_mbx.h b/drivers/net/hns3/hns3_mbx.h
index f07dbe3..f868e33 100644
--- a/drivers/net/hns3/hns3_mbx.h
+++ b/drivers/net/hns3/hns3_mbx.h
@@ -71,6 +71,7 @@ enum hns3_mbx_vlan_cfg_subcode {
 	HNS3_MBX_VLAN_TX_OFF_CFG,               /* set tx side vlan offload */
 	HNS3_MBX_VLAN_RX_OFF_CFG,               /* set rx side vlan offload */
 	HNS3_MBX_GET_PORT_BASE_VLAN_STATE = 4,  /* get port based vlan state */
+	HNS3_MBX_ENABLE_VLAN_FILTER,            /* set vlan filter state */
 };
 
 enum hns3_mbx_tbl_cfg_subcode {
