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