diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index 094bf7e..939bbc2 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -111,6 +111,8 @@ enum hns3_opcode_type {
 
 	HNS3_OPC_QUERY_DEV_SPECS        = 0x0050,
 
+	HNS3_OPC_SSU_DROP_REG           = 0x0065,
+
 	/* MAC command */
 	HNS3_OPC_CONFIG_MAC_MODE        = 0x0301,
 	HNS3_OPC_QUERY_LINK_STATUS      = 0x0307,
@@ -957,6 +959,18 @@ struct hns3_query_rpu_cmd {
 	uint32_t rsv2[2];
 };
 
+#define HNS3_OPC_SSU_DROP_REG_NUM 2
+
+struct hns3_query_ssu_cmd {
+	uint8_t rxtx;
+	uint8_t rsv[3];
+	uint32_t full_drop_cnt;
+	uint32_t part_drop_cnt;
+	uint32_t ncsi_full_drop_cnt;
+	uint32_t ncsi_part_drop_cnt;
+	uint32_t oq_glb_drop_cnt;
+};
+
 #define HNS3_MAX_TQP_NUM_HIP08_PF	64
 #define HNS3_DEFAULT_TX_BUF		0x4000    /* 16k  bytes */
 #define HNS3_TOTAL_PKT_BUF		0x108000  /* 1.03125M bytes */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index 139e893..82538d4 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -3122,6 +3122,7 @@ hns3_get_capability(struct hns3_hw *hw)
 		hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_2US;
 		hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM;
 		hw->vlan_mode = HNS3_SW_SHIFT_AND_DISCARD_MODE;
+		hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE1;
 		hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN;
 		pf->tqp_config_mode = HNS3_FIXED_MAX_TQP_NUM_MODE;
 		hw->rss_info.ipv6_sctp_offload_supported = false;
@@ -3140,6 +3141,7 @@ hns3_get_capability(struct hns3_hw *hw)
 	hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_1US;
 	hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM;
 	hw->vlan_mode = HNS3_HW_SHIFT_AND_DISCARD_MODE;
+	hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE2;
 	hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN;
 	pf->tqp_config_mode = HNS3_FLEX_MAX_TQP_NUM_MODE;
 	hw->rss_info.ipv6_sctp_offload_supported = true;
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index 314916c..6e74ec8 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -426,6 +426,9 @@ struct hns3_queue_intr {
 #define HNS3_TSO_SW_CAL_PSEUDO_H_CSUM		0
 #define HNS3_TSO_HW_CAL_PSEUDO_H_CSUM		1
 
+#define HNS3_PKTS_DROP_STATS_MODE1		0
+#define HNS3_PKTS_DROP_STATS_MODE2		1
+
 struct hns3_hw {
 	struct rte_eth_dev_data *data;
 	void *io_base;
@@ -544,6 +547,24 @@ struct hns3_hw {
 	 *     port won't be copied to the function which has set promisc mode.
 	 */
 	uint8_t promisc_mode;
+
+	/*
+	 * drop_stats_mode mode.
+	 * value range:
+	 *      HNS3_PKTS_DROP_STATS_MODE1/HNS3_PKTS_DROP_STATS_MODE2
+	 *
+	 *  - HNS3_PKTS_DROP_STATS_MODE1
+	 *     This mode for kunpeng920. In this mode, port level imissed stats
+	 *     is supported. It only includes RPU drop stats.
+	 *
+	 *  - HNS3_PKTS_DROP_STATS_MODE2
+	 *     This mode for kunpeng930. In this mode, imissed stats and oerrors
+	 *     stats is supported. Function level imissed stats is supported. It
+	 *     includes RPU drop stats in VF, and includes both RPU drop stats
+	 *     and SSU drop stats in PF. Oerror stats is also supported in PF.
+	 */
+	uint8_t drop_stats_mode;
+
 	uint8_t max_non_tso_bd_num; /* max BD number of one non-TSO packet */
 
 	struct hns3_port_base_vlan_config port_base_vlan_cfg;
diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c
index e1e41b8..7ee468f 100644
--- a/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/drivers/net/hns3/hns3_ethdev_vf.c
@@ -1221,6 +1221,7 @@ hns3vf_get_capability(struct hns3_hw *hw)
 		hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_RSV_ONE;
 		hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_2US;
 		hw->tso_mode = HNS3_TSO_SW_CAL_PSEUDO_H_CSUM;
+		hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE1;
 		hw->min_tx_pkt_len = HNS3_HIP08_MIN_TX_PKT_LEN;
 		hw->rss_info.ipv6_sctp_offload_supported = false;
 		hw->promisc_mode = HNS3_UNLIMIT_PROMISC_MODE;
@@ -1238,6 +1239,7 @@ hns3vf_get_capability(struct hns3_hw *hw)
 	hw->intr.mapping_mode = HNS3_INTR_MAPPING_VEC_ALL;
 	hw->intr.gl_unit = HNS3_INTR_COALESCE_GL_UINT_1US;
 	hw->tso_mode = HNS3_TSO_HW_CAL_PSEUDO_H_CSUM;
+	hw->drop_stats_mode = HNS3_PKTS_DROP_STATS_MODE2;
 	hw->min_tx_pkt_len = HNS3_HIP09_MIN_TX_PKT_LEN;
 	hw->rss_info.ipv6_sctp_offload_supported = true;
 	hw->promisc_mode = HNS3_LIMIT_PROMISC_MODE;
@@ -1875,6 +1877,13 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 	if (ret)
 		goto err_get_config;
 
+	/* Hardware statistics of imissed registers cleared. */
+	ret = hns3_update_imissed_stats(hw, true);
+	if (ret) {
+		hns3_err(hw, "clear imissed stats failed, ret = %d", ret);
+		goto err_set_tc_queue;
+	}
+
 	ret = hns3vf_set_tc_queue_mapping(hns, hw->tqps_num, hw->tqps_num);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "failed to set tc info, ret = %d.", ret);
diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h
index 0540554..e141fe1 100644
--- a/drivers/net/hns3/hns3_regs.h
+++ b/drivers/net/hns3/hns3_regs.h
@@ -36,6 +36,8 @@
 #define HNS3_GLOBAL_RESET_REG		0x20A00
 #define HNS3_FUN_RST_ING		0x20C00
 #define HNS3_GRO_EN_REG			0x28000
+
+#define HNS3_RPU_DROP_CNT_REG		0x28004
 #define HNS3_RXD_ADV_LAYOUT_EN_REG	0x28008
 
 /* Vector0 register bits for reset */
diff --git a/drivers/net/hns3/hns3_stats.c b/drivers/net/hns3/hns3_stats.c
index 7cda36c..ccad477 100644
--- a/drivers/net/hns3/hns3_stats.c
+++ b/drivers/net/hns3/hns3_stats.c
@@ -269,6 +269,8 @@ static const struct hns3_xstats_name_offset hns3_tx_queue_strings[] = {
 static const struct hns3_xstats_name_offset hns3_imissed_stats_strings[] = {
 	{"RPU_DROP_CNT",
 		HNS3_IMISSED_STATS_FIELD_OFFSET(rpu_rx_drop_cnt)},
+	{"SSU_DROP_CNT",
+		HNS3_IMISSED_STATS_FIELD_OFFSET(ssu_rx_drop_cnt)},
 };
 
 #define HNS3_NUM_MAC_STATS (sizeof(hns3_mac_strings) / \
@@ -301,8 +303,7 @@ static const struct hns3_xstats_name_offset hns3_imissed_stats_strings[] = {
 #define HNS3_NUM_IMISSED_XSTATS (sizeof(hns3_imissed_stats_strings) / \
 	sizeof(hns3_imissed_stats_strings[0]))
 
-#define HNS3_FIX_NUM_STATS (HNS3_NUM_MAC_STATS + \
-			    HNS3_NUM_RESET_XSTATS + HNS3_NUM_IMISSED_XSTATS)
+#define HNS3_FIX_NUM_STATS (HNS3_NUM_MAC_STATS + HNS3_NUM_RESET_XSTATS)
 
 static void hns3_tqp_stats_clear(struct hns3_hw *hw);
 
@@ -419,7 +420,7 @@ hns3_query_update_mac_stats(struct rte_eth_dev *dev)
 }
 
 static int
-hns3_update_rpu_drop_stats(struct hns3_hw *hw)
+hns3_update_port_rpu_drop_stats(struct hns3_hw *hw)
 {
 	struct hns3_rx_missed_stats *stats = &hw->imissed_stats;
 	struct hns3_query_rpu_cmd *req;
@@ -449,11 +450,89 @@ hns3_update_rpu_drop_stats(struct hns3_hw *hw)
 	return 0;
 }
 
+static void
+hns3_update_function_rpu_drop_stats(struct hns3_hw *hw)
+{
+	struct hns3_rx_missed_stats *stats = &hw->imissed_stats;
+
+	stats->rpu_rx_drop_cnt += hns3_read_dev(hw, HNS3_RPU_DROP_CNT_REG);
+}
+
+static int
+hns3_update_rpu_drop_stats(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	int ret = 0;
+
+	if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE1 && !hns->is_vf)
+		ret = hns3_update_port_rpu_drop_stats(hw);
+	else if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE2)
+		hns3_update_function_rpu_drop_stats(hw);
+
+	return ret;
+}
+
+static int
+hns3_get_ssu_drop_stats(struct hns3_hw *hw, struct hns3_cmd_desc *desc,
+			int bd_num, bool is_rx)
+{
+	struct hns3_query_ssu_cmd *req;
+	int ret;
+	int i;
+
+	for (i = 0; i < bd_num - 1; i++) {
+		hns3_cmd_setup_basic_desc(&desc[i],
+					  HNS3_OPC_SSU_DROP_REG, true);
+		desc[i].flag |= rte_cpu_to_le_16(HNS3_CMD_FLAG_NEXT);
+	}
+	hns3_cmd_setup_basic_desc(&desc[i], HNS3_OPC_SSU_DROP_REG, true);
+	req = (struct hns3_query_ssu_cmd *)desc[0].data;
+	req->rxtx = is_rx ? 0 : 1;
+	ret = hns3_cmd_send(hw, desc, bd_num);
+
+	return ret;
+}
+
+static int
+hns3_update_port_rx_ssu_drop_stats(struct hns3_hw *hw)
+{
+	struct hns3_rx_missed_stats *stats = &hw->imissed_stats;
+	struct hns3_cmd_desc desc[HNS3_OPC_SSU_DROP_REG_NUM];
+	struct hns3_query_ssu_cmd *req;
+	uint64_t cnt;
+	int ret;
+
+	ret = hns3_get_ssu_drop_stats(hw, desc, HNS3_OPC_SSU_DROP_REG_NUM,
+				      true);
+	if (ret) {
+		hns3_err(hw, "failed to get Rx SSU drop stats, ret = %d", ret);
+		return ret;
+	}
+
+	req = (struct hns3_query_ssu_cmd *)desc[0].data;
+	cnt = rte_le_to_cpu_32(req->full_drop_cnt) +
+		rte_le_to_cpu_32(req->part_drop_cnt);
+
+	stats->ssu_rx_drop_cnt += cnt;
+
+	return 0;
+}
+
 int
 hns3_update_imissed_stats(struct hns3_hw *hw, bool is_clear)
 {
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	int ret;
 
+	if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE1 && hns->is_vf)
+		return 0;
+
+	if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE2 && !hns->is_vf) {
+		ret = hns3_update_port_rx_ssu_drop_stats(hw);
+		if (ret)
+			return ret;
+	}
+
 	ret = hns3_update_rpu_drop_stats(hw);
 	if (ret)
 		return ret;
@@ -488,19 +567,17 @@ hns3_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *rte_stats)
 	uint16_t i;
 	int ret;
 
-	if (!hns->is_vf) {
-		/* Update imissed stats */
-		ret = hns3_update_imissed_stats(hw, false);
-		if (ret) {
-			hns3_err(hw, "update imissed stats failed, ret = %d",
-				 ret);
-			return ret;
-		}
-
-		rte_stats->imissed = imissed_stats->rpu_rx_drop_cnt;
+	/* Update imissed stats */
+	ret = hns3_update_imissed_stats(hw, false);
+	if (ret) {
+		hns3_err(hw, "update imissed stats failed, ret = %d",
+			 ret);
+		return ret;
 	}
+	rte_stats->imissed = imissed_stats->rpu_rx_drop_cnt +
+				imissed_stats->ssu_rx_drop_cnt;
 
-	/* Reads all the stats of a rxq in a loop to keep them synchronized */
+	/* Get the error stats and bytes of received packets */
 	for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
 		rxq = eth_dev->data->rx_queues[i];
 		if (rxq == NULL)
@@ -556,17 +633,14 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 	uint16_t i;
 	int ret;
 
-	if (!hns->is_vf) {
-		/*
-		 * Note: Reading hardware statistics of imissed registers will
-		 * clear them.
-		 */
-		ret = hns3_update_imissed_stats(hw, true);
-		if (ret) {
-			hns3_err(hw, "clear imissed stats failed, ret = %d",
-				 ret);
-			return ret;
-		}
+	/*
+	 * Note: Reading hardware statistics of imissed registers will
+	 * clear them.
+	 */
+	ret = hns3_update_imissed_stats(hw, true);
+	if (ret) {
+		hns3_err(hw, "clear imissed stats failed, ret = %d", ret);
+		return ret;
 	}
 
 	for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
@@ -630,6 +704,22 @@ hns3_mac_stats_reset(__rte_unused struct rte_eth_dev *dev)
 	return 0;
 }
 
+static int
+hns3_get_imissed_stats_num(struct hns3_adapter *hns)
+{
+#define NO_IMISSED_STATS_NUM   0
+#define RPU_STATS_ITEM_NUM     1
+	struct hns3_hw *hw = &hns->hw;
+
+	if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE1 && hns->is_vf)
+		return NO_IMISSED_STATS_NUM;
+
+	if (hw->drop_stats_mode == HNS3_PKTS_DROP_STATS_MODE2 && !hns->is_vf)
+		return HNS3_NUM_IMISSED_XSTATS;
+
+	return RPU_STATS_ITEM_NUM;
+}
+
 /* This function calculates the number of xstats based on the current config */
 static int
 hns3_xstats_calc_num(struct rte_eth_dev *dev)
@@ -647,13 +737,17 @@ hns3_xstats_calc_num(struct rte_eth_dev *dev)
 	uint16_t nb_tx_q = dev->data->nb_tx_queues;
 	int rx_comm_stats_num = nb_rx_q * HNS3_PF_VF_RX_COMM_STATS_NUM;
 	int tx_comm_stats_num = nb_tx_q * HNS3_PF_VF_TX_COMM_STATS_NUM;
+	int stats_num;
+
+	stats_num = rx_comm_stats_num + tx_comm_stats_num;
+	stats_num += hns3_get_imissed_stats_num(hns);
 
 	if (hns->is_vf)
-		return rx_comm_stats_num + tx_comm_stats_num +
-			HNS3_NUM_RESET_XSTATS;
+		stats_num += HNS3_NUM_RESET_XSTATS;
 	else
-		return rx_comm_stats_num + tx_comm_stats_num +
-			HNS3_FIX_NUM_STATS;
+		stats_num += HNS3_FIX_NUM_STATS;
+
+	return stats_num;
 }
 
 static void
@@ -835,6 +929,31 @@ hns3_tqp_basic_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	hns3_txq_basic_stats_get(dev, xstats, count);
 }
 
+static void
+hns3_imissed_stats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+			  int *count)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_rx_missed_stats *imissed_stats = &hw->imissed_stats;
+	int imissed_stats_num;
+	int cnt = *count;
+	char *addr;
+	uint16_t i;
+
+	imissed_stats_num = hns3_get_imissed_stats_num(hns);
+
+	for (i = 0; i < imissed_stats_num; i++) {
+		addr = (char *)imissed_stats +
+			hns3_imissed_stats_strings[i].offset;
+		xstats[cnt].value = *(uint64_t *)addr;
+		xstats[cnt].id = cnt;
+		cnt++;
+	}
+
+	*count = cnt;
+}
+
 /*
  * Retrieve extended(tqp | Mac) statistics of an Ethernet device.
  * @param dev
@@ -854,7 +973,6 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	struct hns3_rx_missed_stats *imissed_stats = &hw->imissed_stats;
 	struct hns3_mac_stats *mac_stats = &hw->mac_stats;
 	struct hns3_reset_stats *reset_stats = &hw->reset.stats;
 	struct hns3_rx_bd_errors_stats *rx_err_stats;
@@ -890,24 +1008,17 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 			xstats[count].id = count;
 			count++;
 		}
+	}
 
-		ret = hns3_update_imissed_stats(hw, false);
-		if (ret) {
-			hns3_err(hw, "update imissed stats failed, ret = %d",
-				 ret);
-			return ret;
-		}
-
-		for (i = 0; i < HNS3_NUM_IMISSED_XSTATS; i++) {
-			addr = (char *)imissed_stats +
-				hns3_imissed_stats_strings[i].offset;
-			xstats[count].value = *(uint64_t *)addr;
-			xstats[count].id = count;
-			count++;
-		}
-
+	ret = hns3_update_imissed_stats(hw, false);
+	if (ret) {
+		hns3_err(hw, "update imissed stats failed, ret = %d",
+			 ret);
+		return ret;
 	}
 
+	hns3_imissed_stats_get(dev, xstats, &count);
+
 	/* Get the reset stat */
 	for (i = 0; i < HNS3_NUM_RESET_XSTATS; i++) {
 		addr = (char *)reset_stats + hns3_reset_stats_strings[i].offset;
@@ -992,6 +1103,28 @@ hns3_tqp_dfx_stats_name_get(struct rte_eth_dev *dev,
 	}
 }
 
+static void
+hns3_imissed_stats_name_get(struct rte_eth_dev *dev,
+			    struct rte_eth_xstat_name *xstats_names,
+			    uint32_t *count)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	uint32_t cnt = *count;
+	int imissed_stats_num;
+	uint16_t i;
+
+	imissed_stats_num = hns3_get_imissed_stats_num(hns);
+
+	for (i = 0; i < imissed_stats_num; i++) {
+		snprintf(xstats_names[cnt].name,
+			 sizeof(xstats_names[cnt].name),
+			 "%s", hns3_imissed_stats_strings[i].name);
+		cnt++;
+	}
+
+	*count = cnt;
+}
+
 /*
  * Retrieve names of extended statistics of an Ethernet device.
  *
@@ -1040,14 +1173,10 @@ hns3_dev_xstats_get_names(struct rte_eth_dev *dev,
 				 "%s", hns3_mac_strings[i].name);
 			count++;
 		}
-
-		for (i = 0; i < HNS3_NUM_IMISSED_XSTATS; i++) {
-			snprintf(xstats_names[count].name,
-				 sizeof(xstats_names[count].name),
-				 "%s", hns3_imissed_stats_strings[i].name);
-			count++;
-		}
 	}
+
+	hns3_imissed_stats_name_get(dev, xstats_names, &count);
+
 	for (i = 0; i < HNS3_NUM_RESET_XSTATS; i++) {
 		snprintf(xstats_names[count].name,
 			 sizeof(xstats_names[count].name),
diff --git a/drivers/net/hns3/hns3_stats.h b/drivers/net/hns3/hns3_stats.h
index 8ea69b4..273be42 100644
--- a/drivers/net/hns3/hns3_stats.h
+++ b/drivers/net/hns3/hns3_stats.h
@@ -112,6 +112,7 @@ struct hns3_mac_stats {
 
 struct hns3_rx_missed_stats {
 	uint64_t rpu_rx_drop_cnt;
+	uint64_t ssu_rx_drop_cnt;
 };
 
 /* store statistics names and its offset in stats structure */
