diff --git a/doc/guides/nics/hns3.rst b/doc/guides/nics/hns3.rst
index 5373ec5a8f..0d546f0a05 100644
--- a/doc/guides/nics/hns3.rst
+++ b/doc/guides/nics/hns3.rst
@@ -140,6 +140,32 @@ Runtime Configuration
    For example::
    -a 0000:7d:00.0,mbx_time_limit_ms=600
 
+- ``fdir_vlan_match_mode`` (default `strict`)
+
+  Used to select VLAN match mode. This runtime config can be `strict`
+  or `nostrict` and is only valid for PF drives.
+  If driver works on `strict` mode (default mode), hardware does strictly
+  match the input flow base on VLAN number.
+
+  For the following scenarios with two rules:
+
+  .. code-block:: console
+
+    rule0:
+      pattern: eth type is 0x0806
+      actions: queue index 3
+    rule1:
+      pattern: eth type is 0x0806 / vlan vid is 20
+      actions: queue index 4
+
+  If application select `strict` mode, only the ARP packets with VLAN
+  20 are directed to queue 4, and the ARP packets with other VLAN ID
+  cannot be directed to the specified queue. If application want to all
+  ARP packets with or without VLAN to be directed to the specified queue,
+  application can select `nostrict` mode and just need to set rule0.
+
+  For example::
+  -a 0000:7d:00.0,fdir_vlan_match_mode=nostrict
 
 Driver compilation and testing
 ------------------------------
diff --git a/drivers/net/hns3/hns3_common.c b/drivers/net/hns3/hns3_common.c
index f077ef5057..a11ea686fd 100644
--- a/drivers/net/hns3/hns3_common.c
+++ b/drivers/net/hns3/hns3_common.c
@@ -238,6 +238,34 @@ hns3_parse_mbx_time_limit(const char *key, const char *value, void *extra_args)
 	return 0;
 }
 
+static int
+hns3_parse_vlan_match_mode(const char *key, const char *value, void *args)
+{
+	uint8_t mode;
+
+	RTE_SET_USED(key);
+
+	if (value == NULL) {
+		PMD_INIT_LOG(WARNING, "no value for key:\"%s\"", key);
+		return -1;
+	}
+
+	if (strcmp(value, "strict") == 0) {
+		mode = HNS3_FDIR_VLAN_STRICT_MATCH;
+	} else if (strcmp(value, "nostrict") == 0) {
+		mode = HNS3_FDIR_VLAN_NOSTRICT_MATCH;
+	} else {
+		PMD_INIT_LOG(WARNING, "invalid value:\"%s\" for key:\"%s\", "
+			"value must be 'strict' or 'nostrict'",
+			value, key);
+		return -1;
+	}
+
+	*(uint8_t *)args = mode;
+
+	return 0;
+}
+
 void
 hns3_parse_devargs(struct rte_eth_dev *dev)
 {
@@ -254,6 +282,8 @@ hns3_parse_devargs(struct rte_eth_dev *dev)
 	hns->tx_func_hint = HNS3_IO_FUNC_HINT_NONE;
 	hns->dev_caps_mask = 0;
 	hns->mbx_time_limit_ms = HNS3_MBX_DEF_TIME_LIMIT_MS;
+	if (!hns->is_vf)
+		hns->pf.fdir.vlan_match_mode = HNS3_FDIR_VLAN_STRICT_MATCH;
 
 	if (dev->device->devargs == NULL)
 		return;
@@ -270,6 +300,11 @@ hns3_parse_devargs(struct rte_eth_dev *dev)
 			   &hns3_parse_dev_caps_mask, &dev_caps_mask);
 	(void)rte_kvargs_process(kvlist, HNS3_DEVARG_MBX_TIME_LIMIT_MS,
 			   &hns3_parse_mbx_time_limit, &mbx_time_limit_ms);
+	if (!hns->is_vf)
+		(void)rte_kvargs_process(kvlist,
+					 HNS3_DEVARG_FDIR_VALN_MATCH_MODE,
+					 &hns3_parse_vlan_match_mode,
+					 &hns->pf.fdir.vlan_match_mode);
 
 	rte_kvargs_free(kvlist);
 
diff --git a/drivers/net/hns3/hns3_common.h b/drivers/net/hns3/hns3_common.h
index 8eaeda26e7..cf9593bd0c 100644
--- a/drivers/net/hns3/hns3_common.h
+++ b/drivers/net/hns3/hns3_common.h
@@ -27,6 +27,8 @@ enum {
 
 #define HNS3_DEVARG_MBX_TIME_LIMIT_MS	"mbx_time_limit_ms"
 
+#define HNS3_DEVARG_FDIR_VALN_MATCH_MODE	"fdir_vlan_match_mode"
+
 #define MSEC_PER_SEC              1000L
 #define USEC_PER_MSEC             1000L
 
diff --git a/drivers/net/hns3/hns3_fdir.c b/drivers/net/hns3/hns3_fdir.c
index 48a91fb517..c80fa59e63 100644
--- a/drivers/net/hns3/hns3_fdir.c
+++ b/drivers/net/hns3/hns3_fdir.c
@@ -355,9 +355,13 @@ int hns3_init_fd_config(struct hns3_adapter *hns)
 	/* roce_type is used to filter roce frames
 	 * dst_vport is used to specify the rule
 	 */
-	key_cfg->meta_data_active = BIT(DST_VPORT) | BIT(TUNNEL_PACKET) |
-	    BIT(VLAN_NUMBER);
-	hns3_dbg(hw, "fdir meta data: dst_vport tunnel_packet vlan_number");
+	key_cfg->meta_data_active = BIT(DST_VPORT) | BIT(TUNNEL_PACKET);
+	if (pf->fdir.vlan_match_mode)
+		key_cfg->meta_data_active |= BIT(VLAN_NUMBER);
+
+	hns3_dbg(hw, "fdir meta data: dst_vport tunnel_packet %s",
+		 (pf->fdir.vlan_match_mode == HNS3_FDIR_VLAN_STRICT_MATCH) ?
+		 "vlan_number" : "");
 
 	ret = hns3_get_fd_allocation(hw,
 				     &pf->fdir.fd_cfg.rule_num[HNS3_FD_STAGE_1],
diff --git a/drivers/net/hns3/hns3_fdir.h b/drivers/net/hns3/hns3_fdir.h
index ce70a534dc..308cfbe56f 100644
--- a/drivers/net/hns3/hns3_fdir.h
+++ b/drivers/net/hns3/hns3_fdir.h
@@ -170,6 +170,13 @@ struct hns3_fdir_rule_ele {
 
 TAILQ_HEAD(hns3_fdir_rule_list, hns3_fdir_rule_ele);
 
+/*
+ * On 'strict' mode, hardware bases on VLAN number to exactly match the
+ * input flow.
+ */
+#define HNS3_FDIR_VLAN_STRICT_MATCH	1
+#define HNS3_FDIR_VLAN_NOSTRICT_MATCH	0
+
 /*
  *  A structure used to define fields of a FDIR related info.
  */
@@ -178,6 +185,7 @@ struct hns3_fdir_info {
 	struct hns3_fdir_rule_ele **hash_map;
 	struct rte_hash *hash_handle;
 	struct hns3_fd_cfg fd_cfg;
+	uint8_t vlan_match_mode;
 };
 
 struct hns3_adapter;
