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(*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 : : uint64_t qid;
463 : : int ret;
464 : :
465 : 6 : ret = eth_dev_parse_port_params(params, port_id, &end_param, true);
466 [ + + ]: 6 : if (ret < 0)
467 : : return ret;
468 : :
469 : 2 : dev = &rte_eth_devices[*port_id];
470 [ + + ]: 2 : nb_queues = is_rx ? dev->data->nb_rx_queues : dev->data->nb_tx_queues;
471 [ + - - + ]: 2 : if (nb_queues == 1 && *end_param == '\0')
472 : : qid = 0;
473 : : else {
474 : 0 : qid_param = strtok(end_param, ",");
475 [ # # # # : 0 : if (!qid_param || strlen(qid_param) == 0 || !isdigit(*qid_param))
# # ]
476 : : return -EINVAL;
477 : :
478 : 0 : qid = strtoul(qid_param, &end_param, 0);
479 : : }
480 [ - + ]: 2 : if (*end_param != '\0')
481 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
482 : : "Extra parameters passed to ethdev telemetry command, ignoring");
483 : :
484 [ + - ]: 2 : if (qid >= UINT16_MAX)
485 : : return -EINVAL;
486 : :
487 : 2 : *queue_id = qid;
488 : 2 : return 0;
489 : : }
490 : :
491 : : static int
492 : 0 : eth_dev_add_burst_mode(uint16_t port_id, uint16_t queue_id,
493 : : bool is_rx, struct rte_tel_data *d)
494 : : {
495 : : struct rte_eth_burst_mode mode;
496 : : int ret;
497 : :
498 [ # # ]: 0 : if (is_rx)
499 : 0 : ret = rte_eth_rx_burst_mode_get(port_id, queue_id, &mode);
500 : : else
501 : 0 : ret = rte_eth_tx_burst_mode_get(port_id, queue_id, &mode);
502 : :
503 [ # # ]: 0 : if (ret == -ENOTSUP)
504 : : return 0;
505 : :
506 [ # # ]: 0 : if (ret != 0) {
507 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
508 : : "Failed to get burst mode for port %u", port_id);
509 : 0 : return ret;
510 : : }
511 : :
512 : 0 : rte_tel_data_add_dict_uint(d, "burst_flags", mode.flags);
513 : 0 : rte_tel_data_add_dict_string(d, "burst_mode", mode.info);
514 : 0 : return 0;
515 : : }
516 : :
517 : : static int
518 : 3 : eth_dev_handle_port_rxq(const char *cmd __rte_unused,
519 : : const char *params,
520 : : struct rte_tel_data *d)
521 : : {
522 : : struct rte_eth_thresh *rx_thresh;
523 : : struct rte_eth_rxconf *rxconf;
524 : : struct rte_eth_rxq_info qinfo;
525 : : struct rte_tel_data *offload;
526 : : uint16_t port_id, queue_id;
527 : : int ret;
528 : :
529 : 3 : ret = ethdev_parse_queue_params(params, true, &port_id, &queue_id);
530 [ + + ]: 3 : if (ret != 0)
531 : : return ret;
532 : :
533 : 1 : ret = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
534 [ - + ]: 1 : if (ret != 0)
535 : : return ret;
536 : :
537 : 0 : rte_tel_data_start_dict(d);
538 : 0 : rte_tel_data_add_dict_string(d, "mempool_name", qinfo.mp->name);
539 : 0 : rte_tel_data_add_dict_uint(d, "socket_id", qinfo.mp->socket_id);
540 : :
541 : : rx_thresh = &qinfo.conf.rx_thresh;
542 : 0 : rte_tel_data_add_dict_uint(d, "host_threshold", rx_thresh->hthresh);
543 : 0 : rte_tel_data_add_dict_uint(d, "prefetch_threshold", rx_thresh->pthresh);
544 : 0 : rte_tel_data_add_dict_uint(d, "writeback_threshold", rx_thresh->wthresh);
545 : :
546 : : rxconf = &qinfo.conf;
547 : 0 : rte_tel_data_add_dict_uint(d, "free_threshold", rxconf->rx_free_thresh);
548 : 0 : rte_tel_data_add_dict_string(d, "rx_drop_en",
549 [ # # ]: 0 : rxconf->rx_drop_en == 0 ? "off" : "on");
550 : 0 : rte_tel_data_add_dict_string(d, "deferred_start",
551 [ # # ]: 0 : rxconf->rx_deferred_start == 0 ? "off" : "on");
552 : 0 : rte_tel_data_add_dict_uint(d, "rx_nseg", rxconf->rx_nseg);
553 : 0 : rte_tel_data_add_dict_uint(d, "share_group", rxconf->share_group);
554 : 0 : rte_tel_data_add_dict_uint(d, "share_qid", rxconf->share_qid);
555 : :
556 : 0 : offload = rte_tel_data_alloc();
557 [ # # ]: 0 : if (offload == NULL)
558 : : return -ENOMEM;
559 : :
560 : 0 : eth_dev_parse_rx_offloads(rxconf->offloads, offload);
561 : 0 : rte_tel_data_add_dict_container(d, "offloads", offload, 0);
562 : :
563 : 0 : rte_tel_data_add_dict_uint(d, "rx_nmempool", rxconf->rx_nmempool);
564 : :
565 : 0 : rte_tel_data_add_dict_string(d, "scattered_rx",
566 [ # # ]: 0 : qinfo.scattered_rx == 0 ? "off" : "on");
567 : 0 : rte_tel_data_add_dict_uint(d, "queue_state", qinfo.queue_state);
568 : 0 : rte_tel_data_add_dict_uint(d, "nb_desc", qinfo.nb_desc);
569 : 0 : rte_tel_data_add_dict_uint(d, "rx_buf_size", qinfo.rx_buf_size);
570 : 0 : rte_tel_data_add_dict_uint(d, "avail_thresh", qinfo.avail_thresh);
571 : :
572 : 0 : ret = eth_dev_add_burst_mode(port_id, queue_id, true, d);
573 [ # # ]: 0 : if (ret != 0)
574 : 0 : rte_tel_data_free(offload);
575 : :
576 : : return ret;
577 : : }
578 : :
579 : : static int
580 : 3 : eth_dev_handle_port_txq(const char *cmd __rte_unused,
581 : : const char *params,
582 : : struct rte_tel_data *d)
583 : : {
584 : : struct rte_eth_thresh *tx_thresh;
585 : : struct rte_eth_txconf *txconf;
586 : : struct rte_eth_txq_info qinfo;
587 : : struct rte_tel_data *offload;
588 : : uint16_t port_id, queue_id;
589 : : int ret;
590 : :
591 : 3 : ret = ethdev_parse_queue_params(params, false, &port_id, &queue_id);
592 [ + + ]: 3 : if (ret != 0)
593 : : return ret;
594 : :
595 : 1 : ret = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
596 [ - + ]: 1 : if (ret != 0)
597 : : return ret;
598 : :
599 : 0 : rte_tel_data_start_dict(d);
600 : : tx_thresh = &qinfo.conf.tx_thresh;
601 : : txconf = &qinfo.conf;
602 : 0 : rte_tel_data_add_dict_uint(d, "host_threshold", tx_thresh->hthresh);
603 : 0 : rte_tel_data_add_dict_uint(d, "prefetch_threshold", tx_thresh->pthresh);
604 : 0 : rte_tel_data_add_dict_uint(d, "writeback_threshold", tx_thresh->wthresh);
605 : 0 : rte_tel_data_add_dict_uint(d, "rs_threshold", txconf->tx_rs_thresh);
606 : 0 : rte_tel_data_add_dict_uint(d, "free_threshold", txconf->tx_free_thresh);
607 : 0 : rte_tel_data_add_dict_string(d, "deferred_start",
608 [ # # ]: 0 : txconf->tx_deferred_start == 0 ? "off" : "on");
609 : :
610 : 0 : offload = rte_tel_data_alloc();
611 [ # # ]: 0 : if (offload == NULL)
612 : : return -ENOMEM;
613 : :
614 : 0 : eth_dev_parse_tx_offloads(txconf->offloads, offload);
615 : 0 : rte_tel_data_add_dict_container(d, "offloads", offload, 0);
616 : :
617 : 0 : rte_tel_data_add_dict_uint(d, "queue_state", qinfo.queue_state);
618 : 0 : rte_tel_data_add_dict_uint(d, "nb_desc", qinfo.nb_desc);
619 : :
620 : 0 : ret = eth_dev_add_burst_mode(port_id, queue_id, false, d);
621 [ # # ]: 0 : if (ret != 0)
622 : 0 : rte_tel_data_free(offload);
623 : :
624 : : return 0;
625 : : }
626 : :
627 : : static int
628 : 0 : eth_dev_add_dcb_tc(struct rte_eth_dcb_info *dcb_info, struct rte_tel_data *d)
629 : : {
630 : 0 : struct rte_tel_data *tcds[RTE_ETH_DCB_NUM_TCS] = {NULL};
631 : : struct rte_eth_dcb_tc_queue_mapping *tcq;
632 : : char bw_percent[RTE_TEL_MAX_STRING_LEN];
633 : : char name[RTE_TEL_MAX_STRING_LEN];
634 : : struct rte_tel_data *tcd;
635 : : uint32_t i;
636 : :
637 [ # # ]: 0 : for (i = 0; i < dcb_info->nb_tcs; i++) {
638 : 0 : tcd = rte_tel_data_alloc();
639 [ # # ]: 0 : if (tcd == NULL) {
640 [ # # ]: 0 : while (i-- > 0)
641 : 0 : rte_tel_data_free(tcds[i]);
642 : : return -ENOMEM;
643 : : }
644 : :
645 : 0 : tcds[i] = tcd;
646 : 0 : rte_tel_data_start_dict(tcd);
647 : :
648 : 0 : rte_tel_data_add_dict_uint(tcd, "priority", dcb_info->prio_tc[i]);
649 : 0 : snprintf(bw_percent, RTE_TEL_MAX_STRING_LEN,
650 : 0 : "%u%%", dcb_info->tc_bws[i]);
651 : 0 : rte_tel_data_add_dict_string(tcd, "bw_percent", bw_percent);
652 : :
653 : : tcq = &dcb_info->tc_queue;
654 : 0 : rte_tel_data_add_dict_uint(tcd, "rxq_base", tcq->tc_rxq[0][i].base);
655 : 0 : rte_tel_data_add_dict_uint(tcd, "txq_base", tcq->tc_txq[0][i].base);
656 : 0 : rte_tel_data_add_dict_uint(tcd, "nb_rxq", tcq->tc_rxq[0][i].nb_queue);
657 : 0 : rte_tel_data_add_dict_uint(tcd, "nb_txq", tcq->tc_txq[0][i].nb_queue);
658 : :
659 : : snprintf(name, RTE_TEL_MAX_STRING_LEN, "tc%u", i);
660 : 0 : rte_tel_data_add_dict_container(d, name, tcd, 0);
661 : : }
662 : :
663 : : return 0;
664 : : }
665 : :
666 : : static int
667 : 1 : eth_dev_add_dcb_info(uint16_t port_id, struct rte_tel_data *d)
668 : : {
669 : : struct rte_eth_dcb_info dcb_info;
670 : : int ret;
671 : :
672 : 1 : ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
673 [ + - ]: 1 : if (ret != 0) {
674 : 1 : RTE_ETHDEV_LOG_LINE(ERR,
675 : : "Failed to get dcb info, ret = %d", ret);
676 : 1 : return ret;
677 : : }
678 : :
679 : 0 : rte_tel_data_start_dict(d);
680 : 0 : rte_tel_data_add_dict_uint(d, "tc_num", dcb_info.nb_tcs);
681 : :
682 [ # # ]: 0 : if (dcb_info.nb_tcs > 0)
683 : 0 : return eth_dev_add_dcb_tc(&dcb_info, d);
684 : :
685 : : return 0;
686 : : }
687 : :
688 : : static int
689 : 3 : eth_dev_handle_port_dcb(const char *cmd __rte_unused,
690 : : const char *params,
691 : : struct rte_tel_data *d)
692 : : {
693 : : uint16_t port_id;
694 : : char *end_param;
695 : : int ret;
696 : :
697 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
698 [ + + ]: 3 : if (ret < 0)
699 : : return ret;
700 : :
701 : 1 : return eth_dev_add_dcb_info(port_id, d);
702 : : }
703 : :
704 : : static int
705 : 1 : eth_dev_add_rss_info(struct rte_eth_rss_conf *rss_conf, struct rte_tel_data *d)
706 : : {
707 : 1 : const uint32_t key_len = rss_conf->rss_key_len * 2 + 1;
708 : : char *rss_key;
709 : : char key[3]; /* FF\0 */
710 : : uint32_t i;
711 : : int ret;
712 : :
713 : 1 : rss_key = malloc(key_len);
714 [ + - ]: 1 : if (rss_key == NULL)
715 : : return -ENOMEM;
716 : :
717 : 1 : rte_tel_data_start_dict(d);
718 : 1 : rte_tel_data_add_dict_uint_hex(d, "rss_hf", rss_conf->rss_hf, 0);
719 : 1 : rte_tel_data_add_dict_uint(d, "rss_key_len", rss_conf->rss_key_len);
720 : :
721 : : memset(rss_key, 0, key_len);
722 [ + + ]: 41 : for (i = 0; i < rss_conf->rss_key_len; i++) {
723 [ - + ]: 40 : ret = snprintf(key, 3, "%02x", rss_conf->rss_key[i]);
724 [ - + ]: 40 : if (ret < 0)
725 : 0 : goto free_rss_key;
726 : 40 : strlcat(rss_key, key, key_len);
727 : : }
728 : 1 : ret = rte_tel_data_add_dict_string(d, "rss_key", rss_key);
729 [ - + ]: 1 : if (ret < 0)
730 : 0 : goto free_rss_key;
731 : 1 : ret = rte_tel_data_add_dict_string(d, "algorithm",
732 : : rte_eth_dev_rss_algo_name(rss_conf->algorithm));
733 : :
734 : 1 : free_rss_key:
735 : 1 : free(rss_key);
736 : :
737 : 1 : return ret;
738 : : }
739 : :
740 : : static int
741 : 3 : eth_dev_handle_port_rss_info(const char *cmd __rte_unused,
742 : : const char *params,
743 : : struct rte_tel_data *d)
744 : : {
745 : : struct rte_eth_dev_info dev_info;
746 : : struct rte_eth_rss_conf rss_conf;
747 : : uint8_t key_len;
748 : : uint16_t port_id;
749 : : char *end_param;
750 : : int ret;
751 : :
752 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
753 [ + + ]: 3 : if (ret < 0)
754 : : return ret;
755 : :
756 : 1 : ret = rte_eth_dev_info_get(port_id, &dev_info);
757 [ - + ]: 1 : if (ret != 0) {
758 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
759 : : "Failed to get device info, ret = %d", ret);
760 : 0 : return ret;
761 : : }
762 : :
763 [ + - ]: 1 : key_len = dev_info.hash_key_size ? dev_info.hash_key_size : 40;
764 : 1 : rss_conf.rss_key_len = key_len;
765 : 1 : rss_conf.rss_key = malloc(key_len);
766 [ + - ]: 1 : if (rss_conf.rss_key == NULL)
767 : : return -ENOMEM;
768 : :
769 : 1 : ret = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
770 [ - + ]: 1 : if (ret != 0) {
771 : 0 : free(rss_conf.rss_key);
772 : 0 : return ret;
773 : : }
774 : :
775 : 1 : ret = eth_dev_add_rss_info(&rss_conf, d);
776 : 1 : free(rss_conf.rss_key);
777 : 1 : return ret;
778 : : }
779 : :
780 : : static const char *
781 : : eth_dev_fec_capa_to_string(uint32_t fec_capa)
782 : : {
783 : : uint32_t i;
784 : :
785 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
786 [ # # ]: 0 : if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0)
787 : 0 : return rte_eth_fec_capa_name[i].name;
788 : : }
789 : :
790 : : return "unknown";
791 : : }
792 : :
793 : : static void
794 : 0 : eth_dev_fec_capas_to_string(uint32_t fec_capa, char *fec_name, uint32_t len)
795 : : {
796 : : bool valid = false;
797 : : size_t count = 0;
798 : : uint32_t i;
799 : :
800 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
801 [ # # ]: 0 : if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0) {
802 : 0 : strlcat(fec_name, rte_eth_fec_capa_name[i].name, len);
803 : 0 : count = strlcat(fec_name, " ", len);
804 : : valid = true;
805 : : }
806 : : }
807 : :
808 [ # # ]: 0 : if (!valid)
809 : 0 : count = snprintf(fec_name, len, "unknown ");
810 : :
811 [ # # ]: 0 : if (count >= len) {
812 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "FEC capa names may be truncated");
813 : : count = len;
814 : : }
815 : :
816 : 0 : fec_name[count - 1] = '\0';
817 : 0 : }
818 : :
819 : : static int
820 : 0 : eth_dev_get_fec_capability(uint16_t port_id, struct rte_tel_data *d)
821 : : {
822 : : struct rte_eth_fec_capa *speed_fec_capa;
823 : : char fec_name[RTE_TEL_MAX_STRING_LEN];
824 : : char speed[RTE_TEL_MAX_STRING_LEN];
825 : : uint32_t capa_num;
826 : : uint32_t i, j;
827 : : int ret;
828 : :
829 : 0 : ret = rte_eth_fec_get_capability(port_id, NULL, 0);
830 [ # # ]: 0 : if (ret <= 0)
831 [ # # ]: 0 : return ret == 0 ? -EINVAL : ret;
832 : :
833 : 0 : capa_num = ret;
834 : 0 : speed_fec_capa = calloc(capa_num, sizeof(struct rte_eth_fec_capa));
835 [ # # ]: 0 : if (speed_fec_capa == NULL)
836 : : return -ENOMEM;
837 : :
838 : 0 : ret = rte_eth_fec_get_capability(port_id, speed_fec_capa, capa_num);
839 [ # # ]: 0 : if (ret <= 0) {
840 [ # # ]: 0 : ret = ret == 0 ? -EINVAL : ret;
841 : 0 : goto out;
842 : : }
843 : :
844 [ # # ]: 0 : for (i = 0; i < capa_num; i++) {
845 : : memset(fec_name, 0, RTE_TEL_MAX_STRING_LEN);
846 : 0 : eth_dev_fec_capas_to_string(speed_fec_capa[i].capa, fec_name,
847 : : RTE_TEL_MAX_STRING_LEN);
848 : :
849 : : memset(speed, 0, RTE_TEL_MAX_STRING_LEN);
850 : 0 : ret = snprintf(speed, RTE_TEL_MAX_STRING_LEN, "%s",
851 : : rte_eth_link_speed_to_str(speed_fec_capa[i].speed));
852 [ # # ]: 0 : if (ret < 0)
853 : 0 : goto out;
854 : :
855 [ # # ]: 0 : for (j = 0; j < strlen(speed); j++) {
856 [ # # ]: 0 : if (speed[j] == ' ')
857 : 0 : speed[j] = '_';
858 : : }
859 : :
860 : 0 : rte_tel_data_add_dict_string(d, speed, fec_name);
861 : : }
862 : :
863 : 0 : out:
864 : 0 : free(speed_fec_capa);
865 : 0 : return ret > 0 ? 0 : ret;
866 : : }
867 : :
868 : : static int
869 : 3 : eth_dev_handle_port_fec(const char *cmd __rte_unused,
870 : : const char *params,
871 : : struct rte_tel_data *d)
872 : : {
873 : : struct rte_tel_data *fec_capas;
874 : : uint32_t fec_mode;
875 : : uint16_t port_id;
876 : : char *end_param;
877 : : int ret;
878 : :
879 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
880 [ + + ]: 3 : if (ret < 0)
881 : : return ret;
882 : :
883 : 1 : ret = rte_eth_fec_get(port_id, &fec_mode);
884 [ - + ]: 1 : if (ret != 0)
885 : : return ret;
886 : :
887 : 0 : rte_tel_data_start_dict(d);
888 : 0 : rte_tel_data_add_dict_string(d, "fec_mode",
889 : : eth_dev_fec_capa_to_string(fec_mode));
890 : :
891 : 0 : fec_capas = rte_tel_data_alloc();
892 [ # # ]: 0 : if (fec_capas == NULL)
893 : : return -ENOMEM;
894 : :
895 : 0 : rte_tel_data_start_dict(fec_capas);
896 : 0 : ret = eth_dev_get_fec_capability(port_id, fec_capas);
897 [ # # ]: 0 : if (ret != 0) {
898 : 0 : rte_tel_data_free(fec_capas);
899 : 0 : return ret;
900 : : }
901 : :
902 : 0 : rte_tel_data_add_dict_container(d, "fec_capability", fec_capas, 0);
903 : 0 : return 0;
904 : : }
905 : :
906 : : static int
907 : 1 : eth_dev_add_vlan_id(int port_id, struct rte_tel_data *d)
908 : : {
909 : 1 : struct rte_tel_data *vlan_blks[64] = {NULL};
910 : : uint16_t vlan_num, vidx, vbit, num_blks;
911 : : char blk_name[RTE_TEL_MAX_STRING_LEN];
912 : : struct rte_vlan_filter_conf *vfc;
913 : : struct rte_tel_data *vlan_blk;
914 : : struct rte_tel_data *vd;
915 : : uint64_t bit_width;
916 : : uint64_t vlan_id;
917 : :
918 : 1 : vd = rte_tel_data_alloc();
919 [ + - ]: 1 : if (vd == NULL)
920 : : return -ENOMEM;
921 : :
922 : 1 : vfc = &rte_eth_devices[port_id].data->vlan_filter_conf;
923 : : bit_width = CHAR_BIT * sizeof(uint64_t);
924 : : vlan_num = 0;
925 : : num_blks = 0;
926 : :
927 : 1 : rte_tel_data_start_dict(vd);
928 [ + + ]: 65 : for (vidx = 0; vidx < RTE_DIM(vfc->ids); vidx++) {
929 [ + - ]: 64 : if (vfc->ids[vidx] == 0)
930 : 64 : continue;
931 : :
932 : 0 : vlan_blk = rte_tel_data_alloc();
933 [ # # ]: 0 : if (vlan_blk == NULL)
934 : 0 : goto free_all;
935 : :
936 : 0 : vlan_blks[num_blks] = vlan_blk;
937 : 0 : num_blks++;
938 : 0 : snprintf(blk_name, RTE_TEL_MAX_STRING_LEN, "vlan_%"PRIu64"_to_%"PRIu64"",
939 : 0 : bit_width * vidx, bit_width * (vidx + 1) - 1);
940 : 0 : rte_tel_data_start_array(vlan_blk, RTE_TEL_UINT_VAL);
941 : 0 : rte_tel_data_add_dict_container(vd, blk_name, vlan_blk, 0);
942 : :
943 [ # # ]: 0 : for (vbit = 0; vbit < bit_width; vbit++) {
944 [ # # ]: 0 : if ((vfc->ids[vidx] & RTE_BIT64(vbit)) == 0)
945 : 0 : continue;
946 : :
947 : 0 : vlan_id = bit_width * vidx + vbit;
948 : 0 : rte_tel_data_add_array_uint(vlan_blk, vlan_id);
949 : 0 : vlan_num++;
950 : : }
951 : : }
952 : :
953 : 1 : rte_tel_data_add_dict_uint(d, "vlan_num", vlan_num);
954 : 1 : rte_tel_data_add_dict_container(d, "vlan_ids", vd, 0);
955 : :
956 : 1 : return 0;
957 : :
958 : : free_all:
959 [ # # ]: 0 : while (num_blks-- > 0)
960 : 0 : rte_tel_data_free(vlan_blks[num_blks]);
961 : :
962 : 0 : rte_tel_data_free(vd);
963 : 0 : return -ENOMEM;
964 : : }
965 : :
966 : : static int
967 : 3 : eth_dev_handle_port_vlan(const char *cmd __rte_unused,
968 : : const char *params,
969 : : struct rte_tel_data *d)
970 : : {
971 : : struct rte_eth_txmode *txmode;
972 : : struct rte_eth_conf dev_conf;
973 : : uint16_t port_id;
974 : : int offload, ret;
975 : : char *end_param;
976 : :
977 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
978 [ + + ]: 3 : if (ret < 0)
979 : : return ret;
980 : :
981 : 1 : ret = rte_eth_dev_conf_get(port_id, &dev_conf);
982 [ - + ]: 1 : if (ret != 0) {
983 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
984 : : "Failed to get device configuration, ret = %d", ret);
985 : 0 : return ret;
986 : : }
987 : :
988 : : txmode = &dev_conf.txmode;
989 : 1 : rte_tel_data_start_dict(d);
990 : 1 : rte_tel_data_add_dict_uint(d, "pvid", txmode->pvid);
991 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_reject_tagged",
992 : 1 : txmode->hw_vlan_reject_tagged);
993 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_reject_untagged",
994 : 1 : txmode->hw_vlan_reject_untagged);
995 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_insert_pvid",
996 : 1 : txmode->hw_vlan_insert_pvid);
997 : :
998 : 1 : offload = rte_eth_dev_get_vlan_offload(port_id);
999 : 1 : rte_tel_data_add_dict_string(d, "VLAN_STRIP",
1000 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_STRIP_OFFLOAD) != 0) ? "on" : "off");
1001 : 1 : rte_tel_data_add_dict_string(d, "VLAN_EXTEND",
1002 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_EXTEND_OFFLOAD) != 0) ? "on" : "off");
1003 : 1 : rte_tel_data_add_dict_string(d, "QINQ_STRIP",
1004 [ + - ]: 1 : ((offload & RTE_ETH_QINQ_STRIP_OFFLOAD) != 0) ? "on" : "off");
1005 : 1 : rte_tel_data_add_dict_string(d, "VLAN_FILTER",
1006 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_FILTER_OFFLOAD) != 0) ? "on" : "off");
1007 : :
1008 : 1 : return eth_dev_add_vlan_id(port_id, d);
1009 : : }
1010 : :
1011 : : static void
1012 : 0 : eth_dev_add_tm_caps(struct rte_tel_data *d, struct rte_tm_capabilities *cap)
1013 : : {
1014 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1015 : 0 : rte_tel_data_add_dict_uint(d, "n_levels_max", cap->n_levels_max);
1016 : 0 : rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1017 : 0 : cap->non_leaf_nodes_identical);
1018 : 0 : rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1019 : 0 : cap->leaf_nodes_identical);
1020 : 0 : rte_tel_data_add_dict_uint(d, "shaper_n_max", cap->shaper_n_max);
1021 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_n_max",
1022 : 0 : cap->shaper_private_n_max);
1023 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_dual_rate_n_max",
1024 : 0 : cap->shaper_private_dual_rate_n_max);
1025 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_rate_min",
1026 : : cap->shaper_private_rate_min);
1027 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_rate_max",
1028 : : cap->shaper_private_rate_max);
1029 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_packet_mode_supported",
1030 : 0 : cap->shaper_private_packet_mode_supported);
1031 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_byte_mode_supported",
1032 : 0 : cap->shaper_private_byte_mode_supported);
1033 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_max",
1034 : 0 : cap->shaper_shared_n_max);
1035 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_nodes_per_shaper_max",
1036 : 0 : cap->shaper_shared_n_nodes_per_shaper_max);
1037 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_shapers_per_node_max",
1038 : 0 : cap->shaper_shared_n_shapers_per_node_max);
1039 : 0 : rte_tel_data_add_dict_uint(d, "shaper_share_dual_rate_n_max",
1040 : 0 : cap->shaper_shared_dual_rate_n_max);
1041 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_rate_min",
1042 : : cap->shaper_shared_rate_min);
1043 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_rate_max",
1044 : : cap->shaper_shared_rate_max);
1045 : 0 : rte_tel_data_add_dict_int(d, "shaper_shared_packet_mode_supported",
1046 : 0 : cap->shaper_shared_packet_mode_supported);
1047 : 0 : rte_tel_data_add_dict_int(d, "shaper_shared_byte_mode_supported",
1048 : 0 : cap->shaper_shared_byte_mode_supported);
1049 : 0 : rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_min",
1050 : 0 : cap->shaper_pkt_length_adjust_min);
1051 : 0 : rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_max",
1052 : 0 : cap->shaper_pkt_length_adjust_max);
1053 : 0 : rte_tel_data_add_dict_uint(d, "sched_n_children_max",
1054 : 0 : cap->sched_n_children_max);
1055 : 0 : rte_tel_data_add_dict_uint(d, "sched_sp_n_priorities_max",
1056 : 0 : cap->sched_sp_n_priorities_max);
1057 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1058 : 0 : cap->sched_wfq_n_children_per_group_max);
1059 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1060 : 0 : cap->sched_wfq_n_groups_max);
1061 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1062 : 0 : cap->sched_wfq_weight_max);
1063 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1064 : 0 : cap->sched_wfq_packet_mode_supported);
1065 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1066 : 0 : cap->sched_wfq_byte_mode_supported);
1067 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1068 : 0 : cap->cman_wred_packet_mode_supported);
1069 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1070 : 0 : cap->cman_wred_byte_mode_supported);
1071 : 0 : rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1072 : 0 : cap->cman_head_drop_supported);
1073 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_n_max",
1074 : 0 : cap->cman_wred_context_n_max);
1075 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_private_n_max",
1076 : 0 : cap->cman_wred_context_private_n_max);
1077 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1078 : 0 : cap->cman_wred_context_shared_n_max);
1079 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_nodes_per_context_max",
1080 : 0 : cap->cman_wred_context_shared_n_nodes_per_context_max);
1081 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_contexts_per_node_max",
1082 : 0 : cap->cman_wred_context_shared_n_contexts_per_node_max);
1083 : 0 : rte_tel_data_add_dict_uint_hex(d, "dynamic_update", cap->dynamic_update_mask, 0);
1084 : 0 : rte_tel_data_add_dict_uint_hex(d, "stats_mask", cap->stats_mask, 0);
1085 : 0 : }
1086 : :
1087 : : static int
1088 : 3 : eth_dev_handle_port_tm_caps(const char *cmd __rte_unused,
1089 : : const char *params,
1090 : : struct rte_tel_data *d)
1091 : : {
1092 : 3 : struct rte_tm_capabilities cap = {0};
1093 : 3 : struct rte_tm_error error = {0};
1094 : : uint16_t port_id;
1095 : : char *end_param;
1096 : : int ret;
1097 : :
1098 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
1099 [ + + ]: 3 : if (ret != 0)
1100 : : return ret;
1101 : :
1102 : 1 : ret = rte_tm_capabilities_get(port_id, &cap, &error);
1103 [ + - ]: 1 : if (ret != 0) {
1104 [ + - ]: 2 : RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1105 : : error.message ? error.message : "no stated reason",
1106 : : error.type);
1107 : 1 : return ret;
1108 : : }
1109 : :
1110 : 0 : rte_tel_data_start_dict(d);
1111 : 0 : eth_dev_add_tm_caps(d, &cap);
1112 : :
1113 : 0 : return 0;
1114 : : }
1115 : :
1116 : : static void
1117 : 0 : eth_dev_add_tm_level_basic_caps(struct rte_tel_data *d,
1118 : : struct rte_tm_level_capabilities *cap)
1119 : : {
1120 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1121 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_nonleaf_max",
1122 : 0 : cap->n_nodes_nonleaf_max);
1123 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_leaf_max", cap->n_nodes_leaf_max);
1124 : 0 : rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1125 : 0 : cap->non_leaf_nodes_identical);
1126 : 0 : rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1127 : 0 : cap->leaf_nodes_identical);
1128 : 0 : }
1129 : :
1130 : : static void
1131 : 0 : eth_dev_add_tm_level_nonleaf_caps(struct rte_tel_data *nonleaf,
1132 : : struct rte_tm_level_capabilities *cap)
1133 : : {
1134 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_supported",
1135 : 0 : cap->nonleaf.shaper_private_supported);
1136 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_dual_rate_supported",
1137 : 0 : cap->nonleaf.shaper_private_dual_rate_supported);
1138 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_min",
1139 : : cap->nonleaf.shaper_private_rate_min);
1140 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_max",
1141 : : cap->nonleaf.shaper_private_rate_max);
1142 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_packet_mode_supported",
1143 : 0 : cap->nonleaf.shaper_private_packet_mode_supported);
1144 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_byte_mode_supported",
1145 : 0 : cap->nonleaf.shaper_private_byte_mode_supported);
1146 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_shared_n_max",
1147 : 0 : cap->nonleaf.shaper_shared_n_max);
1148 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_shared_packet_mode_supported",
1149 : 0 : cap->nonleaf.shaper_shared_packet_mode_supported);
1150 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_shared_byte_mode_supported",
1151 : 0 : cap->nonleaf.shaper_shared_byte_mode_supported);
1152 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_n_children_max",
1153 : 0 : cap->nonleaf.sched_n_children_max);
1154 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_sp_n_priorities_max",
1155 : 0 : cap->nonleaf.sched_sp_n_priorities_max);
1156 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_children_per_group_max",
1157 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max);
1158 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_groups_max",
1159 : 0 : cap->nonleaf.sched_wfq_n_groups_max);
1160 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_weight_max",
1161 : 0 : cap->nonleaf.sched_wfq_weight_max);
1162 : 0 : rte_tel_data_add_dict_int(nonleaf, "sched_wfq_packet_mode_supported",
1163 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported);
1164 : 0 : rte_tel_data_add_dict_int(nonleaf, "sched_wfq_byte_mode_supported",
1165 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported);
1166 : 0 : rte_tel_data_add_dict_uint_hex(nonleaf, "stats_mask",
1167 : : cap->nonleaf.stats_mask, 0);
1168 : 0 : }
1169 : :
1170 : : static void
1171 : 0 : eth_dev_add_tm_level_leaf_caps(struct rte_tel_data *leaf,
1172 : : struct rte_tm_level_capabilities *cap)
1173 : : {
1174 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_supported",
1175 : 0 : cap->leaf.shaper_private_supported);
1176 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_dual_rate_supported",
1177 : 0 : cap->leaf.shaper_private_dual_rate_supported);
1178 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_min",
1179 : : cap->leaf.shaper_private_rate_min);
1180 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_max",
1181 : : cap->leaf.shaper_private_rate_max);
1182 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_packet_mode_supported",
1183 : 0 : cap->leaf.shaper_private_packet_mode_supported);
1184 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_byte_mode_supported",
1185 : 0 : cap->leaf.shaper_private_byte_mode_supported);
1186 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_shared_n_max",
1187 : 0 : cap->leaf.shaper_shared_n_max);
1188 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_shared_packet_mode_supported",
1189 : 0 : cap->leaf.shaper_shared_packet_mode_supported);
1190 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_shared_byte_mode_supported",
1191 : 0 : cap->leaf.shaper_shared_byte_mode_supported);
1192 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_packet_mode_supported",
1193 : 0 : cap->leaf.cman_wred_packet_mode_supported);
1194 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_byte_mode_supported",
1195 : 0 : cap->leaf.cman_wred_byte_mode_supported);
1196 : 0 : rte_tel_data_add_dict_int(leaf, "cman_head_drop_supported",
1197 : 0 : cap->leaf.cman_head_drop_supported);
1198 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_context_private_supported",
1199 : 0 : cap->leaf.cman_wred_context_private_supported);
1200 : 0 : rte_tel_data_add_dict_uint(leaf, "cman_wred_context_shared_n_max",
1201 : 0 : cap->leaf.cman_wred_context_shared_n_max);
1202 : 0 : rte_tel_data_add_dict_uint_hex(leaf, "stats_mask",
1203 : : cap->leaf.stats_mask, 0);
1204 : 0 : }
1205 : :
1206 : : static int
1207 : 2 : eth_dev_parse_tm_params(char *params, uint32_t *result)
1208 : : {
1209 : : const char *splited_param;
1210 : : uint64_t ret;
1211 : :
1212 : 2 : splited_param = strtok(params, ",");
1213 [ - + - - : 2 : if (!splited_param || strlen(splited_param) == 0 || !isdigit(*splited_param))
- - ]
1214 : : return -EINVAL;
1215 : :
1216 : 0 : ret = strtoul(splited_param, ¶ms, 0);
1217 [ # # ]: 0 : if (*params != '\0')
1218 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
1219 : : "Extra parameters passed to ethdev telemetry command, ignoring");
1220 : :
1221 [ # # ]: 0 : if (ret >= UINT32_MAX)
1222 : : return -EINVAL;
1223 : :
1224 : 0 : *result = ret;
1225 : 0 : return 0;
1226 : : }
1227 : :
1228 : : static int
1229 : 3 : eth_dev_handle_port_tm_level_caps(const char *cmd __rte_unused,
1230 : : const char *params,
1231 : : struct rte_tel_data *d)
1232 : : {
1233 : 3 : struct rte_tm_level_capabilities cap = {0};
1234 : 3 : struct rte_tm_error error = {0};
1235 : : struct rte_tel_data *nonleaf;
1236 : : struct rte_tel_data *leaf;
1237 : : uint32_t level_id;
1238 : : uint16_t port_id;
1239 : : char *end_param;
1240 : : int ret;
1241 : :
1242 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1243 [ + + ]: 3 : if (ret != 0)
1244 : : return ret;
1245 : :
1246 : 1 : ret = eth_dev_parse_tm_params(end_param, &level_id);
1247 [ - + ]: 1 : if (ret != 0)
1248 : : return ret;
1249 : :
1250 : 0 : ret = rte_tm_level_capabilities_get(port_id, level_id, &cap, &error);
1251 [ # # ]: 0 : if (ret != 0) {
1252 [ # # ]: 0 : RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1253 : : error.message ? error.message : "no stated reason",
1254 : : error.type);
1255 : 0 : return ret;
1256 : : }
1257 : :
1258 : 0 : rte_tel_data_start_dict(d);
1259 : 0 : eth_dev_add_tm_level_basic_caps(d, &cap);
1260 : :
1261 : 0 : nonleaf = rte_tel_data_alloc();
1262 [ # # ]: 0 : if (nonleaf == NULL)
1263 : : return -ENOMEM;
1264 : :
1265 : 0 : rte_tel_data_start_dict(nonleaf);
1266 : 0 : eth_dev_add_tm_level_nonleaf_caps(nonleaf, &cap);
1267 : 0 : rte_tel_data_add_dict_container(d, "nonleaf_cap", nonleaf, 0);
1268 : :
1269 : 0 : leaf = rte_tel_data_alloc();
1270 [ # # ]: 0 : if (leaf == NULL) {
1271 : 0 : rte_tel_data_free(nonleaf);
1272 : 0 : return -ENOMEM;
1273 : : }
1274 : :
1275 : 0 : rte_tel_data_start_dict(leaf);
1276 : 0 : eth_dev_add_tm_level_leaf_caps(leaf, &cap);
1277 : 0 : rte_tel_data_add_dict_container(d, "leaf_cap", leaf, 0);
1278 : :
1279 : 0 : return 0;
1280 : : }
1281 : :
1282 : : static void
1283 : 0 : eth_dev_add_tm_node_basic_caps(struct rte_tel_data *node_data,
1284 : : struct rte_tm_node_capabilities *capnode)
1285 : : {
1286 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_supported",
1287 : 0 : capnode->shaper_private_supported);
1288 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_dual_rate_supported",
1289 : 0 : capnode->shaper_private_dual_rate_supported);
1290 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_min",
1291 : : capnode->shaper_private_rate_min);
1292 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_max",
1293 : : capnode->shaper_private_rate_max);
1294 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_packet_mode_supported",
1295 : 0 : capnode->shaper_private_packet_mode_supported);
1296 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_byte_mode_supported",
1297 : 0 : capnode->shaper_private_byte_mode_supported);
1298 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_shared_n_max",
1299 : 0 : capnode->shaper_shared_n_max);
1300 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_shared_packet_mode_supported",
1301 : 0 : capnode->shaper_shared_packet_mode_supported);
1302 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_shared_byte_mode_supported",
1303 : 0 : capnode->shaper_shared_byte_mode_supported);
1304 : 0 : rte_tel_data_add_dict_uint_hex(node_data, "stats_mask",
1305 : : capnode->stats_mask, 0);
1306 : 0 : }
1307 : :
1308 : : static void
1309 : 0 : eth_dev_add_tm_type_node_caps(struct rte_tel_data *d, int is_leaf,
1310 : : struct rte_tm_node_capabilities *cap)
1311 : : {
1312 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "node_type",
1313 : : is_leaf == 0 ? "nonleaf" : "leaf");
1314 [ # # ]: 0 : if (is_leaf == 0) {
1315 : 0 : rte_tel_data_add_dict_uint(d, "children_max",
1316 : 0 : cap->nonleaf.sched_n_children_max);
1317 : 0 : rte_tel_data_add_dict_uint(d, "priorities_max",
1318 : 0 : cap->nonleaf.sched_sp_n_priorities_max);
1319 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1320 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max);
1321 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1322 : 0 : cap->nonleaf.sched_wfq_n_groups_max);
1323 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1324 : 0 : cap->nonleaf.sched_wfq_weight_max);
1325 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1326 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported);
1327 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1328 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported);
1329 : : } else {
1330 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1331 : 0 : cap->leaf.cman_wred_packet_mode_supported);
1332 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1333 : 0 : cap->leaf.cman_wred_byte_mode_supported);
1334 : 0 : rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1335 : 0 : cap->leaf.cman_head_drop_supported);
1336 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_context_private_supported",
1337 : 0 : cap->leaf.cman_wred_context_private_supported);
1338 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1339 : 0 : cap->leaf.cman_wred_context_shared_n_max);
1340 : : }
1341 : 0 : }
1342 : :
1343 : : static int
1344 : 3 : eth_dev_handle_port_tm_node_caps(const char *cmd __rte_unused,
1345 : : const char *params,
1346 : : struct rte_tel_data *d)
1347 : : {
1348 : 3 : struct rte_tm_node_capabilities cap = {0};
1349 : 3 : struct rte_tm_error error = {0};
1350 : : uint32_t node_id;
1351 : : uint16_t port_id;
1352 : : char *end_param;
1353 : : int is_leaf;
1354 : : int ret;
1355 : :
1356 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1357 [ + + ]: 3 : if (ret != 0)
1358 : : return ret;
1359 : :
1360 : 1 : ret = eth_dev_parse_tm_params(end_param, &node_id);
1361 [ - + ]: 1 : if (ret != 0)
1362 : : return ret;
1363 : :
1364 : 0 : ret = rte_tm_node_capabilities_get(port_id, node_id, &cap, &error);
1365 [ # # ]: 0 : if (ret != 0)
1366 : 0 : goto out;
1367 : :
1368 : 0 : ret = rte_tm_node_type_get(port_id, node_id, &is_leaf, &error);
1369 [ # # ]: 0 : if (ret != 0)
1370 : 0 : goto out;
1371 : :
1372 : 0 : rte_tel_data_start_dict(d);
1373 : 0 : eth_dev_add_tm_node_basic_caps(d, &cap);
1374 : 0 : eth_dev_add_tm_type_node_caps(d, is_leaf, &cap);
1375 : :
1376 : 0 : return 0;
1377 : 0 : out:
1378 [ # # ]: 0 : RTE_ETHDEV_LOG_LINE(WARNING, "error: %s, error type: %u",
1379 : : error.message ? error.message : "no stated reason",
1380 : : error.type);
1381 : 0 : return ret;
1382 : : }
1383 : :
1384 : : static void
1385 : 0 : eth_dev_add_reg_data(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info,
1386 : : uint32_t idx, bool hide_zero)
1387 : : {
1388 : : uint64_t val;
1389 : :
1390 [ # # ]: 0 : if (reg_info->width == sizeof(uint32_t))
1391 : 0 : val = *((uint32_t *)reg_info->data + idx);
1392 : : else
1393 : 0 : val = *((uint64_t *)reg_info->data + idx);
1394 : :
1395 [ # # ]: 0 : if (!hide_zero || val > 0)
1396 : 0 : rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name, val, 0);
1397 : 0 : }
1398 : :
1399 : : static int
1400 : 0 : eth_dev_store_regs(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info, bool hide_zero)
1401 : : {
1402 : : struct rte_tel_data *groups[RTE_TEL_MAX_DICT_ENTRIES];
1403 : 0 : char group_name[RTE_TEL_MAX_STRING_LEN] = {0};
1404 : : struct rte_tel_data *group = NULL;
1405 : : uint32_t grp_num = 0;
1406 : : uint32_t i, max_cap;
1407 : : int ret;
1408 : :
1409 : 0 : rte_tel_data_start_dict(d);
1410 : 0 : rte_tel_data_add_dict_uint(d, "register_length", reg_info->length);
1411 : 0 : rte_tel_data_add_dict_uint(d, "register_width", reg_info->width);
1412 : 0 : rte_tel_data_add_dict_uint_hex(d, "register_offset", reg_info->offset, 0);
1413 : 0 : rte_tel_data_add_dict_uint_hex(d, "version", reg_info->version, 0);
1414 : :
1415 : : max_cap = (RTE_TEL_MAX_DICT_ENTRIES - 4) * RTE_TEL_MAX_DICT_ENTRIES;
1416 [ # # ]: 0 : if (reg_info->length > max_cap) {
1417 : 0 : RTE_ETHDEV_LOG_LINE(WARNING,
1418 : : "Registers to be displayed are reduced from %u to %u due to limited capacity",
1419 : : reg_info->length, max_cap);
1420 : 0 : reg_info->length = max_cap;
1421 : : }
1422 : :
1423 [ # # ]: 0 : for (i = 0; i < reg_info->length; i++) {
1424 [ # # ]: 0 : if (i % RTE_TEL_MAX_DICT_ENTRIES != 0) {
1425 : 0 : eth_dev_add_reg_data(group, reg_info, i, hide_zero);
1426 : 0 : continue;
1427 : : }
1428 : :
1429 : 0 : group = rte_tel_data_alloc();
1430 [ # # ]: 0 : if (group == NULL) {
1431 : : ret = -ENOMEM;
1432 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "No enough memory for group data");
1433 : 0 : goto out;
1434 : : }
1435 : 0 : groups[grp_num++] = group;
1436 : 0 : rte_tel_data_start_dict(group);
1437 : 0 : eth_dev_add_reg_data(group, reg_info, i, hide_zero);
1438 : : }
1439 : :
1440 [ # # ]: 0 : for (i = 0; i < grp_num; i++) {
1441 : : snprintf(group_name, RTE_TEL_MAX_STRING_LEN, "group_%u", i);
1442 : 0 : rte_tel_data_add_dict_container(d, group_name, groups[i], 0);
1443 : : }
1444 : : return 0;
1445 : : out:
1446 [ # # ]: 0 : for (i = 0; i < grp_num; i++)
1447 : 0 : rte_tel_data_free(groups[i]);
1448 : :
1449 : : return ret;
1450 : : }
1451 : :
1452 : : static int
1453 : 1 : eth_dev_get_port_regs(int port_id, struct rte_tel_data *d, char *filter, bool hide_zero)
1454 : : {
1455 : : struct rte_dev_reg_info reg_info;
1456 : : int ret;
1457 : :
1458 : : memset(®_info, 0, sizeof(reg_info));
1459 : 1 : reg_info.filter = filter;
1460 : :
1461 : 1 : ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
1462 [ + - ]: 1 : if (ret != 0) {
1463 : 1 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1464 : 1 : return ret;
1465 : : }
1466 : :
1467 : 0 : reg_info.data = calloc(reg_info.length, reg_info.width);
1468 [ # # ]: 0 : if (reg_info.data == NULL) {
1469 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.data");
1470 : 0 : return -ENOMEM;
1471 : : }
1472 : :
1473 : 0 : reg_info.names = calloc(reg_info.length, sizeof(struct rte_eth_reg_name));
1474 [ # # ]: 0 : if (reg_info.names == NULL) {
1475 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.names");
1476 : 0 : free(reg_info.data);
1477 : 0 : return -ENOMEM;
1478 : : }
1479 : :
1480 : 0 : ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
1481 [ # # ]: 0 : if (ret != 0) {
1482 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1483 : : ret = -EINVAL;
1484 : 0 : goto out;
1485 : : }
1486 : :
1487 : 0 : ret = eth_dev_store_regs(d, ®_info, hide_zero);
1488 : 0 : out:
1489 : 0 : free(reg_info.data);
1490 : 0 : free(reg_info.names);
1491 : :
1492 : 0 : return ret;
1493 : : }
1494 : :
1495 : : static int
1496 : 3 : eth_dev_handle_port_regs(const char *cmd __rte_unused,
1497 : : const char *params,
1498 : : struct rte_tel_data *d)
1499 : : {
1500 : 3 : const char *const valid_keys[] = { "filter", "hide_zero", NULL };
1501 : : struct rte_kvargs *kvlist = NULL;
1502 : : char *filter = NULL, *end_param;
1503 : : const char *filter_val;
1504 : 3 : bool hide_zero = false;
1505 : : uint16_t port_id;
1506 : : int ret;
1507 : :
1508 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1509 [ + + ]: 3 : if (ret != 0)
1510 : : return ret;
1511 : :
1512 [ - + ]: 1 : if (*end_param != '\0') {
1513 : 0 : kvlist = rte_kvargs_parse(end_param, valid_keys);
1514 : 0 : filter_val = rte_kvargs_get(kvlist, "filter");
1515 : 0 : ret = rte_kvargs_process(kvlist, "hide_zero", eth_dev_parse_hide_zero, &hide_zero);
1516 [ # # # # : 0 : if (kvlist == NULL || (filter_val != NULL && strlen(filter_val) == 0) || ret != 0) {
# # # # ]
1517 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
1518 : : "Unknown extra parameters passed to ethdev telemetry command, ignoring");
1519 : : } else {
1520 [ # # ]: 0 : filter = (filter_val != NULL) ? strdup(filter_val) : NULL;
1521 : 0 : hide_zero = false;
1522 : : }
1523 : 0 : rte_kvargs_free(kvlist);
1524 : : }
1525 : :
1526 : 1 : ret = eth_dev_get_port_regs(port_id, d, filter, hide_zero);
1527 : 1 : free(filter);
1528 : :
1529 : 1 : return ret;
1530 : : }
1531 : :
1532 : 54 : static int eth_dev_telemetry_do(const char *cmd, const char *params, void *arg,
1533 : : struct rte_tel_data *d)
1534 : : {
1535 : 54 : telemetry_cb fn = arg;
1536 : : int ret;
1537 : :
1538 : : /* Protect against port removal while invoking callback, calling ethdev API. */
1539 : 54 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
1540 : 54 : ret = fn(cmd, params, d);
1541 : 54 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
1542 : :
1543 : 54 : return ret;
1544 : : }
1545 : :
1546 : 254 : RTE_INIT(ethdev_init_telemetry)
1547 : : {
1548 : 254 : rte_telemetry_register_cmd_arg("/ethdev/list",
1549 : : eth_dev_telemetry_do, eth_dev_handle_port_list,
1550 : : "Returns list of available ethdev ports. Takes no parameters");
1551 : 254 : rte_telemetry_register_cmd_arg("/ethdev/stats",
1552 : : eth_dev_telemetry_do, eth_dev_handle_port_stats,
1553 : : "Returns the common stats for a port. Parameters: int port_id");
1554 : 254 : rte_telemetry_register_cmd_arg("/ethdev/xstats",
1555 : : eth_dev_telemetry_do, eth_dev_handle_port_xstats,
1556 : : "Returns the extended stats for a port. Parameters: int port_id,hide_zero=true|false(Optional for indicates hide zero xstats)");
1557 : : #ifndef RTE_EXEC_ENV_WINDOWS
1558 : 254 : rte_telemetry_register_cmd_arg("/ethdev/dump_priv",
1559 : : eth_dev_telemetry_do, eth_dev_handle_port_dump_priv,
1560 : : "Returns dump private information for a port. Parameters: int port_id");
1561 : : #endif
1562 : 254 : rte_telemetry_register_cmd_arg("/ethdev/link_status",
1563 : : eth_dev_telemetry_do, eth_dev_handle_port_link_status,
1564 : : "Returns the link status for a port. Parameters: int port_id");
1565 : 254 : rte_telemetry_register_cmd_arg("/ethdev/info",
1566 : : eth_dev_telemetry_do, eth_dev_handle_port_info,
1567 : : "Returns the device info for a port. Parameters: int port_id");
1568 : 254 : rte_telemetry_register_cmd_arg("/ethdev/module_eeprom",
1569 : : eth_dev_telemetry_do, eth_dev_handle_port_module_eeprom,
1570 : : "Returns module EEPROM info with SFF specs. Parameters: int port_id");
1571 : 254 : rte_telemetry_register_cmd_arg("/ethdev/macs",
1572 : : eth_dev_telemetry_do, eth_dev_handle_port_macs,
1573 : : "Returns the MAC addresses for a port. Parameters: int port_id");
1574 : 254 : rte_telemetry_register_cmd_arg("/ethdev/flow_ctrl",
1575 : : eth_dev_telemetry_do, eth_dev_handle_port_flow_ctrl,
1576 : : "Returns flow ctrl info for a port. Parameters: int port_id");
1577 : 254 : rte_telemetry_register_cmd_arg("/ethdev/rx_queue",
1578 : : eth_dev_telemetry_do, eth_dev_handle_port_rxq,
1579 : : "Returns Rx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
1580 : 254 : rte_telemetry_register_cmd_arg("/ethdev/tx_queue",
1581 : : eth_dev_telemetry_do, eth_dev_handle_port_txq,
1582 : : "Returns Tx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
1583 : 254 : rte_telemetry_register_cmd_arg("/ethdev/dcb",
1584 : : eth_dev_telemetry_do, eth_dev_handle_port_dcb,
1585 : : "Returns DCB info for a port. Parameters: int port_id");
1586 : 254 : rte_telemetry_register_cmd_arg("/ethdev/rss_info",
1587 : : eth_dev_telemetry_do, eth_dev_handle_port_rss_info,
1588 : : "Returns RSS info for a port. Parameters: int port_id");
1589 : 254 : rte_telemetry_register_cmd_arg("/ethdev/fec",
1590 : : eth_dev_telemetry_do, eth_dev_handle_port_fec,
1591 : : "Returns FEC info for a port. Parameters: int port_id");
1592 : 254 : rte_telemetry_register_cmd_arg("/ethdev/vlan",
1593 : : eth_dev_telemetry_do, eth_dev_handle_port_vlan,
1594 : : "Returns VLAN info for a port. Parameters: int port_id");
1595 : 254 : rte_telemetry_register_cmd_arg("/ethdev/tm_capability",
1596 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_caps,
1597 : : "Returns TM Capabilities info for a port. Parameters: int port_id");
1598 : 254 : rte_telemetry_register_cmd_arg("/ethdev/tm_level_capability",
1599 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_level_caps,
1600 : : "Returns TM Level Capabilities info for a port. Parameters: int port_id, int level_id (see tm_capability for the max)");
1601 : 254 : rte_telemetry_register_cmd_arg("/ethdev/tm_node_capability",
1602 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_node_caps,
1603 : : "Returns TM Node Capabilities info for a port. Parameters: int port_id, int node_id (see tm_capability for the max)");
1604 : 254 : rte_telemetry_register_cmd("/ethdev/regs", eth_dev_handle_port_regs,
1605 : : "Returns registers info for a port. Parameters: int port_id,filter=xxx(Optional if show all),hide_zero=true|false(Optional)");
1606 : 254 : }
|