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 : :
730 : 1 : free_rss_key:
731 : 1 : free(rss_key);
732 : :
733 : 1 : return ret;
734 : : }
735 : :
736 : : static int
737 : 3 : eth_dev_handle_port_rss_info(const char *cmd __rte_unused,
738 : : const char *params,
739 : : struct rte_tel_data *d)
740 : : {
741 : : struct rte_eth_dev_info dev_info;
742 : : struct rte_eth_rss_conf rss_conf;
743 : : uint8_t key_len;
744 : : uint16_t port_id;
745 : : char *end_param;
746 : : int ret;
747 : :
748 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
749 [ + + ]: 3 : if (ret < 0)
750 : : return ret;
751 : :
752 : 1 : ret = rte_eth_dev_info_get(port_id, &dev_info);
753 [ - + ]: 1 : if (ret != 0) {
754 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
755 : : "Failed to get device info, ret = %d", ret);
756 : 0 : return ret;
757 : : }
758 : :
759 [ + - ]: 1 : key_len = dev_info.hash_key_size ? dev_info.hash_key_size : 40;
760 : 1 : rss_conf.rss_key_len = key_len;
761 : 1 : rss_conf.rss_key = malloc(key_len);
762 [ + - ]: 1 : if (rss_conf.rss_key == NULL)
763 : : return -ENOMEM;
764 : :
765 : 1 : ret = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
766 [ - + ]: 1 : if (ret != 0) {
767 : 0 : free(rss_conf.rss_key);
768 : 0 : return ret;
769 : : }
770 : :
771 : 1 : ret = eth_dev_add_rss_info(&rss_conf, d);
772 : 1 : free(rss_conf.rss_key);
773 : 1 : return ret;
774 : : }
775 : :
776 : : static const char *
777 : : eth_dev_fec_capa_to_string(uint32_t fec_capa)
778 : : {
779 : : uint32_t i;
780 : :
781 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
782 [ # # ]: 0 : if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0)
783 : 0 : return rte_eth_fec_capa_name[i].name;
784 : : }
785 : :
786 : : return "unknown";
787 : : }
788 : :
789 : : static void
790 : 0 : eth_dev_fec_capas_to_string(uint32_t fec_capa, char *fec_name, uint32_t len)
791 : : {
792 : : bool valid = false;
793 : : size_t count = 0;
794 : : uint32_t i;
795 : :
796 [ # # ]: 0 : for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
797 [ # # ]: 0 : if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0) {
798 : 0 : strlcat(fec_name, rte_eth_fec_capa_name[i].name, len);
799 : 0 : count = strlcat(fec_name, " ", len);
800 : : valid = true;
801 : : }
802 : : }
803 : :
804 [ # # ]: 0 : if (!valid)
805 : 0 : count = snprintf(fec_name, len, "unknown ");
806 : :
807 [ # # ]: 0 : if (count >= len) {
808 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "FEC capa names may be truncated");
809 : : count = len;
810 : : }
811 : :
812 : 0 : fec_name[count - 1] = '\0';
813 : 0 : }
814 : :
815 : : static int
816 : 0 : eth_dev_get_fec_capability(uint16_t port_id, struct rte_tel_data *d)
817 : : {
818 : : struct rte_eth_fec_capa *speed_fec_capa;
819 : : char fec_name[RTE_TEL_MAX_STRING_LEN];
820 : : char speed[RTE_TEL_MAX_STRING_LEN];
821 : : uint32_t capa_num;
822 : : uint32_t i, j;
823 : : int ret;
824 : :
825 : 0 : ret = rte_eth_fec_get_capability(port_id, NULL, 0);
826 [ # # ]: 0 : if (ret <= 0)
827 [ # # ]: 0 : return ret == 0 ? -EINVAL : ret;
828 : :
829 : 0 : capa_num = ret;
830 : 0 : speed_fec_capa = calloc(capa_num, sizeof(struct rte_eth_fec_capa));
831 [ # # ]: 0 : if (speed_fec_capa == NULL)
832 : : return -ENOMEM;
833 : :
834 : 0 : ret = rte_eth_fec_get_capability(port_id, speed_fec_capa, capa_num);
835 [ # # ]: 0 : if (ret <= 0) {
836 [ # # ]: 0 : ret = ret == 0 ? -EINVAL : ret;
837 : 0 : goto out;
838 : : }
839 : :
840 [ # # ]: 0 : for (i = 0; i < capa_num; i++) {
841 : : memset(fec_name, 0, RTE_TEL_MAX_STRING_LEN);
842 : 0 : eth_dev_fec_capas_to_string(speed_fec_capa[i].capa, fec_name,
843 : : RTE_TEL_MAX_STRING_LEN);
844 : :
845 : : memset(speed, 0, RTE_TEL_MAX_STRING_LEN);
846 : 0 : ret = snprintf(speed, RTE_TEL_MAX_STRING_LEN, "%s",
847 : : rte_eth_link_speed_to_str(speed_fec_capa[i].speed));
848 [ # # ]: 0 : if (ret < 0)
849 : 0 : goto out;
850 : :
851 [ # # ]: 0 : for (j = 0; j < strlen(speed); j++) {
852 [ # # ]: 0 : if (speed[j] == ' ')
853 : 0 : speed[j] = '_';
854 : : }
855 : :
856 : 0 : rte_tel_data_add_dict_string(d, speed, fec_name);
857 : : }
858 : :
859 : 0 : out:
860 : 0 : free(speed_fec_capa);
861 : 0 : return ret > 0 ? 0 : ret;
862 : : }
863 : :
864 : : static int
865 : 3 : eth_dev_handle_port_fec(const char *cmd __rte_unused,
866 : : const char *params,
867 : : struct rte_tel_data *d)
868 : : {
869 : : struct rte_tel_data *fec_capas;
870 : : uint32_t fec_mode;
871 : : uint16_t port_id;
872 : : char *end_param;
873 : : int ret;
874 : :
875 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
876 [ + + ]: 3 : if (ret < 0)
877 : : return ret;
878 : :
879 : 1 : ret = rte_eth_fec_get(port_id, &fec_mode);
880 [ - + ]: 1 : if (ret != 0)
881 : : return ret;
882 : :
883 : 0 : rte_tel_data_start_dict(d);
884 : 0 : rte_tel_data_add_dict_string(d, "fec_mode",
885 : : eth_dev_fec_capa_to_string(fec_mode));
886 : :
887 : 0 : fec_capas = rte_tel_data_alloc();
888 [ # # ]: 0 : if (fec_capas == NULL)
889 : : return -ENOMEM;
890 : :
891 : 0 : rte_tel_data_start_dict(fec_capas);
892 : 0 : ret = eth_dev_get_fec_capability(port_id, fec_capas);
893 [ # # ]: 0 : if (ret != 0) {
894 : 0 : rte_tel_data_free(fec_capas);
895 : 0 : return ret;
896 : : }
897 : :
898 : 0 : rte_tel_data_add_dict_container(d, "fec_capability", fec_capas, 0);
899 : 0 : return 0;
900 : : }
901 : :
902 : : static int
903 : 1 : eth_dev_add_vlan_id(int port_id, struct rte_tel_data *d)
904 : : {
905 : 1 : struct rte_tel_data *vlan_blks[64] = {NULL};
906 : : uint16_t vlan_num, vidx, vbit, num_blks;
907 : : char blk_name[RTE_TEL_MAX_STRING_LEN];
908 : : struct rte_vlan_filter_conf *vfc;
909 : : struct rte_tel_data *vlan_blk;
910 : : struct rte_tel_data *vd;
911 : : uint64_t bit_width;
912 : : uint64_t vlan_id;
913 : :
914 : 1 : vd = rte_tel_data_alloc();
915 [ + - ]: 1 : if (vd == NULL)
916 : : return -ENOMEM;
917 : :
918 : 1 : vfc = &rte_eth_devices[port_id].data->vlan_filter_conf;
919 : : bit_width = CHAR_BIT * sizeof(uint64_t);
920 : : vlan_num = 0;
921 : : num_blks = 0;
922 : :
923 : 1 : rte_tel_data_start_dict(vd);
924 [ + + ]: 65 : for (vidx = 0; vidx < RTE_DIM(vfc->ids); vidx++) {
925 [ + - ]: 64 : if (vfc->ids[vidx] == 0)
926 : 64 : continue;
927 : :
928 : 0 : vlan_blk = rte_tel_data_alloc();
929 [ # # ]: 0 : if (vlan_blk == NULL)
930 : 0 : goto free_all;
931 : :
932 : 0 : vlan_blks[num_blks] = vlan_blk;
933 : 0 : num_blks++;
934 : 0 : snprintf(blk_name, RTE_TEL_MAX_STRING_LEN, "vlan_%"PRIu64"_to_%"PRIu64"",
935 : 0 : bit_width * vidx, bit_width * (vidx + 1) - 1);
936 : 0 : rte_tel_data_start_array(vlan_blk, RTE_TEL_UINT_VAL);
937 : 0 : rte_tel_data_add_dict_container(vd, blk_name, vlan_blk, 0);
938 : :
939 [ # # ]: 0 : for (vbit = 0; vbit < bit_width; vbit++) {
940 [ # # ]: 0 : if ((vfc->ids[vidx] & RTE_BIT64(vbit)) == 0)
941 : 0 : continue;
942 : :
943 : 0 : vlan_id = bit_width * vidx + vbit;
944 : 0 : rte_tel_data_add_array_uint(vlan_blk, vlan_id);
945 : 0 : vlan_num++;
946 : : }
947 : : }
948 : :
949 : 1 : rte_tel_data_add_dict_uint(d, "vlan_num", vlan_num);
950 : 1 : rte_tel_data_add_dict_container(d, "vlan_ids", vd, 0);
951 : :
952 : 1 : return 0;
953 : :
954 : : free_all:
955 [ # # ]: 0 : while (num_blks-- > 0)
956 : 0 : rte_tel_data_free(vlan_blks[num_blks]);
957 : :
958 : 0 : rte_tel_data_free(vd);
959 : 0 : return -ENOMEM;
960 : : }
961 : :
962 : : static int
963 : 3 : eth_dev_handle_port_vlan(const char *cmd __rte_unused,
964 : : const char *params,
965 : : struct rte_tel_data *d)
966 : : {
967 : : struct rte_eth_txmode *txmode;
968 : : struct rte_eth_conf dev_conf;
969 : : uint16_t port_id;
970 : : int offload, ret;
971 : : char *end_param;
972 : :
973 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
974 [ + + ]: 3 : if (ret < 0)
975 : : return ret;
976 : :
977 : 1 : ret = rte_eth_dev_conf_get(port_id, &dev_conf);
978 [ - + ]: 1 : if (ret != 0) {
979 : 0 : RTE_ETHDEV_LOG_LINE(ERR,
980 : : "Failed to get device configuration, ret = %d", ret);
981 : 0 : return ret;
982 : : }
983 : :
984 : : txmode = &dev_conf.txmode;
985 : 1 : rte_tel_data_start_dict(d);
986 : 1 : rte_tel_data_add_dict_uint(d, "pvid", txmode->pvid);
987 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_reject_tagged",
988 : 1 : txmode->hw_vlan_reject_tagged);
989 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_reject_untagged",
990 : 1 : txmode->hw_vlan_reject_untagged);
991 : 1 : rte_tel_data_add_dict_uint(d, "hw_vlan_insert_pvid",
992 : 1 : txmode->hw_vlan_insert_pvid);
993 : :
994 : 1 : offload = rte_eth_dev_get_vlan_offload(port_id);
995 : 1 : rte_tel_data_add_dict_string(d, "VLAN_STRIP",
996 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_STRIP_OFFLOAD) != 0) ? "on" : "off");
997 : 1 : rte_tel_data_add_dict_string(d, "VLAN_EXTEND",
998 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_EXTEND_OFFLOAD) != 0) ? "on" : "off");
999 : 1 : rte_tel_data_add_dict_string(d, "QINQ_STRIP",
1000 [ + - ]: 1 : ((offload & RTE_ETH_QINQ_STRIP_OFFLOAD) != 0) ? "on" : "off");
1001 : 1 : rte_tel_data_add_dict_string(d, "VLAN_FILTER",
1002 [ + - ]: 1 : ((offload & RTE_ETH_VLAN_FILTER_OFFLOAD) != 0) ? "on" : "off");
1003 : :
1004 : 1 : return eth_dev_add_vlan_id(port_id, d);
1005 : : }
1006 : :
1007 : : static void
1008 : 0 : eth_dev_add_tm_caps(struct rte_tel_data *d, struct rte_tm_capabilities *cap)
1009 : : {
1010 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1011 : 0 : rte_tel_data_add_dict_uint(d, "n_levels_max", cap->n_levels_max);
1012 : 0 : rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1013 : 0 : cap->non_leaf_nodes_identical);
1014 : 0 : rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1015 : 0 : cap->leaf_nodes_identical);
1016 : 0 : rte_tel_data_add_dict_uint(d, "shaper_n_max", cap->shaper_n_max);
1017 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_n_max",
1018 : 0 : cap->shaper_private_n_max);
1019 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_dual_rate_n_max",
1020 : 0 : cap->shaper_private_dual_rate_n_max);
1021 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_rate_min",
1022 : : cap->shaper_private_rate_min);
1023 : 0 : rte_tel_data_add_dict_uint(d, "shaper_private_rate_max",
1024 : : cap->shaper_private_rate_max);
1025 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_packet_mode_supported",
1026 : 0 : cap->shaper_private_packet_mode_supported);
1027 : 0 : rte_tel_data_add_dict_int(d, "shaper_private_byte_mode_supported",
1028 : 0 : cap->shaper_private_byte_mode_supported);
1029 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_max",
1030 : 0 : cap->shaper_shared_n_max);
1031 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_nodes_per_shaper_max",
1032 : 0 : cap->shaper_shared_n_nodes_per_shaper_max);
1033 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_n_shapers_per_node_max",
1034 : 0 : cap->shaper_shared_n_shapers_per_node_max);
1035 : 0 : rte_tel_data_add_dict_uint(d, "shaper_share_dual_rate_n_max",
1036 : 0 : cap->shaper_shared_dual_rate_n_max);
1037 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_rate_min",
1038 : : cap->shaper_shared_rate_min);
1039 : 0 : rte_tel_data_add_dict_uint(d, "shaper_shared_rate_max",
1040 : : cap->shaper_shared_rate_max);
1041 : 0 : rte_tel_data_add_dict_int(d, "shaper_shared_packet_mode_supported",
1042 : 0 : cap->shaper_shared_packet_mode_supported);
1043 : 0 : rte_tel_data_add_dict_int(d, "shaper_shared_byte_mode_supported",
1044 : 0 : cap->shaper_shared_byte_mode_supported);
1045 : 0 : rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_min",
1046 : 0 : cap->shaper_pkt_length_adjust_min);
1047 : 0 : rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_max",
1048 : 0 : cap->shaper_pkt_length_adjust_max);
1049 : 0 : rte_tel_data_add_dict_uint(d, "sched_n_children_max",
1050 : 0 : cap->sched_n_children_max);
1051 : 0 : rte_tel_data_add_dict_uint(d, "sched_sp_n_priorities_max",
1052 : 0 : cap->sched_sp_n_priorities_max);
1053 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1054 : 0 : cap->sched_wfq_n_children_per_group_max);
1055 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1056 : 0 : cap->sched_wfq_n_groups_max);
1057 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1058 : 0 : cap->sched_wfq_weight_max);
1059 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1060 : 0 : cap->sched_wfq_packet_mode_supported);
1061 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1062 : 0 : cap->sched_wfq_byte_mode_supported);
1063 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1064 : 0 : cap->cman_wred_packet_mode_supported);
1065 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1066 : 0 : cap->cman_wred_byte_mode_supported);
1067 : 0 : rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1068 : 0 : cap->cman_head_drop_supported);
1069 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_n_max",
1070 : 0 : cap->cman_wred_context_n_max);
1071 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_private_n_max",
1072 : 0 : cap->cman_wred_context_private_n_max);
1073 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1074 : 0 : cap->cman_wred_context_shared_n_max);
1075 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_nodes_per_context_max",
1076 : 0 : cap->cman_wred_context_shared_n_nodes_per_context_max);
1077 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_contexts_per_node_max",
1078 : 0 : cap->cman_wred_context_shared_n_contexts_per_node_max);
1079 : 0 : rte_tel_data_add_dict_uint_hex(d, "dynamic_update", cap->dynamic_update_mask, 0);
1080 : 0 : rte_tel_data_add_dict_uint_hex(d, "stats_mask", cap->stats_mask, 0);
1081 : 0 : }
1082 : :
1083 : : static int
1084 : 3 : eth_dev_handle_port_tm_caps(const char *cmd __rte_unused,
1085 : : const char *params,
1086 : : struct rte_tel_data *d)
1087 : : {
1088 : 3 : struct rte_tm_capabilities cap = {0};
1089 : 3 : struct rte_tm_error error = {0};
1090 : : uint16_t port_id;
1091 : : char *end_param;
1092 : : int ret;
1093 : :
1094 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
1095 [ + + ]: 3 : if (ret != 0)
1096 : : return ret;
1097 : :
1098 : 1 : ret = rte_tm_capabilities_get(port_id, &cap, &error);
1099 [ + - ]: 1 : if (ret != 0) {
1100 [ + - ]: 2 : RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1101 : : error.message ? error.message : "no stated reason",
1102 : : error.type);
1103 : 1 : return ret;
1104 : : }
1105 : :
1106 : 0 : rte_tel_data_start_dict(d);
1107 : 0 : eth_dev_add_tm_caps(d, &cap);
1108 : :
1109 : 0 : return 0;
1110 : : }
1111 : :
1112 : : static void
1113 : 0 : eth_dev_add_tm_level_basic_caps(struct rte_tel_data *d,
1114 : : struct rte_tm_level_capabilities *cap)
1115 : : {
1116 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1117 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_nonleaf_max",
1118 : 0 : cap->n_nodes_nonleaf_max);
1119 : 0 : rte_tel_data_add_dict_uint(d, "n_nodes_leaf_max", cap->n_nodes_leaf_max);
1120 : 0 : rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1121 : 0 : cap->non_leaf_nodes_identical);
1122 : 0 : rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1123 : 0 : cap->leaf_nodes_identical);
1124 : 0 : }
1125 : :
1126 : : static void
1127 : 0 : eth_dev_add_tm_level_nonleaf_caps(struct rte_tel_data *nonleaf,
1128 : : struct rte_tm_level_capabilities *cap)
1129 : : {
1130 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_supported",
1131 : 0 : cap->nonleaf.shaper_private_supported);
1132 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_dual_rate_supported",
1133 : 0 : cap->nonleaf.shaper_private_dual_rate_supported);
1134 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_min",
1135 : : cap->nonleaf.shaper_private_rate_min);
1136 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_max",
1137 : : cap->nonleaf.shaper_private_rate_max);
1138 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_packet_mode_supported",
1139 : 0 : cap->nonleaf.shaper_private_packet_mode_supported);
1140 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_private_byte_mode_supported",
1141 : 0 : cap->nonleaf.shaper_private_byte_mode_supported);
1142 : 0 : rte_tel_data_add_dict_uint(nonleaf, "shaper_shared_n_max",
1143 : 0 : cap->nonleaf.shaper_shared_n_max);
1144 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_shared_packet_mode_supported",
1145 : 0 : cap->nonleaf.shaper_shared_packet_mode_supported);
1146 : 0 : rte_tel_data_add_dict_int(nonleaf, "shaper_shared_byte_mode_supported",
1147 : 0 : cap->nonleaf.shaper_shared_byte_mode_supported);
1148 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_n_children_max",
1149 : 0 : cap->nonleaf.sched_n_children_max);
1150 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_sp_n_priorities_max",
1151 : 0 : cap->nonleaf.sched_sp_n_priorities_max);
1152 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_children_per_group_max",
1153 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max);
1154 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_groups_max",
1155 : 0 : cap->nonleaf.sched_wfq_n_groups_max);
1156 : 0 : rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_weight_max",
1157 : 0 : cap->nonleaf.sched_wfq_weight_max);
1158 : 0 : rte_tel_data_add_dict_int(nonleaf, "sched_wfq_packet_mode_supported",
1159 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported);
1160 : 0 : rte_tel_data_add_dict_int(nonleaf, "sched_wfq_byte_mode_supported",
1161 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported);
1162 : 0 : rte_tel_data_add_dict_uint_hex(nonleaf, "stats_mask",
1163 : : cap->nonleaf.stats_mask, 0);
1164 : 0 : }
1165 : :
1166 : : static void
1167 : 0 : eth_dev_add_tm_level_leaf_caps(struct rte_tel_data *leaf,
1168 : : struct rte_tm_level_capabilities *cap)
1169 : : {
1170 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_supported",
1171 : 0 : cap->leaf.shaper_private_supported);
1172 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_dual_rate_supported",
1173 : 0 : cap->leaf.shaper_private_dual_rate_supported);
1174 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_min",
1175 : : cap->leaf.shaper_private_rate_min);
1176 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_max",
1177 : : cap->leaf.shaper_private_rate_max);
1178 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_packet_mode_supported",
1179 : 0 : cap->leaf.shaper_private_packet_mode_supported);
1180 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_private_byte_mode_supported",
1181 : 0 : cap->leaf.shaper_private_byte_mode_supported);
1182 : 0 : rte_tel_data_add_dict_uint(leaf, "shaper_shared_n_max",
1183 : 0 : cap->leaf.shaper_shared_n_max);
1184 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_shared_packet_mode_supported",
1185 : 0 : cap->leaf.shaper_shared_packet_mode_supported);
1186 : 0 : rte_tel_data_add_dict_int(leaf, "shaper_shared_byte_mode_supported",
1187 : 0 : cap->leaf.shaper_shared_byte_mode_supported);
1188 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_packet_mode_supported",
1189 : 0 : cap->leaf.cman_wred_packet_mode_supported);
1190 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_byte_mode_supported",
1191 : 0 : cap->leaf.cman_wred_byte_mode_supported);
1192 : 0 : rte_tel_data_add_dict_int(leaf, "cman_head_drop_supported",
1193 : 0 : cap->leaf.cman_head_drop_supported);
1194 : 0 : rte_tel_data_add_dict_int(leaf, "cman_wred_context_private_supported",
1195 : 0 : cap->leaf.cman_wred_context_private_supported);
1196 : 0 : rte_tel_data_add_dict_uint(leaf, "cman_wred_context_shared_n_max",
1197 : 0 : cap->leaf.cman_wred_context_shared_n_max);
1198 : 0 : rte_tel_data_add_dict_uint_hex(leaf, "stats_mask",
1199 : : cap->leaf.stats_mask, 0);
1200 : 0 : }
1201 : :
1202 : : static int
1203 : 2 : eth_dev_parse_tm_params(char *params, uint32_t *result)
1204 : : {
1205 : : const char *splited_param;
1206 : : uint64_t ret;
1207 : :
1208 : 2 : splited_param = strtok(params, ",");
1209 [ - + - - : 2 : if (!splited_param || strlen(splited_param) == 0 || !isdigit(*splited_param))
- - ]
1210 : : return -EINVAL;
1211 : :
1212 : 0 : ret = strtoul(splited_param, ¶ms, 0);
1213 [ # # ]: 0 : if (*params != '\0')
1214 : 0 : RTE_ETHDEV_LOG_LINE(NOTICE,
1215 : : "Extra parameters passed to ethdev telemetry command, ignoring");
1216 : :
1217 [ # # ]: 0 : if (ret >= UINT32_MAX)
1218 : : return -EINVAL;
1219 : :
1220 : 0 : *result = ret;
1221 : 0 : return 0;
1222 : : }
1223 : :
1224 : : static int
1225 : 3 : eth_dev_handle_port_tm_level_caps(const char *cmd __rte_unused,
1226 : : const char *params,
1227 : : struct rte_tel_data *d)
1228 : : {
1229 : 3 : struct rte_tm_level_capabilities cap = {0};
1230 : 3 : struct rte_tm_error error = {0};
1231 : : struct rte_tel_data *nonleaf;
1232 : : struct rte_tel_data *leaf;
1233 : : uint32_t level_id;
1234 : : uint16_t port_id;
1235 : : char *end_param;
1236 : : int ret;
1237 : :
1238 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1239 [ + + ]: 3 : if (ret != 0)
1240 : : return ret;
1241 : :
1242 : 1 : ret = eth_dev_parse_tm_params(end_param, &level_id);
1243 [ - + ]: 1 : if (ret != 0)
1244 : : return ret;
1245 : :
1246 : 0 : ret = rte_tm_level_capabilities_get(port_id, level_id, &cap, &error);
1247 [ # # ]: 0 : if (ret != 0) {
1248 [ # # ]: 0 : RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1249 : : error.message ? error.message : "no stated reason",
1250 : : error.type);
1251 : 0 : return ret;
1252 : : }
1253 : :
1254 : 0 : rte_tel_data_start_dict(d);
1255 : 0 : eth_dev_add_tm_level_basic_caps(d, &cap);
1256 : :
1257 : 0 : nonleaf = rte_tel_data_alloc();
1258 [ # # ]: 0 : if (nonleaf == NULL)
1259 : : return -ENOMEM;
1260 : :
1261 : 0 : rte_tel_data_start_dict(nonleaf);
1262 : 0 : eth_dev_add_tm_level_nonleaf_caps(nonleaf, &cap);
1263 : 0 : rte_tel_data_add_dict_container(d, "nonleaf_cap", nonleaf, 0);
1264 : :
1265 : 0 : leaf = rte_tel_data_alloc();
1266 [ # # ]: 0 : if (leaf == NULL) {
1267 : 0 : rte_tel_data_free(nonleaf);
1268 : 0 : return -ENOMEM;
1269 : : }
1270 : :
1271 : 0 : rte_tel_data_start_dict(leaf);
1272 : 0 : eth_dev_add_tm_level_leaf_caps(leaf, &cap);
1273 : 0 : rte_tel_data_add_dict_container(d, "leaf_cap", leaf, 0);
1274 : :
1275 : 0 : return 0;
1276 : : }
1277 : :
1278 : : static void
1279 : 0 : eth_dev_add_tm_node_basic_caps(struct rte_tel_data *node_data,
1280 : : struct rte_tm_node_capabilities *capnode)
1281 : : {
1282 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_supported",
1283 : 0 : capnode->shaper_private_supported);
1284 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_dual_rate_supported",
1285 : 0 : capnode->shaper_private_dual_rate_supported);
1286 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_min",
1287 : : capnode->shaper_private_rate_min);
1288 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_max",
1289 : : capnode->shaper_private_rate_max);
1290 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_packet_mode_supported",
1291 : 0 : capnode->shaper_private_packet_mode_supported);
1292 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_private_byte_mode_supported",
1293 : 0 : capnode->shaper_private_byte_mode_supported);
1294 : 0 : rte_tel_data_add_dict_uint(node_data, "shaper_shared_n_max",
1295 : 0 : capnode->shaper_shared_n_max);
1296 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_shared_packet_mode_supported",
1297 : 0 : capnode->shaper_shared_packet_mode_supported);
1298 : 0 : rte_tel_data_add_dict_int(node_data, "shaper_shared_byte_mode_supported",
1299 : 0 : capnode->shaper_shared_byte_mode_supported);
1300 : 0 : rte_tel_data_add_dict_uint_hex(node_data, "stats_mask",
1301 : : capnode->stats_mask, 0);
1302 : 0 : }
1303 : :
1304 : : static void
1305 : 0 : eth_dev_add_tm_type_node_caps(struct rte_tel_data *d, int is_leaf,
1306 : : struct rte_tm_node_capabilities *cap)
1307 : : {
1308 [ # # ]: 0 : rte_tel_data_add_dict_string(d, "node_type",
1309 : : is_leaf == 0 ? "nonleaf" : "leaf");
1310 [ # # ]: 0 : if (is_leaf == 0) {
1311 : 0 : rte_tel_data_add_dict_uint(d, "children_max",
1312 : 0 : cap->nonleaf.sched_n_children_max);
1313 : 0 : rte_tel_data_add_dict_uint(d, "priorities_max",
1314 : 0 : cap->nonleaf.sched_sp_n_priorities_max);
1315 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1316 : 0 : cap->nonleaf.sched_wfq_n_children_per_group_max);
1317 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1318 : 0 : cap->nonleaf.sched_wfq_n_groups_max);
1319 : 0 : rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1320 : 0 : cap->nonleaf.sched_wfq_weight_max);
1321 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1322 : 0 : cap->nonleaf.sched_wfq_packet_mode_supported);
1323 : 0 : rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1324 : 0 : cap->nonleaf.sched_wfq_byte_mode_supported);
1325 : : } else {
1326 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1327 : 0 : cap->leaf.cman_wred_packet_mode_supported);
1328 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1329 : 0 : cap->leaf.cman_wred_byte_mode_supported);
1330 : 0 : rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1331 : 0 : cap->leaf.cman_head_drop_supported);
1332 : 0 : rte_tel_data_add_dict_int(d, "cman_wred_context_private_supported",
1333 : 0 : cap->leaf.cman_wred_context_private_supported);
1334 : 0 : rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1335 : 0 : cap->leaf.cman_wred_context_shared_n_max);
1336 : : }
1337 : 0 : }
1338 : :
1339 : : static int
1340 : 3 : eth_dev_handle_port_tm_node_caps(const char *cmd __rte_unused,
1341 : : const char *params,
1342 : : struct rte_tel_data *d)
1343 : : {
1344 : 3 : struct rte_tm_node_capabilities cap = {0};
1345 : 3 : struct rte_tm_error error = {0};
1346 : : uint32_t node_id;
1347 : : uint16_t port_id;
1348 : : char *end_param;
1349 : : int is_leaf;
1350 : : int ret;
1351 : :
1352 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1353 [ + + ]: 3 : if (ret != 0)
1354 : : return ret;
1355 : :
1356 : 1 : ret = eth_dev_parse_tm_params(end_param, &node_id);
1357 [ - + ]: 1 : if (ret != 0)
1358 : : return ret;
1359 : :
1360 : 0 : ret = rte_tm_node_capabilities_get(port_id, node_id, &cap, &error);
1361 [ # # ]: 0 : if (ret != 0)
1362 : 0 : goto out;
1363 : :
1364 : 0 : ret = rte_tm_node_type_get(port_id, node_id, &is_leaf, &error);
1365 [ # # ]: 0 : if (ret != 0)
1366 : 0 : goto out;
1367 : :
1368 : 0 : rte_tel_data_start_dict(d);
1369 : 0 : eth_dev_add_tm_node_basic_caps(d, &cap);
1370 : 0 : eth_dev_add_tm_type_node_caps(d, is_leaf, &cap);
1371 : :
1372 : 0 : return 0;
1373 : 0 : out:
1374 [ # # ]: 0 : RTE_ETHDEV_LOG_LINE(WARNING, "error: %s, error type: %u",
1375 : : error.message ? error.message : "no stated reason",
1376 : : error.type);
1377 : 0 : return ret;
1378 : : }
1379 : :
1380 : : static void
1381 : 0 : eth_dev_add_reg_data(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info,
1382 : : uint32_t idx)
1383 : : {
1384 [ # # ]: 0 : if (reg_info->width == sizeof(uint32_t))
1385 : 0 : rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name,
1386 : 0 : *((uint32_t *)reg_info->data + idx), 0);
1387 : : else
1388 : 0 : rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name,
1389 : 0 : *((uint64_t *)reg_info->data + idx), 0);
1390 : 0 : }
1391 : :
1392 : : static int
1393 : 0 : eth_dev_store_regs(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info)
1394 : : {
1395 : : struct rte_tel_data *groups[RTE_TEL_MAX_DICT_ENTRIES];
1396 : 0 : char group_name[RTE_TEL_MAX_STRING_LEN] = {0};
1397 : : struct rte_tel_data *group = NULL;
1398 : : uint32_t grp_num = 0;
1399 : : uint32_t i, max_cap;
1400 : : int ret;
1401 : :
1402 : 0 : rte_tel_data_start_dict(d);
1403 : 0 : rte_tel_data_add_dict_uint(d, "register_length", reg_info->length);
1404 : 0 : rte_tel_data_add_dict_uint(d, "register_width", reg_info->width);
1405 : 0 : rte_tel_data_add_dict_uint_hex(d, "register_offset", reg_info->offset, 0);
1406 : 0 : rte_tel_data_add_dict_uint_hex(d, "version", reg_info->version, 0);
1407 : :
1408 : : max_cap = (RTE_TEL_MAX_DICT_ENTRIES - 4) * RTE_TEL_MAX_DICT_ENTRIES;
1409 [ # # ]: 0 : if (reg_info->length > max_cap) {
1410 : 0 : RTE_ETHDEV_LOG_LINE(WARNING,
1411 : : "Registers to be displayed are reduced from %u to %u due to limited capacity",
1412 : : reg_info->length, max_cap);
1413 : 0 : reg_info->length = max_cap;
1414 : : }
1415 : :
1416 [ # # ]: 0 : for (i = 0; i < reg_info->length; i++) {
1417 [ # # ]: 0 : if (i % RTE_TEL_MAX_DICT_ENTRIES != 0) {
1418 : 0 : eth_dev_add_reg_data(group, reg_info, i);
1419 : 0 : continue;
1420 : : }
1421 : :
1422 : 0 : group = rte_tel_data_alloc();
1423 [ # # ]: 0 : if (group == NULL) {
1424 : : ret = -ENOMEM;
1425 : 0 : RTE_ETHDEV_LOG_LINE(WARNING, "No enough memory for group data");
1426 : 0 : goto out;
1427 : : }
1428 : 0 : groups[grp_num++] = group;
1429 : 0 : rte_tel_data_start_dict(group);
1430 : 0 : eth_dev_add_reg_data(group, reg_info, i);
1431 : : }
1432 : :
1433 [ # # ]: 0 : for (i = 0; i < grp_num; i++) {
1434 : : snprintf(group_name, RTE_TEL_MAX_STRING_LEN, "group_%u", i);
1435 : 0 : rte_tel_data_add_dict_container(d, group_name, groups[i], 0);
1436 : : }
1437 : : return 0;
1438 : : out:
1439 [ # # ]: 0 : for (i = 0; i < grp_num; i++)
1440 : 0 : rte_tel_data_free(groups[i]);
1441 : :
1442 : : return ret;
1443 : : }
1444 : :
1445 : : static int
1446 : 1 : eth_dev_get_port_regs(int port_id, struct rte_tel_data *d, char *filter)
1447 : : {
1448 : : struct rte_dev_reg_info reg_info;
1449 : : int ret;
1450 : :
1451 : : memset(®_info, 0, sizeof(reg_info));
1452 : 1 : reg_info.filter = filter;
1453 : :
1454 : 1 : ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
1455 [ + - ]: 1 : if (ret != 0) {
1456 : 1 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1457 : 1 : return ret;
1458 : : }
1459 : :
1460 : 0 : reg_info.data = calloc(reg_info.length, reg_info.width);
1461 [ # # ]: 0 : if (reg_info.data == NULL) {
1462 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.data");
1463 : 0 : return -ENOMEM;
1464 : : }
1465 : :
1466 : 0 : reg_info.names = calloc(reg_info.length, sizeof(struct rte_eth_reg_name));
1467 [ # # ]: 0 : if (reg_info.names == NULL) {
1468 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.names");
1469 : 0 : free(reg_info.data);
1470 : 0 : return -ENOMEM;
1471 : : }
1472 : :
1473 : 0 : ret = rte_eth_dev_get_reg_info_ext(port_id, ®_info);
1474 [ # # ]: 0 : if (ret != 0) {
1475 : 0 : RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1476 : : ret = -EINVAL;
1477 : 0 : goto out;
1478 : : }
1479 : :
1480 : 0 : ret = eth_dev_store_regs(d, ®_info);
1481 : 0 : out:
1482 : 0 : free(reg_info.data);
1483 : 0 : free(reg_info.names);
1484 : :
1485 : 0 : return ret;
1486 : : }
1487 : :
1488 : : static int
1489 : 3 : eth_dev_handle_port_regs(const char *cmd __rte_unused,
1490 : : const char *params,
1491 : : struct rte_tel_data *d)
1492 : : {
1493 : : char *filter, *end_param;
1494 : : uint16_t port_id;
1495 : : int ret;
1496 : :
1497 : 3 : ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1498 [ + + ]: 3 : if (ret != 0)
1499 : : return ret;
1500 : :
1501 : 1 : filter = strtok(end_param, ",");
1502 [ - + - - ]: 1 : if (filter != NULL && strlen(filter) == 0)
1503 : : filter = NULL;
1504 : :
1505 : 1 : return eth_dev_get_port_regs(port_id, d, filter);
1506 : : }
1507 : :
1508 : 54 : static int eth_dev_telemetry_do(const char *cmd, const char *params, void *arg,
1509 : : struct rte_tel_data *d)
1510 : : {
1511 : 54 : telemetry_cb fn = arg;
1512 : : int ret;
1513 : :
1514 : : /* Protect against port removal while invoking callback, calling ethdev API. */
1515 : 54 : rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
1516 : 54 : ret = fn(cmd, params, d);
1517 : 54 : rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
1518 : :
1519 : 54 : return ret;
1520 : : }
1521 : :
1522 : 253 : RTE_INIT(ethdev_init_telemetry)
1523 : : {
1524 : 253 : rte_telemetry_register_cmd_arg("/ethdev/list",
1525 : : eth_dev_telemetry_do, eth_dev_handle_port_list,
1526 : : "Returns list of available ethdev ports. Takes no parameters");
1527 : 253 : rte_telemetry_register_cmd_arg("/ethdev/stats",
1528 : : eth_dev_telemetry_do, eth_dev_handle_port_stats,
1529 : : "Returns the common stats for a port. Parameters: int port_id");
1530 : 253 : rte_telemetry_register_cmd_arg("/ethdev/xstats",
1531 : : eth_dev_telemetry_do, eth_dev_handle_port_xstats,
1532 : : "Returns the extended stats for a port. Parameters: int port_id,hide_zero=true|false(Optional for indicates hide zero xstats)");
1533 : : #ifndef RTE_EXEC_ENV_WINDOWS
1534 : 253 : rte_telemetry_register_cmd_arg("/ethdev/dump_priv",
1535 : : eth_dev_telemetry_do, eth_dev_handle_port_dump_priv,
1536 : : "Returns dump private information for a port. Parameters: int port_id");
1537 : : #endif
1538 : 253 : rte_telemetry_register_cmd_arg("/ethdev/link_status",
1539 : : eth_dev_telemetry_do, eth_dev_handle_port_link_status,
1540 : : "Returns the link status for a port. Parameters: int port_id");
1541 : 253 : rte_telemetry_register_cmd_arg("/ethdev/info",
1542 : : eth_dev_telemetry_do, eth_dev_handle_port_info,
1543 : : "Returns the device info for a port. Parameters: int port_id");
1544 : 253 : rte_telemetry_register_cmd_arg("/ethdev/module_eeprom",
1545 : : eth_dev_telemetry_do, eth_dev_handle_port_module_eeprom,
1546 : : "Returns module EEPROM info with SFF specs. Parameters: int port_id");
1547 : 253 : rte_telemetry_register_cmd_arg("/ethdev/macs",
1548 : : eth_dev_telemetry_do, eth_dev_handle_port_macs,
1549 : : "Returns the MAC addresses for a port. Parameters: int port_id");
1550 : 253 : rte_telemetry_register_cmd_arg("/ethdev/flow_ctrl",
1551 : : eth_dev_telemetry_do, eth_dev_handle_port_flow_ctrl,
1552 : : "Returns flow ctrl info for a port. Parameters: int port_id");
1553 : 253 : rte_telemetry_register_cmd_arg("/ethdev/rx_queue",
1554 : : eth_dev_telemetry_do, eth_dev_handle_port_rxq,
1555 : : "Returns Rx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
1556 : 253 : rte_telemetry_register_cmd_arg("/ethdev/tx_queue",
1557 : : eth_dev_telemetry_do, eth_dev_handle_port_txq,
1558 : : "Returns Tx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
1559 : 253 : rte_telemetry_register_cmd_arg("/ethdev/dcb",
1560 : : eth_dev_telemetry_do, eth_dev_handle_port_dcb,
1561 : : "Returns DCB info for a port. Parameters: int port_id");
1562 : 253 : rte_telemetry_register_cmd_arg("/ethdev/rss_info",
1563 : : eth_dev_telemetry_do, eth_dev_handle_port_rss_info,
1564 : : "Returns RSS info for a port. Parameters: int port_id");
1565 : 253 : rte_telemetry_register_cmd_arg("/ethdev/fec",
1566 : : eth_dev_telemetry_do, eth_dev_handle_port_fec,
1567 : : "Returns FEC info for a port. Parameters: int port_id");
1568 : 253 : rte_telemetry_register_cmd_arg("/ethdev/vlan",
1569 : : eth_dev_telemetry_do, eth_dev_handle_port_vlan,
1570 : : "Returns VLAN info for a port. Parameters: int port_id");
1571 : 253 : rte_telemetry_register_cmd_arg("/ethdev/tm_capability",
1572 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_caps,
1573 : : "Returns TM Capabilities info for a port. Parameters: int port_id");
1574 : 253 : rte_telemetry_register_cmd_arg("/ethdev/tm_level_capability",
1575 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_level_caps,
1576 : : "Returns TM Level Capabilities info for a port. Parameters: int port_id, int level_id (see tm_capability for the max)");
1577 : 253 : rte_telemetry_register_cmd_arg("/ethdev/tm_node_capability",
1578 : : eth_dev_telemetry_do, eth_dev_handle_port_tm_node_caps,
1579 : : "Returns TM Node Capabilities info for a port. Parameters: int port_id, int node_id (see tm_capability for the max)");
1580 : 253 : rte_telemetry_register_cmd("/ethdev/regs", eth_dev_handle_port_regs,
1581 : : "Returns all or filtered registers info for a port. Parameters: int port_id, string module_name (Optional if show all)");
1582 : 253 : }
|