Thread (25 messages) 25 messages, 1 author, 2021-12-23
STALE1674d
Revisions (5)
  1. v1 [diff vs current]
  2. v2 current
  3. v3 [diff vs current]
  4. v4 [diff vs current]
  5. v6 [diff vs current]

[PATCH v2 22/25] net/spnic: net/spnic: support xstats statistics

From: Yanling Song <hidden>
Date: 2021-12-23 08:27:04
Subsystem: networking drivers, the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

This commit implements DFX statistics of
physical port, function, Rx queues and Tx queues,
which includes MAC statistic, unicast/multicast/broadcast
packets statistic, rx_mbuf, tx_busy and etc.

Signed-off-by: Yanling Song <redacted>
---
 drivers/net/spnic/base/spnic_nic_cfg.c | 118 ++++++
 drivers/net/spnic/base/spnic_nic_cfg.h | 206 +++++++++++
 drivers/net/spnic/spnic_ethdev.c       | 474 +++++++++++++++++++++++++
 3 files changed, 798 insertions(+)
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.c b/drivers/net/spnic/base/spnic_nic_cfg.c
index 258c6cf8c7..e740138b8e 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.c
+++ b/drivers/net/spnic/base/spnic_nic_cfg.c
@@ -493,6 +493,124 @@ int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
 	return spnic_cfg_hw_pause(hwdev, SPNIC_CMD_OP_GET, nic_pause);
 }
 
+int spnic_get_vport_stats(void *hwdev, struct spnic_vport_stats *stats)
+{
+	struct spnic_port_stats_info stats_info;
+	struct spnic_cmd_vport_stats vport_stats;
+	u16 out_size = sizeof(vport_stats);
+	int err;
+
+	if (!hwdev || !stats)
+		return -EINVAL;
+
+	memset(&stats_info, 0, sizeof(stats_info));
+	memset(&vport_stats, 0, sizeof(vport_stats));
+
+	stats_info.func_id = spnic_global_func_id(hwdev);
+
+	err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_GET_VPORT_STAT,
+				     &stats_info, sizeof(stats_info),
+				     &vport_stats, &out_size);
+	if (err || !out_size || vport_stats.msg_head.status) {
+		PMD_DRV_LOG(ERR, "Get function stats failed, err: %d, status: 0x%x, out size: 0x%x",
+			    err, vport_stats.msg_head.status, out_size);
+		return -EIO;
+	}
+
+	memcpy(stats, &vport_stats.stats, sizeof(*stats));
+
+	return 0;
+}
+
+int spnic_get_phy_port_stats(void *hwdev, struct mag_phy_port_stats *stats)
+{
+	struct mag_cmd_get_port_stat *port_stats = NULL;
+	struct mag_cmd_port_stats_info stats_info;
+	u16 out_size = sizeof(*port_stats);
+	int err;
+
+	port_stats = rte_zmalloc("port_stats", sizeof(*port_stats), 0);
+	if (!port_stats)
+		return -ENOMEM;
+
+	memset(&stats_info, 0, sizeof(stats_info));
+	stats_info.port_id = spnic_physical_port_id(hwdev);
+
+	err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_PORT_STAT,
+				   &stats_info, sizeof(stats_info),
+				   port_stats, &out_size);
+	if (err || !out_size || port_stats->head.status) {
+		PMD_DRV_LOG(ERR,
+			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
+			err, port_stats->head.status, out_size);
+		err = -EIO;
+		goto out;
+	}
+
+	memcpy(stats, &port_stats->counter, sizeof(*stats));
+
+out:
+	rte_free(port_stats);
+
+	return err;
+}
+
+int spnic_clear_vport_stats(void *hwdev)
+{
+	struct spnic_cmd_clear_vport_stats clear_vport_stats;
+	u16 out_size = sizeof(clear_vport_stats);
+	int err;
+
+	if (!hwdev) {
+		PMD_DRV_LOG(ERR, "Hwdev is NULL");
+		return -EINVAL;
+	}
+
+	memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
+	clear_vport_stats.func_id = spnic_global_func_id(hwdev);
+
+	err = l2nic_msg_to_mgmt_sync(hwdev, SPNIC_CMD_CLEAN_VPORT_STAT,
+				     &clear_vport_stats,
+				     sizeof(clear_vport_stats),
+				     &clear_vport_stats, &out_size);
+	if (err || !out_size || clear_vport_stats.msg_head.status) {
+		PMD_DRV_LOG(ERR, "Clear vport stats failed, err: %d, status: 0x%x, out size: 0x%x",
+			    err, clear_vport_stats.msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int spnic_clear_phy_port_stats(void *hwdev)
+{
+	struct mag_cmd_clr_port_stat *port_stats = NULL;
+	u16 out_size = sizeof(*port_stats);
+	int err;
+
+	port_stats = rte_zmalloc("port_stats", sizeof(*port_stats), 0);
+	if (!port_stats)
+		return -ENOMEM;
+
+	port_stats->port_id = spnic_physical_port_id(hwdev);
+
+	err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_PORT_STAT,
+				   &port_stats, sizeof(port_stats),
+				   port_stats, &out_size);
+	if (err || !out_size || port_stats->head.status) {
+		PMD_DRV_LOG(ERR,
+			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
+			err, port_stats->head.status, out_size);
+		err = -EIO;
+		goto out;
+	}
+
+out:
+	rte_free(port_stats);
+
+	return err;
+}
+
 static int spnic_set_function_table(void *hwdev, u32 cfg_bitmap,
 				     struct spnic_func_tbl_cfg *cfg)
 {
diff --git a/drivers/net/spnic/base/spnic_nic_cfg.h b/drivers/net/spnic/base/spnic_nic_cfg.h
index bc4707c05b..560c9e4e7d 100644
--- a/drivers/net/spnic/base/spnic_nic_cfg.h
+++ b/drivers/net/spnic/base/spnic_nic_cfg.h
@@ -259,6 +259,160 @@ struct spnic_cmd_clear_qp_resource {
 	u16 rsvd1;
 };
 
+struct spnic_port_stats_info {
+	struct mgmt_msg_head msg_head;
+
+	u16 func_id;
+	u16 rsvd1;
+};
+
+struct spnic_vport_stats {
+	u64 tx_unicast_pkts_vport;
+	u64 tx_unicast_bytes_vport;
+	u64 tx_multicast_pkts_vport;
+	u64 tx_multicast_bytes_vport;
+	u64 tx_broadcast_pkts_vport;
+	u64 tx_broadcast_bytes_vport;
+
+	u64 rx_unicast_pkts_vport;
+	u64 rx_unicast_bytes_vport;
+	u64 rx_multicast_pkts_vport;
+	u64 rx_multicast_bytes_vport;
+	u64 rx_broadcast_pkts_vport;
+	u64 rx_broadcast_bytes_vport;
+
+	u64 tx_discard_vport;
+	u64 rx_discard_vport;
+	u64 tx_err_vport;
+	u64 rx_err_vport;
+};
+
+struct spnic_cmd_vport_stats {
+	struct mgmt_msg_head msg_head;
+
+	u32 stats_size;
+	u32 rsvd1;
+	struct spnic_vport_stats stats;
+	u64 rsvd2[6];
+};
+
+struct mag_phy_port_stats {
+	u64 mac_tx_fragment_pkt_num;
+	u64 mac_tx_undersize_pkt_num;
+	u64 mac_tx_undermin_pkt_num;
+	u64 mac_tx_64_oct_pkt_num;
+	u64 mac_tx_65_127_oct_pkt_num;
+	u64 mac_tx_128_255_oct_pkt_num;
+	u64 mac_tx_256_511_oct_pkt_num;
+	u64 mac_tx_512_1023_oct_pkt_num;
+	u64 mac_tx_1024_1518_oct_pkt_num;
+	u64 mac_tx_1519_2047_oct_pkt_num;
+	u64 mac_tx_2048_4095_oct_pkt_num;
+	u64 mac_tx_4096_8191_oct_pkt_num;
+	u64 mac_tx_8192_9216_oct_pkt_num;
+	u64 mac_tx_9217_12287_oct_pkt_num;
+	u64 mac_tx_12288_16383_oct_pkt_num;
+	u64 mac_tx_1519_max_bad_pkt_num;
+	u64 mac_tx_1519_max_good_pkt_num;
+	u64 mac_tx_oversize_pkt_num;
+	u64 mac_tx_jabber_pkt_num;
+	u64 mac_tx_bad_pkt_num;
+	u64 mac_tx_bad_oct_num;
+	u64 mac_tx_good_pkt_num;
+	u64 mac_tx_good_oct_num;
+	u64 mac_tx_total_pkt_num;
+	u64 mac_tx_total_oct_num;
+	u64 mac_tx_uni_pkt_num;
+	u64 mac_tx_multi_pkt_num;
+	u64 mac_tx_broad_pkt_num;
+	u64 mac_tx_pause_num;
+	u64 mac_tx_pfc_pkt_num;
+	u64 mac_tx_pfc_pri0_pkt_num;
+	u64 mac_tx_pfc_pri1_pkt_num;
+	u64 mac_tx_pfc_pri2_pkt_num;
+	u64 mac_tx_pfc_pri3_pkt_num;
+	u64 mac_tx_pfc_pri4_pkt_num;
+	u64 mac_tx_pfc_pri5_pkt_num;
+	u64 mac_tx_pfc_pri6_pkt_num;
+	u64 mac_tx_pfc_pri7_pkt_num;
+	u64 mac_tx_control_pkt_num;
+	u64 mac_tx_err_all_pkt_num;
+	u64 mac_tx_from_app_good_pkt_num;
+	u64 mac_tx_from_app_bad_pkt_num;
+
+	u64 mac_rx_fragment_pkt_num;
+	u64 mac_rx_undersize_pkt_num;
+	u64 mac_rx_undermin_pkt_num;
+	u64 mac_rx_64_oct_pkt_num;
+	u64 mac_rx_65_127_oct_pkt_num;
+	u64 mac_rx_128_255_oct_pkt_num;
+	u64 mac_rx_256_511_oct_pkt_num;
+	u64 mac_rx_512_1023_oct_pkt_num;
+	u64 mac_rx_1024_1518_oct_pkt_num;
+	u64 mac_rx_1519_2047_oct_pkt_num;
+	u64 mac_rx_2048_4095_oct_pkt_num;
+	u64 mac_rx_4096_8191_oct_pkt_num;
+	u64 mac_rx_8192_9216_oct_pkt_num;
+	u64 mac_rx_9217_12287_oct_pkt_num;
+	u64 mac_rx_12288_16383_oct_pkt_num;
+	u64 mac_rx_1519_max_bad_pkt_num;
+	u64 mac_rx_1519_max_good_pkt_num;
+	u64 mac_rx_oversize_pkt_num;
+	u64 mac_rx_jabber_pkt_num;
+	u64 mac_rx_bad_pkt_num;
+	u64 mac_rx_bad_oct_num;
+	u64 mac_rx_good_pkt_num;
+	u64 mac_rx_good_oct_num;
+	u64 mac_rx_total_pkt_num;
+	u64 mac_rx_total_oct_num;
+	u64 mac_rx_uni_pkt_num;
+	u64 mac_rx_multi_pkt_num;
+	u64 mac_rx_broad_pkt_num;
+	u64 mac_rx_pause_num;
+	u64 mac_rx_pfc_pkt_num;
+	u64 mac_rx_pfc_pri0_pkt_num;
+	u64 mac_rx_pfc_pri1_pkt_num;
+	u64 mac_rx_pfc_pri2_pkt_num;
+	u64 mac_rx_pfc_pri3_pkt_num;
+	u64 mac_rx_pfc_pri4_pkt_num;
+	u64 mac_rx_pfc_pri5_pkt_num;
+	u64 mac_rx_pfc_pri6_pkt_num;
+	u64 mac_rx_pfc_pri7_pkt_num;
+	u64 mac_rx_control_pkt_num;
+	u64 mac_rx_sym_err_pkt_num;
+	u64 mac_rx_fcs_err_pkt_num;
+	u64 mac_rx_send_app_good_pkt_num;
+	u64 mac_rx_send_app_bad_pkt_num;
+	u64 mac_rx_unfilter_pkt_num;
+};
+
+struct mag_cmd_port_stats_info {
+	struct mgmt_msg_head head;
+
+	u8 port_id;
+	u8 rsvd0[3];
+};
+
+struct mag_cmd_get_port_stat {
+	struct mgmt_msg_head head;
+
+	struct mag_phy_port_stats counter;
+	u64 rsvd1[15];
+};
+
+struct mag_cmd_clr_port_stat {
+	struct mgmt_msg_head head;
+
+	u8 port_id;
+	u8 rsvd0[3];
+};
+
+struct spnic_cmd_clear_vport_stats {
+	struct mgmt_msg_head msg_head;
+
+	u16 func_id;
+	u16 rsvd;
+};
 
 enum spnic_func_tbl_cfg_bitmap {
 	FUNC_CFG_INIT,
@@ -586,6 +740,58 @@ int spnic_set_pause_info(void *hwdev, struct nic_pause_config nic_pause);
  */
 int spnic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause);
 
+/**
+ * Get function stats
+ *
+ * @param[in] hwdev
+ *   Device pointer to hwdev
+ * @param[out] stats
+ *   Function stats
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_get_vport_stats(void *hwdev, struct spnic_vport_stats *stats);
+
+/**
+ * Get port stats
+ *
+ * @param[in] hwdev
+ *   Device pointer to hwdev
+ * @param[out] stats
+ *   Port stats
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_get_phy_port_stats(void *hwdev, struct mag_phy_port_stats *stats);
+
+/**
+ * Clear function stats
+ *
+ * @param[in] hwdev
+ *   Device pointer to hwdev
+ * @param[out] stats
+ *   Function stats
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_clear_vport_stats(void *hwdev);
+
+/**
+ * Clear port stats
+ *
+ * @param[in] hwdev
+ *   Device pointer to hwdev
+ * @param[out] stats
+ *   Port stats
+ *
+ * @retval zero : Success
+ * @retval non-zero : Failure
+ */
+int spnic_clear_phy_port_stats(void *hwdev);
+
 /**
  * Init nic hwdev
  *
diff --git a/drivers/net/spnic/spnic_ethdev.c b/drivers/net/spnic/spnic_ethdev.c
index 0dc7c367e7..b53eb96903 100644
--- a/drivers/net/spnic/spnic_ethdev.c
+++ b/drivers/net/spnic/spnic_ethdev.c
@@ -66,6 +66,171 @@ enum spnic_rx_mod {
 #define SPNIC_DEFAULT_RX_MODE	(SPNIC_RX_MODE_UC | SPNIC_RX_MODE_MC | \
 				SPNIC_RX_MODE_BC)
 
+struct spnic_xstats_name_off {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	u32  offset;
+};
+
+#define SPNIC_FUNC_STAT(_stat_item) {	\
+	.name = #_stat_item, \
+	.offset = offsetof(struct spnic_vport_stats, _stat_item) \
+}
+
+#define SPNIC_PORT_STAT(_stat_item) { \
+	.name = #_stat_item, \
+	.offset = offsetof(struct mag_phy_port_stats, _stat_item) \
+}
+
+static const struct spnic_xstats_name_off spnic_vport_stats_strings[] = {
+	SPNIC_FUNC_STAT(tx_unicast_pkts_vport),
+	SPNIC_FUNC_STAT(tx_unicast_bytes_vport),
+	SPNIC_FUNC_STAT(tx_multicast_pkts_vport),
+	SPNIC_FUNC_STAT(tx_multicast_bytes_vport),
+	SPNIC_FUNC_STAT(tx_broadcast_pkts_vport),
+	SPNIC_FUNC_STAT(tx_broadcast_bytes_vport),
+
+	SPNIC_FUNC_STAT(rx_unicast_pkts_vport),
+	SPNIC_FUNC_STAT(rx_unicast_bytes_vport),
+	SPNIC_FUNC_STAT(rx_multicast_pkts_vport),
+	SPNIC_FUNC_STAT(rx_multicast_bytes_vport),
+	SPNIC_FUNC_STAT(rx_broadcast_pkts_vport),
+	SPNIC_FUNC_STAT(rx_broadcast_bytes_vport),
+
+	SPNIC_FUNC_STAT(tx_discard_vport),
+	SPNIC_FUNC_STAT(rx_discard_vport),
+	SPNIC_FUNC_STAT(tx_err_vport),
+	SPNIC_FUNC_STAT(rx_err_vport),
+};
+
+#define SPNIC_VPORT_XSTATS_NUM (sizeof(spnic_vport_stats_strings) / \
+		sizeof(spnic_vport_stats_strings[0]))
+
+static const struct spnic_xstats_name_off spnic_phyport_stats_strings[] = {
+	SPNIC_PORT_STAT(mac_tx_fragment_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_undersize_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_undermin_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_64_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_oversize_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_jabber_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_bad_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_bad_oct_num),
+	SPNIC_PORT_STAT(mac_tx_good_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_good_oct_num),
+	SPNIC_PORT_STAT(mac_tx_total_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_total_oct_num),
+	SPNIC_PORT_STAT(mac_tx_uni_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_multi_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_broad_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pause_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_control_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_err_all_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
+	SPNIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
+
+	SPNIC_PORT_STAT(mac_rx_fragment_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_undersize_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_undermin_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_64_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_oversize_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_jabber_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_bad_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_bad_oct_num),
+	SPNIC_PORT_STAT(mac_rx_good_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_good_oct_num),
+	SPNIC_PORT_STAT(mac_rx_total_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_total_oct_num),
+	SPNIC_PORT_STAT(mac_rx_uni_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_multi_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_broad_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pause_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_control_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_sym_err_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
+	SPNIC_PORT_STAT(mac_rx_unfilter_pkt_num)
+};
+
+#define SPNIC_PHYPORT_XSTATS_NUM (sizeof(spnic_phyport_stats_strings) / \
+		sizeof(spnic_phyport_stats_strings[0]))
+
+static const struct spnic_xstats_name_off spnic_rxq_stats_strings[] = {
+	{"rx_nombuf", offsetof(struct spnic_rxq_stats, rx_nombuf)},
+	{"burst_pkt", offsetof(struct spnic_rxq_stats, burst_pkts)},
+};
+
+#define SPNIC_RXQ_XSTATS_NUM (sizeof(spnic_rxq_stats_strings) / \
+		sizeof(spnic_rxq_stats_strings[0]))
+
+static const struct spnic_xstats_name_off spnic_txq_stats_strings[] = {
+	{"tx_busy", offsetof(struct spnic_txq_stats, tx_busy)},
+	{"offload_errors", offsetof(struct spnic_txq_stats, off_errs)},
+	{"burst_pkts", offsetof(struct spnic_txq_stats, burst_pkts)},
+	{"sge_len0", offsetof(struct spnic_txq_stats, sge_len0)},
+	{"mbuf_null", offsetof(struct spnic_txq_stats, mbuf_null)},
+};
+
+#define SPNIC_TXQ_XSTATS_NUM (sizeof(spnic_txq_stats_strings) / \
+		sizeof(spnic_txq_stats_strings[0]))
+
+static int spnic_xstats_calc_num(struct spnic_nic_dev *nic_dev)
+{
+	if (SPNIC_IS_VF(nic_dev->hwdev)) {
+		return (SPNIC_VPORT_XSTATS_NUM +
+			SPNIC_RXQ_XSTATS_NUM * nic_dev->num_rqs +
+			SPNIC_TXQ_XSTATS_NUM * nic_dev->num_sqs);
+	} else {
+		return (SPNIC_VPORT_XSTATS_NUM +
+			SPNIC_PHYPORT_XSTATS_NUM +
+			SPNIC_RXQ_XSTATS_NUM * nic_dev->num_rqs +
+			SPNIC_TXQ_XSTATS_NUM * nic_dev->num_sqs);
+	}
+}
+
 #define SPNIC_MAX_QUEUE_DEPTH		16384
 #define SPNIC_MIN_QUEUE_DEPTH		128
 #define SPNIC_TXD_ALIGN			1
@@ -1827,6 +1992,305 @@ static int spnic_rss_reta_update(struct rte_eth_dev *dev,
 	return err;
 }
 
+/**
+ * Get device generic statistics.
+ *
+ * @param[in] dev
+ *   Pointer to ethernet device structure.
+ * @param[out] stats
+ *   Stats structure output buffer.
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_dev_stats_get(struct rte_eth_dev *dev,
+			       struct rte_eth_stats *stats)
+{
+	struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	struct spnic_vport_stats vport_stats;
+	struct spnic_rxq *rxq = NULL;
+	struct spnic_txq *txq = NULL;
+	int i, err, q_num;
+	u64 rx_discards_pmd = 0;
+
+	err = spnic_get_vport_stats(nic_dev->hwdev, &vport_stats);
+	if (err) {
+		PMD_DRV_LOG(ERR, "Get vport stats from fw failed, nic_dev: %s",
+			    nic_dev->dev_name);
+		return err;
+	}
+
+	dev->data->rx_mbuf_alloc_failed = 0;
+
+	/* Rx queue stats */
+	q_num = (nic_dev->num_rqs < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+		nic_dev->num_rqs : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+	for (i = 0; i < q_num; i++) {
+		rxq = nic_dev->rxqs[i];
+		stats->q_ipackets[i] = rxq->rxq_stats.packets;
+		stats->q_ibytes[i] = rxq->rxq_stats.bytes;
+		stats->q_errors[i] = rxq->rxq_stats.dropped;
+
+		stats->ierrors += rxq->rxq_stats.errors;
+		rx_discards_pmd += rxq->rxq_stats.dropped;
+		dev->data->rx_mbuf_alloc_failed += rxq->rxq_stats.rx_nombuf;
+	}
+
+	/* Tx queue stats */
+	q_num = (nic_dev->num_sqs < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
+		nic_dev->num_sqs : RTE_ETHDEV_QUEUE_STAT_CNTRS;
+	for (i = 0; i < q_num; i++) {
+		txq = nic_dev->txqs[i];
+		stats->q_opackets[i] = txq->txq_stats.packets;
+		stats->q_obytes[i] = txq->txq_stats.bytes;
+		stats->oerrors += (txq->txq_stats.tx_busy +
+				  txq->txq_stats.off_errs);
+	}
+
+	/* Vport stats */
+	stats->oerrors += vport_stats.tx_discard_vport;
+
+	stats->imissed = vport_stats.rx_discard_vport + rx_discards_pmd;
+
+	stats->ipackets = (vport_stats.rx_unicast_pkts_vport +
+			  vport_stats.rx_multicast_pkts_vport +
+			  vport_stats.rx_broadcast_pkts_vport -
+			  rx_discards_pmd);
+
+	stats->opackets = (vport_stats.tx_unicast_pkts_vport +
+			  vport_stats.tx_multicast_pkts_vport +
+			  vport_stats.tx_broadcast_pkts_vport);
+
+	stats->ibytes = (vport_stats.rx_unicast_bytes_vport +
+			vport_stats.rx_multicast_bytes_vport +
+			vport_stats.rx_broadcast_bytes_vport);
+
+	stats->obytes = (vport_stats.tx_unicast_bytes_vport +
+			vport_stats.tx_multicast_bytes_vport +
+			vport_stats.tx_broadcast_bytes_vport);
+	return 0;
+}
+
+/**
+ * Clear device generic statistics.
+ *
+ * @param[in] dev
+ *   Pointer to ethernet device structure.
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_dev_stats_reset(struct rte_eth_dev *dev)
+{
+	struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	struct spnic_rxq *rxq = NULL;
+	struct spnic_txq *txq = NULL;
+	int qid;
+	int err;
+
+	err = spnic_clear_vport_stats(nic_dev->hwdev);
+	if (err)
+		return err;
+
+	for (qid = 0; qid < nic_dev->num_rqs; qid++) {
+		rxq = nic_dev->rxqs[qid];
+		memset(&rxq->rxq_stats, 0, sizeof(struct spnic_rxq_stats));
+	}
+
+	for (qid = 0; qid < nic_dev->num_sqs; qid++) {
+		txq = nic_dev->txqs[qid];
+		memset(&txq->txq_stats, 0, sizeof(struct spnic_txq_stats));
+	}
+
+	return 0;
+}
+
+/**
+ * Get device extended statistics.
+ *
+ * @param[in] dev
+ *   Pointer to ethernet device structure.
+ * @param[out] xstats
+ *   Pointer to rte extended stats table.
+ * @param[in] n
+ *   The size of the stats table.
+ *
+ * @retval positive: Number of extended stats on success and stats is filled
+ * @retval negative: Failure
+ */
+static int spnic_dev_xstats_get(struct rte_eth_dev *dev,
+				struct rte_eth_xstat *xstats, unsigned int n)
+{
+	struct spnic_nic_dev *nic_dev;
+	struct mag_phy_port_stats port_stats;
+	struct spnic_vport_stats vport_stats;
+	struct spnic_rxq *rxq = NULL;
+	struct spnic_rxq_stats rxq_stats;
+	struct spnic_txq *txq = NULL;
+	struct spnic_txq_stats txq_stats;
+	u16 qid;
+	u32 i;
+	int err, count;
+
+	nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	count = spnic_xstats_calc_num(nic_dev);
+	if ((int)n < count)
+		return count;
+
+	count = 0;
+
+	/* Get stats from rxq stats structure */
+	for (qid = 0; qid < nic_dev->num_rqs; qid++) {
+		rxq = nic_dev->rxqs[qid];
+		memcpy(&rxq_stats, &rxq->rxq_stats, sizeof(rxq->rxq_stats));
+
+		for (i = 0; i < SPNIC_RXQ_XSTATS_NUM; i++) {
+			xstats[count].value =
+				*(uint64_t *)(((char *)&rxq_stats) +
+				spnic_rxq_stats_strings[i].offset);
+			xstats[count].id = count;
+			count++;
+		}
+	}
+
+	/* Get stats from txq stats structure */
+	for (qid = 0; qid < nic_dev->num_sqs; qid++) {
+		txq = nic_dev->txqs[qid];
+		memcpy(&txq_stats, &txq->txq_stats, sizeof(txq->txq_stats));
+
+		for (i = 0; i < SPNIC_TXQ_XSTATS_NUM; i++) {
+			xstats[count].value =
+				*(uint64_t *)(((char *)&txq_stats) +
+				spnic_txq_stats_strings[i].offset);
+			xstats[count].id = count;
+			count++;
+		}
+	}
+
+	/* Get stats from vport stats structure */
+	err = spnic_get_vport_stats(nic_dev->hwdev, &vport_stats);
+	if (err)
+		return err;
+
+	for (i = 0; i < SPNIC_VPORT_XSTATS_NUM; i++) {
+		xstats[count].value =
+			*(uint64_t *)(((char *)&vport_stats) +
+			spnic_vport_stats_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
+	if (SPNIC_IS_VF(nic_dev->hwdev))
+		return count;
+
+	/* Get stats from phy port stats structure */
+	err = spnic_get_phy_port_stats(nic_dev->hwdev, &port_stats);
+	if (err)
+		return err;
+
+	for (i = 0; i < SPNIC_PHYPORT_XSTATS_NUM; i++) {
+		xstats[count].value = *(uint64_t *)(((char *)&port_stats) +
+				spnic_phyport_stats_strings[i].offset);
+		xstats[count].id = count;
+		count++;
+	}
+
+	return count;
+}
+
+/**
+ * Clear device extended statistics.
+ *
+ * @param[in] dev
+ *   Pointer to ethernet device structure.
+ *
+ * @retval zero: Success
+ * @retval non-zero: Failure
+ */
+static int spnic_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+	struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	int err;
+
+	err = spnic_dev_stats_reset(dev);
+	if (err)
+		return err;
+
+	if (spnic_func_type(nic_dev->hwdev) != TYPE_VF) {
+		err = spnic_clear_phy_port_stats(nic_dev->hwdev);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/**
+ * Retrieve names of extended device statistics
+ *
+ * @param[in] dev
+ *   Pointer to ethernet device structure.
+ * @param[out] xstats_names
+ *   Buffer to insert names into.
+ *
+ * @return
+ *   Number of xstats names.
+ */
+static int spnic_dev_xstats_get_names(struct rte_eth_dev *dev,
+				      struct rte_eth_xstat_name *xstats_names,
+				      __rte_unused unsigned int limit)
+{
+	struct spnic_nic_dev *nic_dev = SPNIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	int count = 0;
+	u16 i, q_num;
+
+	if (xstats_names == NULL)
+		return spnic_xstats_calc_num(nic_dev);
+
+	/* Get pmd rxq stats name */
+	for (q_num = 0; q_num < nic_dev->num_rqs; q_num++) {
+		for (i = 0; i < SPNIC_RXQ_XSTATS_NUM; i++) {
+			snprintf(xstats_names[count].name,
+				 sizeof(xstats_names[count].name),
+				 "rxq%d_%s_pmd", q_num,
+				 spnic_rxq_stats_strings[i].name);
+			count++;
+		}
+	}
+
+	/* Get pmd txq stats name */
+	for (q_num = 0; q_num < nic_dev->num_sqs; q_num++) {
+		for (i = 0; i < SPNIC_TXQ_XSTATS_NUM; i++) {
+			snprintf(xstats_names[count].name,
+				 sizeof(xstats_names[count].name),
+				 "txq%d_%s_pmd", q_num,
+				 spnic_txq_stats_strings[i].name);
+			count++;
+		}
+	}
+
+	/* Get vport stats name */
+	for (i = 0; i < SPNIC_VPORT_XSTATS_NUM; i++) {
+		snprintf(xstats_names[count].name,
+			 sizeof(xstats_names[count].name),
+			 "%s", spnic_vport_stats_strings[i].name);
+		count++;
+	}
+
+	if (SPNIC_IS_VF(nic_dev->hwdev))
+		return count;
+
+	/* Get phy port stats name */
+	for (i = 0; i < SPNIC_PHYPORT_XSTATS_NUM; i++) {
+		snprintf(xstats_names[count].name,
+			 sizeof(xstats_names[count].name),
+			 "%s", spnic_phyport_stats_strings[i].name);
+		count++;
+	}
+
+	return count;
+}
+
 static void spnic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
 			       struct rte_eth_rxq_info *rxq_info)
 {
@@ -2059,6 +2523,11 @@ static const struct eth_dev_ops spnic_pmd_ops = {
 	.rss_hash_conf_get             = spnic_rss_conf_get,
 	.reta_update                   = spnic_rss_reta_update,
 	.reta_query                    = spnic_rss_reta_query,
+	.stats_get                     = spnic_dev_stats_get,
+	.stats_reset                   = spnic_dev_stats_reset,
+	.xstats_get                    = spnic_dev_xstats_get,
+	.xstats_reset                  = spnic_dev_xstats_reset,
+	.xstats_get_names              = spnic_dev_xstats_get_names,
 	.rxq_info_get                  = spnic_rxq_info_get,
 	.txq_info_get                  = spnic_txq_info_get,
 	.mac_addr_set                  = spnic_set_mac_addr,
@@ -2092,6 +2561,11 @@ static const struct eth_dev_ops spnic_pmd_vf_ops = {
 	.rss_hash_conf_get             = spnic_rss_conf_get,
 	.reta_update                   = spnic_rss_reta_update,
 	.reta_query                    = spnic_rss_reta_query,
+	.stats_get                     = spnic_dev_stats_get,
+	.stats_reset                   = spnic_dev_stats_reset,
+	.xstats_get                    = spnic_dev_xstats_get,
+	.xstats_reset                  = spnic_dev_xstats_reset,
+	.xstats_get_names              = spnic_dev_xstats_get_names,
 	.rxq_info_get                  = spnic_rxq_info_get,
 	.txq_info_get                  = spnic_txq_info_get,
 	.mac_addr_set                  = spnic_set_mac_addr,
-- 
2.32.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help