[v2,22/32] net/sssnic: add basic and extended stats ops

Message ID 20230831095650.219964-23-wanry@3snic.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series Introduce sssnic PMD for 3SNIC's 9x0 serials Ethernet adapters |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Renyong Wan Aug. 31, 2023, 9:56 a.m. UTC
  From: Renyong Wan <wanry@3snic.com>

Signed-off-by: Steven Song <steven.song@3snic.com>
Signed-off-by: Renyong Wan <wanry@3snic.com>
---
v2:
* Removed error.h from including files.
---
 doc/guides/nics/features/sssnic.ini      |   3 +
 drivers/net/sssnic/base/sssnic_api.c     | 154 +++++++++
 drivers/net/sssnic/base/sssnic_api.h     | 116 +++++++
 drivers/net/sssnic/base/sssnic_cmd.h     |  12 +
 drivers/net/sssnic/meson.build           |   1 +
 drivers/net/sssnic/sssnic_ethdev.c       |   6 +
 drivers/net/sssnic/sssnic_ethdev_rx.c    |  30 ++
 drivers/net/sssnic/sssnic_ethdev_rx.h    |   4 +
 drivers/net/sssnic/sssnic_ethdev_stats.c | 391 +++++++++++++++++++++++
 drivers/net/sssnic/sssnic_ethdev_stats.h |  18 ++
 drivers/net/sssnic/sssnic_ethdev_tx.c    |  36 +++
 drivers/net/sssnic/sssnic_ethdev_tx.h    |   4 +
 12 files changed, 775 insertions(+)
 create mode 100644 drivers/net/sssnic/sssnic_ethdev_stats.c
 create mode 100644 drivers/net/sssnic/sssnic_ethdev_stats.h
  

Patch

diff --git a/doc/guides/nics/features/sssnic.ini b/doc/guides/nics/features/sssnic.ini
index 359834ce4c..aba0b78c95 100644
--- a/doc/guides/nics/features/sssnic.ini
+++ b/doc/guides/nics/features/sssnic.ini
@@ -12,6 +12,9 @@  Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
 Multicast MAC filter = Y
+Basic stats          = Y
+Extended stats       = Y
+Stats per queue      = Y
 Linux                = Y
 ARMv8                = Y
 x86-64               = Y
diff --git a/drivers/net/sssnic/base/sssnic_api.c b/drivers/net/sssnic/base/sssnic_api.c
index 81020387bd..9f063112f2 100644
--- a/drivers/net/sssnic/base/sssnic_api.c
+++ b/drivers/net/sssnic/base/sssnic_api.c
@@ -1005,3 +1005,157 @@  sssnic_port_resource_clean(struct sssnic_hw *hw)
 
 	return 0;
 }
+
+int
+sssnic_port_stats_get(struct sssnic_hw *hw, struct sssnic_port_stats *stats)
+{
+	int ret;
+	struct sssnic_port_stats_cmd cmd;
+	struct sssnic_msg msg;
+	uint32_t cmd_len, resp_len;
+	struct {
+		struct sssnic_cmd_common common;
+		uint32_t size;
+		uint32_t resvd0;
+		struct sssnic_port_stats stats;
+		uint64_t rsvd1[6];
+	} resp;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.function = SSSNIC_FUNC_IDX(hw);
+	cmd_len = sizeof(cmd);
+
+	sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len,
+		SSSNIC_GET_PORT_STATS_CMD, SSSNIC_MPU_FUNC_IDX,
+		SSSNIC_LAN_MODULE, SSSNIC_MSG_TYPE_REQ);
+	memset(&resp, 0, sizeof(resp));
+	resp_len = sizeof(resp);
+	ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&resp, &resp_len, 0);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret);
+		return ret;
+	}
+
+	if (resp_len == 0 || resp.common.status != 0) {
+		PMD_DRV_LOG(ERR,
+			"Bad response to SSSNIC_GET_PORT_STATS_CMD, len=%u, status=%u",
+			resp_len, resp.common.status);
+		return -EIO;
+	}
+
+	memcpy(stats, &resp.stats, sizeof(resp.stats));
+
+	return 0;
+}
+
+int
+sssnic_port_stats_clear(struct sssnic_hw *hw)
+{
+	int ret;
+	struct sssnic_port_stats_cmd cmd;
+	struct sssnic_msg msg;
+	uint32_t cmd_len;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.function = SSSNIC_FUNC_IDX(hw);
+	cmd_len = sizeof(cmd);
+	sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len,
+		SSSNIC_CLEAR_PORT_STATS_CMD, SSSNIC_MPU_FUNC_IDX,
+		SSSNIC_LAN_MODULE, SSSNIC_MSG_TYPE_REQ);
+	ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret);
+		return ret;
+	}
+
+	if (cmd_len == 0 || cmd.common.status != 0) {
+		PMD_DRV_LOG(ERR,
+			"Bad response to SSSNIC_CLEAN_PORT_RES_CMD, len=%u, status=%u",
+			cmd_len, cmd.common.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+sssnic_mac_stats_get(struct sssnic_hw *hw, struct sssnic_mac_stats *stats)
+{
+	int ret;
+	struct sssnic_msg msg;
+	uint32_t cmd_len, resp_len;
+	struct sssnic_mac_stats_cmd cmd;
+	struct {
+		struct sssnic_cmd_common common;
+		struct sssnic_mac_stats stats;
+		uint64_t resvd[15];
+	} *resp;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.port = SSSNIC_PHY_PORT(hw);
+	cmd_len = sizeof(cmd);
+
+	sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len,
+		SSSNIC_GET_NETIF_MAC_STATS_CMD, SSSNIC_MPU_FUNC_IDX,
+		SSSNIC_NETIF_MODULE, SSSNIC_MSG_TYPE_REQ);
+
+	resp_len = sizeof(*resp);
+	resp = rte_zmalloc(NULL, resp_len, 0);
+	if (resp == NULL) {
+		PMD_DRV_LOG(ERR,
+			"Failed to alloc memory for mac stats response cmd");
+		return -ENOMEM;
+	}
+
+	ret = sssnic_mbox_send(hw, &msg, (uint8_t *)resp, &resp_len, 0);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret);
+		goto out;
+	}
+
+	if (resp_len == 0 || resp->common.status != 0) {
+		PMD_DRV_LOG(ERR,
+			"Bad response to SSSNIC_GET_NETIF_MAC_STATS_CMD, len=%u, status=%u",
+			resp_len, resp->common.status);
+		ret = -EIO;
+		goto out;
+	}
+
+	memcpy(stats, &resp->stats, sizeof(resp->stats));
+
+out:
+	rte_free(resp);
+	return ret;
+}
+
+int
+sssnic_mac_stats_clear(struct sssnic_hw *hw)
+{
+	int ret;
+	struct sssnic_mac_stats_cmd cmd;
+	struct sssnic_msg msg;
+	uint32_t cmd_len;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.port = SSSNIC_PHY_PORT(hw);
+	cmd_len = sizeof(cmd);
+
+	sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len,
+		SSSNIC_CLEAR_NETIF_MAC_STATS_CMD, SSSNIC_MPU_FUNC_IDX,
+		SSSNIC_NETIF_MODULE, SSSNIC_MSG_TYPE_REQ);
+
+	ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret);
+		return ret;
+	}
+
+	if (cmd_len == 0 || cmd.common.status != 0) {
+		PMD_DRV_LOG(ERR,
+			"Bad response to SSSNIC_CLEAR_NETIF_MAC_STATS_CMD, len=%u, status=%u",
+			cmd_len, cmd.common.status);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/sssnic/base/sssnic_api.h b/drivers/net/sssnic/base/sssnic_api.h
index 49336f70cf..c2f4f90209 100644
--- a/drivers/net/sssnic/base/sssnic_api.h
+++ b/drivers/net/sssnic/base/sssnic_api.h
@@ -267,6 +267,117 @@  struct sssnic_rxtxq_ctx {
 
 #define SSSNIC_RXTXQ_CTX_SIZE (sizeof(struct sssnic_rxtxq_ctx))
 
+struct sssnic_port_stats {
+	uint64_t tx_ucast_pkts;
+	uint64_t tx_ucast_bytes;
+	uint64_t tx_mcast_pkts;
+	uint64_t tx_mcast_bytes;
+	uint64_t tx_bcast_pkts;
+	uint64_t tx_bcast_bytes;
+
+	uint64_t rx_ucast_pkts;
+	uint64_t rx_ucast_bytes;
+	uint64_t rx_mcast_pkts;
+	uint64_t rx_mcast_bytes;
+	uint64_t rx_bcast_pkts;
+	uint64_t rx_bcast_bytes;
+
+	uint64_t tx_discards;
+	uint64_t rx_discards;
+	uint64_t tx_errors;
+	uint64_t rx_errors;
+};
+
+struct sssnic_mac_stats {
+	uint64_t tx_fragment_pkts;
+	uint64_t tx_undersize_pkts;
+	uint64_t tx_undermin_pkts;
+	uint64_t tx_64b_pkts;
+	uint64_t tx_65b_127b_pkt;
+	uint64_t tx_128b_255b_pkts;
+	uint64_t tx_256b_511b_pkts;
+	uint64_t tx_512b_1023b_pkts;
+	uint64_t tx_1024b_1518b_pkts;
+	uint64_t tx_1519b_2047b_pkts;
+	uint64_t tx_2048b_4095b_pkts;
+	uint64_t tx_4096b_8191b_pkts;
+	uint64_t tx_8192b_9216b_pkts;
+	uint64_t tx_9217b_12287b_pkts;
+	uint64_t tx_12288b_16383b_pkts;
+	uint64_t tx_1519b_bad_pkts;
+	uint64_t tx_1519b_good_pkts;
+	uint64_t tx_oversize_pkts;
+	uint64_t tx_jabber_pkts;
+	uint64_t tx_bad_pkts;
+	uint64_t tx_bad_bytes;
+	uint64_t tx_good_pkts;
+	uint64_t tx_good_bytes;
+	uint64_t tx_total_pkts;
+	uint64_t tx_total_bytes;
+	uint64_t tx_unicast_pkts;
+	uint64_t tx_multicast_bytes;
+	uint64_t tx_broadcast_pkts;
+	uint64_t tx_pause_pkts;
+	uint64_t tx_pfc_pkts;
+	uint64_t tx_pfc_pri0_pkts;
+	uint64_t tx_pfc_pri1_pkts;
+	uint64_t tx_pfc_pri2_pkts;
+	uint64_t tx_pfc_pri3_pkts;
+	uint64_t tx_pfc_pri4_pkts;
+	uint64_t tx_pfc_pri5_pkts;
+	uint64_t tx_pfc_pri6_pkts;
+	uint64_t tx_pfc_pri7_pkts;
+	uint64_t tx_control_pkts;
+	uint64_t tx_total_error_pkts;
+	uint64_t tx_debug_good_pkts;
+	uint64_t tx_debug_bad_pkts;
+
+	uint64_t rx_fragment_pkts;
+	uint64_t rx_undersize_pkts;
+	uint64_t rx_undermin_pkts;
+	uint64_t rx_64b_pkts;
+	uint64_t rx_65b_127b_pkt;
+	uint64_t rx_128b_255b_pkts;
+	uint64_t rx_256b_511b_pkts;
+	uint64_t rx_512b_1023b_pkts;
+	uint64_t rx_1024b_1518b_pkts;
+	uint64_t rx_1519b_2047b_pkts;
+	uint64_t rx_2048b_4095b_pkts;
+	uint64_t rx_4096b_8191b_pkts;
+	uint64_t rx_8192b_9216b_pkts;
+	uint64_t rx_9217b_12287b_pkts;
+	uint64_t rx_12288b_16383b_pkts;
+	uint64_t rx_1519b_bad_pkts;
+	uint64_t rx_1519b_good_pkts;
+	uint64_t rx_oversize_pkts;
+	uint64_t rx_jabber_pkts;
+	uint64_t rx_bad_pkts;
+	uint64_t rx_bad_bytes;
+	uint64_t rx_good_pkts;
+	uint64_t rx_good_bytes;
+	uint64_t rx_total_pkts;
+	uint64_t rx_total_bytes;
+	uint64_t rx_unicast_pkts;
+	uint64_t rx_multicast_bytes;
+	uint64_t rx_broadcast_pkts;
+	uint64_t rx_pause_pkts;
+	uint64_t rx_pfc_pkts;
+	uint64_t rx_pfc_pri0_pkts;
+	uint64_t rx_pfc_pri1_pkts;
+	uint64_t rx_pfc_pri2_pkts;
+	uint64_t rx_pfc_pri3_pkts;
+	uint64_t rx_pfc_pri4_pkts;
+	uint64_t rx_pfc_pri5_pkts;
+	uint64_t rx_pfc_pri6_pkts;
+	uint64_t rx_pfc_pri7_pkts;
+	uint64_t rx_control_pkts;
+	uint64_t rx_symbol_error_pkts;
+	uint64_t rx_fcs_error_pkts;
+	uint64_t rx_debug_good_pkts;
+	uint64_t rx_debug_bad_pkts;
+	uint64_t rx_unfilter_pkts;
+};
+
 int sssnic_msix_attr_get(struct sssnic_hw *hw, uint16_t msix_idx,
 	struct sssnic_msix_attr *attr);
 int sssnic_msix_attr_set(struct sssnic_hw *hw, uint16_t msix_idx,
@@ -304,5 +415,10 @@  int sssnic_lro_timer_set(struct sssnic_hw *hw, uint32_t timer);
 int sssnic_vlan_filter_enable_set(struct sssnic_hw *hw, bool state);
 int sssnic_vlan_strip_enable_set(struct sssnic_hw *hw, bool state);
 int sssnic_port_resource_clean(struct sssnic_hw *hw);
+int sssnic_port_stats_get(struct sssnic_hw *hw,
+	struct sssnic_port_stats *stats);
+int sssnic_port_stats_clear(struct sssnic_hw *hw);
+int sssnic_mac_stats_get(struct sssnic_hw *hw, struct sssnic_mac_stats *stats);
+int sssnic_mac_stats_clear(struct sssnic_hw *hw);
 
 #endif /* _SSSNIC_API_H_ */
diff --git a/drivers/net/sssnic/base/sssnic_cmd.h b/drivers/net/sssnic/base/sssnic_cmd.h
index e89719b0de..bc7303ff57 100644
--- a/drivers/net/sssnic/base/sssnic_cmd.h
+++ b/drivers/net/sssnic/base/sssnic_cmd.h
@@ -336,4 +336,16 @@  struct sssnic_port_resource_clean_cmd {
 	uint16_t resvd;
 };
 
+struct sssnic_port_stats_cmd {
+	struct sssnic_cmd_common common;
+	uint16_t function;
+	uint16_t resvd;
+};
+
+struct sssnic_mac_stats_cmd {
+	struct sssnic_cmd_common common;
+	uint8_t port;
+	uint8_t resvd[3];
+};
+
 #endif /* _SSSNIC_CMD_H_ */
diff --git a/drivers/net/sssnic/meson.build b/drivers/net/sssnic/meson.build
index 0c6e21310d..dea24f4b06 100644
--- a/drivers/net/sssnic/meson.build
+++ b/drivers/net/sssnic/meson.build
@@ -21,4 +21,5 @@  sources = files(
         'sssnic_ethdev_link.c',
         'sssnic_ethdev_rx.c',
         'sssnic_ethdev_tx.c',
+        'sssnic_ethdev_stats.c',
 )
diff --git a/drivers/net/sssnic/sssnic_ethdev.c b/drivers/net/sssnic/sssnic_ethdev.c
index e1c805aeea..99e6d6152a 100644
--- a/drivers/net/sssnic/sssnic_ethdev.c
+++ b/drivers/net/sssnic/sssnic_ethdev.c
@@ -12,6 +12,7 @@ 
 #include "sssnic_ethdev_link.h"
 #include "sssnic_ethdev_rx.h"
 #include "sssnic_ethdev_tx.h"
+#include "sssnic_ethdev_stats.h"
 
 static int sssnic_ethdev_init(struct rte_eth_dev *ethdev);
 
@@ -748,6 +749,11 @@  static const struct eth_dev_ops sssnic_ethdev_ops = {
 	.allmulticast_disable = sssnic_ethdev_allmulticast_disable,
 	.promiscuous_enable = sssnic_ethdev_promiscuous_enable,
 	.promiscuous_disable = sssnic_ethdev_promiscuous_disable,
+	.stats_get = sssnic_ethdev_stats_get,
+	.stats_reset = sssnic_ethdev_stats_reset,
+	.xstats_get_names = sssnic_ethdev_xstats_get_names,
+	.xstats_get = sssnic_ethdev_xstats_get,
+	.xstats_reset = sssnic_ethdev_xstats_reset,
 };
 
 static int
diff --git a/drivers/net/sssnic/sssnic_ethdev_rx.c b/drivers/net/sssnic/sssnic_ethdev_rx.c
index fd4975dfd5..66045f7a98 100644
--- a/drivers/net/sssnic/sssnic_ethdev_rx.c
+++ b/drivers/net/sssnic/sssnic_ethdev_rx.c
@@ -1153,3 +1153,33 @@  sssnic_ethdev_rx_offload_setup(struct rte_eth_dev *ethdev)
 
 	return 0;
 }
+
+int
+sssnic_ethdev_rx_queue_stats_get(struct rte_eth_dev *ethdev, uint16_t qid,
+	struct sssnic_ethdev_rxq_stats *stats)
+{
+	struct sssnic_ethdev_rxq *rxq;
+
+	if (qid >= ethdev->data->nb_rx_queues) {
+		PMD_DRV_LOG(ERR,
+			"Invalid qid, qid must less than nb_rx_queues(%u)",
+			ethdev->data->nb_rx_queues);
+		return -EINVAL;
+	}
+
+	rxq = ethdev->data->rx_queues[qid];
+	memcpy(stats, &rxq->stats, sizeof(rxq->stats));
+
+	return 0;
+}
+
+void
+sssnic_ethdev_rx_queue_stats_clear(struct rte_eth_dev *ethdev, uint16_t qid)
+{
+	struct sssnic_ethdev_rxq *rxq;
+
+	if (qid < ethdev->data->nb_rx_queues) {
+		rxq = ethdev->data->rx_queues[qid];
+		memset(&rxq->stats, 0, sizeof(rxq->stats));
+	}
+};
diff --git a/drivers/net/sssnic/sssnic_ethdev_rx.h b/drivers/net/sssnic/sssnic_ethdev_rx.h
index f4b4545944..5532aced4e 100644
--- a/drivers/net/sssnic/sssnic_ethdev_rx.h
+++ b/drivers/net/sssnic/sssnic_ethdev_rx.h
@@ -38,5 +38,9 @@  uint16_t sssnic_ethdev_rx_queue_depth_get(struct rte_eth_dev *ethdev,
 uint32_t sssnic_ethdev_rx_buf_size_index_get(uint16_t rx_buf_size);
 int sssnic_ethdev_rx_mode_set(struct rte_eth_dev *ethdev, uint32_t mode);
 int sssnic_ethdev_rx_offload_setup(struct rte_eth_dev *ethdev);
+int sssnic_ethdev_rx_queue_stats_get(struct rte_eth_dev *ethdev, uint16_t qid,
+	struct sssnic_ethdev_rxq_stats *stats);
+void sssnic_ethdev_rx_queue_stats_clear(struct rte_eth_dev *ethdev,
+	uint16_t qid);
 
 #endif
diff --git a/drivers/net/sssnic/sssnic_ethdev_stats.c b/drivers/net/sssnic/sssnic_ethdev_stats.c
new file mode 100644
index 0000000000..dd91aef5f7
--- /dev/null
+++ b/drivers/net/sssnic/sssnic_ethdev_stats.c
@@ -0,0 +1,391 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd.
+ */
+
+#include <rte_common.h>
+#include <ethdev_pci.h>
+
+#include "sssnic_log.h"
+#include "sssnic_ethdev.h"
+#include "sssnic_ethdev_rx.h"
+#include "sssnic_ethdev_tx.h"
+#include "sssnic_ethdev_stats.h"
+#include "base/sssnic_hw.h"
+#include "base/sssnic_api.h"
+
+struct sssnic_ethdev_xstats_name_off {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint32_t offset;
+};
+
+#define SSSNIC_ETHDEV_XSTATS_STR_OFF(stats_type, field)                        \
+	{ #field, offsetof(struct stats_type, field) }
+
+#define SSSNIC_ETHDEV_XSTATS_VALUE(data, idx, name_off)                        \
+	(*(uint64_t *)(((uint8_t *)(data)) + (name_off)[idx].offset))
+
+#define SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(field)                                 \
+	SSSNIC_ETHDEV_XSTATS_STR_OFF(sssnic_ethdev_rxq_stats, field)
+
+#define SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(field)                                 \
+	SSSNIC_ETHDEV_XSTATS_STR_OFF(sssnic_ethdev_txq_stats, field)
+
+#define SSSNIC_ETHDEV_PORT_STATS_STR_OFF(field)                                \
+	SSSNIC_ETHDEV_XSTATS_STR_OFF(sssnic_port_stats, field)
+
+#define SSSNIC_ETHDEV_MAC_STATS_STR_OFF(field)                                 \
+	SSSNIC_ETHDEV_XSTATS_STR_OFF(sssnic_mac_stats, field)
+
+static const struct sssnic_ethdev_xstats_name_off rxq_stats_strings[] = {
+	SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(packets),
+	SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(bytes),
+	SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(csum_errors),
+	SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(other_errors),
+	SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(nombuf),
+	SSSNIC_ETHDEV_RXQ_STATS_STR_OFF(burst),
+};
+#define SSSNIC_ETHDEV_NB_RXQ_XSTATS RTE_DIM(rxq_stats_strings)
+
+static const struct sssnic_ethdev_xstats_name_off txq_stats_strings[] = {
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(packets),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(bytes),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(nobuf),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(zero_len_segs),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(too_large_pkts),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(too_many_segs),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(null_segs),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(offload_errors),
+	SSSNIC_ETHDEV_TXQ_STATS_STR_OFF(burst),
+};
+#define SSSNIC_ETHDEV_NB_TXQ_XSTATS RTE_DIM(txq_stats_strings)
+
+static const struct sssnic_ethdev_xstats_name_off port_stats_strings[] = {
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_ucast_pkts),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_ucast_bytes),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_mcast_pkts),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_mcast_bytes),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_bcast_pkts),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_bcast_bytes),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_discards),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(rx_errors),
+
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_ucast_pkts),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_ucast_bytes),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_mcast_pkts),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_mcast_bytes),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_bcast_pkts),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_bcast_bytes),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_discards),
+	SSSNIC_ETHDEV_PORT_STATS_STR_OFF(tx_errors),
+};
+#define SSSNIC_ETHDEV_NB_PORT_XSTATS RTE_DIM(port_stats_strings)
+
+static const struct sssnic_ethdev_xstats_name_off mac_stats_strings[] = {
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_fragment_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_undersize_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_undermin_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_64b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_65b_127b_pkt),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_128b_255b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_256b_511b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_512b_1023b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_1024b_1518b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_1519b_2047b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_2048b_4095b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_4096b_8191b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_8192b_9216b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_9217b_12287b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_12288b_16383b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_1519b_bad_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_1519b_good_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_oversize_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_jabber_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_bad_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_bad_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_good_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_good_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_total_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_total_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_unicast_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_multicast_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_broadcast_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pause_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri0_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri1_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri2_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri3_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri4_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri5_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri6_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_pfc_pri7_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_control_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_symbol_error_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_fcs_error_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(rx_unfilter_pkts),
+
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_fragment_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_undersize_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_undermin_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_64b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_65b_127b_pkt),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_128b_255b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_256b_511b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_512b_1023b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_1024b_1518b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_1519b_2047b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_2048b_4095b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_4096b_8191b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_8192b_9216b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_9217b_12287b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_12288b_16383b_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_1519b_bad_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_1519b_good_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_oversize_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_jabber_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_bad_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_bad_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_good_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_good_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_total_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_total_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_unicast_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_multicast_bytes),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_broadcast_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pause_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri0_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri1_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri2_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri3_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri4_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri5_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri6_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_pfc_pri7_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_control_pkts),
+	SSSNIC_ETHDEV_MAC_STATS_STR_OFF(tx_debug_bad_pkts),
+};
+#define SSSNIC_ETHDEV_NB_MAC_XSTATS RTE_DIM(mac_stats_strings)
+
+int
+sssnic_ethdev_stats_get(struct rte_eth_dev *ethdev, struct rte_eth_stats *stats)
+{
+	struct sssnic_port_stats port_stats;
+	struct sssnic_ethdev_rxq_stats rxq_stats;
+	struct sssnic_ethdev_txq_stats txq_stats;
+	int ret;
+	uint16_t numq, qid;
+
+	ret = sssnic_port_stats_get(SSSNIC_ETHDEV_TO_HW(ethdev), &port_stats);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to get port stats");
+		return ret;
+	}
+
+	stats->ipackets = port_stats.rx_ucast_pkts + port_stats.rx_mcast_pkts +
+			  port_stats.rx_bcast_pkts;
+	stats->ibytes = port_stats.rx_ucast_bytes + port_stats.rx_mcast_bytes +
+			port_stats.rx_bcast_bytes;
+	stats->opackets = port_stats.tx_ucast_pkts + port_stats.tx_mcast_pkts +
+			  port_stats.tx_bcast_pkts;
+	stats->obytes = port_stats.tx_ucast_bytes + port_stats.tx_mcast_bytes +
+			port_stats.tx_bcast_bytes;
+
+	stats->imissed = port_stats.rx_discards;
+	stats->oerrors = port_stats.tx_discards;
+
+	ethdev->data->rx_mbuf_alloc_failed = 0;
+
+	numq = RTE_MIN(ethdev->data->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (qid = 0; qid < numq; qid++) {
+		sssnic_ethdev_rx_queue_stats_get(ethdev, qid, &rxq_stats);
+		stats->q_ipackets[qid] = rxq_stats.packets;
+		stats->q_ibytes[qid] = rxq_stats.bytes;
+		stats->ierrors +=
+			rxq_stats.csum_errors + rxq_stats.other_errors;
+		ethdev->data->rx_mbuf_alloc_failed += rxq_stats.nombuf;
+	}
+
+	numq = RTE_MIN(ethdev->data->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (qid = 0; qid < numq; qid++) {
+		sssnic_ethdev_tx_queue_stats_get(ethdev, qid, &txq_stats);
+		stats->q_opackets[qid] = txq_stats.packets;
+		stats->q_obytes[qid] = txq_stats.bytes;
+		stats->oerrors += txq_stats.nobuf + txq_stats.too_large_pkts +
+				  txq_stats.zero_len_segs +
+				  txq_stats.offload_errors +
+				  txq_stats.null_segs + txq_stats.too_many_segs;
+	}
+
+	return 0;
+}
+
+int
+sssnic_ethdev_stats_reset(struct rte_eth_dev *ethdev)
+{
+	int ret;
+	uint16_t numq, qid;
+
+	ret = sssnic_port_stats_clear(SSSNIC_ETHDEV_TO_HW(ethdev));
+	if (ret)
+		PMD_DRV_LOG(ERR, "Failed to clear port stats");
+
+	numq = RTE_MIN(ethdev->data->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (qid = 0; qid < numq; qid++)
+		sssnic_ethdev_rx_queue_stats_clear(ethdev, qid);
+
+	numq = RTE_MIN(ethdev->data->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (qid = 0; qid < numq; qid++)
+		sssnic_ethdev_tx_queue_stats_clear(ethdev, qid);
+
+	return 0;
+}
+
+static uint32_t
+sssnic_ethdev_xstats_num_calc(struct rte_eth_dev *ethdev)
+{
+	return SSSNIC_ETHDEV_NB_PORT_XSTATS + SSSNIC_ETHDEV_NB_MAC_XSTATS +
+	       (SSSNIC_ETHDEV_NB_TXQ_XSTATS * ethdev->data->nb_tx_queues) +
+	       (SSSNIC_ETHDEV_NB_RXQ_XSTATS * ethdev->data->nb_rx_queues);
+}
+
+int
+sssnic_ethdev_xstats_get_names(struct rte_eth_dev *ethdev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned int limit)
+{
+	uint16_t i, qid, count = 0;
+
+	if (xstats_names == NULL)
+		return sssnic_ethdev_xstats_num_calc(ethdev);
+
+	for (qid = 0; qid < ethdev->data->nb_rx_queues; qid++) {
+		for (i = 0; i < SSSNIC_ETHDEV_NB_RXQ_XSTATS; i++) {
+			snprintf(xstats_names[count].name,
+				RTE_ETH_XSTATS_NAME_SIZE, "rx_q%u_%s", qid,
+				rxq_stats_strings[i].name);
+			count++;
+		}
+	}
+
+	for (qid = 0; qid < ethdev->data->nb_tx_queues; qid++) {
+		for (i = 0; i < SSSNIC_ETHDEV_NB_TXQ_XSTATS; i++) {
+			snprintf(xstats_names[count].name,
+				RTE_ETH_XSTATS_NAME_SIZE, "tx_q%u_%s", qid,
+				txq_stats_strings[i].name);
+			count++;
+		}
+	}
+
+	for (i = 0; i < SSSNIC_ETHDEV_NB_PORT_XSTATS; i++) {
+		snprintf(xstats_names[count].name, RTE_ETH_XSTATS_NAME_SIZE,
+			"port_%s", port_stats_strings[i].name);
+		count++;
+	}
+
+	for (i = 0; i < SSSNIC_ETHDEV_NB_MAC_XSTATS; i++) {
+		snprintf(xstats_names[count].name, RTE_ETH_XSTATS_NAME_SIZE,
+			"mac_%s", mac_stats_strings[i].name);
+		count++;
+	}
+
+	return count;
+}
+
+int
+sssnic_ethdev_xstats_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_xstat *xstats, unsigned int n)
+{
+	struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev);
+	int ret;
+	uint16_t i, qid, count = 0;
+	struct {
+		struct sssnic_ethdev_rxq_stats rxq;
+		struct sssnic_ethdev_txq_stats txq;
+		struct sssnic_port_stats port;
+		struct sssnic_mac_stats mac;
+	} *stats;
+
+	if (n < sssnic_ethdev_xstats_num_calc(ethdev))
+		return count;
+
+	stats = rte_zmalloc(NULL, sizeof(*stats), 0);
+	if (stats == NULL) {
+		PMD_DRV_LOG(ERR, "Failed to alloc memory for xstats");
+		return -ENOMEM;
+	}
+
+	for (qid = 0; qid < ethdev->data->nb_rx_queues; qid++) {
+		sssnic_ethdev_rx_queue_stats_get(ethdev, qid, &stats->rxq);
+		for (i = 0; i < SSSNIC_ETHDEV_NB_RXQ_XSTATS; i++) {
+			xstats[count].value =
+				SSSNIC_ETHDEV_XSTATS_VALUE(&stats->rxq, i,
+					rxq_stats_strings);
+			count++;
+		}
+	}
+
+	for (qid = 0; qid < ethdev->data->nb_tx_queues; qid++) {
+		sssnic_ethdev_tx_queue_stats_get(ethdev, qid, &stats->txq);
+		for (i = 0; i < SSSNIC_ETHDEV_NB_TXQ_XSTATS; i++) {
+			xstats[count].value =
+				SSSNIC_ETHDEV_XSTATS_VALUE(&stats->txq,
+					i, txq_stats_strings);
+			count++;
+		}
+	}
+
+	ret = sssnic_port_stats_get(hw, &stats->port);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to get port %u stats",
+			ethdev->data->port_id);
+		goto out;
+	}
+
+	for (i = 0; i < SSSNIC_ETHDEV_NB_PORT_XSTATS; i++) {
+		xstats[count].value = SSSNIC_ETHDEV_XSTATS_VALUE(&stats->port,
+			i, port_stats_strings);
+		count++;
+	}
+
+	ret = sssnic_mac_stats_get(hw, &stats->mac);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to get port %u mac stats",
+			ethdev->data->port_id);
+		goto out;
+	}
+
+	for (i = 0; i < SSSNIC_ETHDEV_NB_MAC_XSTATS; i++) {
+		xstats[count].value = SSSNIC_ETHDEV_XSTATS_VALUE(&stats->mac, i,
+			mac_stats_strings);
+		count++;
+	}
+
+	ret = count;
+
+out:
+	rte_free(stats);
+	return ret;
+}
+
+int
+sssnic_ethdev_xstats_reset(struct rte_eth_dev *ethdev)
+{
+	int ret;
+
+	ret = sssnic_ethdev_stats_reset(ethdev);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to clear port %u  basic stats",
+			ethdev->data->port_id);
+		return ret;
+	}
+
+	ret = sssnic_mac_stats_clear(SSSNIC_ETHDEV_TO_HW(ethdev));
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to clear port %u MAC stats",
+			ethdev->data->port_id);
+		return ret;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/sssnic/sssnic_ethdev_stats.h b/drivers/net/sssnic/sssnic_ethdev_stats.h
new file mode 100644
index 0000000000..2fdc419e60
--- /dev/null
+++ b/drivers/net/sssnic/sssnic_ethdev_stats.h
@@ -0,0 +1,18 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018-2022 Shenzhen 3SNIC Information Technology Co., Ltd.
+ */
+
+#ifndef _SSSNIC_ETHDEV_STATS_H_
+#define _SSSNIC_ETHDEV_STATS_H_
+
+int sssnic_ethdev_stats_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_stats *stats);
+int sssnic_ethdev_stats_reset(struct rte_eth_dev *ethdev);
+int sssnic_ethdev_xstats_get_names(struct rte_eth_dev *ethdev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned int limit);
+int sssnic_ethdev_xstats_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_xstat *xstats, unsigned int n);
+int sssnic_ethdev_xstats_reset(struct rte_eth_dev *ethdev);
+
+#endif /* _SSSNIC_ETHDEV_STATS_H_ */
diff --git a/drivers/net/sssnic/sssnic_ethdev_tx.c b/drivers/net/sssnic/sssnic_ethdev_tx.c
index 867373efb2..b4df71e616 100644
--- a/drivers/net/sssnic/sssnic_ethdev_tx.c
+++ b/drivers/net/sssnic/sssnic_ethdev_tx.c
@@ -670,3 +670,39 @@  sssnic_ethdev_tx_max_size_set(struct rte_eth_dev *ethdev, uint16_t size)
 
 	return 0;
 };
+
+int
+sssnic_ethdev_tx_queue_stats_get(struct rte_eth_dev *ethdev, uint16_t qid,
+	struct sssnic_ethdev_txq_stats *stats)
+{
+	struct sssnic_ethdev_txq *txq;
+
+	if (qid >= ethdev->data->nb_tx_queues) {
+		PMD_DRV_LOG(ERR,
+			"Invalid qid, qid must less than nb_tx_queues(%u)",
+			ethdev->data->nb_tx_queues);
+		return -EINVAL;
+	}
+
+	txq = ethdev->data->tx_queues[qid];
+	memcpy(stats, &txq->stats, sizeof(txq->stats));
+
+	return 0;
+}
+
+void
+sssnic_ethdev_tx_queue_stats_clear(struct rte_eth_dev *ethdev, uint16_t qid)
+{
+	struct sssnic_ethdev_txq *txq;
+	uint64_t *stat;
+	int i, len;
+
+	len = sizeof(struct sssnic_ethdev_txq_stats) / sizeof(uint64_t);
+
+	if (qid < ethdev->data->nb_tx_queues) {
+		txq = ethdev->data->tx_queues[qid];
+		stat = (uint64_t *)&txq->stats;
+		for (i = 0; i < len; i++)
+			*(stat++) = 0;
+	}
+}
diff --git a/drivers/net/sssnic/sssnic_ethdev_tx.h b/drivers/net/sssnic/sssnic_ethdev_tx.h
index 88ad82a055..f04c3d5be8 100644
--- a/drivers/net/sssnic/sssnic_ethdev_tx.h
+++ b/drivers/net/sssnic/sssnic_ethdev_tx.h
@@ -33,5 +33,9 @@  uint16_t sssnic_ethdev_tx_queue_depth_get(struct rte_eth_dev *ethdev,
 	uint16_t qid);
 int sssnic_ethdev_tx_ci_attr_init(struct rte_eth_dev *ethdev);
 int sssnic_ethdev_tx_max_size_set(struct rte_eth_dev *ethdev, uint16_t size);
+int sssnic_ethdev_tx_queue_stats_get(struct rte_eth_dev *ethdev, uint16_t qid,
+	struct sssnic_ethdev_txq_stats *stats);
+void sssnic_ethdev_tx_queue_stats_clear(struct rte_eth_dev *ethdev,
+	uint16_t qid);
 
 #endif /* _SSSNIC_ETHDEV_TX_H_ */