Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2015 6WIND S.A.
3 : : * Copyright 2015 Mellanox Technologies, Ltd
4 : : */
5 : :
6 : : #include <inttypes.h>
7 : : #include <stdint.h>
8 : : #include <stdio.h>
9 : : #include <unistd.h>
10 : :
11 : : #include <ethdev_driver.h>
12 : : #include <rte_common.h>
13 : : #include <rte_malloc.h>
14 : :
15 : : #include <mlx5_common.h>
16 : :
17 : : #include "mlx5_defs.h"
18 : : #include "mlx5.h"
19 : : #include "mlx5_rx.h"
20 : : #include "mlx5_tx.h"
21 : : #include "mlx5_malloc.h"
22 : :
23 : : /**
24 : : * DPDK callback to get extended device statistics.
25 : : *
26 : : * @param dev
27 : : * Pointer to Ethernet device.
28 : : * @param[out] stats
29 : : * Pointer to rte extended stats table.
30 : : * @param n
31 : : * The size of the stats table.
32 : : *
33 : : * @return
34 : : * Number of extended stats on success and stats is filled,
35 : : * negative on error and rte_errno is set.
36 : : */
37 : : int
38 : 0 : mlx5_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
39 : : unsigned int n)
40 : : {
41 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
42 : : uint64_t counters[MLX5_MAX_XSTATS];
43 : : struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
44 : : unsigned int i;
45 : 0 : uint16_t stats_n = 0;
46 : 0 : uint16_t stats_n_2nd = 0;
47 : 0 : uint16_t mlx5_stats_n = xstats_ctrl->mlx5_stats_n;
48 [ # # # # ]: 0 : bool bond_master = (priv->master && priv->pf_bond >= 0);
49 : :
50 [ # # # # ]: 0 : if (n >= mlx5_stats_n && stats) {
51 : : int ret;
52 : :
53 : 0 : ret = mlx5_os_get_stats_n(dev, bond_master, &stats_n, &stats_n_2nd);
54 [ # # ]: 0 : if (ret < 0)
55 : : return ret;
56 : : /*
57 : : * The number of statistics fetched via "ETH_SS_STATS" may vary because
58 : : * of the port configuration each time. This is also true between 2
59 : : * ports. There might be a case that the numbers are the same even if
60 : : * configurations are different.
61 : : * It is not recommended to change the configuration without using
62 : : * RTE API. The port(traffic) restart may trigger another initialization
63 : : * to make sure the map are correct.
64 : : */
65 [ # # # # ]: 0 : if (xstats_ctrl->stats_n != stats_n ||
66 [ # # ]: 0 : (bond_master && xstats_ctrl->stats_n_2nd != stats_n_2nd))
67 : 0 : mlx5_os_stats_init(dev);
68 : 0 : ret = mlx5_os_read_dev_counters(dev, bond_master, counters);
69 [ # # ]: 0 : if (ret < 0)
70 : : return ret;
71 [ # # ]: 0 : for (i = 0; i != mlx5_stats_n; i++) {
72 : 0 : stats[i].id = i;
73 [ # # ]: 0 : if (xstats_ctrl->info[i].dev) {
74 : : uint64_t wrap_n;
75 : 0 : uint64_t hw_stat = xstats_ctrl->hw_stats[i];
76 : :
77 : 0 : stats[i].value = (counters[i] -
78 : 0 : xstats_ctrl->base[i]) &
79 : : (uint64_t)UINT32_MAX;
80 : 0 : wrap_n = hw_stat >> 32;
81 : 0 : if (stats[i].value <
82 [ # # ]: 0 : (hw_stat & (uint64_t)UINT32_MAX))
83 : 0 : wrap_n++;
84 : 0 : stats[i].value |= (wrap_n) << 32;
85 : 0 : xstats_ctrl->hw_stats[i] = stats[i].value;
86 : : } else {
87 : 0 : stats[i].value =
88 : 0 : (counters[i] - xstats_ctrl->base[i]);
89 : : }
90 : : }
91 : : }
92 : 0 : mlx5_stats_n = mlx5_txpp_xstats_get(dev, stats, n, mlx5_stats_n);
93 : 0 : return mlx5_stats_n;
94 : : }
95 : :
96 : : /**
97 : : * DPDK callback to get device statistics.
98 : : *
99 : : * @param dev
100 : : * Pointer to Ethernet device structure.
101 : : * @param[out] stats
102 : : * Stats structure output buffer.
103 : : *
104 : : * @return
105 : : * 0 on success and stats is filled, negative errno value otherwise and
106 : : * rte_errno is set.
107 : : */
108 : : int
109 : 0 : mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
110 : : {
111 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
112 : : struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
113 : : struct rte_eth_stats tmp;
114 : : unsigned int i;
115 : : unsigned int idx;
116 : : uint64_t wrap_n;
117 : : int ret;
118 : :
119 : : memset(&tmp, 0, sizeof(tmp));
120 : : /* Add software counters. */
121 [ # # ]: 0 : for (i = 0; (i != priv->rxqs_n); ++i) {
122 : 0 : struct mlx5_rxq_data *rxq = mlx5_rxq_data_get(dev, i);
123 : :
124 [ # # ]: 0 : if (rxq == NULL)
125 : 0 : continue;
126 : 0 : idx = rxq->idx;
127 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
128 : : #ifdef MLX5_PMD_SOFT_COUNTERS
129 : 0 : tmp.q_ipackets[idx] += rxq->stats.ipackets -
130 : 0 : rxq->stats_reset.ipackets;
131 : 0 : tmp.q_ibytes[idx] += rxq->stats.ibytes -
132 : 0 : rxq->stats_reset.ibytes;
133 : : #endif
134 : 0 : tmp.q_errors[idx] += (rxq->stats.idropped +
135 : 0 : rxq->stats.rx_nombuf) -
136 : 0 : (rxq->stats_reset.idropped +
137 : 0 : rxq->stats_reset.rx_nombuf);
138 : : }
139 : : #ifdef MLX5_PMD_SOFT_COUNTERS
140 : 0 : tmp.ipackets += rxq->stats.ipackets - rxq->stats_reset.ipackets;
141 : 0 : tmp.ibytes += rxq->stats.ibytes - rxq->stats_reset.ibytes;
142 : : #endif
143 : 0 : tmp.ierrors += rxq->stats.idropped - rxq->stats_reset.idropped;
144 : 0 : tmp.rx_nombuf += rxq->stats.rx_nombuf -
145 : 0 : rxq->stats_reset.rx_nombuf;
146 : : }
147 [ # # ]: 0 : for (i = 0; (i != priv->txqs_n); ++i) {
148 : 0 : struct mlx5_txq_data *txq = (*priv->txqs)[i];
149 : :
150 [ # # ]: 0 : if (txq == NULL)
151 : 0 : continue;
152 : 0 : idx = txq->idx;
153 [ # # ]: 0 : if (idx < RTE_ETHDEV_QUEUE_STAT_CNTRS) {
154 : : #ifdef MLX5_PMD_SOFT_COUNTERS
155 : 0 : tmp.q_opackets[idx] += txq->stats.opackets -
156 : 0 : txq->stats_reset.opackets;
157 : 0 : tmp.q_obytes[idx] += txq->stats.obytes -
158 : 0 : txq->stats_reset.obytes;
159 : : #endif
160 : : }
161 : : #ifdef MLX5_PMD_SOFT_COUNTERS
162 : 0 : tmp.opackets += txq->stats.opackets - txq->stats_reset.opackets;
163 : 0 : tmp.obytes += txq->stats.obytes - txq->stats_reset.obytes;
164 : : #endif
165 : 0 : tmp.oerrors += txq->stats.oerrors - txq->stats_reset.oerrors;
166 : : }
167 : 0 : ret = mlx5_os_read_dev_stat(priv, "out_of_buffer", &tmp.imissed);
168 [ # # ]: 0 : if (ret == 0) {
169 : 0 : tmp.imissed = (tmp.imissed - stats_ctrl->imissed_base) &
170 : : (uint64_t)UINT32_MAX;
171 : 0 : wrap_n = stats_ctrl->imissed >> 32;
172 [ # # ]: 0 : if (tmp.imissed < (stats_ctrl->imissed & (uint64_t)UINT32_MAX))
173 : 0 : wrap_n++;
174 : 0 : tmp.imissed |= (wrap_n) << 32;
175 : 0 : stats_ctrl->imissed = tmp.imissed;
176 : : } else {
177 : 0 : tmp.imissed = stats_ctrl->imissed;
178 : : }
179 : : #ifndef MLX5_PMD_SOFT_COUNTERS
180 : : /* FIXME: retrieve and add hardware counters. */
181 : : #endif
182 : 0 : *stats = tmp;
183 : 0 : return 0;
184 : : }
185 : :
186 : : /**
187 : : * DPDK callback to clear device statistics.
188 : : *
189 : : * @param dev
190 : : * Pointer to Ethernet device structure.
191 : : *
192 : : * @return
193 : : * always 0 on success and stats is reset
194 : : */
195 : : int
196 : 0 : mlx5_stats_reset(struct rte_eth_dev *dev)
197 : : {
198 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
199 : : struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
200 : : unsigned int i;
201 : :
202 [ # # ]: 0 : for (i = 0; (i != priv->rxqs_n); ++i) {
203 : 0 : struct mlx5_rxq_data *rxq_data = mlx5_rxq_data_get(dev, i);
204 : :
205 [ # # ]: 0 : if (rxq_data == NULL)
206 : 0 : continue;
207 : 0 : rxq_data->stats_reset = rxq_data->stats;
208 : : }
209 [ # # ]: 0 : for (i = 0; (i != priv->txqs_n); ++i) {
210 : 0 : struct mlx5_txq_data *txq_data = (*priv->txqs)[i];
211 : :
212 [ # # ]: 0 : if (txq_data == NULL)
213 : 0 : continue;
214 : 0 : txq_data->stats_reset = txq_data->stats;
215 : : }
216 : 0 : mlx5_os_read_dev_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
217 : 0 : stats_ctrl->imissed = 0;
218 : : #ifndef MLX5_PMD_SOFT_COUNTERS
219 : : /* FIXME: reset hardware counters. */
220 : : #endif
221 : :
222 : 0 : return 0;
223 : : }
224 : :
225 : : /**
226 : : * DPDK callback to clear device extended statistics.
227 : : *
228 : : * @param dev
229 : : * Pointer to Ethernet device structure.
230 : : *
231 : : * @return
232 : : * 0 on success and stats is reset, negative errno value otherwise and
233 : : * rte_errno is set.
234 : : */
235 : : int
236 : 0 : mlx5_xstats_reset(struct rte_eth_dev *dev)
237 : : {
238 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
239 : : struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
240 : : unsigned int i;
241 : : uint64_t *counters;
242 : : int ret;
243 : 0 : uint16_t stats_n = 0;
244 : 0 : uint16_t stats_n_2nd = 0;
245 [ # # # # ]: 0 : bool bond_master = (priv->master && priv->pf_bond >= 0);
246 : :
247 : 0 : ret = mlx5_os_get_stats_n(dev, bond_master, &stats_n, &stats_n_2nd);
248 [ # # ]: 0 : if (ret < 0) {
249 : 0 : DRV_LOG(ERR, "port %u cannot get stats: %s", dev->data->port_id,
250 : : strerror(-ret));
251 : 0 : return ret;
252 : : }
253 [ # # # # ]: 0 : if (xstats_ctrl->stats_n != stats_n ||
254 [ # # ]: 0 : (bond_master && xstats_ctrl->stats_n_2nd != stats_n_2nd))
255 : 0 : mlx5_os_stats_init(dev);
256 : : /* Considering to use stack directly. */
257 : 0 : counters = mlx5_malloc(MLX5_MEM_SYS, sizeof(*counters) * xstats_ctrl->mlx5_stats_n,
258 : : 0, SOCKET_ID_ANY);
259 [ # # ]: 0 : if (!counters) {
260 : 0 : DRV_LOG(WARNING, "port %u unable to allocate memory for xstats counters",
261 : : dev->data->port_id);
262 : 0 : rte_errno = ENOMEM;
263 : 0 : return -rte_errno;
264 : : }
265 : 0 : ret = mlx5_os_read_dev_counters(dev, bond_master, counters);
266 [ # # ]: 0 : if (ret) {
267 : 0 : DRV_LOG(ERR, "port %u cannot read device counters: %s",
268 : : dev->data->port_id, strerror(rte_errno));
269 : 0 : mlx5_free(counters);
270 : 0 : return ret;
271 : : }
272 [ # # ]: 0 : for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
273 : 0 : xstats_ctrl->base[i] = counters[i];
274 : 0 : xstats_ctrl->hw_stats[i] = 0;
275 : : }
276 : 0 : mlx5_txpp_xstats_reset(dev);
277 : 0 : mlx5_free(counters);
278 : 0 : return 0;
279 : : }
280 : :
281 : : /**
282 : : * DPDK callback to retrieve names of extended device statistics
283 : : *
284 : : * @param dev
285 : : * Pointer to Ethernet device structure.
286 : : * @param[out] xstats_names
287 : : * Buffer to insert names into.
288 : : * @param n
289 : : * Number of names.
290 : : *
291 : : * @return
292 : : * Number of xstats names.
293 : : */
294 : : int
295 : 0 : mlx5_xstats_get_names(struct rte_eth_dev *dev,
296 : : struct rte_eth_xstat_name *xstats_names, unsigned int n)
297 : : {
298 : : unsigned int i;
299 : 0 : struct mlx5_priv *priv = dev->data->dev_private;
300 : : struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
301 : 0 : unsigned int mlx5_xstats_n = xstats_ctrl->mlx5_stats_n;
302 : :
303 [ # # ]: 0 : if (n >= mlx5_xstats_n && xstats_names) {
304 [ # # ]: 0 : for (i = 0; i != mlx5_xstats_n; ++i) {
305 : 0 : strlcpy(xstats_names[i].name,
306 : : xstats_ctrl->info[i].dpdk_name,
307 : : RTE_ETH_XSTATS_NAME_SIZE);
308 : : }
309 : : }
310 : 0 : mlx5_xstats_n = mlx5_txpp_xstats_get_names(dev, xstats_names,
311 : : n, mlx5_xstats_n);
312 : 0 : return mlx5_xstats_n;
313 : : }
|