xref: /dpdk/lib/ethdev/rte_ethdev_telemetry.c (revision d916d27e3dca9d2e19e411fff9208929a7c7cbdf)
14fe767acSJie Hai /* SPDX-License-Identifier: BSD-3-Clause
24fe767acSJie Hai  * Copyright(c) 2010-2017 Intel Corporation
34fe767acSJie Hai  */
44fe767acSJie Hai 
54fe767acSJie Hai #include <ctype.h>
64fe767acSJie Hai #include <stdlib.h>
74fe767acSJie Hai 
84fe767acSJie Hai #include <rte_kvargs.h>
94fe767acSJie Hai #include <rte_telemetry.h>
104fe767acSJie Hai 
114fe767acSJie Hai #include "rte_ethdev.h"
124fe767acSJie Hai #include "ethdev_driver.h"
134fe767acSJie Hai #include "sff_telemetry.h"
14a590d564SJie Hai #include "rte_tm.h"
154fe767acSJie Hai 
1685576ba6SJie Hai static const struct {
1785576ba6SJie Hai 	uint32_t capa;
1885576ba6SJie Hai 	const char *name;
1985576ba6SJie Hai } rte_eth_fec_capa_name[] = {
2085576ba6SJie Hai 	{ RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC),	"off"	},
2185576ba6SJie Hai 	{ RTE_ETH_FEC_MODE_CAPA_MASK(AUTO),	"auto"	},
2285576ba6SJie Hai 	{ RTE_ETH_FEC_MODE_CAPA_MASK(BASER),	"baser"	},
2385576ba6SJie Hai 	{ RTE_ETH_FEC_MODE_CAPA_MASK(RS),	"rs"	},
2485576ba6SJie Hai 	{ RTE_ETH_FEC_MODE_CAPA_MASK(LLRS),	"llrs"	},
2585576ba6SJie Hai };
2685576ba6SJie Hai 
274fe767acSJie Hai static int
286ca32611SJie Hai eth_dev_parse_port_params(const char *params, uint16_t *port_id,
296ca32611SJie Hai 		char **end_param, bool has_next)
306ca32611SJie Hai {
316ca32611SJie Hai 	uint64_t pi;
326ca32611SJie Hai 
336ca32611SJie Hai 	if (params == NULL || strlen(params) == 0 ||
346ca32611SJie Hai 		!isdigit(*params) || port_id == NULL)
356ca32611SJie Hai 		return -EINVAL;
366ca32611SJie Hai 
376ca32611SJie Hai 	pi = strtoul(params, end_param, 0);
386ca32611SJie Hai 	if (**end_param != '\0' && !has_next)
390e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(NOTICE,
400e21c7c0SDavid Marchand 			"Extra parameters passed to ethdev telemetry command, ignoring");
416ca32611SJie Hai 
426ca32611SJie Hai 	if (pi >= UINT16_MAX || !rte_eth_dev_is_valid_port(pi))
436ca32611SJie Hai 		return -EINVAL;
446ca32611SJie Hai 
456ca32611SJie Hai 	*port_id = (uint16_t)pi;
466ca32611SJie Hai 
476ca32611SJie Hai 	return 0;
486ca32611SJie Hai }
496ca32611SJie Hai 
506ca32611SJie Hai static int
514fe767acSJie Hai eth_dev_handle_port_list(const char *cmd __rte_unused,
524fe767acSJie Hai 		const char *params __rte_unused,
534fe767acSJie Hai 		struct rte_tel_data *d)
544fe767acSJie Hai {
554fe767acSJie Hai 	int port_id;
564fe767acSJie Hai 
574fe767acSJie Hai 	rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
584fe767acSJie Hai 	RTE_ETH_FOREACH_DEV(port_id)
594fe767acSJie Hai 		rte_tel_data_add_array_int(d, port_id);
604fe767acSJie Hai 	return 0;
614fe767acSJie Hai }
624fe767acSJie Hai 
634fe767acSJie Hai static void
644fe767acSJie Hai eth_dev_add_port_queue_stats(struct rte_tel_data *d, uint64_t *q_stats,
654fe767acSJie Hai 		const char *stat_name)
664fe767acSJie Hai {
674fe767acSJie Hai 	int q;
684fe767acSJie Hai 	struct rte_tel_data *q_data = rte_tel_data_alloc();
694fe767acSJie Hai 	if (q_data == NULL)
704fe767acSJie Hai 		return;
714fe767acSJie Hai 	rte_tel_data_start_array(q_data, RTE_TEL_UINT_VAL);
724fe767acSJie Hai 	for (q = 0; q < RTE_ETHDEV_QUEUE_STAT_CNTRS; q++)
734fe767acSJie Hai 		rte_tel_data_add_array_uint(q_data, q_stats[q]);
744fe767acSJie Hai 	rte_tel_data_add_dict_container(d, stat_name, q_data, 0);
754fe767acSJie Hai }
764fe767acSJie Hai 
774fe767acSJie Hai static int
784fe767acSJie Hai eth_dev_parse_hide_zero(const char *key, const char *value, void *extra_args)
794fe767acSJie Hai {
804fe767acSJie Hai 	RTE_SET_USED(key);
814fe767acSJie Hai 
824fe767acSJie Hai 	if (value == NULL)
834fe767acSJie Hai 		return -1;
844fe767acSJie Hai 
854fe767acSJie Hai 	if (strcmp(value, "true") == 0)
864fe767acSJie Hai 		*(bool *)extra_args = true;
874fe767acSJie Hai 	else if (strcmp(value, "false") == 0)
884fe767acSJie Hai 		*(bool *)extra_args = false;
894fe767acSJie Hai 	else
904fe767acSJie Hai 		return -1;
914fe767acSJie Hai 
924fe767acSJie Hai 	return 0;
934fe767acSJie Hai }
944fe767acSJie Hai 
954fe767acSJie Hai #define ADD_DICT_STAT(stats, s) rte_tel_data_add_dict_uint(d, #s, stats.s)
964fe767acSJie Hai 
974fe767acSJie Hai static int
984fe767acSJie Hai eth_dev_handle_port_stats(const char *cmd __rte_unused,
994fe767acSJie Hai 		const char *params,
1004fe767acSJie Hai 		struct rte_tel_data *d)
1014fe767acSJie Hai {
1024fe767acSJie Hai 	struct rte_eth_stats stats;
1036ca32611SJie Hai 	uint16_t port_id;
1046ca32611SJie Hai 	char *end_param;
1056ca32611SJie Hai 	int ret;
1064fe767acSJie Hai 
1076ca32611SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
1086ca32611SJie Hai 	if (ret < 0)
1096ca32611SJie Hai 		return ret;
1104fe767acSJie Hai 
1114fe767acSJie Hai 	ret = rte_eth_stats_get(port_id, &stats);
1124fe767acSJie Hai 	if (ret < 0)
1134fe767acSJie Hai 		return -1;
1144fe767acSJie Hai 
1154fe767acSJie Hai 	rte_tel_data_start_dict(d);
1164fe767acSJie Hai 	ADD_DICT_STAT(stats, ipackets);
1174fe767acSJie Hai 	ADD_DICT_STAT(stats, opackets);
1184fe767acSJie Hai 	ADD_DICT_STAT(stats, ibytes);
1194fe767acSJie Hai 	ADD_DICT_STAT(stats, obytes);
1204fe767acSJie Hai 	ADD_DICT_STAT(stats, imissed);
1214fe767acSJie Hai 	ADD_DICT_STAT(stats, ierrors);
1224fe767acSJie Hai 	ADD_DICT_STAT(stats, oerrors);
1234fe767acSJie Hai 	ADD_DICT_STAT(stats, rx_nombuf);
1244fe767acSJie Hai 	eth_dev_add_port_queue_stats(d, stats.q_ipackets, "q_ipackets");
1254fe767acSJie Hai 	eth_dev_add_port_queue_stats(d, stats.q_opackets, "q_opackets");
1264fe767acSJie Hai 	eth_dev_add_port_queue_stats(d, stats.q_ibytes, "q_ibytes");
1274fe767acSJie Hai 	eth_dev_add_port_queue_stats(d, stats.q_obytes, "q_obytes");
1284fe767acSJie Hai 	eth_dev_add_port_queue_stats(d, stats.q_errors, "q_errors");
1294fe767acSJie Hai 
1304fe767acSJie Hai 	return 0;
1314fe767acSJie Hai }
1324fe767acSJie Hai 
1334fe767acSJie Hai static int
1344fe767acSJie Hai eth_dev_handle_port_xstats(const char *cmd __rte_unused,
1354fe767acSJie Hai 		const char *params,
1364fe767acSJie Hai 		struct rte_tel_data *d)
1374fe767acSJie Hai {
1384fe767acSJie Hai 	const char *const valid_keys[] = { "hide_zero", NULL };
1394fe767acSJie Hai 	struct rte_eth_xstat *eth_xstats;
1404fe767acSJie Hai 	struct rte_eth_xstat_name *xstat_names;
1414fe767acSJie Hai 	struct rte_kvargs *kvlist;
1424fe767acSJie Hai 	bool hide_zero = false;
1436ca32611SJie Hai 	uint16_t port_id;
1444fe767acSJie Hai 	char *end_param;
1456ca32611SJie Hai 	int num_xstats;
1464fe767acSJie Hai 	int i, ret;
1474fe767acSJie Hai 
1486ca32611SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1496ca32611SJie Hai 	if (ret < 0)
1506ca32611SJie Hai 		return ret;
1514fe767acSJie Hai 
1524fe767acSJie Hai 	if (*end_param != '\0') {
1534fe767acSJie Hai 		kvlist = rte_kvargs_parse(end_param, valid_keys);
1544fe767acSJie Hai 		ret = rte_kvargs_process(kvlist, NULL, eth_dev_parse_hide_zero, &hide_zero);
1554fe767acSJie Hai 		if (kvlist == NULL || ret != 0)
1560e21c7c0SDavid Marchand 			RTE_ETHDEV_LOG_LINE(NOTICE,
1570e21c7c0SDavid Marchand 				"Unknown extra parameters passed to ethdev telemetry command, ignoring");
1584fe767acSJie Hai 		rte_kvargs_free(kvlist);
1594fe767acSJie Hai 	}
1604fe767acSJie Hai 
1614fe767acSJie Hai 	num_xstats = rte_eth_xstats_get(port_id, NULL, 0);
1624fe767acSJie Hai 	if (num_xstats < 0)
1634fe767acSJie Hai 		return -1;
1644fe767acSJie Hai 
1654fe767acSJie Hai 	/* use one malloc for both names and stats */
1664fe767acSJie Hai 	eth_xstats = malloc((sizeof(struct rte_eth_xstat) +
1674fe767acSJie Hai 			sizeof(struct rte_eth_xstat_name)) * num_xstats);
1684fe767acSJie Hai 	if (eth_xstats == NULL)
1694fe767acSJie Hai 		return -1;
1704fe767acSJie Hai 	xstat_names = (void *)&eth_xstats[num_xstats];
1714fe767acSJie Hai 
1724fe767acSJie Hai 	ret = rte_eth_xstats_get_names(port_id, xstat_names, num_xstats);
1734fe767acSJie Hai 	if (ret < 0 || ret > num_xstats) {
1744fe767acSJie Hai 		free(eth_xstats);
1754fe767acSJie Hai 		return -1;
1764fe767acSJie Hai 	}
1774fe767acSJie Hai 
1784fe767acSJie Hai 	ret = rte_eth_xstats_get(port_id, eth_xstats, num_xstats);
1794fe767acSJie Hai 	if (ret < 0 || ret > num_xstats) {
1804fe767acSJie Hai 		free(eth_xstats);
1814fe767acSJie Hai 		return -1;
1824fe767acSJie Hai 	}
1834fe767acSJie Hai 
1844fe767acSJie Hai 	rte_tel_data_start_dict(d);
1854fe767acSJie Hai 	for (i = 0; i < num_xstats; i++) {
1864fe767acSJie Hai 		if (hide_zero && eth_xstats[i].value == 0)
1874fe767acSJie Hai 			continue;
1884fe767acSJie Hai 		rte_tel_data_add_dict_uint(d, xstat_names[i].name,
1894fe767acSJie Hai 					   eth_xstats[i].value);
1904fe767acSJie Hai 	}
1914fe767acSJie Hai 	free(eth_xstats);
1924fe767acSJie Hai 	return 0;
1934fe767acSJie Hai }
1944fe767acSJie Hai 
1954fe767acSJie Hai #ifndef RTE_EXEC_ENV_WINDOWS
1964fe767acSJie Hai static int
1974fe767acSJie Hai eth_dev_handle_port_dump_priv(const char *cmd __rte_unused,
1984fe767acSJie Hai 			const char *params,
1994fe767acSJie Hai 			struct rte_tel_data *d)
2004fe767acSJie Hai {
2014fe767acSJie Hai 	char *buf, *end_param;
2026ca32611SJie Hai 	uint16_t port_id;
2036ca32611SJie Hai 	int ret;
2044fe767acSJie Hai 	FILE *f;
2054fe767acSJie Hai 
2066ca32611SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
2076ca32611SJie Hai 	if (ret < 0)
2086ca32611SJie Hai 		return ret;
2094fe767acSJie Hai 
2104fe767acSJie Hai 	buf = calloc(RTE_TEL_MAX_SINGLE_STRING_LEN, sizeof(char));
2114fe767acSJie Hai 	if (buf == NULL)
2124fe767acSJie Hai 		return -ENOMEM;
2134fe767acSJie Hai 
2144fe767acSJie Hai 	f = fmemopen(buf, RTE_TEL_MAX_SINGLE_STRING_LEN - 1, "w+");
2154fe767acSJie Hai 	if (f == NULL) {
2164fe767acSJie Hai 		free(buf);
2174fe767acSJie Hai 		return -EINVAL;
2184fe767acSJie Hai 	}
2194fe767acSJie Hai 
2204fe767acSJie Hai 	ret = rte_eth_dev_priv_dump(port_id, f);
2214fe767acSJie Hai 	fclose(f);
2224fe767acSJie Hai 	if (ret == 0) {
2234fe767acSJie Hai 		rte_tel_data_start_dict(d);
2244fe767acSJie Hai 		rte_tel_data_string(d, buf);
2254fe767acSJie Hai 	}
2264fe767acSJie Hai 
2274fe767acSJie Hai 	free(buf);
2284fe767acSJie Hai 	return 0;
2294fe767acSJie Hai }
2304fe767acSJie Hai #endif /* !RTE_EXEC_ENV_WINDOWS */
2314fe767acSJie Hai 
2324fe767acSJie Hai static int
2334fe767acSJie Hai eth_dev_handle_port_link_status(const char *cmd __rte_unused,
2344fe767acSJie Hai 		const char *params,
2354fe767acSJie Hai 		struct rte_tel_data *d)
2364fe767acSJie Hai {
2374fe767acSJie Hai 	static const char *status_str = "status";
2384fe767acSJie Hai 	struct rte_eth_link link;
2396ca32611SJie Hai 	uint16_t port_id;
2404fe767acSJie Hai 	char *end_param;
2416ca32611SJie Hai 	int ret;
2424fe767acSJie Hai 
2436ca32611SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
2446ca32611SJie Hai 	if (ret < 0)
2456ca32611SJie Hai 		return ret;
2464fe767acSJie Hai 
2474fe767acSJie Hai 	ret = rte_eth_link_get_nowait(port_id, &link);
2484fe767acSJie Hai 	if (ret < 0)
2494fe767acSJie Hai 		return -1;
2504fe767acSJie Hai 
2514fe767acSJie Hai 	rte_tel_data_start_dict(d);
2524fe767acSJie Hai 	if (!link.link_status) {
2534fe767acSJie Hai 		rte_tel_data_add_dict_string(d, status_str, "DOWN");
2544fe767acSJie Hai 		return 0;
2554fe767acSJie Hai 	}
2564fe767acSJie Hai 	rte_tel_data_add_dict_string(d, status_str, "UP");
2574fe767acSJie Hai 	rte_tel_data_add_dict_uint(d, "speed", link.link_speed);
2584fe767acSJie Hai 	rte_tel_data_add_dict_string(d, "duplex",
2594fe767acSJie Hai 			(link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX) ?
2604fe767acSJie Hai 				"full-duplex" : "half-duplex");
2614fe767acSJie Hai 	return 0;
2624fe767acSJie Hai }
2634fe767acSJie Hai 
264aea48618SJie Hai static void
265aea48618SJie Hai eth_dev_parse_rx_offloads(uint64_t offload, struct rte_tel_data *d)
266aea48618SJie Hai {
267aea48618SJie Hai 	uint64_t i;
268aea48618SJie Hai 
269aea48618SJie Hai 	rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
270aea48618SJie Hai 	for (i = 0; i < CHAR_BIT * sizeof(offload); i++) {
271aea48618SJie Hai 		if ((offload & RTE_BIT64(i)) != 0)
272aea48618SJie Hai 			rte_tel_data_add_array_string(d,
273aea48618SJie Hai 				rte_eth_dev_rx_offload_name(offload & RTE_BIT64(i)));
274aea48618SJie Hai 	}
275aea48618SJie Hai }
276aea48618SJie Hai 
277aea48618SJie Hai static void
278aea48618SJie Hai eth_dev_parse_tx_offloads(uint64_t offload, struct rte_tel_data *d)
279aea48618SJie Hai {
280aea48618SJie Hai 	uint64_t i;
281aea48618SJie Hai 
282aea48618SJie Hai 	rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
283aea48618SJie Hai 	for (i = 0; i < CHAR_BIT * sizeof(offload); i++) {
284aea48618SJie Hai 		if ((offload & RTE_BIT64(i)) != 0)
285aea48618SJie Hai 			rte_tel_data_add_array_string(d,
286aea48618SJie Hai 				rte_eth_dev_tx_offload_name(offload & RTE_BIT64(i)));
287aea48618SJie Hai 	}
288aea48618SJie Hai }
289aea48618SJie Hai 
2904fe767acSJie Hai static int
2914fe767acSJie Hai eth_dev_handle_port_info(const char *cmd __rte_unused,
2924fe767acSJie Hai 		const char *params,
2934fe767acSJie Hai 		struct rte_tel_data *d)
2944fe767acSJie Hai {
295aea48618SJie Hai 	struct rte_tel_data *rx_offload, *tx_offload;
2964fe767acSJie Hai 	struct rte_tel_data *rxq_state, *txq_state;
2974b5f5fa9SJie Hai 	char fw_version[RTE_TEL_MAX_STRING_LEN];
2984fe767acSJie Hai 	char mac_addr[RTE_ETHER_ADDR_FMT_SIZE];
2994fe767acSJie Hai 	struct rte_eth_dev *eth_dev;
3006ca32611SJie Hai 	uint16_t port_id;
3014fe767acSJie Hai 	char *end_param;
3026ca32611SJie Hai 	int ret;
3036ca32611SJie Hai 	int i;
3044fe767acSJie Hai 
3056ca32611SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
3066ca32611SJie Hai 	if (ret < 0)
3076ca32611SJie Hai 		return ret;
3084fe767acSJie Hai 
3094fe767acSJie Hai 	eth_dev = &rte_eth_devices[port_id];
3104fe767acSJie Hai 
3114fe767acSJie Hai 	rxq_state = rte_tel_data_alloc();
312aea48618SJie Hai 	if (rxq_state == NULL)
3134fe767acSJie Hai 		return -ENOMEM;
3144fe767acSJie Hai 
3154fe767acSJie Hai 	txq_state = rte_tel_data_alloc();
316aea48618SJie Hai 	if (txq_state == NULL)
317aea48618SJie Hai 		goto free_rxq_state;
318aea48618SJie Hai 
319aea48618SJie Hai 	rx_offload = rte_tel_data_alloc();
320aea48618SJie Hai 	if (rx_offload == NULL)
321aea48618SJie Hai 		goto free_txq_state;
322aea48618SJie Hai 
323aea48618SJie Hai 	tx_offload = rte_tel_data_alloc();
324aea48618SJie Hai 	if (tx_offload == NULL)
325aea48618SJie Hai 		goto free_rx_offload;
3264fe767acSJie Hai 
3274fe767acSJie Hai 	rte_tel_data_start_dict(d);
3284fe767acSJie Hai 	rte_tel_data_add_dict_string(d, "name", eth_dev->data->name);
3294b5f5fa9SJie Hai 
3304b5f5fa9SJie Hai 	if (rte_eth_dev_fw_version_get(port_id, fw_version,
3314b5f5fa9SJie Hai 					 RTE_TEL_MAX_STRING_LEN) == 0)
3324b5f5fa9SJie Hai 		rte_tel_data_add_dict_string(d, "fw_version", fw_version);
3334b5f5fa9SJie Hai 
3344fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "state", eth_dev->state);
3354fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "nb_rx_queues",
3364fe767acSJie Hai 			eth_dev->data->nb_rx_queues);
3374fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "nb_tx_queues",
3384fe767acSJie Hai 			eth_dev->data->nb_tx_queues);
3394fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "port_id", eth_dev->data->port_id);
3404fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "mtu", eth_dev->data->mtu);
3414fe767acSJie Hai 	rte_tel_data_add_dict_uint(d, "rx_mbuf_size_min",
3424fe767acSJie Hai 			eth_dev->data->min_rx_buf_size);
3434fe767acSJie Hai 	rte_ether_format_addr(mac_addr, sizeof(mac_addr),
3444fe767acSJie Hai 			eth_dev->data->mac_addrs);
3454fe767acSJie Hai 	rte_tel_data_add_dict_string(d, "mac_addr", mac_addr);
3464fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "promiscuous",
3474fe767acSJie Hai 			eth_dev->data->promiscuous);
3484fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "scattered_rx",
3494fe767acSJie Hai 			eth_dev->data->scattered_rx);
3504fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "all_multicast",
3514fe767acSJie Hai 			eth_dev->data->all_multicast);
3524fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "dev_started", eth_dev->data->dev_started);
3534fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "lro", eth_dev->data->lro);
3544fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "dev_configured",
3554fe767acSJie Hai 			eth_dev->data->dev_configured);
3564fe767acSJie Hai 
3574fe767acSJie Hai 	rte_tel_data_start_array(rxq_state, RTE_TEL_INT_VAL);
3584fe767acSJie Hai 	for (i = 0; i < eth_dev->data->nb_rx_queues; i++)
3594fe767acSJie Hai 		rte_tel_data_add_array_int(rxq_state,
3604fe767acSJie Hai 				eth_dev->data->rx_queue_state[i]);
3614fe767acSJie Hai 
3624fe767acSJie Hai 	rte_tel_data_start_array(txq_state, RTE_TEL_INT_VAL);
3634fe767acSJie Hai 	for (i = 0; i < eth_dev->data->nb_tx_queues; i++)
3644fe767acSJie Hai 		rte_tel_data_add_array_int(txq_state,
3654fe767acSJie Hai 				eth_dev->data->tx_queue_state[i]);
3664fe767acSJie Hai 
3674fe767acSJie Hai 	rte_tel_data_add_dict_container(d, "rxq_state", rxq_state, 0);
3684fe767acSJie Hai 	rte_tel_data_add_dict_container(d, "txq_state", txq_state, 0);
3694fe767acSJie Hai 	rte_tel_data_add_dict_int(d, "numa_node", eth_dev->data->numa_node);
3704fe767acSJie Hai 	rte_tel_data_add_dict_uint_hex(d, "dev_flags",
3714fe767acSJie Hai 			eth_dev->data->dev_flags, 0);
372aea48618SJie Hai 
373aea48618SJie Hai 	eth_dev_parse_rx_offloads(eth_dev->data->dev_conf.rxmode.offloads,
374aea48618SJie Hai 			rx_offload);
375aea48618SJie Hai 	rte_tel_data_add_dict_container(d, "rx_offloads", rx_offload, 0);
376aea48618SJie Hai 	eth_dev_parse_tx_offloads(eth_dev->data->dev_conf.txmode.offloads,
377aea48618SJie Hai 			tx_offload);
378aea48618SJie Hai 	rte_tel_data_add_dict_container(d, "tx_offloads", tx_offload, 0);
379aea48618SJie Hai 
3804fe767acSJie Hai 	rte_tel_data_add_dict_uint_hex(d, "ethdev_rss_hf",
3814fe767acSJie Hai 			eth_dev->data->dev_conf.rx_adv_conf.rss_conf.rss_hf, 0);
3824fe767acSJie Hai 
3834fe767acSJie Hai 	return 0;
384aea48618SJie Hai 
385aea48618SJie Hai free_rx_offload:
386aea48618SJie Hai 	rte_tel_data_free(rx_offload);
387aea48618SJie Hai free_txq_state:
388aea48618SJie Hai 	rte_tel_data_free(txq_state);
389aea48618SJie Hai free_rxq_state:
390aea48618SJie Hai 	rte_tel_data_free(rxq_state);
391aea48618SJie Hai 
392aea48618SJie Hai 	return -ENOMEM;
3934fe767acSJie Hai }
3944fe767acSJie Hai 
3956732ae1cSDengdui Huang static int
3966732ae1cSDengdui Huang eth_dev_handle_port_macs(const char *cmd __rte_unused,
3976732ae1cSDengdui Huang 		const char *params,
3986732ae1cSDengdui Huang 		struct rte_tel_data *d)
3996732ae1cSDengdui Huang {
4006732ae1cSDengdui Huang 	char mac_addr[RTE_ETHER_ADDR_FMT_SIZE];
4016732ae1cSDengdui Huang 	struct rte_eth_dev_info dev_info;
4026732ae1cSDengdui Huang 	struct rte_eth_dev *eth_dev;
4036732ae1cSDengdui Huang 	uint16_t port_id;
4046732ae1cSDengdui Huang 	char *end_param;
4056732ae1cSDengdui Huang 	uint32_t i;
4066732ae1cSDengdui Huang 	int ret;
4076732ae1cSDengdui Huang 
4086732ae1cSDengdui Huang 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
4096732ae1cSDengdui Huang 	if (ret < 0)
4106732ae1cSDengdui Huang 		return ret;
4116732ae1cSDengdui Huang 
4126732ae1cSDengdui Huang 	ret = rte_eth_dev_info_get(port_id, &dev_info);
4136732ae1cSDengdui Huang 	if (ret != 0)
4146732ae1cSDengdui Huang 		return ret;
4156732ae1cSDengdui Huang 
4166732ae1cSDengdui Huang 	eth_dev = &rte_eth_devices[port_id];
4176732ae1cSDengdui Huang 	rte_tel_data_start_array(d, RTE_TEL_STRING_VAL);
4186732ae1cSDengdui Huang 	for (i = 0; i < dev_info.max_mac_addrs; i++) {
4196732ae1cSDengdui Huang 		if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[i]))
4206732ae1cSDengdui Huang 			continue;
4216732ae1cSDengdui Huang 
4226732ae1cSDengdui Huang 		rte_ether_format_addr(mac_addr, sizeof(mac_addr),
4236732ae1cSDengdui Huang 			&eth_dev->data->mac_addrs[i]);
4246732ae1cSDengdui Huang 		rte_tel_data_add_array_string(d, mac_addr);
4256732ae1cSDengdui Huang 	}
4266732ae1cSDengdui Huang 
4276732ae1cSDengdui Huang 	return 0;
4286732ae1cSDengdui Huang }
4296732ae1cSDengdui Huang 
430499c8486SJie Hai static int
431499c8486SJie Hai eth_dev_handle_port_flow_ctrl(const char *cmd __rte_unused,
432499c8486SJie Hai 		const char *params,
433499c8486SJie Hai 		struct rte_tel_data *d)
434499c8486SJie Hai {
435499c8486SJie Hai 	struct rte_eth_fc_conf fc_conf;
436499c8486SJie Hai 	uint16_t port_id;
437499c8486SJie Hai 	char *end_param;
438499c8486SJie Hai 	bool rx_fc_en;
439499c8486SJie Hai 	bool tx_fc_en;
440499c8486SJie Hai 	int ret;
441499c8486SJie Hai 
442499c8486SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
443499c8486SJie Hai 	if (ret < 0)
444499c8486SJie Hai 		return ret;
445499c8486SJie Hai 
446499c8486SJie Hai 	ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
447499c8486SJie Hai 	if (ret != 0) {
4480e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR,
4490e21c7c0SDavid Marchand 			"Failed to get flow ctrl info, ret = %d", ret);
450499c8486SJie Hai 		return ret;
451499c8486SJie Hai 	}
452499c8486SJie Hai 
453499c8486SJie Hai 	rx_fc_en = fc_conf.mode == RTE_ETH_FC_RX_PAUSE ||
454499c8486SJie Hai 		   fc_conf.mode == RTE_ETH_FC_FULL;
455499c8486SJie Hai 	tx_fc_en = fc_conf.mode == RTE_ETH_FC_TX_PAUSE ||
456499c8486SJie Hai 		   fc_conf.mode == RTE_ETH_FC_FULL;
457499c8486SJie Hai 
458499c8486SJie Hai 	rte_tel_data_start_dict(d);
459499c8486SJie Hai 	rte_tel_data_add_dict_uint_hex(d, "high_waterline", fc_conf.high_water, 0);
460499c8486SJie Hai 	rte_tel_data_add_dict_uint_hex(d, "low_waterline", fc_conf.low_water, 0);
461499c8486SJie Hai 	rte_tel_data_add_dict_uint_hex(d, "pause_time", fc_conf.pause_time, 0);
462499c8486SJie Hai 	rte_tel_data_add_dict_string(d, "send_xon", fc_conf.send_xon ? "on" : "off");
463499c8486SJie Hai 	rte_tel_data_add_dict_string(d, "mac_ctrl_frame_fwd",
464499c8486SJie Hai 			fc_conf.mac_ctrl_frame_fwd ? "on" : "off");
465499c8486SJie Hai 	rte_tel_data_add_dict_string(d, "rx_pause", rx_fc_en ? "on" : "off");
466499c8486SJie Hai 	rte_tel_data_add_dict_string(d, "tx_pause", tx_fc_en ? "on" : "off");
467499c8486SJie Hai 	rte_tel_data_add_dict_string(d, "autoneg", fc_conf.autoneg ? "on" : "off");
468499c8486SJie Hai 
469499c8486SJie Hai 	return 0;
470499c8486SJie Hai }
471499c8486SJie Hai 
472f38f6265SJie Hai static int
473f38f6265SJie Hai ethdev_parse_queue_params(const char *params, bool is_rx,
474f38f6265SJie Hai 		uint16_t *port_id, uint16_t *queue_id)
475f38f6265SJie Hai {
476f38f6265SJie Hai 	struct rte_eth_dev *dev;
477f38f6265SJie Hai 	const char *qid_param;
478f38f6265SJie Hai 	uint16_t nb_queues;
479f38f6265SJie Hai 	char *end_param;
480f38f6265SJie Hai 	uint64_t qid;
481f38f6265SJie Hai 	int ret;
482f38f6265SJie Hai 
483f38f6265SJie Hai 	ret = eth_dev_parse_port_params(params, port_id, &end_param, true);
484f38f6265SJie Hai 	if (ret < 0)
485f38f6265SJie Hai 		return ret;
486f38f6265SJie Hai 
487f38f6265SJie Hai 	dev = &rte_eth_devices[*port_id];
488f38f6265SJie Hai 	nb_queues = is_rx ? dev->data->nb_rx_queues : dev->data->nb_tx_queues;
489f38f6265SJie Hai 	if (nb_queues == 1 && *end_param == '\0')
490f38f6265SJie Hai 		qid = 0;
491f38f6265SJie Hai 	else {
492f38f6265SJie Hai 		qid_param = strtok(end_param, ",");
493f38f6265SJie Hai 		if (!qid_param || strlen(qid_param) == 0 || !isdigit(*qid_param))
494f38f6265SJie Hai 			return -EINVAL;
495f38f6265SJie Hai 
496f38f6265SJie Hai 		qid = strtoul(qid_param, &end_param, 0);
497f38f6265SJie Hai 	}
498f38f6265SJie Hai 	if (*end_param != '\0')
4990e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(NOTICE,
5000e21c7c0SDavid Marchand 			"Extra parameters passed to ethdev telemetry command, ignoring");
501f38f6265SJie Hai 
502f38f6265SJie Hai 	if (qid >= UINT16_MAX)
503f38f6265SJie Hai 		return -EINVAL;
504f38f6265SJie Hai 
505f38f6265SJie Hai 	*queue_id = qid;
506f38f6265SJie Hai 	return 0;
507f38f6265SJie Hai }
508f38f6265SJie Hai 
509f38f6265SJie Hai static int
510f38f6265SJie Hai eth_dev_add_burst_mode(uint16_t port_id, uint16_t queue_id,
511f38f6265SJie Hai 			bool is_rx, struct rte_tel_data *d)
512f38f6265SJie Hai {
513f38f6265SJie Hai 	struct rte_eth_burst_mode mode;
514f38f6265SJie Hai 	int ret;
515f38f6265SJie Hai 
516f38f6265SJie Hai 	if (is_rx)
517f38f6265SJie Hai 		ret = rte_eth_rx_burst_mode_get(port_id, queue_id, &mode);
518f38f6265SJie Hai 	else
519f38f6265SJie Hai 		ret = rte_eth_tx_burst_mode_get(port_id, queue_id, &mode);
520f38f6265SJie Hai 
521f38f6265SJie Hai 	if (ret == -ENOTSUP)
522f38f6265SJie Hai 		return 0;
523f38f6265SJie Hai 
524f38f6265SJie Hai 	if (ret != 0) {
5250e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR,
5260e21c7c0SDavid Marchand 			"Failed to get burst mode for port %u", port_id);
527f38f6265SJie Hai 		return ret;
528f38f6265SJie Hai 	}
529f38f6265SJie Hai 
530f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "burst_flags", mode.flags);
531f38f6265SJie Hai 	rte_tel_data_add_dict_string(d, "burst_mode", mode.info);
532f38f6265SJie Hai 	return 0;
533f38f6265SJie Hai }
534f38f6265SJie Hai 
535f38f6265SJie Hai static int
536f38f6265SJie Hai eth_dev_handle_port_rxq(const char *cmd __rte_unused,
537f38f6265SJie Hai 		const char *params,
538f38f6265SJie Hai 		struct rte_tel_data *d)
539f38f6265SJie Hai {
540f38f6265SJie Hai 	struct rte_eth_thresh *rx_thresh;
541f38f6265SJie Hai 	struct rte_eth_rxconf *rxconf;
542f38f6265SJie Hai 	struct rte_eth_rxq_info qinfo;
543f38f6265SJie Hai 	struct rte_tel_data *offload;
544f38f6265SJie Hai 	uint16_t port_id, queue_id;
545f38f6265SJie Hai 	int ret;
546f38f6265SJie Hai 
547f38f6265SJie Hai 	ret = ethdev_parse_queue_params(params, true, &port_id, &queue_id);
548f38f6265SJie Hai 	if (ret != 0)
549f38f6265SJie Hai 		return ret;
550f38f6265SJie Hai 
551f38f6265SJie Hai 	ret = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
552f38f6265SJie Hai 	if (ret != 0)
553f38f6265SJie Hai 		return ret;
554f38f6265SJie Hai 
555f38f6265SJie Hai 	rte_tel_data_start_dict(d);
556f38f6265SJie Hai 	rte_tel_data_add_dict_string(d, "mempool_name", qinfo.mp->name);
557f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "socket_id", qinfo.mp->socket_id);
558f38f6265SJie Hai 
559f38f6265SJie Hai 	rx_thresh = &qinfo.conf.rx_thresh;
560f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "host_threshold", rx_thresh->hthresh);
561f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "prefetch_threshold", rx_thresh->pthresh);
562f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "writeback_threshold", rx_thresh->wthresh);
563f38f6265SJie Hai 
564f38f6265SJie Hai 	rxconf = &qinfo.conf;
565f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "free_threshold", rxconf->rx_free_thresh);
566f38f6265SJie Hai 	rte_tel_data_add_dict_string(d, "rx_drop_en",
567f38f6265SJie Hai 			rxconf->rx_drop_en == 0 ? "off" : "on");
568f38f6265SJie Hai 	rte_tel_data_add_dict_string(d, "deferred_start",
569f38f6265SJie Hai 			rxconf->rx_deferred_start == 0 ? "off" : "on");
570f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "rx_nseg", rxconf->rx_nseg);
571f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "share_group", rxconf->share_group);
572f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "share_qid", rxconf->share_qid);
573f38f6265SJie Hai 
574f38f6265SJie Hai 	offload = rte_tel_data_alloc();
575f38f6265SJie Hai 	if (offload == NULL)
576f38f6265SJie Hai 		return -ENOMEM;
577f38f6265SJie Hai 
578f38f6265SJie Hai 	eth_dev_parse_rx_offloads(rxconf->offloads, offload);
579f38f6265SJie Hai 	rte_tel_data_add_dict_container(d, "offloads", offload, 0);
580f38f6265SJie Hai 
581f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "rx_nmempool", rxconf->rx_nmempool);
582f38f6265SJie Hai 
583f38f6265SJie Hai 	rte_tel_data_add_dict_string(d, "scattered_rx",
584f38f6265SJie Hai 			qinfo.scattered_rx == 0 ? "off" : "on");
585f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "queue_state", qinfo.queue_state);
586f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "nb_desc", qinfo.nb_desc);
587f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "rx_buf_size", qinfo.rx_buf_size);
588f38f6265SJie Hai 	rte_tel_data_add_dict_uint(d, "avail_thresh", qinfo.avail_thresh);
589f38f6265SJie Hai 
590f38f6265SJie Hai 	ret = eth_dev_add_burst_mode(port_id, queue_id, true, d);
591f38f6265SJie Hai 	if (ret != 0)
592f38f6265SJie Hai 		rte_tel_data_free(offload);
593f38f6265SJie Hai 
594f38f6265SJie Hai 	return ret;
595f38f6265SJie Hai }
596f38f6265SJie Hai 
5971a479610SJie Hai static int
5981a479610SJie Hai eth_dev_handle_port_txq(const char *cmd __rte_unused,
5991a479610SJie Hai 		const char *params,
6001a479610SJie Hai 		struct rte_tel_data *d)
6011a479610SJie Hai {
6021a479610SJie Hai 	struct rte_eth_thresh *tx_thresh;
6031a479610SJie Hai 	struct rte_eth_txconf *txconf;
6041a479610SJie Hai 	struct rte_eth_txq_info qinfo;
6051a479610SJie Hai 	struct rte_tel_data *offload;
6061a479610SJie Hai 	uint16_t port_id, queue_id;
6071a479610SJie Hai 	int ret;
6081a479610SJie Hai 
6091a479610SJie Hai 	ret = ethdev_parse_queue_params(params, false, &port_id, &queue_id);
6101a479610SJie Hai 	if (ret != 0)
6111a479610SJie Hai 		return ret;
6121a479610SJie Hai 
6131a479610SJie Hai 	ret = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
6141a479610SJie Hai 	if (ret != 0)
6151a479610SJie Hai 		return ret;
6161a479610SJie Hai 
6171a479610SJie Hai 	rte_tel_data_start_dict(d);
6181a479610SJie Hai 	tx_thresh = &qinfo.conf.tx_thresh;
6191a479610SJie Hai 	txconf = &qinfo.conf;
6201a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "host_threshold", tx_thresh->hthresh);
6211a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "prefetch_threshold", tx_thresh->pthresh);
6221a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "writeback_threshold", tx_thresh->wthresh);
6231a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "rs_threshold", txconf->tx_rs_thresh);
6241a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "free_threshold", txconf->tx_free_thresh);
6251a479610SJie Hai 	rte_tel_data_add_dict_string(d, "deferred_start",
6261a479610SJie Hai 			txconf->tx_deferred_start == 0 ? "off" : "on");
6271a479610SJie Hai 
6281a479610SJie Hai 	offload = rte_tel_data_alloc();
6291a479610SJie Hai 	if (offload == NULL)
6301a479610SJie Hai 		return -ENOMEM;
6311a479610SJie Hai 
6321a479610SJie Hai 	eth_dev_parse_tx_offloads(txconf->offloads, offload);
6331a479610SJie Hai 	rte_tel_data_add_dict_container(d, "offloads", offload, 0);
6341a479610SJie Hai 
6351a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "queue_state", qinfo.queue_state);
6361a479610SJie Hai 	rte_tel_data_add_dict_uint(d, "nb_desc", qinfo.nb_desc);
6371a479610SJie Hai 
6381a479610SJie Hai 	ret = eth_dev_add_burst_mode(port_id, queue_id, false, d);
6391a479610SJie Hai 	if (ret != 0)
6401a479610SJie Hai 		rte_tel_data_free(offload);
6411a479610SJie Hai 
6421a479610SJie Hai 	return 0;
6431a479610SJie Hai }
6441a479610SJie Hai 
64566f3e047SJie Hai static int
64666f3e047SJie Hai eth_dev_add_dcb_tc(struct rte_eth_dcb_info *dcb_info, struct rte_tel_data *d)
64766f3e047SJie Hai {
64866f3e047SJie Hai 	struct rte_tel_data *tcds[RTE_ETH_DCB_NUM_TCS] = {NULL};
64966f3e047SJie Hai 	struct rte_eth_dcb_tc_queue_mapping *tcq;
65066f3e047SJie Hai 	char bw_percent[RTE_TEL_MAX_STRING_LEN];
65166f3e047SJie Hai 	char name[RTE_TEL_MAX_STRING_LEN];
65266f3e047SJie Hai 	struct rte_tel_data *tcd;
65366f3e047SJie Hai 	uint32_t i;
65466f3e047SJie Hai 
65566f3e047SJie Hai 	for (i = 0; i < dcb_info->nb_tcs; i++) {
65666f3e047SJie Hai 		tcd = rte_tel_data_alloc();
65766f3e047SJie Hai 		if (tcd == NULL) {
65866f3e047SJie Hai 			while (i-- > 0)
65966f3e047SJie Hai 				rte_tel_data_free(tcds[i]);
66066f3e047SJie Hai 			return -ENOMEM;
66166f3e047SJie Hai 		}
66266f3e047SJie Hai 
66366f3e047SJie Hai 		tcds[i] = tcd;
66466f3e047SJie Hai 		rte_tel_data_start_dict(tcd);
66566f3e047SJie Hai 
66666f3e047SJie Hai 		rte_tel_data_add_dict_uint(tcd, "priority", dcb_info->prio_tc[i]);
66766f3e047SJie Hai 		snprintf(bw_percent, RTE_TEL_MAX_STRING_LEN,
66866f3e047SJie Hai 			"%u%%", dcb_info->tc_bws[i]);
66966f3e047SJie Hai 		rte_tel_data_add_dict_string(tcd, "bw_percent", bw_percent);
67066f3e047SJie Hai 
67166f3e047SJie Hai 		tcq = &dcb_info->tc_queue;
67266f3e047SJie Hai 		rte_tel_data_add_dict_uint(tcd, "rxq_base", tcq->tc_rxq[0][i].base);
67366f3e047SJie Hai 		rte_tel_data_add_dict_uint(tcd, "txq_base", tcq->tc_txq[0][i].base);
67466f3e047SJie Hai 		rte_tel_data_add_dict_uint(tcd, "nb_rxq", tcq->tc_rxq[0][i].nb_queue);
67566f3e047SJie Hai 		rte_tel_data_add_dict_uint(tcd, "nb_txq", tcq->tc_txq[0][i].nb_queue);
67666f3e047SJie Hai 
67766f3e047SJie Hai 		snprintf(name, RTE_TEL_MAX_STRING_LEN, "tc%u", i);
67866f3e047SJie Hai 		rte_tel_data_add_dict_container(d, name, tcd, 0);
67966f3e047SJie Hai 	}
68066f3e047SJie Hai 
68166f3e047SJie Hai 	return 0;
68266f3e047SJie Hai }
68366f3e047SJie Hai 
68466f3e047SJie Hai static int
68566f3e047SJie Hai eth_dev_add_dcb_info(uint16_t port_id, struct rte_tel_data *d)
68666f3e047SJie Hai {
68766f3e047SJie Hai 	struct rte_eth_dcb_info dcb_info;
68866f3e047SJie Hai 	int ret;
68966f3e047SJie Hai 
69066f3e047SJie Hai 	ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
69166f3e047SJie Hai 	if (ret != 0) {
6920e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR,
6930e21c7c0SDavid Marchand 			"Failed to get dcb info, ret = %d", ret);
69466f3e047SJie Hai 		return ret;
69566f3e047SJie Hai 	}
69666f3e047SJie Hai 
69766f3e047SJie Hai 	rte_tel_data_start_dict(d);
69866f3e047SJie Hai 	rte_tel_data_add_dict_uint(d, "tc_num", dcb_info.nb_tcs);
69966f3e047SJie Hai 
70066f3e047SJie Hai 	if (dcb_info.nb_tcs > 0)
70166f3e047SJie Hai 		return eth_dev_add_dcb_tc(&dcb_info, d);
70266f3e047SJie Hai 
70366f3e047SJie Hai 	return 0;
70466f3e047SJie Hai }
70566f3e047SJie Hai 
70666f3e047SJie Hai static int
70766f3e047SJie Hai eth_dev_handle_port_dcb(const char *cmd __rte_unused,
70866f3e047SJie Hai 		const char *params,
70966f3e047SJie Hai 		struct rte_tel_data *d)
71066f3e047SJie Hai {
71166f3e047SJie Hai 	uint16_t port_id;
71266f3e047SJie Hai 	char *end_param;
71366f3e047SJie Hai 	int ret;
71466f3e047SJie Hai 
71566f3e047SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
71666f3e047SJie Hai 	if (ret < 0)
71766f3e047SJie Hai 		return ret;
71866f3e047SJie Hai 
71966f3e047SJie Hai 	return eth_dev_add_dcb_info(port_id, d);
72066f3e047SJie Hai }
72166f3e047SJie Hai 
722fde1adbfSJie Hai static int
723fde1adbfSJie Hai eth_dev_add_rss_info(struct rte_eth_rss_conf *rss_conf, struct rte_tel_data *d)
724fde1adbfSJie Hai {
725fde1adbfSJie Hai 	const uint32_t key_len = rss_conf->rss_key_len * 2 + 1;
726fde1adbfSJie Hai 	char *rss_key;
727fde1adbfSJie Hai 	char key[3]; /* FF\0 */
728fde1adbfSJie Hai 	uint32_t i;
729fde1adbfSJie Hai 	int ret;
730fde1adbfSJie Hai 
731fde1adbfSJie Hai 	rss_key = malloc(key_len);
732fde1adbfSJie Hai 	if (rss_key == NULL)
733fde1adbfSJie Hai 		return -ENOMEM;
734fde1adbfSJie Hai 
735fde1adbfSJie Hai 	rte_tel_data_start_dict(d);
736fde1adbfSJie Hai 	rte_tel_data_add_dict_uint_hex(d, "rss_hf", rss_conf->rss_hf, 0);
737fde1adbfSJie Hai 	rte_tel_data_add_dict_uint(d, "rss_key_len", rss_conf->rss_key_len);
738fde1adbfSJie Hai 
739fde1adbfSJie Hai 	memset(rss_key, 0, key_len);
740fde1adbfSJie Hai 	for (i = 0; i < rss_conf->rss_key_len; i++) {
741fde1adbfSJie Hai 		ret = snprintf(key, 3, "%02x", rss_conf->rss_key[i]);
742fde1adbfSJie Hai 		if (ret < 0)
743fde1adbfSJie Hai 			goto free_rss_key;
744fde1adbfSJie Hai 		strlcat(rss_key, key, key_len);
745fde1adbfSJie Hai 	}
746fde1adbfSJie Hai 	ret = rte_tel_data_add_dict_string(d, "rss_key", rss_key);
747fde1adbfSJie Hai 
748fde1adbfSJie Hai free_rss_key:
749fde1adbfSJie Hai 	free(rss_key);
750fde1adbfSJie Hai 
751fde1adbfSJie Hai 	return ret;
752fde1adbfSJie Hai }
753fde1adbfSJie Hai 
754fde1adbfSJie Hai static int
755fde1adbfSJie Hai eth_dev_handle_port_rss_info(const char *cmd __rte_unused,
756fde1adbfSJie Hai 		const char *params,
757fde1adbfSJie Hai 		struct rte_tel_data *d)
758fde1adbfSJie Hai {
759fde1adbfSJie Hai 	struct rte_eth_dev_info dev_info;
760fde1adbfSJie Hai 	struct rte_eth_rss_conf rss_conf;
761fde1adbfSJie Hai 	uint8_t key_len;
762fde1adbfSJie Hai 	uint16_t port_id;
763fde1adbfSJie Hai 	char *end_param;
764fde1adbfSJie Hai 	int ret;
765fde1adbfSJie Hai 
766fde1adbfSJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
767fde1adbfSJie Hai 	if (ret < 0)
768fde1adbfSJie Hai 		return ret;
769fde1adbfSJie Hai 
770fde1adbfSJie Hai 	ret = rte_eth_dev_info_get(port_id, &dev_info);
771fde1adbfSJie Hai 	if (ret != 0) {
7720e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR,
7730e21c7c0SDavid Marchand 			"Failed to get device info, ret = %d", ret);
774fde1adbfSJie Hai 		return ret;
775fde1adbfSJie Hai 	}
776fde1adbfSJie Hai 
777fde1adbfSJie Hai 	key_len = dev_info.hash_key_size ? dev_info.hash_key_size : 40;
778fde1adbfSJie Hai 	rss_conf.rss_key_len = key_len;
779fde1adbfSJie Hai 	rss_conf.rss_key = malloc(key_len);
780fde1adbfSJie Hai 	if (rss_conf.rss_key == NULL)
781fde1adbfSJie Hai 		return -ENOMEM;
782fde1adbfSJie Hai 
783fde1adbfSJie Hai 	ret = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
784fde1adbfSJie Hai 	if (ret != 0) {
785fde1adbfSJie Hai 		free(rss_conf.rss_key);
786fde1adbfSJie Hai 		return ret;
787fde1adbfSJie Hai 	}
788fde1adbfSJie Hai 
789fde1adbfSJie Hai 	ret = eth_dev_add_rss_info(&rss_conf, d);
790fde1adbfSJie Hai 	free(rss_conf.rss_key);
791fde1adbfSJie Hai 	return ret;
792fde1adbfSJie Hai }
793fde1adbfSJie Hai 
79485576ba6SJie Hai static const char *
79585576ba6SJie Hai eth_dev_fec_capa_to_string(uint32_t fec_capa)
79685576ba6SJie Hai {
79785576ba6SJie Hai 	uint32_t i;
79885576ba6SJie Hai 
79985576ba6SJie Hai 	for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
80085576ba6SJie Hai 		if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0)
80185576ba6SJie Hai 			return rte_eth_fec_capa_name[i].name;
80285576ba6SJie Hai 	}
80385576ba6SJie Hai 
80485576ba6SJie Hai 	return "unknown";
80585576ba6SJie Hai }
80685576ba6SJie Hai 
80785576ba6SJie Hai static void
80885576ba6SJie Hai eth_dev_fec_capas_to_string(uint32_t fec_capa, char *fec_name, uint32_t len)
80985576ba6SJie Hai {
81085576ba6SJie Hai 	bool valid = false;
81185576ba6SJie Hai 	size_t count = 0;
81285576ba6SJie Hai 	uint32_t i;
81385576ba6SJie Hai 
81485576ba6SJie Hai 	for (i = 0; i < RTE_DIM(rte_eth_fec_capa_name); i++) {
81585576ba6SJie Hai 		if ((fec_capa & rte_eth_fec_capa_name[i].capa) != 0) {
81685576ba6SJie Hai 			strlcat(fec_name, rte_eth_fec_capa_name[i].name, len);
81785576ba6SJie Hai 			count = strlcat(fec_name, " ", len);
81885576ba6SJie Hai 			valid = true;
81985576ba6SJie Hai 		}
82085576ba6SJie Hai 	}
82185576ba6SJie Hai 
82285576ba6SJie Hai 	if (!valid)
82385576ba6SJie Hai 		count = snprintf(fec_name, len, "unknown ");
82485576ba6SJie Hai 
82585576ba6SJie Hai 	if (count >= len) {
8260e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(WARNING, "FEC capa names may be truncated");
82785576ba6SJie Hai 		count = len;
82885576ba6SJie Hai 	}
82985576ba6SJie Hai 
83085576ba6SJie Hai 	fec_name[count - 1] = '\0';
83185576ba6SJie Hai }
83285576ba6SJie Hai 
83385576ba6SJie Hai static int
83485576ba6SJie Hai eth_dev_get_fec_capability(uint16_t port_id, struct rte_tel_data *d)
83585576ba6SJie Hai {
83685576ba6SJie Hai 	struct rte_eth_fec_capa *speed_fec_capa;
83785576ba6SJie Hai 	char fec_name[RTE_TEL_MAX_STRING_LEN];
83885576ba6SJie Hai 	char speed[RTE_TEL_MAX_STRING_LEN];
83985576ba6SJie Hai 	uint32_t capa_num;
84085576ba6SJie Hai 	uint32_t i, j;
84185576ba6SJie Hai 	int ret;
84285576ba6SJie Hai 
84385576ba6SJie Hai 	ret = rte_eth_fec_get_capability(port_id, NULL, 0);
84485576ba6SJie Hai 	if (ret <= 0)
84585576ba6SJie Hai 		return ret == 0 ? -EINVAL : ret;
84685576ba6SJie Hai 
84785576ba6SJie Hai 	capa_num = ret;
84885576ba6SJie Hai 	speed_fec_capa = calloc(capa_num, sizeof(struct rte_eth_fec_capa));
84985576ba6SJie Hai 	if (speed_fec_capa == NULL)
85085576ba6SJie Hai 		return -ENOMEM;
85185576ba6SJie Hai 
85285576ba6SJie Hai 	ret = rte_eth_fec_get_capability(port_id, speed_fec_capa, capa_num);
85385576ba6SJie Hai 	if (ret <= 0) {
85485576ba6SJie Hai 		ret = ret == 0 ? -EINVAL : ret;
85585576ba6SJie Hai 		goto out;
85685576ba6SJie Hai 	}
85785576ba6SJie Hai 
85885576ba6SJie Hai 	for (i = 0; i < capa_num; i++) {
85985576ba6SJie Hai 		memset(fec_name, 0, RTE_TEL_MAX_STRING_LEN);
86085576ba6SJie Hai 		eth_dev_fec_capas_to_string(speed_fec_capa[i].capa, fec_name,
86185576ba6SJie Hai 					    RTE_TEL_MAX_STRING_LEN);
86285576ba6SJie Hai 
86385576ba6SJie Hai 		memset(speed, 0, RTE_TEL_MAX_STRING_LEN);
86485576ba6SJie Hai 		ret = snprintf(speed, RTE_TEL_MAX_STRING_LEN, "%s",
86585576ba6SJie Hai 			rte_eth_link_speed_to_str(speed_fec_capa[i].speed));
86685576ba6SJie Hai 		if (ret < 0)
86785576ba6SJie Hai 			goto out;
86885576ba6SJie Hai 
86985576ba6SJie Hai 		for (j = 0; j < strlen(speed); j++) {
87085576ba6SJie Hai 			if (speed[j] == ' ')
87185576ba6SJie Hai 				speed[j] = '_';
87285576ba6SJie Hai 		}
87385576ba6SJie Hai 
87485576ba6SJie Hai 		rte_tel_data_add_dict_string(d, speed, fec_name);
87585576ba6SJie Hai 	}
87685576ba6SJie Hai 
87785576ba6SJie Hai out:
87885576ba6SJie Hai 	free(speed_fec_capa);
87985576ba6SJie Hai 	return ret > 0 ? 0 : ret;
88085576ba6SJie Hai }
88185576ba6SJie Hai 
88285576ba6SJie Hai static int
88385576ba6SJie Hai eth_dev_handle_port_fec(const char *cmd __rte_unused,
88485576ba6SJie Hai 		const char *params,
88585576ba6SJie Hai 		struct rte_tel_data *d)
88685576ba6SJie Hai {
88785576ba6SJie Hai 	struct rte_tel_data *fec_capas;
88885576ba6SJie Hai 	uint32_t fec_mode;
88985576ba6SJie Hai 	uint16_t port_id;
89085576ba6SJie Hai 	char *end_param;
89185576ba6SJie Hai 	int ret;
89285576ba6SJie Hai 
89385576ba6SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
89485576ba6SJie Hai 	if (ret < 0)
89585576ba6SJie Hai 		return ret;
89685576ba6SJie Hai 
89785576ba6SJie Hai 	ret = rte_eth_fec_get(port_id, &fec_mode);
89885576ba6SJie Hai 	if (ret != 0)
89985576ba6SJie Hai 		return ret;
90085576ba6SJie Hai 
90185576ba6SJie Hai 	rte_tel_data_start_dict(d);
90285576ba6SJie Hai 	rte_tel_data_add_dict_string(d, "fec_mode",
90385576ba6SJie Hai 				     eth_dev_fec_capa_to_string(fec_mode));
90485576ba6SJie Hai 
90585576ba6SJie Hai 	fec_capas = rte_tel_data_alloc();
90685576ba6SJie Hai 	if (fec_capas == NULL)
90785576ba6SJie Hai 		return -ENOMEM;
90885576ba6SJie Hai 
90985576ba6SJie Hai 	rte_tel_data_start_dict(fec_capas);
91085576ba6SJie Hai 	ret = eth_dev_get_fec_capability(port_id, fec_capas);
91185576ba6SJie Hai 	if (ret != 0) {
91285576ba6SJie Hai 		rte_tel_data_free(fec_capas);
91385576ba6SJie Hai 		return ret;
91485576ba6SJie Hai 	}
91585576ba6SJie Hai 
91685576ba6SJie Hai 	rte_tel_data_add_dict_container(d, "fec_capability", fec_capas, 0);
91785576ba6SJie Hai 	return 0;
91885576ba6SJie Hai }
91985576ba6SJie Hai 
92019f39522SJie Hai static int
92119f39522SJie Hai eth_dev_add_vlan_id(int port_id, struct rte_tel_data *d)
92219f39522SJie Hai {
92319f39522SJie Hai 	struct rte_tel_data *vlan_blks[64] = {NULL};
92419f39522SJie Hai 	uint16_t vlan_num, vidx, vbit, num_blks;
92519f39522SJie Hai 	char blk_name[RTE_TEL_MAX_STRING_LEN];
92619f39522SJie Hai 	struct rte_vlan_filter_conf *vfc;
92719f39522SJie Hai 	struct rte_tel_data *vlan_blk;
92819f39522SJie Hai 	struct rte_tel_data *vd;
92919f39522SJie Hai 	uint64_t bit_width;
93019f39522SJie Hai 	uint64_t vlan_id;
93119f39522SJie Hai 
93219f39522SJie Hai 	vd = rte_tel_data_alloc();
93319f39522SJie Hai 	if (vd == NULL)
93419f39522SJie Hai 		return -ENOMEM;
93519f39522SJie Hai 
93619f39522SJie Hai 	vfc = &rte_eth_devices[port_id].data->vlan_filter_conf;
93719f39522SJie Hai 	bit_width = CHAR_BIT * sizeof(uint64_t);
93819f39522SJie Hai 	vlan_num = 0;
93919f39522SJie Hai 	num_blks = 0;
94019f39522SJie Hai 
94119f39522SJie Hai 	rte_tel_data_start_dict(vd);
94219f39522SJie Hai 	for (vidx = 0; vidx < RTE_DIM(vfc->ids); vidx++) {
94319f39522SJie Hai 		if (vfc->ids[vidx] == 0)
94419f39522SJie Hai 			continue;
94519f39522SJie Hai 
94619f39522SJie Hai 		vlan_blk = rte_tel_data_alloc();
94719f39522SJie Hai 		if (vlan_blk == NULL)
94819f39522SJie Hai 			goto free_all;
94919f39522SJie Hai 
95019f39522SJie Hai 		vlan_blks[num_blks] = vlan_blk;
95119f39522SJie Hai 		num_blks++;
95219f39522SJie Hai 		snprintf(blk_name, RTE_TEL_MAX_STRING_LEN, "vlan_%"PRIu64"_to_%"PRIu64"",
95319f39522SJie Hai 			 bit_width * vidx, bit_width * (vidx + 1) - 1);
95419f39522SJie Hai 		rte_tel_data_start_array(vlan_blk, RTE_TEL_UINT_VAL);
95519f39522SJie Hai 		rte_tel_data_add_dict_container(vd, blk_name, vlan_blk, 0);
95619f39522SJie Hai 
95719f39522SJie Hai 		for (vbit = 0; vbit < bit_width; vbit++) {
95819f39522SJie Hai 			if ((vfc->ids[vidx] & RTE_BIT64(vbit)) == 0)
95919f39522SJie Hai 				continue;
96019f39522SJie Hai 
96119f39522SJie Hai 			vlan_id = bit_width * vidx + vbit;
96219f39522SJie Hai 			rte_tel_data_add_array_uint(vlan_blk, vlan_id);
96319f39522SJie Hai 			vlan_num++;
96419f39522SJie Hai 		}
96519f39522SJie Hai 	}
96619f39522SJie Hai 
96719f39522SJie Hai 	rte_tel_data_add_dict_uint(d, "vlan_num", vlan_num);
96819f39522SJie Hai 	rte_tel_data_add_dict_container(d, "vlan_ids", vd, 0);
96919f39522SJie Hai 
97019f39522SJie Hai 	return 0;
97119f39522SJie Hai 
97219f39522SJie Hai free_all:
97319f39522SJie Hai 	while (num_blks-- > 0)
97419f39522SJie Hai 		rte_tel_data_free(vlan_blks[num_blks]);
97519f39522SJie Hai 
97619f39522SJie Hai 	rte_tel_data_free(vd);
97719f39522SJie Hai 	return -ENOMEM;
97819f39522SJie Hai }
97919f39522SJie Hai 
98019f39522SJie Hai static int
98119f39522SJie Hai eth_dev_handle_port_vlan(const char *cmd __rte_unused,
98219f39522SJie Hai 		const char *params,
98319f39522SJie Hai 		struct rte_tel_data *d)
98419f39522SJie Hai {
98519f39522SJie Hai 	struct rte_eth_txmode *txmode;
98619f39522SJie Hai 	struct rte_eth_conf dev_conf;
98719f39522SJie Hai 	uint16_t port_id;
98819f39522SJie Hai 	int offload, ret;
98919f39522SJie Hai 	char *end_param;
99019f39522SJie Hai 
99119f39522SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
99219f39522SJie Hai 	if (ret < 0)
99319f39522SJie Hai 		return ret;
99419f39522SJie Hai 
99519f39522SJie Hai 	ret = rte_eth_dev_conf_get(port_id, &dev_conf);
99619f39522SJie Hai 	if (ret != 0) {
9970e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR,
9980e21c7c0SDavid Marchand 			"Failed to get device configuration, ret = %d", ret);
99919f39522SJie Hai 		return ret;
100019f39522SJie Hai 	}
100119f39522SJie Hai 
100219f39522SJie Hai 	txmode = &dev_conf.txmode;
100319f39522SJie Hai 	rte_tel_data_start_dict(d);
100419f39522SJie Hai 	rte_tel_data_add_dict_uint(d, "pvid", txmode->pvid);
100519f39522SJie Hai 	rte_tel_data_add_dict_uint(d, "hw_vlan_reject_tagged",
100619f39522SJie Hai 		txmode->hw_vlan_reject_tagged);
100719f39522SJie Hai 	rte_tel_data_add_dict_uint(d, "hw_vlan_reject_untagged",
100819f39522SJie Hai 		txmode->hw_vlan_reject_untagged);
100919f39522SJie Hai 	rte_tel_data_add_dict_uint(d, "hw_vlan_insert_pvid",
101019f39522SJie Hai 		txmode->hw_vlan_insert_pvid);
101119f39522SJie Hai 
101219f39522SJie Hai 	offload = rte_eth_dev_get_vlan_offload(port_id);
101319f39522SJie Hai 	rte_tel_data_add_dict_string(d, "VLAN_STRIP",
101419f39522SJie Hai 		((offload & RTE_ETH_VLAN_STRIP_OFFLOAD) != 0) ? "on" : "off");
101519f39522SJie Hai 	rte_tel_data_add_dict_string(d, "VLAN_EXTEND",
101619f39522SJie Hai 		((offload & RTE_ETH_VLAN_EXTEND_OFFLOAD) != 0) ? "on" : "off");
101719f39522SJie Hai 	rte_tel_data_add_dict_string(d, "QINQ_STRIP",
101819f39522SJie Hai 		((offload & RTE_ETH_QINQ_STRIP_OFFLOAD) != 0) ? "on" : "off");
101919f39522SJie Hai 	rte_tel_data_add_dict_string(d, "VLAN_FILTER",
102019f39522SJie Hai 		((offload & RTE_ETH_VLAN_FILTER_OFFLOAD) != 0) ? "on" : "off");
102119f39522SJie Hai 
102219f39522SJie Hai 	return eth_dev_add_vlan_id(port_id, d);
102319f39522SJie Hai }
102419f39522SJie Hai 
1025a590d564SJie Hai static void
1026a590d564SJie Hai eth_dev_add_tm_caps(struct rte_tel_data *d, struct rte_tm_capabilities *cap)
1027a590d564SJie Hai {
1028a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
1029a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "n_levels_max", cap->n_levels_max);
1030a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
1031a590d564SJie Hai 		cap->non_leaf_nodes_identical);
1032a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
1033a590d564SJie Hai 		cap->leaf_nodes_identical);
1034a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_n_max", cap->shaper_n_max);
1035a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_private_n_max",
1036a590d564SJie Hai 		cap->shaper_private_n_max);
1037a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_private_dual_rate_n_max",
1038a590d564SJie Hai 		cap->shaper_private_dual_rate_n_max);
1039a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_private_rate_min",
1040a590d564SJie Hai 		cap->shaper_private_rate_min);
1041a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_private_rate_max",
1042a590d564SJie Hai 		cap->shaper_private_rate_max);
1043a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_private_packet_mode_supported",
1044a590d564SJie Hai 		cap->shaper_private_packet_mode_supported);
1045a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_private_byte_mode_supported",
1046a590d564SJie Hai 		cap->shaper_private_byte_mode_supported);
1047a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_shared_n_max",
1048a590d564SJie Hai 		cap->shaper_shared_n_max);
1049a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_shared_n_nodes_per_shaper_max",
1050a590d564SJie Hai 		cap->shaper_shared_n_nodes_per_shaper_max);
1051a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_shared_n_shapers_per_node_max",
1052a590d564SJie Hai 		cap->shaper_shared_n_shapers_per_node_max);
1053a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_share_dual_rate_n_max",
1054a590d564SJie Hai 		cap->shaper_shared_dual_rate_n_max);
1055a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_shared_rate_min",
1056a590d564SJie Hai 		cap->shaper_shared_rate_min);
1057a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "shaper_shared_rate_max",
1058a590d564SJie Hai 		cap->shaper_shared_rate_max);
1059a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_shared_packet_mode_supported",
1060a590d564SJie Hai 		cap->shaper_shared_packet_mode_supported);
1061a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_shared_byte_mode_supported",
1062a590d564SJie Hai 		cap->shaper_shared_byte_mode_supported);
1063a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_min",
1064a590d564SJie Hai 		cap->shaper_pkt_length_adjust_min);
1065a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "shaper_pkt_length_adjust_max",
1066a590d564SJie Hai 		cap->shaper_pkt_length_adjust_max);
1067a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "sched_n_children_max",
1068a590d564SJie Hai 		cap->sched_n_children_max);
1069a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "sched_sp_n_priorities_max",
1070a590d564SJie Hai 		cap->sched_sp_n_priorities_max);
1071a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
1072a590d564SJie Hai 		cap->sched_wfq_n_children_per_group_max);
1073a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
1074a590d564SJie Hai 		cap->sched_wfq_n_groups_max);
1075a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
1076a590d564SJie Hai 		cap->sched_wfq_weight_max);
1077a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
1078a590d564SJie Hai 		cap->sched_wfq_packet_mode_supported);
1079a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
1080a590d564SJie Hai 		cap->sched_wfq_byte_mode_supported);
1081a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
1082a590d564SJie Hai 		cap->cman_wred_packet_mode_supported);
1083a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
1084a590d564SJie Hai 		cap->cman_wred_byte_mode_supported);
1085a590d564SJie Hai 	rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
1086a590d564SJie Hai 		cap->cman_head_drop_supported);
1087a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "cman_wred_context_n_max",
1088a590d564SJie Hai 		cap->cman_wred_context_n_max);
1089a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "cman_wred_context_private_n_max",
1090a590d564SJie Hai 		cap->cman_wred_context_private_n_max);
1091a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
1092a590d564SJie Hai 		cap->cman_wred_context_shared_n_max);
1093a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_nodes_per_context_max",
1094a590d564SJie Hai 		cap->cman_wred_context_shared_n_nodes_per_context_max);
1095a590d564SJie Hai 	rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_contexts_per_node_max",
1096a590d564SJie Hai 		cap->cman_wred_context_shared_n_contexts_per_node_max);
1097a590d564SJie Hai 	rte_tel_data_add_dict_uint_hex(d, "dynamic_update", cap->dynamic_update_mask, 0);
1098a590d564SJie Hai 	rte_tel_data_add_dict_uint_hex(d, "stats_mask", cap->stats_mask, 0);
1099a590d564SJie Hai }
1100a590d564SJie Hai 
1101a590d564SJie Hai static int
1102a590d564SJie Hai eth_dev_handle_port_tm_caps(const char *cmd __rte_unused,
1103a590d564SJie Hai 		const char *params,
1104a590d564SJie Hai 		struct rte_tel_data *d)
1105a590d564SJie Hai {
1106a590d564SJie Hai 	struct rte_tm_capabilities cap = {0};
1107a590d564SJie Hai 	struct rte_tm_error error = {0};
1108a590d564SJie Hai 	uint16_t port_id;
1109a590d564SJie Hai 	char *end_param;
1110a590d564SJie Hai 	int ret;
1111a590d564SJie Hai 
1112a590d564SJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, false);
1113a590d564SJie Hai 	if (ret != 0)
1114a590d564SJie Hai 		return ret;
1115a590d564SJie Hai 
1116a590d564SJie Hai 	ret = rte_tm_capabilities_get(port_id, &cap, &error);
1117a590d564SJie Hai 	if (ret != 0) {
11180e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
1119a590d564SJie Hai 			error.message ? error.message : "no stated reason",
1120a590d564SJie Hai 			error.type);
1121a590d564SJie Hai 		return ret;
1122a590d564SJie Hai 	}
1123a590d564SJie Hai 
1124a590d564SJie Hai 	rte_tel_data_start_dict(d);
1125a590d564SJie Hai 	eth_dev_add_tm_caps(d, &cap);
1126a590d564SJie Hai 
1127a590d564SJie Hai 	return 0;
1128a590d564SJie Hai }
1129a590d564SJie Hai 
11309e7533aeSJie Hai static void
11319e7533aeSJie Hai eth_dev_add_tm_level_basic_caps(struct rte_tel_data *d,
11329e7533aeSJie Hai 		struct rte_tm_level_capabilities *cap)
11339e7533aeSJie Hai {
11349e7533aeSJie Hai 	rte_tel_data_add_dict_uint(d, "n_nodes_max", cap->n_nodes_max);
11359e7533aeSJie Hai 	rte_tel_data_add_dict_uint(d, "n_nodes_nonleaf_max",
11369e7533aeSJie Hai 		cap->n_nodes_nonleaf_max);
11379e7533aeSJie Hai 	rte_tel_data_add_dict_uint(d, "n_nodes_leaf_max", cap->n_nodes_leaf_max);
11389e7533aeSJie Hai 	rte_tel_data_add_dict_int(d, "non_leaf_nodes_identical",
11399e7533aeSJie Hai 		cap->non_leaf_nodes_identical);
11409e7533aeSJie Hai 	rte_tel_data_add_dict_int(d, "leaf_nodes_identical",
11419e7533aeSJie Hai 		cap->leaf_nodes_identical);
11429e7533aeSJie Hai }
11439e7533aeSJie Hai 
11449e7533aeSJie Hai static void
11459e7533aeSJie Hai eth_dev_add_tm_level_nonleaf_caps(struct rte_tel_data *nonleaf,
11469e7533aeSJie Hai 		struct rte_tm_level_capabilities *cap)
11479e7533aeSJie Hai {
11489e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "shaper_private_supported",
11499e7533aeSJie Hai 		cap->nonleaf.shaper_private_supported);
11509e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "shaper_private_dual_rate_supported",
11519e7533aeSJie Hai 		cap->nonleaf.shaper_private_dual_rate_supported);
11529e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_min",
11539e7533aeSJie Hai 		cap->nonleaf.shaper_private_rate_min);
11549e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "shaper_private_rate_max",
11559e7533aeSJie Hai 		cap->nonleaf.shaper_private_rate_max);
11569e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "shaper_private_packet_mode_supported",
11579e7533aeSJie Hai 		cap->nonleaf.shaper_private_packet_mode_supported);
11589e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "shaper_private_byte_mode_supported",
11599e7533aeSJie Hai 		cap->nonleaf.shaper_private_byte_mode_supported);
11609e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "shaper_shared_n_max",
11619e7533aeSJie Hai 		cap->nonleaf.shaper_shared_n_max);
11629e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "shaper_shared_packet_mode_supported",
11639e7533aeSJie Hai 		cap->nonleaf.shaper_shared_packet_mode_supported);
11649e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "shaper_shared_byte_mode_supported",
11659e7533aeSJie Hai 		cap->nonleaf.shaper_shared_byte_mode_supported);
11669e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "sched_n_children_max",
11679e7533aeSJie Hai 		cap->nonleaf.sched_n_children_max);
11689e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "sched_sp_n_priorities_max",
11699e7533aeSJie Hai 		cap->nonleaf.sched_sp_n_priorities_max);
11709e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_children_per_group_max",
11719e7533aeSJie Hai 		cap->nonleaf.sched_wfq_n_children_per_group_max);
11729e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_n_groups_max",
11739e7533aeSJie Hai 		cap->nonleaf.sched_wfq_n_groups_max);
11749e7533aeSJie Hai 	rte_tel_data_add_dict_uint(nonleaf, "sched_wfq_weight_max",
11759e7533aeSJie Hai 		cap->nonleaf.sched_wfq_weight_max);
11769e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "sched_wfq_packet_mode_supported",
11779e7533aeSJie Hai 		cap->nonleaf.sched_wfq_packet_mode_supported);
11789e7533aeSJie Hai 	rte_tel_data_add_dict_int(nonleaf, "sched_wfq_byte_mode_supported",
11799e7533aeSJie Hai 		cap->nonleaf.sched_wfq_byte_mode_supported);
11809e7533aeSJie Hai 	rte_tel_data_add_dict_uint_hex(nonleaf, "stats_mask",
11819e7533aeSJie Hai 		cap->nonleaf.stats_mask, 0);
11829e7533aeSJie Hai }
11839e7533aeSJie Hai 
11849e7533aeSJie Hai static void
11859e7533aeSJie Hai eth_dev_add_tm_level_leaf_caps(struct rte_tel_data *leaf,
11869e7533aeSJie Hai 		struct rte_tm_level_capabilities *cap)
11879e7533aeSJie Hai {
11889e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "shaper_private_supported",
11899e7533aeSJie Hai 		cap->leaf.shaper_private_supported);
11909e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "shaper_private_dual_rate_supported",
11919e7533aeSJie Hai 		cap->leaf.shaper_private_dual_rate_supported);
11929e7533aeSJie Hai 	rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_min",
11939e7533aeSJie Hai 		cap->leaf.shaper_private_rate_min);
11949e7533aeSJie Hai 	rte_tel_data_add_dict_uint(leaf, "shaper_private_rate_max",
11959e7533aeSJie Hai 		cap->leaf.shaper_private_rate_max);
11969e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "shaper_private_packet_mode_supported",
11979e7533aeSJie Hai 		cap->leaf.shaper_private_packet_mode_supported);
11989e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "shaper_private_byte_mode_supported",
11999e7533aeSJie Hai 		cap->leaf.shaper_private_byte_mode_supported);
12009e7533aeSJie Hai 	rte_tel_data_add_dict_uint(leaf, "shaper_shared_n_max",
12019e7533aeSJie Hai 		cap->leaf.shaper_shared_n_max);
12029e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "shaper_shared_packet_mode_supported",
12039e7533aeSJie Hai 		cap->leaf.shaper_shared_packet_mode_supported);
12049e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "shaper_shared_byte_mode_supported",
12059e7533aeSJie Hai 		cap->leaf.shaper_shared_byte_mode_supported);
12069e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "cman_wred_packet_mode_supported",
12079e7533aeSJie Hai 		cap->leaf.cman_wred_packet_mode_supported);
12089e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "cman_wred_byte_mode_supported",
12099e7533aeSJie Hai 		cap->leaf.cman_wred_byte_mode_supported);
12109e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "cman_head_drop_supported",
12119e7533aeSJie Hai 		cap->leaf.cman_head_drop_supported);
12129e7533aeSJie Hai 	rte_tel_data_add_dict_int(leaf, "cman_wred_context_private_supported",
12139e7533aeSJie Hai 		cap->leaf.cman_wred_context_private_supported);
12149e7533aeSJie Hai 	rte_tel_data_add_dict_uint(leaf, "cman_wred_context_shared_n_max",
12159e7533aeSJie Hai 		cap->leaf.cman_wred_context_shared_n_max);
12169e7533aeSJie Hai 	rte_tel_data_add_dict_uint_hex(leaf, "stats_mask",
12179e7533aeSJie Hai 		cap->leaf.stats_mask, 0);
12189e7533aeSJie Hai }
12199e7533aeSJie Hai 
12209e7533aeSJie Hai static int
12219e7533aeSJie Hai eth_dev_parse_tm_params(char *params, uint32_t *result)
12229e7533aeSJie Hai {
12239e7533aeSJie Hai 	const char *splited_param;
12249e7533aeSJie Hai 	uint64_t ret;
12259e7533aeSJie Hai 
12269e7533aeSJie Hai 	splited_param = strtok(params, ",");
12279e7533aeSJie Hai 	if (!splited_param || strlen(splited_param) == 0 || !isdigit(*splited_param))
12289e7533aeSJie Hai 		return -EINVAL;
12299e7533aeSJie Hai 
12309e7533aeSJie Hai 	ret = strtoul(splited_param, &params, 0);
12319e7533aeSJie Hai 	if (*params != '\0')
12320e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(NOTICE,
12330e21c7c0SDavid Marchand 			"Extra parameters passed to ethdev telemetry command, ignoring");
12349e7533aeSJie Hai 
12359e7533aeSJie Hai 	if (ret >= UINT32_MAX)
12369e7533aeSJie Hai 		return -EINVAL;
12379e7533aeSJie Hai 
12389e7533aeSJie Hai 	*result = ret;
12399e7533aeSJie Hai 	return 0;
12409e7533aeSJie Hai }
12419e7533aeSJie Hai 
12429e7533aeSJie Hai static int
12439e7533aeSJie Hai eth_dev_handle_port_tm_level_caps(const char *cmd __rte_unused,
12449e7533aeSJie Hai 		const char *params,
12459e7533aeSJie Hai 		struct rte_tel_data *d)
12469e7533aeSJie Hai {
12479e7533aeSJie Hai 	struct rte_tm_level_capabilities cap = {0};
12489e7533aeSJie Hai 	struct rte_tm_error error = {0};
12499e7533aeSJie Hai 	struct rte_tel_data *nonleaf;
12509e7533aeSJie Hai 	struct rte_tel_data *leaf;
12519e7533aeSJie Hai 	uint32_t level_id;
12529e7533aeSJie Hai 	uint16_t port_id;
12539e7533aeSJie Hai 	char *end_param;
12549e7533aeSJie Hai 	int ret;
12559e7533aeSJie Hai 
12569e7533aeSJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
12579e7533aeSJie Hai 	if (ret != 0)
12589e7533aeSJie Hai 		return ret;
12599e7533aeSJie Hai 
12609e7533aeSJie Hai 	ret = eth_dev_parse_tm_params(end_param, &level_id);
12619e7533aeSJie Hai 	if (ret != 0)
12629e7533aeSJie Hai 		return ret;
12639e7533aeSJie Hai 
12649e7533aeSJie Hai 	ret = rte_tm_level_capabilities_get(port_id, level_id, &cap, &error);
12659e7533aeSJie Hai 	if (ret != 0) {
12660e21c7c0SDavid Marchand 		RTE_ETHDEV_LOG_LINE(ERR, "error: %s, error type: %u",
12679e7533aeSJie Hai 			error.message ? error.message : "no stated reason",
12689e7533aeSJie Hai 			error.type);
12699e7533aeSJie Hai 		return ret;
12709e7533aeSJie Hai 	}
12719e7533aeSJie Hai 
12729e7533aeSJie Hai 	rte_tel_data_start_dict(d);
12739e7533aeSJie Hai 	eth_dev_add_tm_level_basic_caps(d, &cap);
12749e7533aeSJie Hai 
12759e7533aeSJie Hai 	nonleaf = rte_tel_data_alloc();
12769e7533aeSJie Hai 	if (nonleaf == NULL)
12779e7533aeSJie Hai 		return -ENOMEM;
12789e7533aeSJie Hai 
12799e7533aeSJie Hai 	rte_tel_data_start_dict(nonleaf);
12809e7533aeSJie Hai 	eth_dev_add_tm_level_nonleaf_caps(nonleaf, &cap);
12819e7533aeSJie Hai 	rte_tel_data_add_dict_container(d, "nonleaf_cap", nonleaf, 0);
12829e7533aeSJie Hai 
12839e7533aeSJie Hai 	leaf = rte_tel_data_alloc();
12849e7533aeSJie Hai 	if (leaf == NULL) {
12859e7533aeSJie Hai 		rte_tel_data_free(nonleaf);
12869e7533aeSJie Hai 		return -ENOMEM;
12879e7533aeSJie Hai 	}
12889e7533aeSJie Hai 
12899e7533aeSJie Hai 	rte_tel_data_start_dict(leaf);
12909e7533aeSJie Hai 	eth_dev_add_tm_level_leaf_caps(leaf, &cap);
12919e7533aeSJie Hai 	rte_tel_data_add_dict_container(d, "leaf_cap", leaf, 0);
12929e7533aeSJie Hai 
12939e7533aeSJie Hai 	return 0;
12949e7533aeSJie Hai }
12959e7533aeSJie Hai 
129670b1ab3fSJie Hai static void
129770b1ab3fSJie Hai eth_dev_add_tm_node_basic_caps(struct rte_tel_data *node_data,
129870b1ab3fSJie Hai 		struct rte_tm_node_capabilities *capnode)
129970b1ab3fSJie Hai {
130070b1ab3fSJie Hai 	rte_tel_data_add_dict_int(node_data, "shaper_private_supported",
130170b1ab3fSJie Hai 		capnode->shaper_private_supported);
130270b1ab3fSJie Hai 	rte_tel_data_add_dict_int(node_data, "shaper_private_dual_rate_supported",
130370b1ab3fSJie Hai 		capnode->shaper_private_dual_rate_supported);
130470b1ab3fSJie Hai 	rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_min",
130570b1ab3fSJie Hai 		capnode->shaper_private_rate_min);
130670b1ab3fSJie Hai 	rte_tel_data_add_dict_uint(node_data, "shaper_private_rate_max",
130770b1ab3fSJie Hai 		capnode->shaper_private_rate_max);
130870b1ab3fSJie Hai 	rte_tel_data_add_dict_int(node_data, "shaper_private_packet_mode_supported",
130970b1ab3fSJie Hai 		capnode->shaper_private_packet_mode_supported);
131070b1ab3fSJie Hai 	rte_tel_data_add_dict_int(node_data, "shaper_private_byte_mode_supported",
131170b1ab3fSJie Hai 		capnode->shaper_private_byte_mode_supported);
131270b1ab3fSJie Hai 	rte_tel_data_add_dict_uint(node_data, "shaper_shared_n_max",
131370b1ab3fSJie Hai 		capnode->shaper_shared_n_max);
131470b1ab3fSJie Hai 	rte_tel_data_add_dict_int(node_data, "shaper_shared_packet_mode_supported",
131570b1ab3fSJie Hai 		capnode->shaper_shared_packet_mode_supported);
131670b1ab3fSJie Hai 	rte_tel_data_add_dict_int(node_data, "shaper_shared_byte_mode_supported",
131770b1ab3fSJie Hai 		capnode->shaper_shared_byte_mode_supported);
131870b1ab3fSJie Hai 	rte_tel_data_add_dict_uint_hex(node_data, "stats_mask",
131970b1ab3fSJie Hai 		capnode->stats_mask, 0);
132070b1ab3fSJie Hai }
132170b1ab3fSJie Hai 
132270b1ab3fSJie Hai static void
132370b1ab3fSJie Hai eth_dev_add_tm_type_node_caps(struct rte_tel_data *d, int is_leaf,
132470b1ab3fSJie Hai 		struct rte_tm_node_capabilities *cap)
132570b1ab3fSJie Hai {
132670b1ab3fSJie Hai 	rte_tel_data_add_dict_string(d, "node_type",
132770b1ab3fSJie Hai 				is_leaf == 0 ? "nonleaf" : "leaf");
132870b1ab3fSJie Hai 	if (is_leaf == 0) {
132970b1ab3fSJie Hai 		rte_tel_data_add_dict_uint(d, "children_max",
133070b1ab3fSJie Hai 			cap->nonleaf.sched_n_children_max);
133170b1ab3fSJie Hai 		rte_tel_data_add_dict_uint(d, "priorities_max",
133270b1ab3fSJie Hai 			cap->nonleaf.sched_sp_n_priorities_max);
133370b1ab3fSJie Hai 		rte_tel_data_add_dict_uint(d, "sched_wfq_n_children_per_group_max",
133470b1ab3fSJie Hai 			cap->nonleaf.sched_wfq_n_children_per_group_max);
133570b1ab3fSJie Hai 		rte_tel_data_add_dict_uint(d, "sched_wfq_n_groups_max",
133670b1ab3fSJie Hai 			cap->nonleaf.sched_wfq_n_groups_max);
133770b1ab3fSJie Hai 		rte_tel_data_add_dict_uint(d, "sched_wfq_weight_max",
133870b1ab3fSJie Hai 			cap->nonleaf.sched_wfq_weight_max);
133970b1ab3fSJie Hai 		rte_tel_data_add_dict_int(d, "sched_wfq_packet_mode_supported",
134070b1ab3fSJie Hai 			cap->nonleaf.sched_wfq_packet_mode_supported);
134170b1ab3fSJie Hai 		rte_tel_data_add_dict_int(d, "sched_wfq_byte_mode_supported",
134270b1ab3fSJie Hai 			cap->nonleaf.sched_wfq_byte_mode_supported);
134370b1ab3fSJie Hai 	} else {
134470b1ab3fSJie Hai 		rte_tel_data_add_dict_int(d, "cman_wred_packet_mode_supported",
134570b1ab3fSJie Hai 			cap->leaf.cman_wred_packet_mode_supported);
134670b1ab3fSJie Hai 		rte_tel_data_add_dict_int(d, "cman_wred_byte_mode_supported",
134770b1ab3fSJie Hai 			cap->leaf.cman_wred_byte_mode_supported);
134870b1ab3fSJie Hai 		rte_tel_data_add_dict_int(d, "cman_head_drop_supported",
134970b1ab3fSJie Hai 			cap->leaf.cman_head_drop_supported);
135070b1ab3fSJie Hai 		rte_tel_data_add_dict_int(d, "cman_wred_context_private_supported",
135170b1ab3fSJie Hai 			cap->leaf.cman_wred_context_private_supported);
135270b1ab3fSJie Hai 		rte_tel_data_add_dict_uint(d, "cman_wred_context_shared_n_max",
135370b1ab3fSJie Hai 			cap->leaf.cman_wred_context_shared_n_max);
135470b1ab3fSJie Hai 	}
135570b1ab3fSJie Hai }
135670b1ab3fSJie Hai 
135770b1ab3fSJie Hai static int
135870b1ab3fSJie Hai eth_dev_handle_port_tm_node_caps(const char *cmd __rte_unused,
135970b1ab3fSJie Hai 		const char *params,
136070b1ab3fSJie Hai 		struct rte_tel_data *d)
136170b1ab3fSJie Hai {
136270b1ab3fSJie Hai 	struct rte_tm_node_capabilities cap = {0};
136370b1ab3fSJie Hai 	struct rte_tm_error error = {0};
136470b1ab3fSJie Hai 	uint32_t node_id;
136570b1ab3fSJie Hai 	uint16_t port_id;
136670b1ab3fSJie Hai 	char *end_param;
136770b1ab3fSJie Hai 	int is_leaf;
136870b1ab3fSJie Hai 	int ret;
136970b1ab3fSJie Hai 
137070b1ab3fSJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
137170b1ab3fSJie Hai 	if (ret != 0)
137270b1ab3fSJie Hai 		return ret;
137370b1ab3fSJie Hai 
137470b1ab3fSJie Hai 	ret = eth_dev_parse_tm_params(end_param, &node_id);
137570b1ab3fSJie Hai 	if (ret != 0)
137670b1ab3fSJie Hai 		return ret;
137770b1ab3fSJie Hai 
137870b1ab3fSJie Hai 	ret = rte_tm_node_capabilities_get(port_id, node_id, &cap, &error);
137970b1ab3fSJie Hai 	if (ret != 0)
138070b1ab3fSJie Hai 		goto out;
138170b1ab3fSJie Hai 
138270b1ab3fSJie Hai 	ret = rte_tm_node_type_get(port_id, node_id, &is_leaf, &error);
138370b1ab3fSJie Hai 	if (ret != 0)
138470b1ab3fSJie Hai 		goto out;
138570b1ab3fSJie Hai 
138670b1ab3fSJie Hai 	rte_tel_data_start_dict(d);
138770b1ab3fSJie Hai 	eth_dev_add_tm_node_basic_caps(d, &cap);
138870b1ab3fSJie Hai 	eth_dev_add_tm_type_node_caps(d, is_leaf, &cap);
138970b1ab3fSJie Hai 
139070b1ab3fSJie Hai 	return 0;
139170b1ab3fSJie Hai out:
13920e21c7c0SDavid Marchand 	RTE_ETHDEV_LOG_LINE(WARNING, "error: %s, error type: %u",
139370b1ab3fSJie Hai 		error.message ? error.message : "no stated reason",
139470b1ab3fSJie Hai 		error.type);
139570b1ab3fSJie Hai 	return ret;
139670b1ab3fSJie Hai }
139770b1ab3fSJie Hai 
1398*d916d27eSJie Hai static void
1399*d916d27eSJie Hai eth_dev_add_reg_data(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info,
1400*d916d27eSJie Hai 		     uint32_t idx)
1401*d916d27eSJie Hai {
1402*d916d27eSJie Hai 	if (reg_info->width == sizeof(uint32_t))
1403*d916d27eSJie Hai 		rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name,
1404*d916d27eSJie Hai 			*((uint32_t *)reg_info->data + idx), 0);
1405*d916d27eSJie Hai 	else
1406*d916d27eSJie Hai 		rte_tel_data_add_dict_uint_hex(d, reg_info->names[idx].name,
1407*d916d27eSJie Hai 			*((uint64_t *)reg_info->data + idx), 0);
1408*d916d27eSJie Hai }
1409*d916d27eSJie Hai 
1410*d916d27eSJie Hai static int
1411*d916d27eSJie Hai eth_dev_store_regs(struct rte_tel_data *d, struct rte_dev_reg_info *reg_info)
1412*d916d27eSJie Hai {
1413*d916d27eSJie Hai 	struct rte_tel_data *groups[RTE_TEL_MAX_DICT_ENTRIES];
1414*d916d27eSJie Hai 	char group_name[RTE_TEL_MAX_STRING_LEN] = {0};
1415*d916d27eSJie Hai 	struct rte_tel_data *group = NULL;
1416*d916d27eSJie Hai 	uint32_t grp_num = 0;
1417*d916d27eSJie Hai 	uint32_t i, max_cap;
1418*d916d27eSJie Hai 	int ret;
1419*d916d27eSJie Hai 
1420*d916d27eSJie Hai 	rte_tel_data_start_dict(d);
1421*d916d27eSJie Hai 	rte_tel_data_add_dict_uint(d, "register_length", reg_info->length);
1422*d916d27eSJie Hai 	rte_tel_data_add_dict_uint(d, "register_width", reg_info->width);
1423*d916d27eSJie Hai 	rte_tel_data_add_dict_uint_hex(d, "register_offset", reg_info->offset, 0);
1424*d916d27eSJie Hai 	rte_tel_data_add_dict_uint_hex(d, "version", reg_info->version, 0);
1425*d916d27eSJie Hai 
1426*d916d27eSJie Hai 	max_cap = (RTE_TEL_MAX_DICT_ENTRIES - 4) * RTE_TEL_MAX_DICT_ENTRIES;
1427*d916d27eSJie Hai 	if (reg_info->length > max_cap) {
1428*d916d27eSJie Hai 		RTE_ETHDEV_LOG_LINE(WARNING,
1429*d916d27eSJie Hai 			"Registers to be displayed are reduced from %u to %u due to limited capacity",
1430*d916d27eSJie Hai 			reg_info->length, max_cap);
1431*d916d27eSJie Hai 		reg_info->length = max_cap;
1432*d916d27eSJie Hai 	}
1433*d916d27eSJie Hai 
1434*d916d27eSJie Hai 	for (i = 0; i < reg_info->length; i++) {
1435*d916d27eSJie Hai 		if (i % RTE_TEL_MAX_DICT_ENTRIES != 0) {
1436*d916d27eSJie Hai 			eth_dev_add_reg_data(group, reg_info, i);
1437*d916d27eSJie Hai 			continue;
1438*d916d27eSJie Hai 		}
1439*d916d27eSJie Hai 
1440*d916d27eSJie Hai 		group = rte_tel_data_alloc();
1441*d916d27eSJie Hai 		if (group == NULL) {
1442*d916d27eSJie Hai 			ret = -ENOMEM;
1443*d916d27eSJie Hai 			RTE_ETHDEV_LOG_LINE(WARNING, "No enough memory for group data");
1444*d916d27eSJie Hai 			goto out;
1445*d916d27eSJie Hai 		}
1446*d916d27eSJie Hai 		groups[grp_num++] = group;
1447*d916d27eSJie Hai 		rte_tel_data_start_dict(group);
1448*d916d27eSJie Hai 		eth_dev_add_reg_data(group, reg_info, i);
1449*d916d27eSJie Hai 	}
1450*d916d27eSJie Hai 
1451*d916d27eSJie Hai 	for (i = 0; i < grp_num; i++) {
1452*d916d27eSJie Hai 		snprintf(group_name, RTE_TEL_MAX_STRING_LEN, "group_%u", i);
1453*d916d27eSJie Hai 		rte_tel_data_add_dict_container(d, group_name, groups[i], 0);
1454*d916d27eSJie Hai 	}
1455*d916d27eSJie Hai 	return 0;
1456*d916d27eSJie Hai out:
1457*d916d27eSJie Hai 	for (i = 0; i < grp_num; i++)
1458*d916d27eSJie Hai 		rte_tel_data_free(groups[i]);
1459*d916d27eSJie Hai 
1460*d916d27eSJie Hai 	return ret;
1461*d916d27eSJie Hai }
1462*d916d27eSJie Hai 
1463*d916d27eSJie Hai static int
1464*d916d27eSJie Hai eth_dev_get_port_regs(int port_id, struct rte_tel_data *d, char *filter)
1465*d916d27eSJie Hai {
1466*d916d27eSJie Hai 	struct rte_dev_reg_info reg_info;
1467*d916d27eSJie Hai 	int ret;
1468*d916d27eSJie Hai 
1469*d916d27eSJie Hai 	memset(&reg_info, 0, sizeof(reg_info));
1470*d916d27eSJie Hai 	reg_info.filter = filter;
1471*d916d27eSJie Hai 
1472*d916d27eSJie Hai 	ret = rte_eth_dev_get_reg_info_ext(port_id, &reg_info);
1473*d916d27eSJie Hai 	if (ret != 0) {
1474*d916d27eSJie Hai 		RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1475*d916d27eSJie Hai 		return ret;
1476*d916d27eSJie Hai 	}
1477*d916d27eSJie Hai 
1478*d916d27eSJie Hai 	reg_info.data = calloc(reg_info.length, reg_info.width);
1479*d916d27eSJie Hai 	if (reg_info.data == NULL) {
1480*d916d27eSJie Hai 		RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.data");
1481*d916d27eSJie Hai 		return -ENOMEM;
1482*d916d27eSJie Hai 	}
1483*d916d27eSJie Hai 
1484*d916d27eSJie Hai 	reg_info.names = calloc(reg_info.length, sizeof(struct rte_eth_reg_name));
1485*d916d27eSJie Hai 	if (reg_info.names == NULL) {
1486*d916d27eSJie Hai 		RTE_ETHDEV_LOG_LINE(ERR, "Failed to allocate memory for reg_info.names");
1487*d916d27eSJie Hai 		free(reg_info.data);
1488*d916d27eSJie Hai 		return -ENOMEM;
1489*d916d27eSJie Hai 	}
1490*d916d27eSJie Hai 
1491*d916d27eSJie Hai 	ret = rte_eth_dev_get_reg_info_ext(port_id, &reg_info);
1492*d916d27eSJie Hai 	if (ret != 0) {
1493*d916d27eSJie Hai 		RTE_ETHDEV_LOG_LINE(ERR, "Failed to get device reg info: %d", ret);
1494*d916d27eSJie Hai 		ret = -EINVAL;
1495*d916d27eSJie Hai 		goto out;
1496*d916d27eSJie Hai 	}
1497*d916d27eSJie Hai 
1498*d916d27eSJie Hai 	ret = eth_dev_store_regs(d, &reg_info);
1499*d916d27eSJie Hai out:
1500*d916d27eSJie Hai 	free(reg_info.data);
1501*d916d27eSJie Hai 	free(reg_info.names);
1502*d916d27eSJie Hai 
1503*d916d27eSJie Hai 	return ret;
1504*d916d27eSJie Hai }
1505*d916d27eSJie Hai 
1506*d916d27eSJie Hai static int
1507*d916d27eSJie Hai eth_dev_handle_port_regs(const char *cmd __rte_unused,
1508*d916d27eSJie Hai 		const char *params,
1509*d916d27eSJie Hai 		struct rte_tel_data *d)
1510*d916d27eSJie Hai {
1511*d916d27eSJie Hai 	char *filter, *end_param;
1512*d916d27eSJie Hai 	uint16_t port_id;
1513*d916d27eSJie Hai 	int ret;
1514*d916d27eSJie Hai 
1515*d916d27eSJie Hai 	ret = eth_dev_parse_port_params(params, &port_id, &end_param, true);
1516*d916d27eSJie Hai 	if (ret != 0)
1517*d916d27eSJie Hai 		return ret;
1518*d916d27eSJie Hai 
1519*d916d27eSJie Hai 	filter = strtok(end_param, ",");
1520*d916d27eSJie Hai 	if (filter != NULL && strlen(filter) == 0)
1521*d916d27eSJie Hai 		filter = NULL;
1522*d916d27eSJie Hai 
1523*d916d27eSJie Hai 	return eth_dev_get_port_regs(port_id, d, filter);
1524*d916d27eSJie Hai }
1525*d916d27eSJie Hai 
15266f96937dSRobin Jarry static int eth_dev_telemetry_do(const char *cmd, const char *params, void *arg,
15276f96937dSRobin Jarry 		struct rte_tel_data *d)
15286f96937dSRobin Jarry {
15296f96937dSRobin Jarry 	telemetry_cb fn = arg;
15306f96937dSRobin Jarry 	int ret;
15316f96937dSRobin Jarry 
15326f96937dSRobin Jarry 	/* Protect against port removal while invoking callback, calling ethdev API. */
15336f96937dSRobin Jarry 	rte_spinlock_lock(rte_mcfg_ethdev_get_lock());
15346f96937dSRobin Jarry 	ret = fn(cmd, params, d);
15356f96937dSRobin Jarry 	rte_spinlock_unlock(rte_mcfg_ethdev_get_lock());
15366f96937dSRobin Jarry 
15376f96937dSRobin Jarry 	return ret;
15386f96937dSRobin Jarry }
15396f96937dSRobin Jarry 
15404fe767acSJie Hai RTE_INIT(ethdev_init_telemetry)
15414fe767acSJie Hai {
15426f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/list",
15436f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_list,
15444fe767acSJie Hai 			"Returns list of available ethdev ports. Takes no parameters");
15456f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/stats",
15466f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_stats,
15474fe767acSJie Hai 			"Returns the common stats for a port. Parameters: int port_id");
15486f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/xstats",
15496f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_xstats,
15504fe767acSJie Hai 			"Returns the extended stats for a port. Parameters: int port_id,hide_zero=true|false(Optional for indicates hide zero xstats)");
15514fe767acSJie Hai #ifndef RTE_EXEC_ENV_WINDOWS
15526f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/dump_priv",
15536f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_dump_priv,
15544fe767acSJie Hai 			"Returns dump private information for a port. Parameters: int port_id");
15554fe767acSJie Hai #endif
15566f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/link_status",
15576f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_link_status,
15584fe767acSJie Hai 			"Returns the link status for a port. Parameters: int port_id");
15596f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/info",
15606f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_info,
15614fe767acSJie Hai 			"Returns the device info for a port. Parameters: int port_id");
15626f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/module_eeprom",
15636f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_module_eeprom,
15644fe767acSJie Hai 			"Returns module EEPROM info with SFF specs. Parameters: int port_id");
15656f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/macs",
15666f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_macs,
15676732ae1cSDengdui Huang 			"Returns the MAC addresses for a port. Parameters: int port_id");
15686f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/flow_ctrl",
15696f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_flow_ctrl,
1570499c8486SJie Hai 			"Returns flow ctrl info for a port. Parameters: int port_id");
15716f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/rx_queue",
15726f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_rxq,
1573f38f6265SJie Hai 			"Returns Rx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
15746f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/tx_queue",
15756f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_txq,
15761a479610SJie Hai 			"Returns Tx queue info for a port. Parameters: int port_id, int queue_id (Optional if only one queue)");
15776f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/dcb",
15786f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_dcb,
157966f3e047SJie Hai 			"Returns DCB info for a port. Parameters: int port_id");
15806f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/rss_info",
15816f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_rss_info,
1582fde1adbfSJie Hai 			"Returns RSS info for a port. Parameters: int port_id");
15836f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/fec",
15846f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_fec,
158585576ba6SJie Hai 			"Returns FEC info for a port. Parameters: int port_id");
15866f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/vlan",
15876f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_vlan,
158819f39522SJie Hai 			"Returns VLAN info for a port. Parameters: int port_id");
15896f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/tm_capability",
15906f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_tm_caps,
1591a590d564SJie Hai 			"Returns TM Capabilities info for a port. Parameters: int port_id");
15926f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/tm_level_capability",
15936f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_tm_level_caps,
15949e7533aeSJie Hai 			"Returns TM Level Capabilities info for a port. Parameters: int port_id, int level_id (see tm_capability for the max)");
15956f96937dSRobin Jarry 	rte_telemetry_register_cmd_arg("/ethdev/tm_node_capability",
15966f96937dSRobin Jarry 			eth_dev_telemetry_do, eth_dev_handle_port_tm_node_caps,
159770b1ab3fSJie Hai 			"Returns TM Node Capabilities info for a port. Parameters: int port_id, int node_id (see tm_capability for the max)");
1598*d916d27eSJie Hai 	rte_telemetry_register_cmd("/ethdev/regs", eth_dev_handle_port_regs,
1599*d916d27eSJie Hai 			"Returns all or filtered registers info for a port. Parameters: int port_id, string module_name (Optional if show all)");
16004fe767acSJie Hai }
1601