Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2017 Intel Corporation
3 : : */
4 : :
5 : : #include <ctype.h>
6 : : #include <stdlib.h>
7 : :
8 : : #include <rte_kvargs.h>
9 : : #include <rte_telemetry.h>
10 : :
11 : : #include "rte_ethdev.h"
12 : : #include "ethdev_driver.h"
13 : : #include "ethdev_private.h"
14 : : #include "sff_telemetry.h"
15 : : #include "rte_tm.h"
16 : :
17 : : static const struct {
18 : : uint32_t capa;
19 : : const char *name;
20 : : } rte_eth_fec_capa_name[] = {
21 : : { RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC), "off" },
22 : : { RTE_ETH_FEC_MODE_CAPA_MASK(AUTO), "auto" },
23 : : { RTE_ETH_FEC_MODE_CAPA_MASK(BASER), "baser" },
24 : : { RTE_ETH_FEC_MODE_CAPA_MASK(RS), "rs" },
25 : : { RTE_ETH_FEC_MODE_CAPA_MASK(LLRS), "llrs" },
26 : : };
27 : :
28 : : static int
29 : 51 : eth_dev_parse_port_params(const char *params, uint16_t *port_id,
30 : : char **end_param, bool has_next)
31 : : {
32 : : uint64_t pi;
33 : :
34 [ + + + - ]: 51 : if (params == NULL || strlen(params) == 0 ||
35 [ + + + - ]: 34 : !isdigit((unsigned char)*params) || port_id == NULL)
36 : : return -EINVAL;
37 : :
38 : 17 : pi = strtoul(params, end_param, 0);
39 [ - + - - ]: 17 : if (**end_param != '\0' && !has_next)
40 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
41 : : "Extra parameters passed to ethdev telemetry command, ignoring");
42 : :
43 [ + - - + ]: 17 : if (pi >= UINT16_MAX || !rte_eth_dev_is_valid_port(pi))
44 : 0 : return -EINVAL;
45 : :
46 : 17 : *port_id = (uint16_t)pi;
47 : :
48 : 17 : return 0;
49 : : }
50 : :
51 : : static int
52 : 3 : eth_dev_handle_port_list(const char *cmd __rte_unused,
53 : : const char *params __rte_unused,
54 : : struct rte_tel_data *d)
55 : : {
56 : : int port_id;
57 : :
58 : 3 : rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
59 [ + + ]: 6 : RTE_ETH_FOREACH_DEV(port_id)
60 : 3 : rte_tel_data_add_array_int(d, port_id);
61 : 3 : return 0;
62 : : }
63 : :
64 : : static int
65 : 0 : eth_dev_parse_hide_zero(const char *key, const char *value, void *extra_args)
66 : : {
67 : : RTE_SET_USED(key);
68 : :
69 [ # # ]: 0 : if (value == NULL)
70 : : return -1;
71 : :
72 [ # # ]: 0 : if (strcmp(value, "true") == 0)
73 : 0 : *(bool *)extra_args = true;
74 [ # # ]: 0 : else if (strcmp(value, "false") == 0)
75 : 0 : *(bool *)extra_args = false;
76 : : else
77 : : return -1;
78 : :
79 : : return 0;
80 : : }
81 : :
82 : : #define ADD_DICT_STAT(stats, s) rte_tel_data_add_dict_uint(d, #s, stats.s)
83 : :
84 : : static int
85 : 3 : eth_dev_handle_port_stats(const char *cmd __rte_unused,
86 : : const char *params,
87 : : struct rte_tel_data *d)
88 : : {
89 : : struct rte_eth_stats stats;
90 : : uint16_t port_id;
91 : : char *end_param;
92 : : int ret;
93 : :
94 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
95 [ + + ]: 3 : if (ret < 0)
96 : : return ret;
97 : :
98 : 1 : ret = rte_eth_stats_get(port_id, &stats);
99 [ + - ]: 1 : if (ret < 0)
100 : : return -1;
101 : :
102 : 1 : rte_tel_data_start_dict(d);
103 : 1 : ADD_DICT_STAT(stats, ipackets);
104 : 1 : ADD_DICT_STAT(stats, opackets);
105 : 1 : ADD_DICT_STAT(stats, ibytes);
106 : 1 : ADD_DICT_STAT(stats, obytes);
107 : 1 : ADD_DICT_STAT(stats, imissed);
108 : 1 : ADD_DICT_STAT(stats, ierrors);
109 : 1 : ADD_DICT_STAT(stats, oerrors);
110 : 1 : ADD_DICT_STAT(stats, rx_nombuf);
111 : :
112 : 1 : return 0;
113 : : }
114 : :
115 : : static int
116 : 3 : eth_dev_handle_port_xstats(const char *cmd __rte_unused,
117 : : const char *params,
118 : : struct rte_tel_data *d)
119 : : {
120 : 3 : const char *const valid_keys[] = { "hide_zero", NULL };
121 : : struct rte_eth_xstat *eth_xstats;
122 : : struct rte_eth_xstat_name *xstat_names;
123 : : struct rte_kvargs *kvlist;
124 : 3 : bool hide_zero = false;
125 : : uint16_t port_id;
126 : : char *end_param;
127 : : int num_xstats;
128 : : int i, ret;
129 : :
130 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
131 [ + + ]: 3 : if (ret < 0)
132 : : return ret;
133 : :
134 [ - + ]: 1 : if (*end_param != '\0') {
135 : 0 : kvlist = rte_kvargs_parse(end_param, valid_keys);
136 : 0 : ret = rte_kvargs_process(kvlist, NULL, eth_dev_parse_hide_zero, &hide_zero);
137 [ # # ]: 0 : if (kvlist == NULL || ret != 0)
138 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
139 : : "Unknown extra parameters passed to ethdev telemetry command, ignoring");
140 : 0 : rte_kvargs_free(kvlist);
141 : : }
142 : :
143 : 1 : num_xstats = rte_eth_xstats_get(port_id, NULL, 0);
144 [ + - ]: 1 : if (num_xstats < 0)
145 : : return -1;
146 : :
147 : : /* use one malloc for both names and stats */
148 : 1 : eth_xstats = malloc((sizeof(struct rte_eth_xstat) +
149 : : sizeof(struct rte_eth_xstat_name)) * num_xstats);
150 [ + - ]: 1 : if (eth_xstats == NULL)
151 : : return -1;
152 : 1 : xstat_names = (void *)ð_xstats[num_xstats];
153 : :
154 : 1 : ret = rte_eth_xstats_get_names(port_id, xstat_names, num_xstats);
155 [ - + ]: 1 : if (ret < 0 || ret > num_xstats) {
156 : 0 : free(eth_xstats);
157 : 0 : return -1;
158 : : }
159 : :
160 : 1 : ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats);
161 [ - + ]: 1 : if (ret < 0 || ret > num_xstats) {
162 : 0 : free(eth_xstats);
163 : 0 : return -1;
164 : : }
165 : :
166 : 1 : rte_tel_data_start_dict(d);
167 [ + + ]: 14 : for (i = 0; i < num_xstats; i++) {
168 [ - + - - ]: 13 : if (hide_zero && eth_xstats[i].value == 0)
169 : 0 : continue;
170 : 13 : rte_tel_data_add_dict_uint(d, xstat_names[i].name,
171 : 13 : eth_xstats[i].value);
172 : : }
173 : 1 : free(eth_xstats);
174 : 1 : return 0;
175 : : }
176 : :
177 : : #ifndef RTE_EXEC_ENV_WINDOWS
178 : : static int
179 : 3 : eth_dev_handle_port_dump_priv(const char *cmd __rte_unused,
180 : : const char *params,
181 : : struct rte_tel_data *d)
182 : : {
183 : : char *buf, *end_param;
184 : : uint16_t port_id;
185 : : int ret;
186 : : FILE *f;
187 : :
188 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
189 [ + + ]: 3 : if (ret < 0)
190 : : return ret;
191 : :
192 : 1 : buf = calloc(RTE_TEL_MAX_SINGLE_STRING_LEN, sizeof(char));
193 [ + - ]: 1 : if (buf == NULL)
194 : : return -ENOMEM;
195 : :
196 : 1 : f = fmemopen(buf, RTE_TEL_MAX_SINGLE_STRING_LEN - 1, "w+");
197 [ - + ]: 1 : if (f == NULL) {
198 : 0 : free(buf);
199 : 0 : return -EINVAL;
200 : : }
201 : :
202 : 1 : ret = rte_eth_dev_priv_dump(port_id, f);
203 : 1 : fclose(f);
204 [ - + ]: 1 : if (ret == 0) {
205 : 0 : rte_tel_data_start_dict(d);
206 : 0 : rte_tel_data_string(d, buf);
207 : : }
208 : :
209 : 1 : free(buf);
210 : 1 : return 0;
211 : : }
212 : : #endif /* !RTE_EXEC_ENV_WINDOWS */
213 : :
214 : : static int
215 : 3 : eth_dev_handle_port_link_status(const char *cmd __rte_unused,
216 : : const char *params,
217 : : struct rte_tel_data *d)
218 : : {
219 : : static const char *status_str = "status";
220 : : struct rte_eth_link link;
221 : : uint16_t port_id;
222 : : char *end_param;
223 : : int ret;
224 : :
225 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
226 [ + + ]: 3 : if (ret < 0)
227 : : return ret;
228 : :
229 : 1 : ret = rte_eth_link_get_nowait(port_id, &link);
230 [ + - ]: 1 : if (ret < 0)
231 : : return -1;
232 : :
233 : 1 : rte_tel_data_start_dict(d);
234 [ + - ]: 1 : if (!link.link_status) {
235 : 1 : rte_tel_data_add_dict_string(d, status_str, "DOWN");
236 : 1 : return 0;
237 : : }
238 : 0 : rte_tel_data_add_dict_string(d, status_str, "UP");
239 : 0 : rte_tel_data_add_dict_uint(d, "speed", link.link_speed);
240 : 0 : rte_tel_data_add_dict_string(d, "duplex",
241 [ # # ]: 0 : (link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
242 : : "full-duplex" : "half-duplex");
243 : 0 : return 0;
244 : : }
245 : :
246 : : static void
247 : 1 : eth_dev_parse_rx_offloads(uint64_t offload, struct rte_tel_data *d)
248 : : {
249 : : uint64_t i;
250 : :
251 : 1 : rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
252 [ + + ]: 65 : for (i = 0; i < CHAR_BIT * sizeof(offload); i++) {
253 [ - + ]: 64 : if ((offload & RTE_BIT64(i)) != 0)
254 : 0 : rte_tel_data_add_array_string(d,
255 : 0 : rte_eth_dev_rx_offload_name(offload & RTE_BIT64(i)));
256 : : }
257 : 1 : }
258 : :
259 : : static void
260 : 1 : eth_dev_parse_tx_offloads(uint64_t offload, struct rte_tel_data *d)
261 : : {
262 : : uint64_t i;
263 : :
264 : 1 : rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
265 [ + + ]: 65 : for (i = 0; i < CHAR_BIT * sizeof(offload); i++) {
266 [ - + ]: 64 : if ((offload & RTE_BIT64(i)) != 0)
267 : 0 : rte_tel_data_add_array_string(d,
268 : 0 : rte_eth_dev_tx_offload_name(offload & RTE_BIT64(i)));
269 : : }
270 : 1 : }
271 : :
272 : : static int
273 : 3 : eth_dev_handle_port_info(const char *cmd __rte_unused,
274 : : const char *params,
275 : : struct rte_tel_data *d)
276 : : {
277 : : struct rte_tel_data *rx_offload, *tx_offload;
278 : : struct rte_tel_data *rxq_state, *txq_state;
279 : : char fw_version[RTE_TEL_MAX_STRING_LEN];
280 : : char mac_addr[RTE_ETHER_ADDR_FMT_SIZE];
281 : : struct rte_eth_dev *eth_dev;
282 : : uint16_t port_id;
283 : : char *end_param;
284 : : int ret;
285 : : int i;
286 : :
287 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
288 [ + + ]: 3 : if (ret < 0)
289 : : return ret;
290 : :
291 : 1 : eth_dev = &rte_eth_devices[port_id];
292 : :
293 : 1 : rxq_state = rte_tel_data_alloc();
294 [ + - ]: 1 : if (rxq_state == NULL)
295 : : return -ENOMEM;
296 : :
297 : 1 : txq_state = rte_tel_data_alloc();
298 [ - + ]: 1 : if (txq_state == NULL)
299 : 0 : goto free_rxq_state;
300 : :
301 : 1 : rx_offload = rte_tel_data_alloc();
302 [ - + ]: 1 : if (rx_offload == NULL)
303 : 0 : goto free_txq_state;
304 : :
305 : 1 : tx_offload = rte_tel_data_alloc();
306 [ - + ]: 1 : if (tx_offload == NULL)
307 : 0 : goto free_rx_offload;
308 : :
309 : 1 : rte_tel_data_start_dict(d);
310 : 1 : rte_tel_data_add_dict_string(d, "name", eth_dev->data->name);
311 : :
312 [ - + ]: 1 : if (rte_eth_dev_fw_version_get(port_id, fw_version,
313 : : RTE_TEL_MAX_STRING_LEN) == 0)
314 : 0 : rte_tel_data_add_dict_string(d, "fw_version", fw_version);
315 : :
316 : 1 : rte_tel_data_add_dict_int(d, "state", eth_dev->state);
317 : 1 : rte_tel_data_add_dict_int(d, "nb_rx_queues",
318 : 1 : eth_dev->data->nb_rx_queues);
319 : 1 : rte_tel_data_add_dict_int(d, "nb_tx_queues",
320 : 1 : eth_dev->data->nb_tx_queues);
321 : 1 : rte_tel_data_add_dict_int(d, "port_id", eth_dev->data->port_id);
322 : 1 : rte_tel_data_add_dict_int(d, "mtu", eth_dev->data->mtu);
323 : 1 : rte_tel_data_add_dict_uint(d, "rx_mbuf_size_min",
324 : 1 : eth_dev->data->min_rx_buf_size);
325 : 1 : rte_ether_format_addr(mac_addr, sizeof(mac_addr),
326 : 1 : eth_dev->data->mac_addrs);
327 : 1 : rte_tel_data_add_dict_string(d, "mac_addr", mac_addr);
328 : 1 : rte_tel_data_add_dict_int(d, "promiscuous",
329 : 1 : eth_dev->data->promiscuous);
330 : 1 : rte_tel_data_add_dict_int(d, "scattered_rx",
331 : 1 : eth_dev->data->scattered_rx);
332 : 1 : rte_tel_data_add_dict_int(d, "all_multicast",
333 : 1 : eth_dev->data->all_multicast);
334 : 1 : rte_tel_data_add_dict_int(d, "dev_started", eth_dev->data->dev_started);
335 : 1 : rte_tel_data_add_dict_int(d, "lro", eth_dev->data->lro);
336 : 1 : rte_tel_data_add_dict_int(d, "dev_configured",
337 : 1 : eth_dev->data->dev_configured);
338 : :
339 : 1 : rte_tel_data_start_array(rxq_state, RTE_TEL_INT_VAL);
340 [ + + ]: 2 : for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
341 : 1 : rte_tel_data_add_array_int(rxq_state,
342 : 1 : eth_dev->data->rx_queue_state[i]);
343 : :
344 : 1 : rte_tel_data_start_array(txq_state, RTE_TEL_INT_VAL);
345 [ + + ]: 2 : for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
346 : 1 : rte_tel_data_add_array_int(txq_state,
347 : 1 : eth_dev->data->tx_queue_state[i]);
348 : :
349 : 1 : rte_tel_data_add_dict_container(d, "rxq_state", rxq_state, 0);
350 : 1 : rte_tel_data_add_dict_container(d, "txq_state", txq_state, 0);
351 : 1 : rte_tel_data_add_dict_int(d, "numa_node", eth_dev->data->numa_node);
352 : 1 : rte_tel_data_add_dict_uint_hex(d, "dev_flags",
353 : 1 : eth_dev->data->dev_flags, 0);
354 : :
355 : 1 : eth_dev_parse_rx_offloads(eth_dev->data->dev_conf.rxmode.offloads,
356 : : rx_offload);
357 : 1 : rte_tel_data_add_dict_container(d, "rx_offloads", rx_offload, 0);
358 : 1 : eth_dev_parse_tx_offloads(eth_dev->data->dev_conf.txmode.offloads,
359 : : tx_offload);
360 : 1 : rte_tel_data_add_dict_container(d, "tx_offloads", tx_offload, 0);
361 : :
362 : 1 : rte_tel_data_add_dict_uint_hex(d, "ethdev_rss_hf",
363 : 1 : eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf, 0);
364 : :
365 : 1 : return 0;
366 : :
367 : : free_rx_offload:
368 : 0 : rte_tel_data_free(rx_offload);
369 : 0 : free_txq_state:
370 : 0 : rte_tel_data_free(txq_state);
371 : 0 : free_rxq_state:
372 : 0 : rte_tel_data_free(rxq_state);
373 : :
374 : 0 : return -ENOMEM;
375 : : }
376 : :
377 : : static int
378 : 3 : eth_dev_handle_port_macs(const char *cmd __rte_unused,
379 : : const char *params,
380 : : struct rte_tel_data *d)
381 : : {
382 : : char mac_addr[RTE_ETHER_ADDR_FMT_SIZE];
383 : : struct rte_eth_dev_info dev_info;
384 : : struct rte_eth_dev *eth_dev;
385 : : uint16_t port_id;
386 : : char *end_param;
387 : : uint32_t i;
388 : : int ret;
389 : :
390 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
391 [ + + ]: 3 : if (ret < 0)
392 : : return ret;
393 : :
394 : 1 : ret = rte_eth_dev_info_get(port_id, &dev_info);
395 [ + - ]: 1 : if (ret != 0)
396 : : return ret;
397 : :
398 : : eth_dev = &rte_eth_devices[port_id];
399 : 1 : rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
400 [ + + ]: 2 : for (i = 0; i < dev_info.max_mac_addrs; i++) {
401 [ - + ]: 1 : if (rte_is_zero_ether_addr(ð_dev->data->mac_addrs[i]))
402 : 0 : continue;
403 : :
404 : 1 : rte_ether_format_addr(mac_addr, sizeof(mac_addr),
405 : : ð_dev->data->mac_addrs[i]);
406 : 1 : rte_tel_data_add_array_string(d, mac_addr);
407 : : }
408 : :
409 : : return 0;
410 : : }
411 : :
412 : : static int
413 : 3 : eth_dev_handle_port_flow_ctrl(const char *cmd __rte_unused,
414 : : const char *params,
415 : : struct rte_tel_data *d)
416 : : {
417 : : struct rte_eth_fc_conf fc_conf;
418 : : uint16_t port_id;
419 : : char *end_param;
420 : : bool rx_fc_en;
421 : : bool tx_fc_en;
422 : : int ret;
423 : :
424 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
425 [ + + ]: 3 : if (ret < 0)
426 : : return ret;
427 : :
428 : 1 : ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
429 [ + - ]: 1 : if (ret != 0) {
430 : 1 : RTE_ETHDEV_LOG_LINE(ERR,
431 : : "Failed to get flow ctrl info, ret = %d", ret);
432 : 1 : return ret;
433 : : }
434 : :
435 : 0 : rx_fc_en = fc_conf.mode == RTE_ETH_FC_RX_PAUSE ||
436 : : fc_conf.mode == RTE_ETH_FC_FULL;
437 : 0 : tx_fc_en = fc_conf.mode == RTE_ETH_FC_TX_PAUSE ||
438 : : fc_conf.mode == RTE_ETH_FC_FULL;
439 : :
440 : 0 : rte_tel_data_start_dict(d);
441 : 0 : rte_tel_data_add_dict_uint_hex(d, "high_waterline", fc_conf.high_water, 0);
442 : 0 : rte_tel_data_add_dict_uint_hex(d, "low_waterline", fc_conf.low_water, 0);
443 : 0 : rte_tel_data_add_dict_uint_hex(d, "pause_time", fc_conf.pause_time, 0);
444 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "send_xon", fc_conf.send_xon ? "on" : "off");
445 : 0 : rte_tel_data_add_dict_string(d, "mac_ctrl_frame_fwd",
446 [ # # ]: 0 : fc_conf.mac_ctrl_frame_fwd ? "on" : "off");
447 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "rx_pause", rx_fc_en ? "on" : "off");
448 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "tx_pause", tx_fc_en ? "on" : "off");
449 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "autoneg", fc_conf.autoneg ? "on" : "off");
450 : :
451 : 0 : return 0;
452 : : }
453 : :
454 : : static int
455 : 6 : ethdev_parse_queue_params(const char *params, bool is_rx,
456 : : uint16_t *port_id, uint16_t *queue_id)
457 : : {
458 : : struct rte_eth_dev *dev;
459 : : const char *qid_param;
460 : : uint16_t nb_queues;
461 : : char *end_param;
462 : 6 : char *saveptr = NULL;
463 : : uint64_t qid;
464 : : int ret;
465 : :
466 : 6 : ret = eth_dev_parse_port_params(params, port_id, &end_param, true);
467 [ + + ]: 6 : if (ret < 0)
468 : : return ret;
469 : :
470 : 2 : dev = &rte_eth_devices[*port_id];
471 [ + + ]: 2 : nb_queues = is_rx ? dev->data->nb_rx_queues : dev->data->nb_tx_queues;
472 [ + - - + ]: 2 : if (nb_queues == 1 && *end_param == '\0')
473 : : qid = 0;
474 : : else {
475 : 0 : qid_param = strtok_r(end_param, ",", &saveptr);
476 [ # # # # : 0 : if (!qid_param || strlen(qid_param) == 0 || !isdigit((unsigned char)*qid_param))
# # ]
477 : : return -EINVAL;
478 : :
479 : 0 : qid = strtoul(qid_param, &end_param, 0);
480 : : }
481 [ - + ]: 2 : if (*end_param != '\0')
482 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
483 : : "Extra parameters passed to ethdev telemetry command, ignoring");
484 : :
485 [ + - ]: 2 : if (qid >= UINT16_MAX)
486 : : return -EINVAL;
487 : :
488 : 2 : *queue_id = qid;
489 : 2 : return 0;
490 : : }
491 : :
492 : : static int
493 : 0 : eth_dev_add_burst_mode(uint16_t port_id, uint16_t queue_id,
494 : : bool is_rx, struct rte_tel_data *d)
495 : : {
496 : : struct rte_eth_burst_mode mode;
497 : : int ret;
498 : :
499 [ # # ]: 0 : if (is_rx)
500 : 0 : ret = rte_eth_rx_burst_mode_get(port_id, queue_id, &mode);
501 : : else
502 : 0 : ret = rte_eth_tx_burst_mode_get(port_id, queue_id, &mode);
503 : :
504 [ # # ]: 0 : if (ret == -ENOTSUP)
505 : : return 0;
506 : :
507 [ # # ]: 0 : if (ret != 0) {
508 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
509 : : "Failed to get burst mode for port %u", port_id);
510 : 0 : return ret;
511 : : }
512 : :
513 : 0 : rte_tel_data_add_dict_uint(d, "burst_flags", mode.flags);
514 : 0 : rte_tel_data_add_dict_string(d, "burst_mode", mode.info);
515 : 0 : return 0;
516 : : }
517 : :
518 : : static int
519 : 3 : eth_dev_handle_port_rxq(const char *cmd __rte_unused,
520 : : const char *params,
521 : : struct rte_tel_data *d)
522 : : {
523 : : struct rte_eth_thresh *rx_thresh;
524 : : struct rte_eth_rxconf *rxconf;
525 : : struct rte_eth_rxq_info qinfo;
526 : : struct rte_tel_data *offload;
527 : : uint16_t port_id, queue_id;
528 : : int ret;
529 : :
530 : 3 : ret = ethdev_parse_queue_params(params, true, &port_id, &queue_id);
531 [ + + ]: 3 : if (ret != 0)
532 : : return ret;
533 : :
534 : 1 : ret = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
535 [ - + ]: 1 : if (ret != 0)
536 : : return ret;
537 : :
538 : 0 : rte_tel_data_start_dict(d);
539 : 0 : rte_tel_data_add_dict_string(d, "mempool_name", qinfo.mp->name);
540 : 0 : rte_tel_data_add_dict_uint(d, "socket_id", qinfo.mp->socket_id);
541 : :
542 : : rx_thresh = &qinfo.conf.rx_thresh;
543 : 0 : rte_tel_data_add_dict_uint(d, "host_threshold", rx_thresh->hthresh);
544 : 0 : rte_tel_data_add_dict_uint(d, "prefetch_threshold", rx_thresh->pthresh);
545 : 0 : rte_tel_data_add_dict_uint(d, "writeback_threshold", rx_thresh->wthresh);
546 : :
547 : : rxconf = &qinfo.conf;
548 : 0 : rte_tel_data_add_dict_uint(d, "free_threshold", rxconf->rx_free_thresh);
549 : 0 : rte_tel_data_add_dict_string(d, "rx_drop_en",
550 [ # # ]: 0 : rxconf->rx_drop_en == 0 ? "off" : "on");
551 : 0 : rte_tel_data_add_dict_string(d, "deferred_start",
552 [ # # ]: 0 : rxconf->rx_deferred_start == 0 ? "off" : "on");
553 : 0 : rte_tel_data_add_dict_uint(d, "rx_nseg", rxconf->rx_nseg);
554 : 0 : rte_tel_data_add_dict_uint(d, "share_group", rxconf->share_group);
555 : 0 : rte_tel_data_add_dict_uint(d, "share_qid", rxconf->share_qid);
556 : :
557 : 0 : offload = rte_tel_data_alloc();
558 [ # # ]: 0 : if (offload == NULL)
559 : : return -ENOMEM;
560 : :
561 : 0 : eth_dev_parse_rx_offloads(rxconf->offloads, offload);
562 : 0 : rte_tel_data_add_dict_container(d, "offloads", offload, 0);
563 : :
564 : 0 : rte_tel_data_add_dict_uint(d, "rx_nmempool", rxconf->rx_nmempool);
565 : :
566 : 0 : rte_tel_data_add_dict_string(d, "scattered_rx",
567 [ # # ]: 0 : qinfo.scattered_rx == 0 ? "off" : "on");
568 : 0 : rte_tel_data_add_dict_uint(d, "queue_state", qinfo.queue_state);
569 : 0 : rte_tel_data_add_dict_uint(d, "nb_desc", qinfo.nb_desc);
570 : 0 : rte_tel_data_add_dict_uint(d, "rx_buf_size", qinfo.rx_buf_size);
571 : 0 : rte_tel_data_add_dict_uint(d, "avail_thresh", qinfo.avail_thresh);
572 : :
573 : 0 : ret = eth_dev_add_burst_mode(port_id, queue_id, true, d);
574 [ # # ]: 0 : if (ret != 0)
575 : 0 : rte_tel_data_free(offload);
576 : :
577 : : return ret;
578 : : }
579 : :
580 : : static int
581 : 3 : eth_dev_handle_port_txq(const char *cmd __rte_unused,
582 : : const char *params,
583 : : struct rte_tel_data *d)
584 : : {
585 : : struct rte_eth_thresh *tx_thresh;
586 : : struct rte_eth_txconf *txconf;
587 : : struct rte_eth_txq_info qinfo;
588 : : struct rte_tel_data *offload;
589 : : uint16_t port_id, queue_id;
590 : : int ret;
591 : :
592 : 3 : ret = ethdev_parse_queue_params(params, false, &port_id, &queue_id);
593 [ + + ]: 3 : if (ret != 0)
594 : : return ret;
595 : :
596 : 1 : ret = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
597 [ - + ]: 1 : if (ret != 0)
598 : : return ret;
599 : :
600 : 0 : rte_tel_data_start_dict(d);
601 : : tx_thresh = &qinfo.conf.tx_thresh;
602 : : txconf = &qinfo.conf;
603 : 0 : rte_tel_data_add_dict_uint(d, "host_threshold", tx_thresh->hthresh);
604 : 0 : rte_tel_data_add_dict_uint(d, "prefetch_threshold", tx_thresh->pthresh);
605 : 0 : rte_tel_data_add_dict_uint(d, "writeback_threshold", tx_thresh->wthresh);
606 : 0 : rte_tel_data_add_dict_uint(d, "rs_threshold", txconf->tx_rs_thresh);
607 : 0 : rte_tel_data_add_dict_uint(d, "free_threshold", txconf->tx_free_thresh);
608 : 0 : rte_tel_data_add_dict_string(d, "deferred_start",
609 [ # # ]: 0 : txconf->tx_deferred_start == 0 ? "off" : "on");
610 : :
611 : 0 : offload = rte_tel_data_alloc();
612 [ # # ]: 0 : if (offload == NULL)
613 : : return -ENOMEM;
614 : :
615 : 0 : eth_dev_parse_tx_offloads(txconf->offloads, offload);
616 : 0 : rte_tel_data_add_dict_container(d, "offloads", offload, 0);
617 : :
618 : 0 : rte_tel_data_add_dict_uint(d, "queue_state", qinfo.queue_state);
619 : 0 : rte_tel_data_add_dict_uint(d, "nb_desc", qinfo.nb_desc);
620 : :
621 : 0 : ret = eth_dev_add_burst_mode(port_id, queue_id, false, d);
622 [ # # ]: 0 : if (ret != 0)
623 : 0 : rte_tel_data_free(offload);
624 : :
625 : : return 0;
626 : : }
627 : :
628 : : static int
629 : 0 : eth_dev_add_dcb_tc(struct rte_eth_dcb_info *dcb_info, struct rte_tel_data *d)
630 : : {
631 : 0 : struct rte_tel_data *tcds[RTE_ETH_DCB_NUM_TCS] = {NULL};
632 : : struct rte_eth_dcb_tc_queue_mapping *tcq;
633 : : char bw_percent[RTE_TEL_MAX_STRING_LEN];
634 : : char name[RTE_TEL_MAX_STRING_LEN];
635 : : struct rte_tel_data *tcd;
636 : : uint32_t i;
637 : :
638 [ # # ]: 0 : for (i = 0; i < dcb_info->nb_tcs; i++) {
639 : 0 : tcd = rte_tel_data_alloc();
640 [ # # ]: 0 : if (tcd == NULL) {
641 [ # # ]: 0 : while (i-- > 0)
642 : 0 : rte_tel_data_free(tcds[i]);
643 : : return -ENOMEM;
644 : : }
645 : :
646 : 0 : tcds[i] = tcd;
647 : 0 : rte_tel_data_start_dict(tcd);
648 : :
649 : 0 : rte_tel_data_add_dict_uint(tcd, "priority", dcb_info->prio_tc[i]);
650 : 0 : snprintf(bw_percent, RTE_TEL_MAX_STRING_LEN,
651 : 0 : "%u%%", dcb_info->tc_bws[i]);
652 : 0 : rte_tel_data_add_dict_string(tcd, "bw_percent", bw_percent);
653 : :
654 : : tcq = &dcb_info->tc_queue;
655 : 0 : rte_tel_data_add_dict_uint(tcd, "rxq_base", tcq->tc_rxq[0][i].base);
656 : 0 : rte_tel_data_add_dict_uint(tcd, "txq_base", tcq->tc_txq[0][i].base);
657 : 0 : rte_tel_data_add_dict_uint(tcd, "nb_rxq", tcq->tc_rxq[0][i].nb_queue);
658 : 0 : rte_tel_data_add_dict_uint(tcd, "nb_txq", tcq->tc_txq[0][i].nb_queue);
659 : :
660 : : snprintf(name, RTE_TEL_MAX_STRING_LEN, "tc%u", i);
661 : 0 : rte_tel_data_add_dict_container(d, name, tcd, 0);
662 : : }
663 : :
664 : : return 0;
665 : : }
666 : :
667 : : static int
668 : 1 : eth_dev_add_dcb_info(uint16_t port_id, struct rte_tel_data *d)
669 : : {
670 : : struct rte_eth_dcb_info dcb_info;
671 : : int ret;
672 : :
673 : 1 : ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
674 [ + - ]: 1 : if (ret != 0) {
675 : 1 : RTE_ETHDEV_LOG_LINE(ERR,
676 : : "Failed to get dcb info, ret = %d", ret);
677 : 1 : return ret;
678 : : }
679 : :
680 : 0 : rte_tel_data_start_dict(d);
681 : 0 : rte_tel_data_add_dict_uint(d, "tc_num", dcb_info.nb_tcs);
682 : :
683 [ # # ]: 0 : if (dcb_info.nb_tcs > 0)
684 : 0 : return eth_dev_add_dcb_tc(&dcb_info, d);
685 : :
686 : : return 0;
687 : : }
688 : :
689 : : static int
690 : 3 : eth_dev_handle_port_dcb(const char *cmd __rte_unused,
691 : : const char *params,
692 : : struct rte_tel_data *d)
693 : : {
694 : : uint16_t port_id;
695 : : char *end_param;
696 : : int ret;
697 : :
698 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
699 [ + + ]: 3 : if (ret < 0)
700 : : return ret;
701 : :
702 : 1 : return eth_dev_add_dcb_info(port_id, d);
703 : : }
704 : :
705 : : static int
706 : 1 : eth_dev_add_rss_info(struct rte_eth_rss_conf *rss_conf, struct rte_tel_data *d)
707 : : {
708 : 1 : const uint32_t key_len = rss_conf->rss_key_len * 2 + 1;
709 : : char *rss_key;
710 : : char key[3]; /* FF\0 */
711 : : uint32_t i;
712 : : int ret;
713 : :
714 : 1 : rss_key = malloc(key_len);
715 [ + - ]: 1 : if (rss_key == NULL)
716 : : return -ENOMEM;
717 : :
718 : 1 : rte_tel_data_start_dict(d);
719 : 1 : rte_tel_data_add_dict_uint_hex(d, "rss_hf", rss_conf->rss_hf, 0);
720 : 1 : rte_tel_data_add_dict_uint(d, "rss_key_len", rss_conf->rss_key_len);
721 : :
722 : : memset(rss_key, 0, key_len);
723 [ + + ]: 41 : for (i = 0; i < rss_conf->rss_key_len; i++) {
724 [ - + ]: 40 : ret = snprintf(key, 3, "%02x", rss_conf->rss_key[i]);
725 [ - + ]: 40 : if (ret < 0)
726 : 0 : goto free_rss_key;
727 : 40 : strlcat(rss_key, key, key_len);
728 : : }
729 : 1 : ret = rte_tel_data_add_dict_string(d, "rss_key", rss_key);
730 [ - + ]: 1 : if (ret < 0)
731 : 0 : goto free_rss_key;
732 : 1 : ret = rte_tel_data_add_dict_string(d, "algorithm",
733 : : rte_eth_dev_rss_algo_name(rss_conf->algorithm));
734 : :
735 : 1 : free_rss_key:
736 : 1 : free(rss_key);
737 : :
738 : 1 : return ret;
739 : : }
740 : :
741 : : static int
742 : 3 : eth_dev_handle_port_rss_info(const char *cmd __rte_unused,
743 : : const char *params,
744 : : struct rte_tel_data *d)
745 : : {
746 : : struct rte_eth_dev_info dev_info;
747 : : struct rte_eth_rss_conf rss_conf;
748 : : uint8_t key_len;
749 : : uint16_t port_id;
750 : : char *end_param;
751 : : int ret;
752 : :
753 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
754 [ + + ]: 3 : if (ret < 0)
755 : : return ret;
756 : :
757 : 1 : ret = rte_eth_dev_info_get(port_id, &dev_info);
758 [ - + ]: 1 : if (ret != 0) {
759 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
760 : : "Failed to get device info, ret = %d", ret);
761 : 0 : return ret;
762 : : }
763 : :
764 [ + - ]: 1 : key_len = dev_info.hash_key_size ? dev_info.hash_key_size : 40;
765 : 1 : rss_conf.rss_key_len = key_len;
766 : 1 : rss_conf.rss_key = malloc(key_len);
767 [ + - ]: 1 : if (rss_conf.rss_key == NULL)
768 : : return -ENOMEM;
769 : :
770 : 1 : ret = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
771 [ - + ]: 1 : if (ret != 0) {
772 : 0 : free(rss_conf.rss_key);
773 : 0 : return ret;
774 : : }
775 : :
776 : 1 : ret = eth_dev_add_rss_info(&rss_conf, d);
777 : 1 : free(rss_conf.rss_key);
778 : 1 : return ret;
779 : : }
780 : :
781 : : static const char *
782 : : eth_dev_fec_capa_to_string(uint32_t fec_capa)
783 : : {
784 : : uint32_t i;
785 : :
786 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
787 [ # # ]: 0 : if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0)
788 : 0 : return rte_eth_fec_capa_name[i].name;
789 : : }
790 : :
791 : : return "unknown";
792 : : }
793 : :
794 : : static void
795 : 0 : eth_dev_fec_capas_to_string(uint32_t fec_capa, char *fec_name, uint32_t len)
796 : : {
797 : : bool valid = false;
798 : : size_t count = 0;
799 : : uint32_t i;
800 : :
801 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
802 [ # # ]: 0 : if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0) {
803 : 0 : strlcat(fec_name, rte_eth_fec_capa_name[i].name, len);
804 : 0 : count = strlcat(fec_name, " ", len);
805 : : valid = true;
806 : : }
807 : : }
808 : :
809 [ # # ]: 0 : if (!valid)
810 : 0 : count = snprintf(fec_name, len, "unknown ");
811 : :
812 [ # # ]: 0 : if (count >= len) {
813 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "FEC capa names may be truncated");
814 : : count = len;
815 : : }
816 : :
817 : 0 : fec_name[count - 1] = '\0';
818 : 0 : }
819 : :
820 : : static int
821 : 0 : eth_dev_get_fec_capability(uint16_t port_id, struct rte_tel_data *d)
822 : : {
823 : : struct rte_eth_fec_capa *speed_fec_capa;
824 : : char fec_name[RTE_TEL_MAX_STRING_LEN];
825 : : char speed[RTE_TEL_MAX_STRING_LEN];
826 : : uint32_t capa_num;
827 : : uint32_t i, j;
828 : : int ret;
829 : :
830 : 0 : ret = rte_eth_fec_get_capability(port_id, NULL, 0);
831 [ # # ]: 0 : if (ret <= 0)
832 [ # # ]: 0 : return ret == 0 ? -EINVAL : ret;
833 : :
834 : 0 : capa_num = ret;
835 : 0 : speed_fec_capa = calloc(capa_num, sizeof(struct rte_eth_fec_capa));
836 [ # # ]: 0 : if (speed_fec_capa == NULL)
837 : : return -ENOMEM;
838 : :
839 : 0 : ret = rte_eth_fec_get_capability(port_id, speed_fec_capa, capa_num);
840 [ # # ]: 0 : if (ret <= 0) {
841 [ # # ]: 0 : ret = ret == 0 ? -EINVAL : ret;
842 : 0 : goto out;
843 : : }
844 : :
845 [ # # ]: 0 : for (i = 0; i < capa_num; i++) {
846 : : memset(fec_name, 0, RTE_TEL_MAX_STRING_LEN);
847 : 0 : eth_dev_fec_capas_to_string(speed_fec_capa[i].capa, fec_name,
848 : : RTE_TEL_MAX_STRING_LEN);
849 : :
850 : : memset(speed, 0, RTE_TEL_MAX_STRING_LEN);
851 : 0 : ret = snprintf(speed, RTE_TEL_MAX_STRING_LEN, "%s",
852 : : rte_eth_link_speed_to_str(speed_fec_capa[i].speed));
853 [ # # ]: 0 : if (ret < 0)
854 : 0 : goto out;
855 : :
856 [ # # ]: 0 : for (j = 0; j < strlen(speed); j++) {
857 [ # # ]: 0 : if (speed[j] == ' ')
858 : 0 : speed[j] = '_';
859 : : }
860 : :
861 : 0 : rte_tel_data_add_dict_string(d, speed, fec_name);
862 : : }
863 : :
864 : 0 : out:
865 : 0 : free(speed_fec_capa);
866 : 0 : return ret > 0 ? 0 : ret;
867 : : }
868 : :
869 : : static int
870 : 3 : eth_dev_handle_port_fec(const char *cmd __rte_unused,
871 : : const char *params,
872 : : struct rte_tel_data *d)
873 : : {
874 : : struct rte_tel_data *fec_capas;
875 : : uint32_t fec_mode;
876 : : uint16_t port_id;
877 : : char *end_param;
878 : : int ret;
879 : :
880 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
881 [ + + ]: 3 : if (ret < 0)
882 : : return ret;
883 : :
884 : 1 : ret = rte_eth_fec_get(port_id, &fec_mode);
885 [ - + ]: 1 : if (ret != 0)
886 : : return ret;
887 : :
888 : 0 : rte_tel_data_start_dict(d);
889 : 0 : rte_tel_data_add_dict_string(d, "fec_mode",
890 : : eth_dev_fec_capa_to_string(fec_mode));
891 : :
892 : 0 : fec_capas = rte_tel_data_alloc();
893 [ # # ]: 0 : if (fec_capas == NULL)
894 : : return -ENOMEM;
895 : :
896 : 0 : rte_tel_data_start_dict(fec_capas);
897 : 0 : ret = eth_dev_get_fec_capability(port_id, fec_capas);
898 [ # # ]: 0 : if (ret != 0) {
899 : 0 : rte_tel_data_free(fec_capas);
900 : 0 : return ret;
901 : : }
902 : :
903 : 0 : rte_tel_data_add_dict_container(d, "fec_capability", fec_capas, 0);
904 : 0 : return 0;
905 : : }
906 : :
907 : : static int
908 : 1 : eth_dev_add_vlan_id(int port_id, struct rte_tel_data *d)
909 : : {
910 : 1 : struct rte_tel_data *vlan_blks[64] = {NULL};
911 : : uint16_t vlan_num, vidx, vbit, num_blks;
912 : : char blk_name[RTE_TEL_MAX_STRING_LEN];
913 : : struct rte_vlan_filter_conf *vfc;
914 : : struct rte_tel_data *vlan_blk;
915 : : struct rte_tel_data *vd;
916 : : uint64_t bit_width;
917 : : uint64_t vlan_id;
918 : :
919 : 1 : vd = rte_tel_data_alloc();
920 [ + - ]: 1 : if (vd == NULL)
921 : : return -ENOMEM;
922 : :
923 : 1 : vfc = &rte_eth_devices[port_id].data->vlan_filter_conf;
924 : : bit_width = CHAR_BIT * sizeof(uint64_t);
925 : : vlan_num = 0;
926 : : num_blks = 0;
927 : :
928 : 1 : rte_tel_data_start_dict(vd);
929 [ + + ]: 65 : for (vidx = 0; vidx < RTE_DIM(vfc->ids); vidx++) {
930 [ + - ]: 64 : if (vfc->ids[vidx] == 0)
931 : 64 : continue;
932 : :
933 : 0 : vlan_blk = rte_tel_data_alloc();
934 [ # # ]: 0 : if (vlan_blk == NULL)
935 : 0 : goto free_all;
936 : :
937 : 0 : vlan_blks[num_blks] = vlan_blk;
938 : 0 : num_blks++;
939 : 0 : snprintf(blk_name, RTE_TEL_MAX_STRING_LEN, "vlan_%"PRIu64"_to_%"PRIu64"",
940 : 0 : bit_width * vidx, bit_width * (vidx + 1) - 1);
941 : 0 : rte_tel_data_start_array(vlan_blk, RTE_TEL_UINT_VAL);
942 : 0 : rte_tel_data_add_dict_container(vd, blk_name, vlan_blk, 0);
943 : :
944 [ # # ]: 0 : for (vbit = 0; vbit < bit_width; vbit++) {
945 [ # # ]: 0 : if ((vfc->ids[vidx] & RTE_BIT64(vbit)) == 0)
946 : 0 : continue;
947 : :
948 : 0 : vlan_id = bit_width * vidx + vbit;
949 : 0 : rte_tel_data_add_array_uint(vlan_blk, vlan_id);
950 : 0 : vlan_num++;
951 : : }
952 : : }
953 : :
954 : 1 : rte_tel_data_add_dict_uint(d, "vlan_num", vlan_num);
955 : 1 : rte_tel_data_add_dict_container(d, "vlan_ids", vd, 0);
956 : :
957 : 1 : return 0;
958 : :
959 : : free_all:
960 [ # # ]: 0 : while (num_blks-- > 0)
961 : 0 : rte_tel_data_free(vlan_blks[num_blks]);
962 : :
963 : 0 : rte_tel_data_free(vd);
964 : 0 : return -ENOMEM;
965 : : }
966 : :
967 : : static int
968 : 3 : eth_dev_handle_port_vlan(const char *cmd __rte_unused,
969 : : const char *params,
970 : : struct rte_tel_data *d)
971 : : {
972 : : struct rte_eth_txmode *txmode;
973 : : struct rte_eth_conf dev_conf;
974 : : uint16_t port_id;
975 : : int offload, ret;
976 : : char *end_param;
977 : :
978 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
979 [ + + ]: 3 : if (ret < 0)
980 : : return ret;
981 : :
982 : 1 : ret = rte_eth_dev_conf_get(port_id, &dev_conf);
983 [ - + ]: 1 : if (ret != 0) {
984 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
985 : : "Failed to get device configuration, ret = %d", ret);
986 : 0 : return ret;
987 : : }
988 : :
989 : : txmode = &dev_conf.txmode;
990 : 1 : rte_tel_data_start_dict(d);
991 : 1 : rte_tel_data_add_dict_uint(d, "pvid", txmode->pvid);
992 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_reject_tagged",
993 : 1 : txmode->hw_vlan_reject_tagged);
994 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_reject_untagged",
995 : 1 : txmode->hw_vlan_reject_untagged);
996 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_insert_pvid",
997 : 1 : txmode->hw_vlan_insert_pvid);
998 : :
999 : 1 : offload = rte_eth_dev_get_vlan_offload(port_id);
1000 : 1 : rte_tel_data_add_dict_string(d, "VLAN_STRIP",
1001 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_STRIP_OFFLOAD) != 0) ? "on" : "off");
1002 : 1 : rte_tel_data_add_dict_string(d, "VLAN_EXTEND",
1003 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_EXTEND_OFFLOAD) != 0) ? "on" : "off");
1004 : 1 : rte_tel_data_add_dict_string(d, "QINQ_STRIP",
1005 [ + - ]: 1 : ((offload & RTE_ETH_QINQ_STRIP_OFFLOAD) != 0) ? "on" : "off");
1006 : 1 : rte_tel_data_add_dict_string(d, "VLAN_FILTER",
1007 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_FILTER_OFFLOAD) != 0) ? "on" : "off");
1008 : :
1009 : 1 : return eth_dev_add_vlan_id(port_id, d);
1010 : : }
1011 : :
1012 : : static void
1013 : 0 : eth_dev_add_tm_caps(struct rte_tel_data *d, struct rte_tm_capabilities *cap)
1014 : : {
1015 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1016 : 0 : rte_tel_data_add_dict_uint(d, "n_levels_max", cap->n_levels_max);
1017 : 0 : rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1018 : 0 : cap->non_leaf_nodes_identical);
1019 : 0 : rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1020 : 0 : cap->leaf_nodes_identical);
1021 : 0 : rte_tel_data_add_dict_uint(d, "shaper_n_max", cap->shaper_n_max);
1022 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_n_max",
1023 : 0 : cap->shaper_private_n_max);
1024 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_dual_rate_n_max",
1025 : 0 : cap->shaper_private_dual_rate_n_max);
1026 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_rate_min",
1027 : : cap->shaper_private_rate_min);
1028 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_rate_max",
1029 : : cap->shaper_private_rate_max);
1030 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_packet_mode_supported",
1031 : 0 : cap->shaper_private_packet_mode_supported);
1032 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_byte_mode_supported",
1033 : 0 : cap->shaper_private_byte_mode_supported);
1034 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_max",
1035 : 0 : cap->shaper_shared_n_max);
1036 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_nodes_per_shaper_max",
1037 : 0 : cap->shaper_shared_n_nodes_per_shaper_max);
1038 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_shapers_per_node_max",
1039 : 0 : cap->shaper_shared_n_shapers_per_node_max);
1040 : 0 : rte_tel_data_add_dict_uint(d, "shaper_share_dual_rate_n_max",
1041 : 0 : cap->shaper_shared_dual_rate_n_max);
1042 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_rate_min",
1043 : : cap->shaper_shared_rate_min);
1044 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_rate_max",
1045 : : cap->shaper_shared_rate_max);
1046 : 0 : rte_tel_data_add_dict_int(d, "shaper_shared_packet_mode_supported",
1047 : 0 : cap->shaper_shared_packet_mode_supported);
1048 : 0 : rte_tel_data_add_dict_int(d, "shaper_shared_byte_mode_supported",
1049 : 0 : cap->shaper_shared_byte_mode_supported);
1050 : 0 : rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_min",
1051 : 0 : cap->shaper_pkt_length_adjust_min);
1052 : 0 : rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_max",
1053 : 0 : cap->shaper_pkt_length_adjust_max);
1054 : 0 : rte_tel_data_add_dict_uint(d, "sched_n_children_max",
1055 : 0 : cap->sched_n_children_max);
1056 : 0 : rte_tel_data_add_dict_uint(d, "sched_sp_n_priorities_max",
1057 : 0 : cap->sched_sp_n_priorities_max);
1058 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1059 : 0 : cap->sched_wfq_n_children_per_group_max);
1060 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1061 : 0 : cap->sched_wfq_n_groups_max);
1062 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1063 : 0 : cap->sched_wfq_weight_max);
1064 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1065 : 0 : cap->sched_wfq_packet_mode_supported);
1066 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1067 : 0 : cap->sched_wfq_byte_mode_supported);
1068 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1069 : 0 : cap->cman_wred_packet_mode_supported);
1070 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1071 : 0 : cap->cman_wred_byte_mode_supported);
1072 : 0 : rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1073 : 0 : cap->cman_head_drop_supported);
1074 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_n_max",
1075 : 0 : cap->cman_wred_context_n_max);
1076 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_private_n_max",
1077 : 0 : cap->cman_wred_context_private_n_max);
1078 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1079 : 0 : cap->cman_wred_context_shared_n_max);
1080 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_nodes_per_context_max",
1081 : 0 : cap->cman_wred_context_shared_n_nodes_per_context_max);
1082 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_contexts_per_node_max",
1083 : 0 : cap->cman_wred_context_shared_n_contexts_per_node_max);
1084 : 0 : rte_tel_data_add_dict_uint_hex(d, "dynamic_update", cap->dynamic_update_mask, 0);
1085 : 0 : rte_tel_data_add_dict_uint_hex(d, "stats_mask", cap->stats_mask, 0);
1086 : 0 : }
1087 : :
1088 : : static int
1089 : 3 : eth_dev_handle_port_tm_caps(const char *cmd __rte_unused,
1090 : : const char *params,
1091 : : struct rte_tel_data *d)
1092 : : {
1093 : 3 : struct rte_tm_capabilities cap = {0};
1094 : 3 : struct rte_tm_error error = {0};
1095 : : uint16_t port_id;
1096 : : char *end_param;
1097 : : int ret;
1098 : :
1099 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
1100 [ + + ]: 3 : if (ret != 0)
1101 : : return ret;
1102 : :
1103 : 1 : ret = rte_tm_capabilities_get(port_id, &cap, &error);
1104 [ + - ]: 1 : if (ret != 0) {
1105 [ + - ]: 2 : RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1106 : : error.message ? error.message : "no stated reason",
1107 : : error.type);
1108 : 1 : return ret;
1109 : : }
1110 : :
1111 : 0 : rte_tel_data_start_dict(d);
1112 : 0 : eth_dev_add_tm_caps(d, &cap);
1113 : :
1114 : 0 : return 0;
1115 : : }
1116 : :
1117 : : static void
1118 : 0 : eth_dev_add_tm_level_basic_caps(struct rte_tel_data *d,
1119 : : struct rte_tm_level_capabilities *cap)
1120 : : {
1121 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1122 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_nonleaf_max",
1123 : 0 : cap->n_nodes_nonleaf_max);
1124 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_leaf_max", cap->n_nodes_leaf_max);
1125 : 0 : rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1126 : 0 : cap->non_leaf_nodes_identical);
1127 : 0 : rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1128 : 0 : cap->leaf_nodes_identical);
1129 : 0 : }
1130 : :
1131 : : static void
1132 : 0 : eth_dev_add_tm_level_nonleaf_caps(struct rte_tel_data *nonleaf,
1133 : : struct rte_tm_level_capabilities *cap)
1134 : : {
1135 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_supported",
1136 : 0 : cap->nonleaf.shaper_private_supported);
1137 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_dual_rate_supported",
1138 : 0 : cap->nonleaf.shaper_private_dual_rate_supported);
1139 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_min",
1140 : : cap->nonleaf.shaper_private_rate_min);
1141 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_max",
1142 : : cap->nonleaf.shaper_private_rate_max);
1143 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_packet_mode_supported",
1144 : 0 : cap->nonleaf.shaper_private_packet_mode_supported);
1145 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_byte_mode_supported",
1146 : 0 : cap->nonleaf.shaper_private_byte_mode_supported);
1147 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_shared_n_max",
1148 : 0 : cap->nonleaf.shaper_shared_n_max);
1149 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_shared_packet_mode_supported",
1150 : 0 : cap->nonleaf.shaper_shared_packet_mode_supported);
1151 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_shared_byte_mode_supported",
1152 : 0 : cap->nonleaf.shaper_shared_byte_mode_supported);
1153 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_n_children_max",
1154 : 0 : cap->nonleaf.sched_n_children_max);
1155 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_sp_n_priorities_max",
1156 : 0 : cap->nonleaf.sched_sp_n_priorities_max);
1157 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_children_per_group_max",
1158 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max);
1159 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_groups_max",
1160 : 0 : cap->nonleaf.sched_wfq_n_groups_max);
1161 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_weight_max",
1162 : 0 : cap->nonleaf.sched_wfq_weight_max);
1163 : 0 : rte_tel_data_add_dict_int(nonleaf, "sched_wfq_packet_mode_supported",
1164 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported);
1165 : 0 : rte_tel_data_add_dict_int(nonleaf, "sched_wfq_byte_mode_supported",
1166 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported);
1167 : 0 : rte_tel_data_add_dict_uint_hex(nonleaf, "stats_mask",
1168 : : cap->nonleaf.stats_mask, 0);
1169 : 0 : }
1170 : :
1171 : : static void
1172 : 0 : eth_dev_add_tm_level_leaf_caps(struct rte_tel_data *leaf,
1173 : : struct rte_tm_level_capabilities *cap)
1174 : : {
1175 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_supported",
1176 : 0 : cap->leaf.shaper_private_supported);
1177 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_dual_rate_supported",
1178 : 0 : cap->leaf.shaper_private_dual_rate_supported);
1179 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_min",
1180 : : cap->leaf.shaper_private_rate_min);
1181 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_max",
1182 : : cap->leaf.shaper_private_rate_max);
1183 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_packet_mode_supported",
1184 : 0 : cap->leaf.shaper_private_packet_mode_supported);
1185 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_byte_mode_supported",
1186 : 0 : cap->leaf.shaper_private_byte_mode_supported);
1187 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_shared_n_max",
1188 : 0 : cap->leaf.shaper_shared_n_max);
1189 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_shared_packet_mode_supported",
1190 : 0 : cap->leaf.shaper_shared_packet_mode_supported);
1191 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_shared_byte_mode_supported",
1192 : 0 : cap->leaf.shaper_shared_byte_mode_supported);
1193 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_packet_mode_supported",
1194 : 0 : cap->leaf.cman_wred_packet_mode_supported);
1195 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_byte_mode_supported",
1196 : 0 : cap->leaf.cman_wred_byte_mode_supported);
1197 : 0 : rte_tel_data_add_dict_int(leaf, "cman_head_drop_supported",
1198 : 0 : cap->leaf.cman_head_drop_supported);
1199 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_context_private_supported",
1200 : 0 : cap->leaf.cman_wred_context_private_supported);
1201 : 0 : rte_tel_data_add_dict_uint(leaf, "cman_wred_context_shared_n_max",
1202 : 0 : cap->leaf.cman_wred_context_shared_n_max);
1203 : 0 : rte_tel_data_add_dict_uint_hex(leaf, "stats_mask",
1204 : : cap->leaf.stats_mask, 0);
1205 : 0 : }
1206 : :
1207 : : static int
1208 : 2 : eth_dev_parse_tm_params(char *params, uint32_t *result)
1209 : : {
1210 : : const char *splited_param;
1211 : 2 : char *saveptr = NULL;
1212 : : uint64_t ret;
1213 : :
1214 : 2 : splited_param = strtok_r(params, ",", &saveptr);
1215 [ - + - - : 2 : if (!splited_param || strlen(splited_param) == 0 || !isdigit((unsigned char)*splited_param))
- - ]
1216 : : return -EINVAL;
1217 : :
1218 : 0 : ret = strtoul(splited_param, ¶ms, 0);
1219 [ # # ]: 0 : if (*params != '\0')
1220 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
1221 : : "Extra parameters passed to ethdev telemetry command, ignoring");
1222 : :
1223 [ # # ]: 0 : if (ret >= UINT32_MAX)
1224 : : return -EINVAL;
1225 : :
1226 : 0 : *result = ret;
1227 : 0 : return 0;
1228 : : }
1229 : :
1230 : : static int
1231 : 3 : eth_dev_handle_port_tm_level_caps(const char *cmd __rte_unused,
1232 : : const char *params,
1233 : : struct rte_tel_data *d)
1234 : : {
1235 : 3 : struct rte_tm_level_capabilities cap = {0};
1236 : 3 : struct rte_tm_error error = {0};
1237 : : struct rte_tel_data *nonleaf;
1238 : : struct rte_tel_data *leaf;
1239 : : uint32_t level_id;
1240 : : uint16_t port_id;
1241 : : char *end_param;
1242 : : int ret;
1243 : :
1244 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1245 [ + + ]: 3 : if (ret != 0)
1246 : : return ret;
1247 : :
1248 : 1 : ret = eth_dev_parse_tm_params(end_param, &level_id);
1249 [ - + ]: 1 : if (ret != 0)
1250 : : return ret;
1251 : :
1252 : 0 : ret = rte_tm_level_capabilities_get(port_id, level_id, &cap, &error);
1253 [ # # ]: 0 : if (ret != 0) {
1254 [ # # ]: 0 : RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1255 : : error.message ? error.message : "no stated reason",
1256 : : error.type);
1257 : 0 : return ret;
1258 : : }
1259 : :
1260 : 0 : rte_tel_data_start_dict(d);
1261 : 0 : eth_dev_add_tm_level_basic_caps(d, &cap);
1262 : :
1263 : 0 : nonleaf = rte_tel_data_alloc();
1264 [ # # ]: 0 : if (nonleaf == NULL)
1265 : : return -ENOMEM;
1266 : :
1267 : 0 : rte_tel_data_start_dict(nonleaf);
1268 : 0 : eth_dev_add_tm_level_nonleaf_caps(nonleaf, &cap);
1269 : 0 : rte_tel_data_add_dict_container(d, "nonleaf_cap", nonleaf, 0);
1270 : :
1271 : 0 : leaf = rte_tel_data_alloc();
1272 [ # # ]: 0 : if (leaf == NULL) {
1273 : 0 : rte_tel_data_free(nonleaf);
1274 : 0 : return -ENOMEM;
1275 : : }
1276 : :
1277 : 0 : rte_tel_data_start_dict(leaf);
1278 : 0 : eth_dev_add_tm_level_leaf_caps(leaf, &cap);
1279 : 0 : rte_tel_data_add_dict_container(d, "leaf_cap", leaf, 0);
1280 : :
1281 : 0 : return 0;
1282 : : }
1283 : :
1284 : : static void
1285 : 0 : eth_dev_add_tm_node_basic_caps(struct rte_tel_data *node_data,
1286 : : struct rte_tm_node_capabilities *capnode)
1287 : : {
1288 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_supported",
1289 : 0 : capnode->shaper_private_supported);
1290 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_dual_rate_supported",
1291 : 0 : capnode->shaper_private_dual_rate_supported);
1292 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_min",
1293 : : capnode->shaper_private_rate_min);
1294 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_max",
1295 : : capnode->shaper_private_rate_max);
1296 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_packet_mode_supported",
1297 : 0 : capnode->shaper_private_packet_mode_supported);
1298 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_byte_mode_supported",
1299 : 0 : capnode->shaper_private_byte_mode_supported);
1300 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_shared_n_max",
1301 : 0 : capnode->shaper_shared_n_max);
1302 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_shared_packet_mode_supported",
1303 : 0 : capnode->shaper_shared_packet_mode_supported);
1304 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_shared_byte_mode_supported",
1305 : 0 : capnode->shaper_shared_byte_mode_supported);
1306 : 0 : rte_tel_data_add_dict_uint_hex(node_data, "stats_mask",
1307 : : capnode->stats_mask, 0);
1308 : 0 : }
1309 : :
1310 : : static void
1311 : 0 : eth_dev_add_tm_type_node_caps(struct rte_tel_data *d, int is_leaf,
1312 : : struct rte_tm_node_capabilities *cap)
1313 : : {
1314 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "node_type",
1315 : : is_leaf == 0 ? "nonleaf" : "leaf");
1316 [ # # ]: 0 : if (is_leaf == 0) {
1317 : 0 : rte_tel_data_add_dict_uint(d, "children_max",
1318 : 0 : cap->nonleaf.sched_n_children_max);
1319 : 0 : rte_tel_data_add_dict_uint(d, "priorities_max",
1320 : 0 : cap->nonleaf.sched_sp_n_priorities_max);
1321 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1322 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max);
1323 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1324 : 0 : cap->nonleaf.sched_wfq_n_groups_max);
1325 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1326 : 0 : cap->nonleaf.sched_wfq_weight_max);
1327 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1328 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported);
1329 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1330 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported);
1331 : : } else {
1332 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1333 : 0 : cap->leaf.cman_wred_packet_mode_supported);
1334 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1335 : 0 : cap->leaf.cman_wred_byte_mode_supported);
1336 : 0 : rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1337 : 0 : cap->leaf.cman_head_drop_supported);
1338 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_context_private_supported",
1339 : 0 : cap->leaf.cman_wred_context_private_supported);
1340 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1341 : 0 : cap->leaf.cman_wred_context_shared_n_max);
1342 : : }
1343 : 0 : }
1344 : :
1345 : : static int
1346 : 3 : eth_dev_handle_port_tm_node_caps(const char *cmd __rte_unused,
1347 : : const char *params,
1348 : : struct rte_tel_data *d)
1349 : : {
1350 : 3 : struct rte_tm_node_capabilities cap = {0};
1351 : 3 : struct rte_tm_error error = {0};
1352 : : uint32_t node_id;
1353 : : uint16_t port_id;
1354 : : char *end_param;
1355 : : int is_leaf;
1356 : : int ret;
1357 : :
1358 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1359 [ + + ]: 3 : if (ret != 0)
1360 : : return ret;
1361 : :
1362 : 1 : ret = eth_dev_parse_tm_params(end_param, &node_id);
1363 [ - + ]: 1 : if (ret != 0)
1364 : : return ret;
1365 : :
1366 : 0 : ret = rte_tm_node_capabilities_get(port_id, node_id, &cap, &error);
1367 [ # # ]: 0 : if (ret != 0)
1368 : 0 : goto out;
1369 : :
1370 : 0 : ret = rte_tm_node_type_get(port_id, node_id, &is_leaf, &error);
1371 [ # # ]: 0 : if (ret != 0)
1372 : 0 : goto out;
1373 : :
1374 : 0 : rte_tel_data_start_dict(d);
1375 : 0 : eth_dev_add_tm_node_basic_caps(d, &cap);
1376 : 0 : eth_dev_add_tm_type_node_caps(d, is_leaf, &cap);
1377 : :
1378 : 0 : return 0;
1379 : 0 : out:
1380 [ # # ]: 0 : RTE_ETHDEV_LOG_LINE(WARNING, "error: %s, error type: %u",
1381 : : error.message ? error.message : "no stated reason",
1382 : : error.type);
1383 : 0 : return ret;
1384 : : }
1385 : :
1386 : : static void
1387 : 0 : eth_dev_add_reg_data(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info,
1388 : : uint32_t idx, bool hide_zero)
1389 : : {
1390 : : uint64_t val;
1391 : :
1392 [ # # ]: 0 : if (reg_info->width == sizeof(uint32_t))
1393 : 0 : val = *((uint32_t *)reg_info->data + idx);
1394 : : else
1395 : 0 : val = *((uint64_t *)reg_info->data + idx);
1396 : :
1397 [ # # ]: 0 : if (!hide_zero || val > 0)
1398 : 0 : rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name, val, 0);
1399 : 0 : }
1400 : :
1401 : : static int
1402 : 0 : eth_dev_store_regs(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info, bool hide_zero)
1403 : : {
1404 : : struct rte_tel_data *groups[RTE_TEL_MAX_DICT_ENTRIES];
1405 : 0 : char group_name[RTE_TEL_MAX_STRING_LEN] = {0};
1406 : : struct rte_tel_data *group = NULL;
1407 : : uint32_t grp_num = 0;
1408 : : uint32_t i, max_cap;
1409 : : int ret;
1410 : :
1411 : 0 : rte_tel_data_start_dict(d);
1412 : 0 : rte_tel_data_add_dict_uint(d, "register_length", reg_info->length);
1413 : 0 : rte_tel_data_add_dict_uint(d, "register_width", reg_info->width);
1414 : 0 : rte_tel_data_add_dict_uint_hex(d, "register_offset", reg_info->offset, 0);
1415 : 0 : rte_tel_data_add_dict_uint_hex(d, "version", reg_info->version, 0);
1416 : :
1417 : : max_cap = (RTE_TEL_MAX_DICT_ENTRIES - 4) * RTE_TEL_MAX_DICT_ENTRIES;
1418 [ # # ]: 0 : if (reg_info->length > max_cap) {
1419 : 0 : RTE_ETHDEV_LOG_LINE(WARNING,
1420 : : "Registers to be displayed are reduced from %u to %u due to limited capacity",
1421 : : reg_info->length, max_cap);
1422 : 0 : reg_info->length = max_cap;
1423 : : }
1424 : :
1425 [ # # ]: 0 : for (i = 0; i < reg_info->length; i++) {
1426 [ # # ]: 0 : if (i % RTE_TEL_MAX_DICT_ENTRIES != 0) {
1427 : 0 : eth_dev_add_reg_data(group, reg_info, i, hide_zero);
1428 : 0 : continue;
1429 : : }
1430 : :
1431 : 0 : group = rte_tel_data_alloc();
1432 [ # # ]: 0 : if (group == NULL) {
1433 : : ret = -ENOMEM;
1434 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "No enough memory for group data");
1435 : 0 : goto out;
1436 : : }
1437 : 0 : groups[grp_num++] = group;
1438 : 0 : rte_tel_data_start_dict(group);
1439 : 0 : eth_dev_add_reg_data(group, reg_info, i, hide_zero);
1440 : : }
1441 : :
1442 [ # # ]: 0 : for (i = 0; i < grp_num; i++) {
1443 : : snprintf(group_name, RTE_TEL_MAX_STRING_LEN, "group_%u", i);
1444 : 0 : rte_tel_data_add_dict_container(d, group_name, groups[i], 0);
1445 : : }
1446 : : return 0;
1447 : : out:
1448 [ # # ]: 0 : for (i = 0; i < grp_num; i++)
1449 : 0 : rte_tel_data_free(groups[i]);
1450 : :
1451 : : return ret;
1452 : : }
1453 : :
1454 : : static int
1455 : 1 : eth_dev_get_port_regs(int port_id, struct rte_tel_data *d, char *filter, bool hide_zero)
1456 : : {
1457 : : struct rte_dev_reg_info reg_info;
1458 : : int ret;
1459 : :
1460 : : memset(®_info, 0, sizeof(reg_info));
1461 : 1 : reg_info.filter = filter;
1462 : :
1463 : 1 : ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
1464 [ + - ]: 1 : if (ret != 0) {
1465 : 1 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1466 : 1 : return ret;
1467 : : }
1468 : :
1469 : 0 : reg_info.data = calloc(reg_info.length, reg_info.width);
1470 [ # # ]: 0 : if (reg_info.data == NULL) {
1471 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.data");
1472 : 0 : return -ENOMEM;
1473 : : }
1474 : :
1475 : 0 : reg_info.names = calloc(reg_info.length, sizeof(struct rte_eth_reg_name));
1476 [ # # ]: 0 : if (reg_info.names == NULL) {
1477 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.names");
1478 : 0 : free(reg_info.data);
1479 : 0 : return -ENOMEM;
1480 : : }
1481 : :
1482 : 0 : ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
1483 [ # # ]: 0 : if (ret != 0) {
1484 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1485 : : ret = -EINVAL;
1486 : 0 : goto out;
1487 : : }
1488 : :
1489 : 0 : ret = eth_dev_store_regs(d, ®_info, hide_zero);
1490 : 0 : out:
1491 : 0 : free(reg_info.data);
1492 : 0 : free(reg_info.names);
1493 : :
1494 : 0 : return ret;
1495 : : }
1496 : :
1497 : : static int
1498 : 3 : eth_dev_handle_port_regs(const char *cmd __rte_unused,
1499 : : const char *params,
1500 : : struct rte_tel_data *d)
1501 : : {
1502 : 3 : const char *const valid_keys[] = { "filter", "hide_zero", NULL };
1503 : : struct rte_kvargs *kvlist = NULL;
1504 : : char *filter = NULL, *end_param;
1505 : : const char *filter_val;
1506 : 3 : bool hide_zero = false;
1507 : : uint16_t port_id;
1508 : : int ret;
1509 : :
1510 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1511 [ + + ]: 3 : if (ret != 0)
1512 : : return ret;
1513 : :
1514 [ - + ]: 1 : if (*end_param != '\0') {
1515 : 0 : kvlist = rte_kvargs_parse(end_param, valid_keys);
1516 : 0 : filter_val = rte_kvargs_get(kvlist, "filter");
1517 : 0 : ret = rte_kvargs_process(kvlist, "hide_zero", eth_dev_parse_hide_zero, &hide_zero);
1518 [ # # # # : 0 : if (kvlist == NULL || (filter_val != NULL && strlen(filter_val) == 0) || ret != 0) {
# # # # ]
1519 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
1520 : : "Unknown extra parameters passed to ethdev telemetry command, ignoring");
1521 : : } else {
1522 [ # # ]: 0 : filter = (filter_val != NULL) ? strdup(filter_val) : NULL;
1523 : 0 : hide_zero = false;
1524 : : }
1525 : 0 : rte_kvargs_free(kvlist);
1526 : : }
1527 : :
1528 : 1 : ret = eth_dev_get_port_regs(port_id, d, filter, hide_zero);
1529 : 1 : free(filter);
1530 : :
1531 : 1 : return ret;
1532 : : }
1533 : :
1534 : 54 : static int eth_dev_telemetry_do(const char *cmd, const char *params, void *arg,
1535 : : struct rte_tel_data *d)
1536 : : {
1537 : 54 : telemetry_cb fn = arg;
1538 : : int ret;
1539 : :
1540 : : /* Protect against port removal while invoking callback, calling ethdev API. */
1541 : 54 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
1542 : 54 : ret = fn(cmd, params, d);
1543 : 54 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
1544 : :
1545 : 54 : return ret;
1546 : : }
1547 : :
1548 : 301 : RTE_INIT(ethdev_init_telemetry)
1549 : : {
1550 : 301 : rte_telemetry_register_cmd_arg("/ethdev/list",
1551 : : eth_dev_telemetry_do, eth_dev_handle_port_list,
1552 : : "Returns list of available ethdev ports. Takes no parameters");
1553 : 301 : rte_telemetry_register_cmd_arg("/ethdev/stats",
1554 : : eth_dev_telemetry_do, eth_dev_handle_port_stats,
1555 : : "Returns the common stats for a port. Parameters: int port_id");
1556 : 301 : rte_telemetry_register_cmd_arg("/ethdev/xstats",
1557 : : eth_dev_telemetry_do, eth_dev_handle_port_xstats,
1558 : : "Returns the extended stats for a port. Parameters: int port_id,hide_zero=true|false(Optional for indicates hide zero xstats)");
1559 : : #ifndef RTE_EXEC_ENV_WINDOWS
1560 : 301 : rte_telemetry_register_cmd_arg("/ethdev/dump_priv",
1561 : : eth_dev_telemetry_do, eth_dev_handle_port_dump_priv,
1562 : : "Returns dump private information for a port. Parameters: int port_id");
1563 : : #endif
1564 : 301 : rte_telemetry_register_cmd_arg("/ethdev/link_status",
1565 : : eth_dev_telemetry_do, eth_dev_handle_port_link_status,
1566 : : "Returns the link status for a port. Parameters: int port_id");
1567 : 301 : rte_telemetry_register_cmd_arg("/ethdev/info",
1568 : : eth_dev_telemetry_do, eth_dev_handle_port_info,
1569 : : "Returns the device info for a port. Parameters: int port_id");
1570 : 301 : rte_telemetry_register_cmd_arg("/ethdev/module_eeprom",
1571 : : eth_dev_telemetry_do, eth_dev_handle_port_module_eeprom,
1572 : : "Returns module EEPROM info with SFF specs. Parameters: int port_id");
1573 : 301 : rte_telemetry_register_cmd_arg("/ethdev/macs",
1574 : : eth_dev_telemetry_do, eth_dev_handle_port_macs,
1575 : : "Returns the MAC addresses for a port. Parameters: int port_id");
1576 : 301 : rte_telemetry_register_cmd_arg("/ethdev/flow_ctrl",
1577 : : eth_dev_telemetry_do, eth_dev_handle_port_flow_ctrl,
1578 : : "Returns flow ctrl info for a port. Parameters: int port_id");
1579 : 301 : rte_telemetry_register_cmd_arg("/ethdev/rx_queue",
1580 : : eth_dev_telemetry_do, eth_dev_handle_port_rxq,
1581 : : "Returns Rx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
1582 : 301 : rte_telemetry_register_cmd_arg("/ethdev/tx_queue",
1583 : : eth_dev_telemetry_do, eth_dev_handle_port_txq,
1584 : : "Returns Tx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
1585 : 301 : rte_telemetry_register_cmd_arg("/ethdev/dcb",
1586 : : eth_dev_telemetry_do, eth_dev_handle_port_dcb,
1587 : : "Returns DCB info for a port. Parameters: int port_id");
1588 : 301 : rte_telemetry_register_cmd_arg("/ethdev/rss_info",
1589 : : eth_dev_telemetry_do, eth_dev_handle_port_rss_info,
1590 : : "Returns RSS info for a port. Parameters: int port_id");
1591 : 301 : rte_telemetry_register_cmd_arg("/ethdev/fec",
1592 : : eth_dev_telemetry_do, eth_dev_handle_port_fec,
1593 : : "Returns FEC info for a port. Parameters: int port_id");
1594 : 301 : rte_telemetry_register_cmd_arg("/ethdev/vlan",
1595 : : eth_dev_telemetry_do, eth_dev_handle_port_vlan,
1596 : : "Returns VLAN info for a port. Parameters: int port_id");
1597 : 301 : rte_telemetry_register_cmd_arg("/ethdev/tm_capability",
1598 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_caps,
1599 : : "Returns TM Capabilities info for a port. Parameters: int port_id");
1600 : 301 : rte_telemetry_register_cmd_arg("/ethdev/tm_level_capability",
1601 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_level_caps,
1602 : : "Returns TM Level Capabilities info for a port. Parameters: int port_id, int level_id (see tm_capability for the max)");
1603 : 301 : rte_telemetry_register_cmd_arg("/ethdev/tm_node_capability",
1604 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_node_caps,
1605 : : "Returns TM Node Capabilities info for a port. Parameters: int port_id, int node_id (see tm_capability for the max)");
1606 : 301 : rte_telemetry_register_cmd("/ethdev/regs", eth_dev_handle_port_regs,
1607 : : "Returns registers info for a port. Parameters: int port_id,filter=xxx(Optional if show all),hide_zero=true|false(Optional)");
1608 : 301 : }
|