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 <son...@ramaxel.com>
---
 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 67aae4620d..d1ecf98263 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)
 {
@@ -2063,6 +2527,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

Reply via email to