xref: /dpdk/drivers/net/mlx5/mlx5_stats.c (revision a170a30d22a8c34c36541d0dd6bcc2fcc4c9ee2f)
18fd92a66SOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
287011737SAdrien Mazarguil  * Copyright 2015 6WIND S.A.
387011737SAdrien Mazarguil  * Copyright 2015 Mellanox.
487011737SAdrien Mazarguil  */
587011737SAdrien Mazarguil 
6fc40db99SAdrien Mazarguil #include <inttypes.h>
7a4193ae3SShahaf Shuler #include <linux/sockios.h>
8a4193ae3SShahaf Shuler #include <linux/ethtool.h>
9fc40db99SAdrien Mazarguil #include <stdint.h>
10fc40db99SAdrien Mazarguil #include <stdio.h>
11a4193ae3SShahaf Shuler 
12ffc905f3SFerruh Yigit #include <rte_ethdev_driver.h>
13a4193ae3SShahaf Shuler #include <rte_common.h>
14a4193ae3SShahaf Shuler #include <rte_malloc.h>
1587011737SAdrien Mazarguil 
1687011737SAdrien Mazarguil #include "mlx5.h"
1787011737SAdrien Mazarguil #include "mlx5_rxtx.h"
1887011737SAdrien Mazarguil #include "mlx5_defs.h"
1987011737SAdrien Mazarguil 
20a4193ae3SShahaf Shuler struct mlx5_counter_ctrl {
21a4193ae3SShahaf Shuler 	/* Name of the counter. */
22a4193ae3SShahaf Shuler 	char dpdk_name[RTE_ETH_XSTATS_NAME_SIZE];
23a4193ae3SShahaf Shuler 	/* Name of the counter on the device table. */
24a4193ae3SShahaf Shuler 	char ctr_name[RTE_ETH_XSTATS_NAME_SIZE];
25fc40db99SAdrien Mazarguil 	uint32_t ib:1; /**< Nonzero for IB counters. */
26a4193ae3SShahaf Shuler };
27a4193ae3SShahaf Shuler 
28a4193ae3SShahaf Shuler static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
29a4193ae3SShahaf Shuler 	{
30a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_unicast_bytes",
31a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_unicast_bytes",
32a4193ae3SShahaf Shuler 	},
33a4193ae3SShahaf Shuler 	{
34a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_multicast_bytes",
35a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_multicast_bytes",
36a4193ae3SShahaf Shuler 	},
37a4193ae3SShahaf Shuler 	{
38a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_broadcast_bytes",
39a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_broadcast_bytes",
40a4193ae3SShahaf Shuler 	},
41a4193ae3SShahaf Shuler 	{
42a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_unicast_packets",
43a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_unicast_packets",
44a4193ae3SShahaf Shuler 	},
45a4193ae3SShahaf Shuler 	{
46a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_multicast_packets",
47a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_multicast_packets",
48a4193ae3SShahaf Shuler 	},
49a4193ae3SShahaf Shuler 	{
50a4193ae3SShahaf Shuler 		.dpdk_name = "rx_port_broadcast_packets",
51a4193ae3SShahaf Shuler 		.ctr_name = "rx_vport_broadcast_packets",
52a4193ae3SShahaf Shuler 	},
53a4193ae3SShahaf Shuler 	{
54a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_unicast_bytes",
55a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_unicast_bytes",
56a4193ae3SShahaf Shuler 	},
57a4193ae3SShahaf Shuler 	{
58a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_multicast_bytes",
59a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_multicast_bytes",
60a4193ae3SShahaf Shuler 	},
61a4193ae3SShahaf Shuler 	{
62a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_broadcast_bytes",
63a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_broadcast_bytes",
64a4193ae3SShahaf Shuler 	},
65a4193ae3SShahaf Shuler 	{
66a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_unicast_packets",
67a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_unicast_packets",
68a4193ae3SShahaf Shuler 	},
69a4193ae3SShahaf Shuler 	{
70a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_multicast_packets",
71a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_multicast_packets",
72a4193ae3SShahaf Shuler 	},
73a4193ae3SShahaf Shuler 	{
74a4193ae3SShahaf Shuler 		.dpdk_name = "tx_port_broadcast_packets",
75a4193ae3SShahaf Shuler 		.ctr_name = "tx_vport_broadcast_packets",
76a4193ae3SShahaf Shuler 	},
77a4193ae3SShahaf Shuler 	{
78a4193ae3SShahaf Shuler 		.dpdk_name = "rx_wqe_err",
79a4193ae3SShahaf Shuler 		.ctr_name = "rx_wqe_err",
80a4193ae3SShahaf Shuler 	},
81a4193ae3SShahaf Shuler 	{
82a4193ae3SShahaf Shuler 		.dpdk_name = "rx_crc_errors_phy",
83a4193ae3SShahaf Shuler 		.ctr_name = "rx_crc_errors_phy",
84a4193ae3SShahaf Shuler 	},
85a4193ae3SShahaf Shuler 	{
86a4193ae3SShahaf Shuler 		.dpdk_name = "rx_in_range_len_errors_phy",
87a4193ae3SShahaf Shuler 		.ctr_name = "rx_in_range_len_errors_phy",
88a4193ae3SShahaf Shuler 	},
89a4193ae3SShahaf Shuler 	{
90a4193ae3SShahaf Shuler 		.dpdk_name = "rx_symbol_err_phy",
91a4193ae3SShahaf Shuler 		.ctr_name = "rx_symbol_err_phy",
92a4193ae3SShahaf Shuler 	},
93a4193ae3SShahaf Shuler 	{
94a4193ae3SShahaf Shuler 		.dpdk_name = "tx_errors_phy",
95a4193ae3SShahaf Shuler 		.ctr_name = "tx_errors_phy",
96a4193ae3SShahaf Shuler 	},
97859081d3SShahaf Shuler 	{
98859081d3SShahaf Shuler 		.dpdk_name = "rx_out_of_buffer",
99859081d3SShahaf Shuler 		.ctr_name = "out_of_buffer",
100fc40db99SAdrien Mazarguil 		.ib = 1,
101859081d3SShahaf Shuler 	},
1020c62250bSShahaf Shuler 	{
1030c62250bSShahaf Shuler 		.dpdk_name = "tx_packets_phy",
1040c62250bSShahaf Shuler 		.ctr_name = "tx_packets_phy",
1050c62250bSShahaf Shuler 	},
1060c62250bSShahaf Shuler 	{
1070c62250bSShahaf Shuler 		.dpdk_name = "rx_packets_phy",
1080c62250bSShahaf Shuler 		.ctr_name = "rx_packets_phy",
1090c62250bSShahaf Shuler 	},
1100c62250bSShahaf Shuler 	{
1110c62250bSShahaf Shuler 		.dpdk_name = "tx_bytes_phy",
1120c62250bSShahaf Shuler 		.ctr_name = "tx_bytes_phy",
1130c62250bSShahaf Shuler 	},
1140c62250bSShahaf Shuler 	{
1150c62250bSShahaf Shuler 		.dpdk_name = "rx_bytes_phy",
1160c62250bSShahaf Shuler 		.ctr_name = "rx_bytes_phy",
1170c62250bSShahaf Shuler 	},
118a4193ae3SShahaf Shuler };
119a4193ae3SShahaf Shuler 
120a4193ae3SShahaf Shuler static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
121a4193ae3SShahaf Shuler 
122a4193ae3SShahaf Shuler /**
123a4193ae3SShahaf Shuler  * Read device counters table.
124a4193ae3SShahaf Shuler  *
125af4f09f2SNélio Laranjeiro  * @param dev
126af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
127a4193ae3SShahaf Shuler  * @param[out] stats
128a4193ae3SShahaf Shuler  *   Counters table output buffer.
129a4193ae3SShahaf Shuler  *
130a4193ae3SShahaf Shuler  * @return
131a6d83b6aSNélio Laranjeiro  *   0 on success and stats is filled, negative errno value otherwise and
132a6d83b6aSNélio Laranjeiro  *   rte_errno is set.
133a4193ae3SShahaf Shuler  */
134a4193ae3SShahaf Shuler static int
135af4f09f2SNélio Laranjeiro mlx5_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)
136a4193ae3SShahaf Shuler {
137af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
138a4193ae3SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
139a4193ae3SShahaf Shuler 	unsigned int i;
140a4193ae3SShahaf Shuler 	struct ifreq ifr;
14125b73ba6SThierry Herbelot 	unsigned int stats_sz = xstats_ctrl->stats_n * sizeof(uint64_t);
14225b73ba6SThierry Herbelot 	unsigned char et_stat_buf[sizeof(struct ethtool_stats) + stats_sz];
14325b73ba6SThierry Herbelot 	struct ethtool_stats *et_stats = (struct ethtool_stats *)et_stat_buf;
144a6d83b6aSNélio Laranjeiro 	int ret;
145a4193ae3SShahaf Shuler 
146a4193ae3SShahaf Shuler 	et_stats->cmd = ETHTOOL_GSTATS;
147a4193ae3SShahaf Shuler 	et_stats->n_stats = xstats_ctrl->stats_n;
148a4193ae3SShahaf Shuler 	ifr.ifr_data = (caddr_t)et_stats;
149a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
150a6d83b6aSNélio Laranjeiro 	if (ret) {
151*a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING,
152*a170a30dSNélio Laranjeiro 			"port %u unable to read statistic values from device",
1530f99970bSNélio Laranjeiro 			dev->data->port_id);
154a6d83b6aSNélio Laranjeiro 		return ret;
155a4193ae3SShahaf Shuler 	}
156859081d3SShahaf Shuler 	for (i = 0; i != xstats_n; ++i) {
157fc40db99SAdrien Mazarguil 		if (mlx5_counters_init[i].ib) {
158fc40db99SAdrien Mazarguil 			FILE *file;
159fc40db99SAdrien Mazarguil 			MKSTR(path, "%s/ports/1/hw_counters/%s",
160fc40db99SAdrien Mazarguil 			      priv->ibdev_path,
161fc40db99SAdrien Mazarguil 			      mlx5_counters_init[i].ctr_name);
162fc40db99SAdrien Mazarguil 
163fc40db99SAdrien Mazarguil 			file = fopen(path, "rb");
164fc40db99SAdrien Mazarguil 			if (file) {
165fc40db99SAdrien Mazarguil 				int n = fscanf(file, "%" SCNu64, &stats[i]);
166fc40db99SAdrien Mazarguil 
167fc40db99SAdrien Mazarguil 				fclose(file);
168fc40db99SAdrien Mazarguil 				if (n != 1)
169fc40db99SAdrien Mazarguil 					stats[i] = 0;
170fc40db99SAdrien Mazarguil 			}
171fc40db99SAdrien Mazarguil 		} else {
172a4193ae3SShahaf Shuler 			stats[i] = (uint64_t)
173a4193ae3SShahaf Shuler 				et_stats->data[xstats_ctrl->dev_table_idx[i]];
174859081d3SShahaf Shuler 		}
175fc40db99SAdrien Mazarguil 	}
176a4193ae3SShahaf Shuler 	return 0;
177a4193ae3SShahaf Shuler }
178a4193ae3SShahaf Shuler 
179a4193ae3SShahaf Shuler /**
180e62bc9e7SShahaf Shuler  * Query the number of statistics provided by ETHTOOL.
181e62bc9e7SShahaf Shuler  *
182af4f09f2SNélio Laranjeiro  * @param dev
183af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
184e62bc9e7SShahaf Shuler  *
185e62bc9e7SShahaf Shuler  * @return
186a6d83b6aSNélio Laranjeiro  *   Number of statistics on success, negative errno value otherwise and
187a6d83b6aSNélio Laranjeiro  *   rte_errno is set.
188e62bc9e7SShahaf Shuler  */
189e62bc9e7SShahaf Shuler static int
190af4f09f2SNélio Laranjeiro mlx5_ethtool_get_stats_n(struct rte_eth_dev *dev) {
191e62bc9e7SShahaf Shuler 	struct ethtool_drvinfo drvinfo;
192e62bc9e7SShahaf Shuler 	struct ifreq ifr;
193a6d83b6aSNélio Laranjeiro 	int ret;
194e62bc9e7SShahaf Shuler 
195e62bc9e7SShahaf Shuler 	drvinfo.cmd = ETHTOOL_GDRVINFO;
196e62bc9e7SShahaf Shuler 	ifr.ifr_data = (caddr_t)&drvinfo;
197a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
198a6d83b6aSNélio Laranjeiro 	if (ret) {
199*a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u unable to query number of statistics",
2000f99970bSNélio Laranjeiro 			dev->data->port_id);
201a6d83b6aSNélio Laranjeiro 		return ret;
202e62bc9e7SShahaf Shuler 	}
203e62bc9e7SShahaf Shuler 	return drvinfo.n_stats;
204e62bc9e7SShahaf Shuler }
205e62bc9e7SShahaf Shuler 
206e62bc9e7SShahaf Shuler /**
207a4193ae3SShahaf Shuler  * Init the structures to read device counters.
208a4193ae3SShahaf Shuler  *
209af4f09f2SNélio Laranjeiro  * @param dev
210af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
211a4193ae3SShahaf Shuler  */
212a4193ae3SShahaf Shuler void
213af4f09f2SNélio Laranjeiro mlx5_xstats_init(struct rte_eth_dev *dev)
214a4193ae3SShahaf Shuler {
215af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
216a4193ae3SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
217a4193ae3SShahaf Shuler 	unsigned int i;
218a4193ae3SShahaf Shuler 	unsigned int j;
219a4193ae3SShahaf Shuler 	struct ifreq ifr;
220a4193ae3SShahaf Shuler 	struct ethtool_gstrings *strings = NULL;
221a4193ae3SShahaf Shuler 	unsigned int dev_stats_n;
222a4193ae3SShahaf Shuler 	unsigned int str_sz;
223a6d83b6aSNélio Laranjeiro 	int ret;
224a4193ae3SShahaf Shuler 
225a6d83b6aSNélio Laranjeiro 	ret = mlx5_ethtool_get_stats_n(dev);
226a6d83b6aSNélio Laranjeiro 	if (ret < 0) {
227*a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u no extended statistics available",
2280f99970bSNélio Laranjeiro 			dev->data->port_id);
229a4193ae3SShahaf Shuler 		return;
230a4193ae3SShahaf Shuler 	}
231a6d83b6aSNélio Laranjeiro 	dev_stats_n = ret;
232a4193ae3SShahaf Shuler 	xstats_ctrl->stats_n = dev_stats_n;
233a4193ae3SShahaf Shuler 	/* Allocate memory to grab stat names and values. */
234a4193ae3SShahaf Shuler 	str_sz = dev_stats_n * ETH_GSTRING_LEN;
235a4193ae3SShahaf Shuler 	strings = (struct ethtool_gstrings *)
236a4193ae3SShahaf Shuler 		  rte_malloc("xstats_strings",
237a4193ae3SShahaf Shuler 			     str_sz + sizeof(struct ethtool_gstrings), 0);
238a4193ae3SShahaf Shuler 	if (!strings) {
239*a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u unable to allocate memory for xstats",
2400f99970bSNélio Laranjeiro 		     dev->data->port_id);
241a4193ae3SShahaf Shuler 		return;
242a4193ae3SShahaf Shuler 	}
243a4193ae3SShahaf Shuler 	strings->cmd = ETHTOOL_GSTRINGS;
244a4193ae3SShahaf Shuler 	strings->string_set = ETH_SS_STATS;
245a4193ae3SShahaf Shuler 	strings->len = dev_stats_n;
246a4193ae3SShahaf Shuler 	ifr.ifr_data = (caddr_t)strings;
247a6d83b6aSNélio Laranjeiro 	ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
248a6d83b6aSNélio Laranjeiro 	if (ret) {
249*a170a30dSNélio Laranjeiro 		DRV_LOG(WARNING, "port %u unable to get statistic names",
2500f99970bSNélio Laranjeiro 			dev->data->port_id);
251a4193ae3SShahaf Shuler 		goto free;
252a4193ae3SShahaf Shuler 	}
253a4193ae3SShahaf Shuler 	for (j = 0; j != xstats_n; ++j)
254a4193ae3SShahaf Shuler 		xstats_ctrl->dev_table_idx[j] = dev_stats_n;
255a4193ae3SShahaf Shuler 	for (i = 0; i != dev_stats_n; ++i) {
256a4193ae3SShahaf Shuler 		const char *curr_string = (const char *)
257a4193ae3SShahaf Shuler 			&strings->data[i * ETH_GSTRING_LEN];
258a4193ae3SShahaf Shuler 
259a4193ae3SShahaf Shuler 		for (j = 0; j != xstats_n; ++j) {
260a4193ae3SShahaf Shuler 			if (!strcmp(mlx5_counters_init[j].ctr_name,
261a4193ae3SShahaf Shuler 				    curr_string)) {
262a4193ae3SShahaf Shuler 				xstats_ctrl->dev_table_idx[j] = i;
263a4193ae3SShahaf Shuler 				break;
264a4193ae3SShahaf Shuler 			}
265a4193ae3SShahaf Shuler 		}
266a4193ae3SShahaf Shuler 	}
267a4193ae3SShahaf Shuler 	for (j = 0; j != xstats_n; ++j) {
268fc40db99SAdrien Mazarguil 		if (mlx5_counters_init[j].ib)
269859081d3SShahaf Shuler 			continue;
270a4193ae3SShahaf Shuler 		if (xstats_ctrl->dev_table_idx[j] >= dev_stats_n) {
271*a170a30dSNélio Laranjeiro 			DRV_LOG(WARNING,
272*a170a30dSNélio Laranjeiro 				"port %u counter \"%s\" is not recognized",
2730f99970bSNélio Laranjeiro 				dev->data->port_id,
274a4193ae3SShahaf Shuler 				mlx5_counters_init[j].dpdk_name);
275a4193ae3SShahaf Shuler 			goto free;
276a4193ae3SShahaf Shuler 		}
277a4193ae3SShahaf Shuler 	}
278a4193ae3SShahaf Shuler 	/* Copy to base at first time. */
279a4193ae3SShahaf Shuler 	assert(xstats_n <= MLX5_MAX_XSTATS);
280a6d83b6aSNélio Laranjeiro 	ret = mlx5_read_dev_counters(dev, xstats_ctrl->base);
281a6d83b6aSNélio Laranjeiro 	if (ret)
282*a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot read device counters: %s",
2830f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
284a4193ae3SShahaf Shuler free:
285a4193ae3SShahaf Shuler 	rte_free(strings);
286a4193ae3SShahaf Shuler }
287a4193ae3SShahaf Shuler 
288a4193ae3SShahaf Shuler /**
289af4f09f2SNélio Laranjeiro  * DPDK callback to get extended device statistics.
290a4193ae3SShahaf Shuler  *
291af4f09f2SNélio Laranjeiro  * @param dev
292af4f09f2SNélio Laranjeiro  *   Pointer to Ethernet device.
293a4193ae3SShahaf Shuler  * @param[out] stats
294a4193ae3SShahaf Shuler  *   Pointer to rte extended stats table.
295af4f09f2SNélio Laranjeiro  * @param n
296af4f09f2SNélio Laranjeiro  *   The size of the stats table.
297a4193ae3SShahaf Shuler  *
298a4193ae3SShahaf Shuler  * @return
299a4193ae3SShahaf Shuler  *   Number of extended stats on success and stats is filled,
300a6d83b6aSNélio Laranjeiro  *   negative on error and rte_errno is set.
301a4193ae3SShahaf Shuler  */
302af4f09f2SNélio Laranjeiro int
303af4f09f2SNélio Laranjeiro mlx5_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
304af4f09f2SNélio Laranjeiro 		unsigned int n)
305a4193ae3SShahaf Shuler {
306af4f09f2SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
307a4193ae3SShahaf Shuler 	unsigned int i;
308a4193ae3SShahaf Shuler 	uint64_t counters[n];
309a4193ae3SShahaf Shuler 
310af4f09f2SNélio Laranjeiro 	if (n >= xstats_n && stats) {
311af4f09f2SNélio Laranjeiro 		struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
312af4f09f2SNélio Laranjeiro 		int stats_n;
313a6d83b6aSNélio Laranjeiro 		int ret;
314af4f09f2SNélio Laranjeiro 
315af4f09f2SNélio Laranjeiro 		stats_n = mlx5_ethtool_get_stats_n(dev);
316af4f09f2SNélio Laranjeiro 		if (stats_n < 0)
317a6d83b6aSNélio Laranjeiro 			return stats_n;
318af4f09f2SNélio Laranjeiro 		if (xstats_ctrl->stats_n != stats_n)
319af4f09f2SNélio Laranjeiro 			mlx5_xstats_init(dev);
320af4f09f2SNélio Laranjeiro 		ret = mlx5_read_dev_counters(dev, counters);
321af4f09f2SNélio Laranjeiro 		if (ret)
322af4f09f2SNélio Laranjeiro 			return ret;
323a4193ae3SShahaf Shuler 		for (i = 0; i != xstats_n; ++i) {
324a4193ae3SShahaf Shuler 			stats[i].id = i;
325a4193ae3SShahaf Shuler 			stats[i].value = (counters[i] - xstats_ctrl->base[i]);
326a4193ae3SShahaf Shuler 		}
327a4193ae3SShahaf Shuler 	}
328af4f09f2SNélio Laranjeiro 	return n;
329a4193ae3SShahaf Shuler }
330a4193ae3SShahaf Shuler 
33187011737SAdrien Mazarguil /**
33287011737SAdrien Mazarguil  * DPDK callback to get device statistics.
33387011737SAdrien Mazarguil  *
33487011737SAdrien Mazarguil  * @param dev
33587011737SAdrien Mazarguil  *   Pointer to Ethernet device structure.
33687011737SAdrien Mazarguil  * @param[out] stats
33787011737SAdrien Mazarguil  *   Stats structure output buffer.
338a6d83b6aSNélio Laranjeiro  *
339a6d83b6aSNélio Laranjeiro  * @return
340a6d83b6aSNélio Laranjeiro  *   0 on success and stats is filled, negative errno value otherwise and
341a6d83b6aSNélio Laranjeiro  *   rte_errno is set.
34287011737SAdrien Mazarguil  */
343d5b0924bSMatan Azrad int
34487011737SAdrien Mazarguil mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
34587011737SAdrien Mazarguil {
34601d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
34787011737SAdrien Mazarguil 	struct rte_eth_stats tmp = {0};
34887011737SAdrien Mazarguil 	unsigned int i;
34987011737SAdrien Mazarguil 	unsigned int idx;
35087011737SAdrien Mazarguil 
35187011737SAdrien Mazarguil 	/* Add software counters. */
35287011737SAdrien Mazarguil 	for (i = 0; (i != priv->rxqs_n); ++i) {
35378142aacSNélio Laranjeiro 		struct mlx5_rxq_data *rxq = (*priv->rxqs)[i];
35487011737SAdrien Mazarguil 
35587011737SAdrien Mazarguil 		if (rxq == NULL)
35687011737SAdrien Mazarguil 			continue;
35787011737SAdrien Mazarguil 		idx = rxq->stats.idx;
35887011737SAdrien Mazarguil 		if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
35987011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
36087011737SAdrien Mazarguil 			tmp.q_ipackets[idx] += rxq->stats.ipackets;
36187011737SAdrien Mazarguil 			tmp.q_ibytes[idx] += rxq->stats.ibytes;
36287011737SAdrien Mazarguil #endif
36387011737SAdrien Mazarguil 			tmp.q_errors[idx] += (rxq->stats.idropped +
36487011737SAdrien Mazarguil 					      rxq->stats.rx_nombuf);
36587011737SAdrien Mazarguil 		}
36687011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
36787011737SAdrien Mazarguil 		tmp.ipackets += rxq->stats.ipackets;
36887011737SAdrien Mazarguil 		tmp.ibytes += rxq->stats.ibytes;
36987011737SAdrien Mazarguil #endif
37087011737SAdrien Mazarguil 		tmp.ierrors += rxq->stats.idropped;
37187011737SAdrien Mazarguil 		tmp.rx_nombuf += rxq->stats.rx_nombuf;
37287011737SAdrien Mazarguil 	}
37387011737SAdrien Mazarguil 	for (i = 0; (i != priv->txqs_n); ++i) {
374991b04f6SNélio Laranjeiro 		struct mlx5_txq_data *txq = (*priv->txqs)[i];
37587011737SAdrien Mazarguil 
37687011737SAdrien Mazarguil 		if (txq == NULL)
37787011737SAdrien Mazarguil 			continue;
37887011737SAdrien Mazarguil 		idx = txq->stats.idx;
37987011737SAdrien Mazarguil 		if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
38087011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
38187011737SAdrien Mazarguil 			tmp.q_opackets[idx] += txq->stats.opackets;
38287011737SAdrien Mazarguil 			tmp.q_obytes[idx] += txq->stats.obytes;
38387011737SAdrien Mazarguil #endif
3849f9a48ebSShahaf Shuler 			tmp.q_errors[idx] += txq->stats.oerrors;
38587011737SAdrien Mazarguil 		}
38687011737SAdrien Mazarguil #ifdef MLX5_PMD_SOFT_COUNTERS
38787011737SAdrien Mazarguil 		tmp.opackets += txq->stats.opackets;
38887011737SAdrien Mazarguil 		tmp.obytes += txq->stats.obytes;
38987011737SAdrien Mazarguil #endif
3909f9a48ebSShahaf Shuler 		tmp.oerrors += txq->stats.oerrors;
39187011737SAdrien Mazarguil 	}
39287011737SAdrien Mazarguil #ifndef MLX5_PMD_SOFT_COUNTERS
39387011737SAdrien Mazarguil 	/* FIXME: retrieve and add hardware counters. */
39487011737SAdrien Mazarguil #endif
39587011737SAdrien Mazarguil 	*stats = tmp;
396d5b0924bSMatan Azrad 	return 0;
39787011737SAdrien Mazarguil }
39887011737SAdrien Mazarguil 
39987011737SAdrien Mazarguil /**
40087011737SAdrien Mazarguil  * DPDK callback to clear device statistics.
40187011737SAdrien Mazarguil  *
40287011737SAdrien Mazarguil  * @param dev
40387011737SAdrien Mazarguil  *   Pointer to Ethernet device structure.
40487011737SAdrien Mazarguil  */
40587011737SAdrien Mazarguil void
40687011737SAdrien Mazarguil mlx5_stats_reset(struct rte_eth_dev *dev)
40787011737SAdrien Mazarguil {
40887011737SAdrien Mazarguil 	struct priv *priv = dev->data->dev_private;
40987011737SAdrien Mazarguil 	unsigned int i;
41087011737SAdrien Mazarguil 	unsigned int idx;
41187011737SAdrien Mazarguil 
41287011737SAdrien Mazarguil 	for (i = 0; (i != priv->rxqs_n); ++i) {
41387011737SAdrien Mazarguil 		if ((*priv->rxqs)[i] == NULL)
41487011737SAdrien Mazarguil 			continue;
41587011737SAdrien Mazarguil 		idx = (*priv->rxqs)[i]->stats.idx;
41687011737SAdrien Mazarguil 		(*priv->rxqs)[i]->stats =
41787011737SAdrien Mazarguil 			(struct mlx5_rxq_stats){ .idx = idx };
41887011737SAdrien Mazarguil 	}
41987011737SAdrien Mazarguil 	for (i = 0; (i != priv->txqs_n); ++i) {
42087011737SAdrien Mazarguil 		if ((*priv->txqs)[i] == NULL)
42187011737SAdrien Mazarguil 			continue;
4227efc807dSAdrien Mazarguil 		idx = (*priv->txqs)[i]->stats.idx;
42387011737SAdrien Mazarguil 		(*priv->txqs)[i]->stats =
42487011737SAdrien Mazarguil 			(struct mlx5_txq_stats){ .idx = idx };
42587011737SAdrien Mazarguil 	}
42687011737SAdrien Mazarguil #ifndef MLX5_PMD_SOFT_COUNTERS
42787011737SAdrien Mazarguil 	/* FIXME: reset hardware counters. */
42887011737SAdrien Mazarguil #endif
42987011737SAdrien Mazarguil }
430a4193ae3SShahaf Shuler 
431a4193ae3SShahaf Shuler /**
432a4193ae3SShahaf Shuler  * DPDK callback to clear device extended statistics.
433a4193ae3SShahaf Shuler  *
434a4193ae3SShahaf Shuler  * @param dev
435a4193ae3SShahaf Shuler  *   Pointer to Ethernet device structure.
436a4193ae3SShahaf Shuler  */
437a4193ae3SShahaf Shuler void
438a4193ae3SShahaf Shuler mlx5_xstats_reset(struct rte_eth_dev *dev)
439a4193ae3SShahaf Shuler {
44001d79216SNélio Laranjeiro 	struct priv *priv = dev->data->dev_private;
441e62bc9e7SShahaf Shuler 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
442e62bc9e7SShahaf Shuler 	int stats_n;
443af4f09f2SNélio Laranjeiro 	unsigned int i;
444af4f09f2SNélio Laranjeiro 	unsigned int n = xstats_n;
445af4f09f2SNélio Laranjeiro 	uint64_t counters[n];
446a6d83b6aSNélio Laranjeiro 	int ret;
447a4193ae3SShahaf Shuler 
448af4f09f2SNélio Laranjeiro 	stats_n = mlx5_ethtool_get_stats_n(dev);
449a6d83b6aSNélio Laranjeiro 	if (stats_n < 0) {
450*a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot get stats: %s", dev->data->port_id,
451a6d83b6aSNélio Laranjeiro 			strerror(-stats_n));
4527b2423cdSNélio Laranjeiro 		return;
453a6d83b6aSNélio Laranjeiro 	}
454e62bc9e7SShahaf Shuler 	if (xstats_ctrl->stats_n != stats_n)
455af4f09f2SNélio Laranjeiro 		mlx5_xstats_init(dev);
456a6d83b6aSNélio Laranjeiro 	ret = mlx5_read_dev_counters(dev, counters);
457a6d83b6aSNélio Laranjeiro 	if (ret) {
458*a170a30dSNélio Laranjeiro 		DRV_LOG(ERR, "port %u cannot read device counters: %s",
4590f99970bSNélio Laranjeiro 			dev->data->port_id, strerror(rte_errno));
460af4f09f2SNélio Laranjeiro 		return;
461a6d83b6aSNélio Laranjeiro 	}
462af4f09f2SNélio Laranjeiro 	for (i = 0; i != n; ++i)
463af4f09f2SNélio Laranjeiro 		xstats_ctrl->base[i] = counters[i];
464a4193ae3SShahaf Shuler }
465a4193ae3SShahaf Shuler 
466a4193ae3SShahaf Shuler /**
467a4193ae3SShahaf Shuler  * DPDK callback to retrieve names of extended device statistics
468a4193ae3SShahaf Shuler  *
469a4193ae3SShahaf Shuler  * @param dev
470a4193ae3SShahaf Shuler  *   Pointer to Ethernet device structure.
471a4193ae3SShahaf Shuler  * @param[out] xstats_names
472a4193ae3SShahaf Shuler  *   Buffer to insert names into.
473a4193ae3SShahaf Shuler  * @param n
474a4193ae3SShahaf Shuler  *   Number of names.
475a4193ae3SShahaf Shuler  *
476a4193ae3SShahaf Shuler  * @return
477a4193ae3SShahaf Shuler  *   Number of xstats names.
478a4193ae3SShahaf Shuler  */
479a4193ae3SShahaf Shuler int
48056f08e16SNélio Laranjeiro mlx5_xstats_get_names(struct rte_eth_dev *dev __rte_unused,
481a4193ae3SShahaf Shuler 		      struct rte_eth_xstat_name *xstats_names, unsigned int n)
482a4193ae3SShahaf Shuler {
483a4193ae3SShahaf Shuler 	unsigned int i;
484a4193ae3SShahaf Shuler 
485a4193ae3SShahaf Shuler 	if (n >= xstats_n && xstats_names) {
486a4193ae3SShahaf Shuler 		for (i = 0; i != xstats_n; ++i) {
487a4193ae3SShahaf Shuler 			strncpy(xstats_names[i].name,
488a4193ae3SShahaf Shuler 				mlx5_counters_init[i].dpdk_name,
489a4193ae3SShahaf Shuler 				RTE_ETH_XSTATS_NAME_SIZE);
490a4193ae3SShahaf Shuler 			xstats_names[i].name[RTE_ETH_XSTATS_NAME_SIZE - 1] = 0;
491a4193ae3SShahaf Shuler 		}
492a4193ae3SShahaf Shuler 	}
493a4193ae3SShahaf Shuler 	return xstats_n;
494a4193ae3SShahaf Shuler }
495