xref: /dpdk/app/proc-info/main.c (revision f8dbaebbf1c9efcbb2e2354b341ed62175466a57)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2017 Intel Corporation
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdint.h>
8 #include <stdbool.h>
9 #include <errno.h>
10 #include <stdarg.h>
11 #include <inttypes.h>
12 #include <sys/queue.h>
13 #include <stdlib.h>
14 #include <getopt.h>
15 #include <unistd.h>
16 #include <strings.h>
17 
18 #include <rte_eal.h>
19 #include <rte_common.h>
20 #include <rte_debug.h>
21 #include <rte_ethdev.h>
22 #include <rte_malloc.h>
23 #include <rte_memory.h>
24 #include <rte_memzone.h>
25 #include <rte_launch.h>
26 #include <rte_tailq.h>
27 #include <rte_per_lcore.h>
28 #include <rte_lcore.h>
29 #include <rte_log.h>
30 #include <rte_branch_prediction.h>
31 #include <rte_string_fns.h>
32 #ifdef RTE_LIB_METRICS
33 #include <rte_metrics.h>
34 #endif
35 #include <rte_cycles.h>
36 #ifdef RTE_LIB_SECURITY
37 #include <rte_security.h>
38 #endif
39 #include <rte_cryptodev.h>
40 #include <rte_tm.h>
41 #include <rte_hexdump.h>
42 
43 /* Maximum long option length for option parsing. */
44 #define MAX_LONG_OPT_SZ 64
45 #define MAX_STRING_LEN 256
46 
47 #define STATS_BDR_FMT "========================================"
48 #define STATS_BDR_STR(w, s) printf("%.*s%s%.*s\n", w, \
49 	STATS_BDR_FMT, s, w, STATS_BDR_FMT)
50 
51 /**< mask of enabled ports */
52 static unsigned long enabled_port_mask;
53 /**< Enable stats. */
54 static uint32_t enable_stats;
55 /**< Enable xstats. */
56 static uint32_t enable_xstats;
57 /**< Enable collectd format*/
58 static uint32_t enable_collectd_format;
59 /**< FD to send collectd format messages to STDOUT*/
60 static int stdout_fd;
61 /**< Host id process is running on */
62 static char host_id[MAX_LONG_OPT_SZ];
63 #ifdef RTE_LIB_METRICS
64 /**< Enable metrics. */
65 static uint32_t enable_metrics;
66 #endif
67 /**< Enable stats reset. */
68 static uint32_t reset_stats;
69 /**< Enable xstats reset. */
70 static uint32_t reset_xstats;
71 /**< Enable memory info. */
72 static uint32_t mem_info;
73 /**< Enable displaying xstat name. */
74 static uint32_t enable_xstats_name;
75 static char *xstats_name;
76 
77 /**< Enable xstats by ids. */
78 #define MAX_NB_XSTATS_IDS 1024
79 static uint32_t nb_xstats_ids;
80 static uint64_t xstats_ids[MAX_NB_XSTATS_IDS];
81 
82 /* show border */
83 static char bdr_str[MAX_STRING_LEN];
84 
85 /**< Enable show port. */
86 static uint32_t enable_shw_port;
87 /**< Enable show tm. */
88 static uint32_t enable_shw_tm;
89 /**< Enable show crypto. */
90 static uint32_t enable_shw_crypto;
91 /**< Enable show ring. */
92 static uint32_t enable_shw_ring;
93 static char *ring_name;
94 /**< Enable show mempool. */
95 static uint32_t enable_shw_mempool;
96 static char *mempool_name;
97 /**< Enable iter mempool. */
98 static uint32_t enable_iter_mempool;
99 static char *mempool_iter_name;
100 /**< Enable dump regs. */
101 static uint32_t enable_dump_regs;
102 static char *dump_regs_file_prefix;
103 
104 /**< display usage */
105 static void
106 proc_info_usage(const char *prgname)
107 {
108 	printf("%s [EAL options] -- -p PORTMASK\n"
109 		"  -m to display DPDK memory zones, segments and TAILQ information\n"
110 		"  -p PORTMASK: hexadecimal bitmask of ports to retrieve stats for\n"
111 		"  --stats: to display port statistics, enabled by default\n"
112 		"  --xstats: to display extended port statistics, disabled by "
113 			"default\n"
114 #ifdef RTE_LIB_METRICS
115 		"  --metrics: to display derived metrics of the ports, disabled by "
116 			"default\n"
117 #endif
118 		"  --xstats-name NAME: to display single xstat id by NAME\n"
119 		"  --xstats-ids IDLIST: to display xstat values by id. "
120 			"The argument is comma-separated list of xstat ids to print out.\n"
121 		"  --stats-reset: to reset port statistics\n"
122 		"  --xstats-reset: to reset port extended statistics\n"
123 		"  --collectd-format: to print statistics to STDOUT in expected by collectd format\n"
124 		"  --host-id STRING: host id used to identify the system process is running on\n"
125 		"  --show-port: to display ports information\n"
126 		"  --show-tm: to display traffic manager information for ports\n"
127 		"  --show-crypto: to display crypto information\n"
128 		"  --show-ring[=name]: to display ring information\n"
129 		"  --show-mempool[=name]: to display mempool information\n"
130 		"  --iter-mempool=name: iterate mempool elements to display content\n"
131 		"  --dump-regs=file-prefix: dump registers to file with the file-prefix\n",
132 		prgname);
133 }
134 
135 /*
136  * Parse the portmask provided at run time.
137  */
138 static int
139 parse_portmask(const char *portmask)
140 {
141 	char *end = NULL;
142 
143 	errno = 0;
144 
145 	/* parse hexadecimal string */
146 	enabled_port_mask = strtoul(portmask, &end, 16);
147 	if (portmask[0] == '\0' || end == NULL || *end != '\0' || errno != 0) {
148 		fprintf(stderr, "Invalid portmask '%s'\n", portmask);
149 		return -1;
150 	}
151 
152 	return 0;
153 }
154 
155 /*
156  * Parse ids value list into array
157  */
158 static int
159 parse_xstats_ids(char *list, uint64_t *ids, int limit) {
160 	int length;
161 	char *token;
162 	char *ctx = NULL;
163 	char *endptr;
164 
165 	length = 0;
166 	token = strtok_r(list, ",", &ctx);
167 	while (token != NULL) {
168 		ids[length] = strtoull(token, &endptr, 10);
169 		if (*endptr != '\0')
170 			return -EINVAL;
171 
172 		length++;
173 		if (length >= limit)
174 			return -E2BIG;
175 
176 		token = strtok_r(NULL, ",", &ctx);
177 	}
178 
179 	return length;
180 }
181 
182 static int
183 proc_info_preparse_args(int argc, char **argv)
184 {
185 	char *prgname = argv[0];
186 	int i;
187 
188 	for (i = 0; i < argc; i++) {
189 		/* Print stats or xstats to STDOUT in collectd format */
190 		if (!strncmp(argv[i], "--collectd-format", MAX_LONG_OPT_SZ)) {
191 			enable_collectd_format = 1;
192 			stdout_fd = dup(STDOUT_FILENO);
193 			close(STDOUT_FILENO);
194 		}
195 		if (!strncmp(argv[i], "--host-id", MAX_LONG_OPT_SZ)) {
196 			if ((i + 1) == argc) {
197 				printf("Invalid host id or not specified\n");
198 				proc_info_usage(prgname);
199 				return -1;
200 			}
201 			strlcpy(host_id, argv[i + 1], sizeof(host_id));
202 		}
203 	}
204 
205 	if (!strlen(host_id)) {
206 		int err = gethostname(host_id, MAX_LONG_OPT_SZ-1);
207 
208 		if (err)
209 			strlcpy(host_id, "unknown", sizeof(host_id));
210 	}
211 
212 	return 0;
213 }
214 
215 /* Parse the argument given in the command line of the application */
216 static int
217 proc_info_parse_args(int argc, char **argv)
218 {
219 	int opt;
220 	int option_index;
221 	char *prgname = argv[0];
222 	static struct option long_option[] = {
223 		{"stats", 0, NULL, 0},
224 		{"stats-reset", 0, NULL, 0},
225 		{"xstats", 0, NULL, 0},
226 #ifdef RTE_LIB_METRICS
227 		{"metrics", 0, NULL, 0},
228 #endif
229 		{"xstats-reset", 0, NULL, 0},
230 		{"xstats-name", required_argument, NULL, 1},
231 		{"collectd-format", 0, NULL, 0},
232 		{"xstats-ids", 1, NULL, 1},
233 		{"host-id", 0, NULL, 0},
234 		{"show-port", 0, NULL, 0},
235 		{"show-tm", 0, NULL, 0},
236 		{"show-crypto", 0, NULL, 0},
237 		{"show-ring", optional_argument, NULL, 0},
238 		{"show-mempool", optional_argument, NULL, 0},
239 		{"iter-mempool", required_argument, NULL, 0},
240 		{"dump-regs", required_argument, NULL, 0},
241 		{NULL, 0, 0, 0}
242 	};
243 
244 	if (argc == 1)
245 		proc_info_usage(prgname);
246 
247 	/* Parse command line */
248 	while ((opt = getopt_long(argc, argv, "p:m",
249 			long_option, &option_index)) != EOF) {
250 		switch (opt) {
251 		/* portmask */
252 		case 'p':
253 			if (parse_portmask(optarg) < 0) {
254 				proc_info_usage(prgname);
255 				return -1;
256 			}
257 			break;
258 		case 'm':
259 			mem_info = 1;
260 			break;
261 		case 0:
262 			/* Print stats */
263 			if (!strncmp(long_option[option_index].name, "stats",
264 					MAX_LONG_OPT_SZ))
265 				enable_stats = 1;
266 			/* Print xstats */
267 			else if (!strncmp(long_option[option_index].name, "xstats",
268 					MAX_LONG_OPT_SZ))
269 				enable_xstats = 1;
270 #ifdef RTE_LIB_METRICS
271 			else if (!strncmp(long_option[option_index].name,
272 					"metrics",
273 					MAX_LONG_OPT_SZ))
274 				enable_metrics = 1;
275 #endif
276 			/* Reset stats */
277 			if (!strncmp(long_option[option_index].name, "stats-reset",
278 					MAX_LONG_OPT_SZ))
279 				reset_stats = 1;
280 			/* Reset xstats */
281 			else if (!strncmp(long_option[option_index].name, "xstats-reset",
282 					MAX_LONG_OPT_SZ))
283 				reset_xstats = 1;
284 			else if (!strncmp(long_option[option_index].name,
285 					"show-port", MAX_LONG_OPT_SZ))
286 				enable_shw_port = 1;
287 			else if (!strncmp(long_option[option_index].name,
288 					"show-tm", MAX_LONG_OPT_SZ))
289 				enable_shw_tm = 1;
290 			else if (!strncmp(long_option[option_index].name,
291 					"show-crypto", MAX_LONG_OPT_SZ))
292 				enable_shw_crypto = 1;
293 			else if (!strncmp(long_option[option_index].name,
294 					"show-ring", MAX_LONG_OPT_SZ)) {
295 				enable_shw_ring = 1;
296 				ring_name = optarg;
297 			} else if (!strncmp(long_option[option_index].name,
298 					"show-mempool", MAX_LONG_OPT_SZ)) {
299 				enable_shw_mempool = 1;
300 				mempool_name = optarg;
301 			} else if (!strncmp(long_option[option_index].name,
302 					"iter-mempool", MAX_LONG_OPT_SZ)) {
303 				enable_iter_mempool = 1;
304 				mempool_iter_name = optarg;
305 			} else if (!strncmp(long_option[option_index].name,
306 					"dump-regs", MAX_LONG_OPT_SZ)) {
307 				enable_dump_regs = 1;
308 				dump_regs_file_prefix = optarg;
309 			}
310 			break;
311 		case 1:
312 			/* Print xstat single value given by name*/
313 			if (!strncmp(long_option[option_index].name,
314 					"xstats-name", MAX_LONG_OPT_SZ)) {
315 				enable_xstats_name = 1;
316 				xstats_name = optarg;
317 				printf("name:%s:%s\n",
318 						long_option[option_index].name,
319 						optarg);
320 			} else if (!strncmp(long_option[option_index].name,
321 					"xstats-ids",
322 					MAX_LONG_OPT_SZ))	{
323 				int ret = parse_xstats_ids(optarg,
324 						xstats_ids, MAX_NB_XSTATS_IDS);
325 				if (ret <= 0) {
326 					printf("xstats-id list parse error.\n");
327 					return -1;
328 				}
329 				nb_xstats_ids = ret;
330 			}
331 			break;
332 		default:
333 			proc_info_usage(prgname);
334 			return -1;
335 		}
336 	}
337 	return 0;
338 }
339 
340 static void
341 meminfo_display(void)
342 {
343 	printf("----------- MEMORY_SEGMENTS -----------\n");
344 	rte_dump_physmem_layout(stdout);
345 	printf("--------- END_MEMORY_SEGMENTS ---------\n");
346 
347 	printf("------------ MEMORY_ZONES -------------\n");
348 	rte_memzone_dump(stdout);
349 	printf("---------- END_MEMORY_ZONES -----------\n");
350 
351 	printf("------------- TAIL_QUEUES -------------\n");
352 	rte_dump_tailq(stdout);
353 	printf("---------- END_TAIL_QUEUES ------------\n");
354 }
355 
356 static void
357 nic_stats_display(uint16_t port_id)
358 {
359 	struct rte_eth_stats stats;
360 	uint8_t i;
361 
362 	static const char *nic_stats_border = "########################";
363 
364 	rte_eth_stats_get(port_id, &stats);
365 	printf("\n  %s NIC statistics for port %-2d %s\n",
366 		   nic_stats_border, port_id, nic_stats_border);
367 
368 	printf("  RX-packets: %-10"PRIu64"  RX-errors:  %-10"PRIu64
369 	       "  RX-bytes:  %-10"PRIu64"\n", stats.ipackets, stats.ierrors,
370 	       stats.ibytes);
371 	printf("  RX-nombuf:  %-10"PRIu64"\n", stats.rx_nombuf);
372 	printf("  TX-packets: %-10"PRIu64"  TX-errors:  %-10"PRIu64
373 	       "  TX-bytes:  %-10"PRIu64"\n", stats.opackets, stats.oerrors,
374 	       stats.obytes);
375 
376 	printf("\n");
377 	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
378 		printf("  Stats reg %2d RX-packets: %-10"PRIu64
379 		       "  RX-errors: %-10"PRIu64
380 		       "  RX-bytes: %-10"PRIu64"\n",
381 		       i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
382 	}
383 
384 	printf("\n");
385 	for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
386 		printf("  Stats reg %2d TX-packets: %-10"PRIu64
387 		       "  TX-bytes: %-10"PRIu64"\n",
388 		       i, stats.q_opackets[i], stats.q_obytes[i]);
389 	}
390 
391 	printf("  %s############################%s\n",
392 		   nic_stats_border, nic_stats_border);
393 }
394 
395 static void
396 nic_stats_clear(uint16_t port_id)
397 {
398 	printf("\n Clearing NIC stats for port %d\n", port_id);
399 	rte_eth_stats_reset(port_id);
400 	printf("\n  NIC statistics for port %d cleared\n", port_id);
401 }
402 
403 static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len,
404 				      const char *cnt_name) {
405 	char *type_end = strrchr(cnt_name, '_');
406 
407 	if ((type_end != NULL) &&
408 	    (strncmp(cnt_name, "rx_", strlen("rx_")) == 0)) {
409 		if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
410 			strlcpy(cnt_type, "if_rx_errors", cnt_type_len);
411 		else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0)
412 			strlcpy(cnt_type, "if_rx_dropped", cnt_type_len);
413 		else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0)
414 			strlcpy(cnt_type, "if_rx_octets", cnt_type_len);
415 		else if (strncmp(type_end, "_packets", strlen("_packets")) == 0)
416 			strlcpy(cnt_type, "if_rx_packets", cnt_type_len);
417 		else if (strncmp(type_end, "_placement",
418 				 strlen("_placement")) == 0)
419 			strlcpy(cnt_type, "if_rx_errors", cnt_type_len);
420 		else if (strncmp(type_end, "_buff", strlen("_buff")) == 0)
421 			strlcpy(cnt_type, "if_rx_errors", cnt_type_len);
422 		else
423 			/* Does not fit obvious type: use a more generic one */
424 			strlcpy(cnt_type, "derive", cnt_type_len);
425 	} else if ((type_end != NULL) &&
426 		(strncmp(cnt_name, "tx_", strlen("tx_"))) == 0) {
427 		if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
428 			strlcpy(cnt_type, "if_tx_errors", cnt_type_len);
429 		else if (strncmp(type_end, "_dropped", strlen("_dropped")) == 0)
430 			strlcpy(cnt_type, "if_tx_dropped", cnt_type_len);
431 		else if (strncmp(type_end, "_bytes", strlen("_bytes")) == 0)
432 			strlcpy(cnt_type, "if_tx_octets", cnt_type_len);
433 		else if (strncmp(type_end, "_packets", strlen("_packets")) == 0)
434 			strlcpy(cnt_type, "if_tx_packets", cnt_type_len);
435 		else
436 			/* Does not fit obvious type: use a more generic one */
437 			strlcpy(cnt_type, "derive", cnt_type_len);
438 	} else if ((type_end != NULL) &&
439 		   (strncmp(cnt_name, "flow_", strlen("flow_"))) == 0) {
440 		if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
441 			strlcpy(cnt_type, "filter_result", cnt_type_len);
442 		else if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
443 			strlcpy(cnt_type, "errors", cnt_type_len);
444 	} else if ((type_end != NULL) &&
445 		   (strncmp(cnt_name, "mac_", strlen("mac_"))) == 0) {
446 		if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
447 			strlcpy(cnt_type, "errors", cnt_type_len);
448 	} else {
449 		/* Does not fit obvious type, or strrchr error: */
450 		/* use a more generic type */
451 		strlcpy(cnt_type, "derive", cnt_type_len);
452 	}
453 }
454 
455 static void
456 nic_xstats_by_name_display(uint16_t port_id, char *name)
457 {
458 	uint64_t id;
459 
460 	printf("###### NIC statistics for port %-2d, statistic name '%s':\n",
461 			   port_id, name);
462 
463 	if (rte_eth_xstats_get_id_by_name(port_id, name, &id) == 0)
464 		printf("%s: %"PRIu64"\n", name, id);
465 	else
466 		printf("Statistic not found...\n");
467 
468 }
469 
470 static void
471 nic_xstats_by_ids_display(uint16_t port_id, uint64_t *ids, int len)
472 {
473 	struct rte_eth_xstat_name *xstats_names;
474 	uint64_t *values;
475 	int ret, i;
476 	static const char *nic_stats_border = "########################";
477 
478 	values = malloc(sizeof(*values) * len);
479 	if (values == NULL) {
480 		printf("Cannot allocate memory for xstats\n");
481 		return;
482 	}
483 
484 	xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
485 	if (xstats_names == NULL) {
486 		printf("Cannot allocate memory for xstat names\n");
487 		free(values);
488 		return;
489 	}
490 
491 	if (len != rte_eth_xstats_get_names_by_id(
492 			port_id, xstats_names, len, ids)) {
493 		printf("Cannot get xstat names\n");
494 		goto err;
495 	}
496 
497 	printf("###### NIC extended statistics for port %-2d #########\n",
498 			   port_id);
499 	printf("%s############################\n", nic_stats_border);
500 	ret = rte_eth_xstats_get_by_id(port_id, ids, values, len);
501 	if (ret < 0 || ret > len) {
502 		printf("Cannot get xstats\n");
503 		goto err;
504 	}
505 
506 	for (i = 0; i < len; i++)
507 		printf("%s: %"PRIu64"\n",
508 			xstats_names[i].name,
509 			values[i]);
510 
511 	printf("%s############################\n", nic_stats_border);
512 err:
513 	free(values);
514 	free(xstats_names);
515 }
516 
517 static void
518 nic_xstats_display(uint16_t port_id)
519 {
520 	struct rte_eth_xstat_name *xstats_names;
521 	uint64_t *values;
522 	int len, ret, i;
523 	static const char *nic_stats_border = "########################";
524 
525 	len = rte_eth_xstats_get_names_by_id(port_id, NULL, 0, NULL);
526 	if (len < 0) {
527 		printf("Cannot get xstats count\n");
528 		return;
529 	}
530 	values = malloc(sizeof(*values) * len);
531 	if (values == NULL) {
532 		printf("Cannot allocate memory for xstats\n");
533 		return;
534 	}
535 
536 	xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
537 	if (xstats_names == NULL) {
538 		printf("Cannot allocate memory for xstat names\n");
539 		free(values);
540 		return;
541 	}
542 	if (len != rte_eth_xstats_get_names_by_id(
543 			port_id, xstats_names, len, NULL)) {
544 		printf("Cannot get xstat names\n");
545 		goto err;
546 	}
547 
548 	printf("###### NIC extended statistics for port %-2d #########\n",
549 			   port_id);
550 	printf("%s############################\n",
551 			   nic_stats_border);
552 	ret = rte_eth_xstats_get_by_id(port_id, NULL, values, len);
553 	if (ret < 0 || ret > len) {
554 		printf("Cannot get xstats\n");
555 		goto err;
556 	}
557 
558 	for (i = 0; i < len; i++) {
559 		if (enable_collectd_format) {
560 			char counter_type[MAX_STRING_LEN];
561 			char buf[MAX_STRING_LEN];
562 			size_t n;
563 
564 			collectd_resolve_cnt_type(counter_type,
565 						  sizeof(counter_type),
566 						  xstats_names[i].name);
567 			n = snprintf(buf, MAX_STRING_LEN,
568 				"PUTVAL %s/dpdkstat-port.%u/%s-%s N:%"
569 				PRIu64"\n", host_id, port_id, counter_type,
570 				xstats_names[i].name, values[i]);
571 			if (n > sizeof(buf) - 1)
572 				n = sizeof(buf) - 1;
573 			ret = write(stdout_fd, buf, n);
574 			if (ret < 0)
575 				goto err;
576 		} else {
577 			printf("%s: %"PRIu64"\n", xstats_names[i].name,
578 					values[i]);
579 		}
580 	}
581 
582 	printf("%s############################\n",
583 			   nic_stats_border);
584 err:
585 	free(values);
586 	free(xstats_names);
587 }
588 
589 static void
590 nic_xstats_clear(uint16_t port_id)
591 {
592 	int ret;
593 
594 	printf("\n Clearing NIC xstats for port %d\n", port_id);
595 	ret = rte_eth_xstats_reset(port_id);
596 	if (ret != 0) {
597 		printf("\n Error clearing xstats for port %d: %s\n", port_id,
598 		       strerror(-ret));
599 		return;
600 	}
601 
602 	printf("\n  NIC extended statistics for port %d cleared\n", port_id);
603 }
604 
605 #ifdef RTE_LIB_METRICS
606 static void
607 metrics_display(int port_id)
608 {
609 	struct rte_metric_value *metrics;
610 	struct rte_metric_name *names;
611 	int len, ret;
612 	static const char *nic_stats_border = "########################";
613 
614 	len = rte_metrics_get_names(NULL, 0);
615 	if (len < 0) {
616 		printf("Cannot get metrics count\n");
617 		return;
618 	}
619 	if (len == 0) {
620 		printf("No metrics to display (none have been registered)\n");
621 		return;
622 	}
623 
624 	metrics = rte_malloc("proc_info_metrics",
625 		sizeof(struct rte_metric_value) * len, 0);
626 	if (metrics == NULL) {
627 		printf("Cannot allocate memory for metrics\n");
628 		return;
629 	}
630 
631 	names =  rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0);
632 	if (names == NULL) {
633 		printf("Cannot allocate memory for metrcis names\n");
634 		rte_free(metrics);
635 		return;
636 	}
637 
638 	if (len != rte_metrics_get_names(names, len)) {
639 		printf("Cannot get metrics names\n");
640 		rte_free(metrics);
641 		rte_free(names);
642 		return;
643 	}
644 
645 	if (port_id == RTE_METRICS_GLOBAL)
646 		printf("###### Non port specific metrics  #########\n");
647 	else
648 		printf("###### metrics for port %-2d #########\n", port_id);
649 	printf("%s############################\n", nic_stats_border);
650 	ret = rte_metrics_get_values(port_id, metrics, len);
651 	if (ret < 0 || ret > len) {
652 		printf("Cannot get metrics values\n");
653 		rte_free(metrics);
654 		rte_free(names);
655 		return;
656 	}
657 
658 	int i;
659 	for (i = 0; i < len; i++)
660 		printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value);
661 
662 	printf("%s############################\n", nic_stats_border);
663 	rte_free(metrics);
664 	rte_free(names);
665 }
666 #endif
667 
668 static void
669 show_security_context(uint16_t portid, bool inline_offload)
670 {
671 	void *p_ctx;
672 	const struct rte_security_capability *s_cap;
673 
674 	if (inline_offload)
675 		p_ctx = rte_eth_dev_get_sec_ctx(portid);
676 	else
677 		p_ctx = rte_cryptodev_get_sec_ctx(portid);
678 
679 	if (p_ctx == NULL)
680 		return;
681 
682 	printf("  - crypto context\n");
683 	printf("\t  -- security context - %p\n", p_ctx);
684 	printf("\t  -- size %u\n",
685 	       rte_security_session_get_size(p_ctx));
686 
687 	s_cap = rte_security_capabilities_get(p_ctx);
688 	if (s_cap) {
689 		printf("\t  -- action (0x%x), protocol (0x%x),"
690 		       " offload flags (0x%x)\n",
691 		       s_cap->action,
692 		       s_cap->protocol,
693 		       s_cap->ol_flags);
694 		printf("\t  -- capabilities - oper type %x\n",
695 		       s_cap->crypto_capabilities->op);
696 	}
697 }
698 
699 static void
700 show_offloads(uint64_t offloads,
701 	      const char *(show_offload)(uint64_t))
702 {
703 	printf(" offloads :");
704 	while (offloads != 0) {
705 		uint64_t offload_flag = 1ULL << __builtin_ctzll(offloads);
706 		printf(" %s", show_offload(offload_flag));
707 		offloads &= ~offload_flag;
708 	}
709 }
710 
711 static void
712 show_port(void)
713 {
714 	int i, ret, j, k;
715 
716 	snprintf(bdr_str, MAX_STRING_LEN, " show - Port PMD ");
717 	STATS_BDR_STR(10, bdr_str);
718 
719 	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
720 		uint16_t mtu = 0;
721 		struct rte_eth_link link;
722 		struct rte_eth_dev_info dev_info;
723 		struct rte_eth_rss_conf rss_conf;
724 		char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
725 		struct rte_eth_fc_conf fc_conf;
726 		struct rte_ether_addr mac;
727 		struct rte_eth_dev_owner owner;
728 
729 		/* Skip if port is not in mask */
730 		if ((enabled_port_mask & (1ul << i)) == 0)
731 			continue;
732 
733 		/* Skip if port is unused */
734 		if (!rte_eth_dev_is_valid_port(i))
735 			continue;
736 
737 		memset(&rss_conf, 0, sizeof(rss_conf));
738 
739 		snprintf(bdr_str, MAX_STRING_LEN, " Port %u ", i);
740 		STATS_BDR_STR(5, bdr_str);
741 		printf("  - generic config\n");
742 
743 		ret = rte_eth_dev_info_get(i, &dev_info);
744 		if (ret != 0) {
745 			printf("Error during getting device info: %s\n",
746 				strerror(-ret));
747 			return;
748 		}
749 
750 		printf("\t  -- driver %s device %s socket %d\n",
751 		       dev_info.driver_name, dev_info.device->name,
752 		       rte_eth_dev_socket_id(i));
753 
754 		ret = rte_eth_dev_owner_get(i, &owner);
755 		if (ret == 0 && owner.id != RTE_ETH_DEV_NO_OWNER)
756 			printf("\t --  owner %#"PRIx64":%s\n",
757 			       owner.id, owner.name);
758 
759 		ret = rte_eth_link_get(i, &link);
760 		if (ret < 0) {
761 			printf("Link get failed (port %u): %s\n",
762 			       i, rte_strerror(-ret));
763 		} else {
764 			rte_eth_link_to_str(link_status_text,
765 					sizeof(link_status_text),
766 					&link);
767 			printf("\t%s\n", link_status_text);
768 		}
769 
770 		ret = rte_eth_dev_flow_ctrl_get(i, &fc_conf);
771 		if (ret == 0 && fc_conf.mode != RTE_ETH_FC_NONE)  {
772 			printf("\t  -- flow control mode %s%s high %u low %u pause %u%s%s\n",
773 			       fc_conf.mode == RTE_ETH_FC_RX_PAUSE ? "rx " :
774 			       fc_conf.mode == RTE_ETH_FC_TX_PAUSE ? "tx " :
775 			       fc_conf.mode == RTE_ETH_FC_FULL ? "full" : "???",
776 			       fc_conf.autoneg ? " auto" : "",
777 			       fc_conf.high_water,
778 			       fc_conf.low_water,
779 			       fc_conf.pause_time,
780 			       fc_conf.send_xon ? " xon" : "",
781 			       fc_conf.mac_ctrl_frame_fwd ? " mac_ctrl" : "");
782 		}
783 
784 		ret = rte_eth_macaddr_get(i, &mac);
785 		if (ret == 0) {
786 			char ebuf[RTE_ETHER_ADDR_FMT_SIZE];
787 
788 			rte_ether_format_addr(ebuf, sizeof(ebuf), &mac);
789 			printf("\t  -- mac %s\n", ebuf);
790 		}
791 
792 		ret = rte_eth_promiscuous_get(i);
793 		if (ret >= 0)
794 			printf("\t  -- promiscuous mode %s\n",
795 			       ret > 0 ? "enabled" : "disabled");
796 
797 		ret = rte_eth_allmulticast_get(i);
798 		if (ret >= 0)
799 			printf("\t  -- all multicast mode %s\n",
800 			       ret > 0 ? "enabled" : "disabled");
801 
802 		ret = rte_eth_dev_get_mtu(i, &mtu);
803 		if (ret == 0)
804 			printf("\t  -- mtu (%d)\n", mtu);
805 
806 		for (j = 0; j < dev_info.nb_rx_queues; j++) {
807 			struct rte_eth_rxq_info queue_info;
808 			int count;
809 
810 			ret = rte_eth_rx_queue_info_get(i, j, &queue_info);
811 			if (ret != 0)
812 				break;
813 
814 			if (j == 0)
815 				printf("  - rx queue\n");
816 
817 			printf("\t  -- %d descriptors ", j);
818 			count = rte_eth_rx_queue_count(i, j);
819 			if (count >= 0)
820 				printf("%d/", count);
821 			printf("%u", queue_info.nb_desc);
822 
823 			if (queue_info.scattered_rx)
824 				printf(" scattered");
825 
826 			if (queue_info.conf.rx_drop_en)
827 				printf(" drop_en");
828 
829 			if (queue_info.conf.rx_deferred_start)
830 				printf(" deferred_start");
831 
832 			if (queue_info.rx_buf_size != 0)
833 				printf(" rx buffer size %u",
834 				       queue_info.rx_buf_size);
835 
836 			printf(" mempool %s socket %d",
837 			       queue_info.mp->name,
838 			       queue_info.mp->socket_id);
839 
840 			if (queue_info.conf.offloads != 0)
841 				show_offloads(queue_info.conf.offloads, rte_eth_dev_rx_offload_name);
842 
843 			printf("\n");
844 		}
845 
846 		for (j = 0; j < dev_info.nb_tx_queues; j++) {
847 			struct rte_eth_txq_info queue_info;
848 
849 			ret = rte_eth_tx_queue_info_get(i, j, &queue_info);
850 			if (ret != 0)
851 				break;
852 
853 			if (j == 0)
854 				printf("  - tx queue\n");
855 
856 			printf("\t  -- %d descriptors %d",
857 			       j, queue_info.nb_desc);
858 
859 			printf(" thresh %u/%u",
860 			       queue_info.conf.tx_rs_thresh,
861 			       queue_info.conf.tx_free_thresh);
862 
863 			if (queue_info.conf.tx_deferred_start)
864 				printf(" deferred_start");
865 
866 			if (queue_info.conf.offloads != 0)
867 				show_offloads(queue_info.conf.offloads, rte_eth_dev_tx_offload_name);
868 			printf("\n");
869 		}
870 
871 		ret = rte_eth_dev_rss_hash_conf_get(i, &rss_conf);
872 		if (ret == 0) {
873 			if (rss_conf.rss_key) {
874 				printf("  - RSS\n");
875 				printf("\t  -- RSS len %u key (hex):",
876 						rss_conf.rss_key_len);
877 				for (k = 0; k < rss_conf.rss_key_len; k++)
878 					printf(" %x", rss_conf.rss_key[k]);
879 				printf("\t  -- hf 0x%"PRIx64"\n",
880 						rss_conf.rss_hf);
881 			}
882 		}
883 
884 #ifdef RTE_LIB_SECURITY
885 		show_security_context(i, true);
886 #endif
887 	}
888 }
889 
890 static void
891 display_nodecap_info(int is_leaf, struct rte_tm_node_capabilities *cap)
892 {
893 	if (cap == NULL)
894 		return;
895 
896 	if (!is_leaf) {
897 		printf("\t  -- nonleaf sched max:\n"
898 			"\t\t  + children (%u)\n"
899 			"\t\t  + sp priorities (%u)\n"
900 			"\t\t  + wfq children per group (%u)\n"
901 			"\t\t  + wfq groups (%u)\n"
902 			"\t\t  + wfq weight (%u)\n",
903 			cap->nonleaf.sched_n_children_max,
904 			cap->nonleaf.sched_sp_n_priorities_max,
905 			cap->nonleaf.sched_wfq_n_children_per_group_max,
906 			cap->nonleaf.sched_wfq_n_groups_max,
907 			cap->nonleaf.sched_wfq_weight_max);
908 	} else {
909 		printf("\t  -- leaf cman support:\n"
910 			"\t\t  + wred pkt mode (%d)\n"
911 			"\t\t  + wred byte mode (%d)\n"
912 			"\t\t  + head drop (%d)\n"
913 			"\t\t  + wred context private (%d)\n"
914 			"\t\t  + wred context shared (%u)\n",
915 			cap->leaf.cman_wred_packet_mode_supported,
916 			cap->leaf.cman_wred_byte_mode_supported,
917 			cap->leaf.cman_head_drop_supported,
918 			cap->leaf.cman_wred_context_private_supported,
919 			cap->leaf.cman_wred_context_shared_n_max);
920 	}
921 }
922 
923 static void
924 display_levelcap_info(int is_leaf, struct rte_tm_level_capabilities *cap)
925 {
926 	if (cap == NULL)
927 		return;
928 
929 	if (!is_leaf) {
930 		printf("\t  -- shaper private: (%d) dual rate (%d)\n",
931 			cap->nonleaf.shaper_private_supported,
932 			cap->nonleaf.shaper_private_dual_rate_supported);
933 		printf("\t  -- shaper share: (%u)\n",
934 			cap->nonleaf.shaper_shared_n_max);
935 		printf("\t  -- non leaf sched MAX:\n"
936 			"\t\t  + children (%u)\n"
937 			"\t\t  + sp (%u)\n"
938 			"\t\t  + wfq children per group (%u)\n"
939 			"\t\t  + wfq groups (%u)\n"
940 			"\t\t  + wfq weight (%u)\n",
941 			cap->nonleaf.sched_n_children_max,
942 			cap->nonleaf.sched_sp_n_priorities_max,
943 			cap->nonleaf.sched_wfq_n_children_per_group_max,
944 			cap->nonleaf.sched_wfq_n_groups_max,
945 			cap->nonleaf.sched_wfq_weight_max);
946 	} else {
947 		printf("\t  -- shaper private: (%d) dual rate (%d)\n",
948 			cap->leaf.shaper_private_supported,
949 			cap->leaf.shaper_private_dual_rate_supported);
950 		printf("\t  -- shaper share: (%u)\n",
951 			cap->leaf.shaper_shared_n_max);
952 		printf("  -- leaf cman support:\n"
953 			"\t\t  + wred pkt mode (%d)\n"
954 			"\t\t  + wred byte mode (%d)\n"
955 			"\t\t  + head drop (%d)\n"
956 			"\t\t  + wred context private (%d)\n"
957 			"\t\t  + wred context shared (%u)\n",
958 			cap->leaf.cman_wred_packet_mode_supported,
959 			cap->leaf.cman_wred_byte_mode_supported,
960 			cap->leaf.cman_head_drop_supported,
961 			cap->leaf.cman_wred_context_private_supported,
962 			cap->leaf.cman_wred_context_shared_n_max);
963 	}
964 }
965 
966 static void
967 show_tm(void)
968 {
969 	int ret = 0, check_for_leaf = 0, is_leaf = 0;
970 	unsigned int j, k;
971 	uint16_t i = 0;
972 
973 	snprintf(bdr_str, MAX_STRING_LEN, " show - TM PMD ");
974 	STATS_BDR_STR(10, bdr_str);
975 
976 	RTE_ETH_FOREACH_DEV(i) {
977 		struct rte_eth_dev_info dev_info;
978 		struct rte_tm_capabilities cap;
979 		struct rte_tm_error error;
980 		struct rte_tm_node_capabilities capnode;
981 		struct rte_tm_level_capabilities caplevel;
982 		uint32_t n_leaf_nodes = 0;
983 
984 		memset(&cap, 0, sizeof(cap));
985 		memset(&error, 0, sizeof(error));
986 
987 		ret = rte_eth_dev_info_get(i, &dev_info);
988 		if (ret != 0) {
989 			printf("Error during getting device (port %u) info: %s\n",
990 				i, strerror(-ret));
991 			return;
992 		}
993 
994 		printf("  - Generic for port (%u)\n"
995 			"\t  -- driver name %s\n"
996 			"\t  -- max vf (%u)\n"
997 			"\t  -- max tx queues (%u)\n"
998 			"\t  -- number of tx queues (%u)\n",
999 			i,
1000 			dev_info.driver_name,
1001 			dev_info.max_vfs,
1002 			dev_info.max_tx_queues,
1003 			dev_info.nb_tx_queues);
1004 
1005 		ret = rte_tm_capabilities_get(i, &cap, &error);
1006 		if (ret)
1007 			continue;
1008 
1009 		printf("  - MAX: nodes (%u) levels (%u) children (%u)\n",
1010 			cap.n_nodes_max,
1011 			cap.n_levels_max,
1012 			cap.sched_n_children_max);
1013 
1014 		printf("  - identical nodes: non leaf (%d) leaf (%d)\n",
1015 			cap.non_leaf_nodes_identical,
1016 			cap.leaf_nodes_identical);
1017 
1018 		printf("  - Shaper MAX:\n"
1019 			"\t  -- total (%u)\n"
1020 			"\t  -- private (%u) private dual (%d)\n"
1021 			"\t  -- shared (%u) shared dual (%u)\n",
1022 			cap.shaper_n_max,
1023 			cap.shaper_private_n_max,
1024 			cap.shaper_private_dual_rate_n_max,
1025 			cap.shaper_shared_n_max,
1026 			cap.shaper_shared_dual_rate_n_max);
1027 
1028 		printf("  - mark support:\n");
1029 		printf("\t  -- vlan dei: GREEN (%d) YELLOW (%d) RED (%d)\n",
1030 			cap.mark_vlan_dei_supported[RTE_COLOR_GREEN],
1031 			cap.mark_vlan_dei_supported[RTE_COLOR_YELLOW],
1032 			cap.mark_vlan_dei_supported[RTE_COLOR_RED]);
1033 		printf("\t  -- ip ecn tcp: GREEN (%d) YELLOW (%d) RED (%d)\n",
1034 			cap.mark_ip_ecn_tcp_supported[RTE_COLOR_GREEN],
1035 			cap.mark_ip_ecn_tcp_supported[RTE_COLOR_YELLOW],
1036 			cap.mark_ip_ecn_tcp_supported[RTE_COLOR_RED]);
1037 		printf("\t  -- ip ecn sctp: GREEN (%d) YELLOW (%d) RED (%d)\n",
1038 			cap.mark_ip_ecn_sctp_supported[RTE_COLOR_GREEN],
1039 			cap.mark_ip_ecn_sctp_supported[RTE_COLOR_YELLOW],
1040 			cap.mark_ip_ecn_sctp_supported[RTE_COLOR_RED]);
1041 		printf("\t  -- ip dscp: GREEN (%d) YELLOW (%d) RED (%d)\n",
1042 			cap.mark_ip_dscp_supported[RTE_COLOR_GREEN],
1043 			cap.mark_ip_dscp_supported[RTE_COLOR_YELLOW],
1044 			cap.mark_ip_dscp_supported[RTE_COLOR_RED]);
1045 
1046 		printf("  - mask stats (0x%"PRIx64")"
1047 			" dynamic update (0x%"PRIx64")\n",
1048 			cap.stats_mask,
1049 			cap.dynamic_update_mask);
1050 
1051 		printf("  - sched MAX:\n"
1052 			"\t  -- total (%u)\n"
1053 			"\t  -- sp levels (%u)\n"
1054 			"\t  -- wfq children per group (%u)\n"
1055 			"\t  -- wfq groups (%u)\n"
1056 			"\t  -- wfq weight (%u)\n",
1057 			cap.sched_sp_n_priorities_max,
1058 			cap.sched_sp_n_priorities_max,
1059 			cap.sched_wfq_n_children_per_group_max,
1060 			cap.sched_wfq_n_groups_max,
1061 			cap.sched_wfq_weight_max);
1062 
1063 		printf("  - CMAN support:\n"
1064 			"\t  -- WRED mode: pkt (%d) byte (%d)\n"
1065 			"\t  -- head drop (%d)\n",
1066 			cap.cman_wred_packet_mode_supported,
1067 			cap.cman_wred_byte_mode_supported,
1068 			cap.cman_head_drop_supported);
1069 		printf("\t  -- MAX WRED CONTEXT:"
1070 			" total (%u) private (%u) shared (%u)\n",
1071 			cap.cman_wred_context_n_max,
1072 			cap.cman_wred_context_private_n_max,
1073 			cap.cman_wred_context_shared_n_max);
1074 
1075 		for (j = 0; j < cap.n_nodes_max; j++) {
1076 			memset(&capnode, 0, sizeof(capnode));
1077 			ret = rte_tm_node_capabilities_get(i, j,
1078 					&capnode, &error);
1079 			if (ret)
1080 				continue;
1081 
1082 			check_for_leaf = 1;
1083 
1084 			printf("  NODE %u\n", j);
1085 			printf("\t  - shaper private: (%d) dual rate (%d)\n",
1086 				capnode.shaper_private_supported,
1087 				capnode.shaper_private_dual_rate_supported);
1088 			printf("\t  - shaper shared max: (%u)\n",
1089 				capnode.shaper_shared_n_max);
1090 			printf("\t  - stats mask %"PRIx64"\n",
1091 				capnode.stats_mask);
1092 
1093 			ret = rte_tm_node_type_get(i, j, &is_leaf, &error);
1094 			if (ret)
1095 				continue;
1096 
1097 			display_nodecap_info(is_leaf, &capnode);
1098 		}
1099 
1100 		for (j = 0; j < cap.n_levels_max; j++) {
1101 			memset(&caplevel, 0, sizeof(caplevel));
1102 			ret = rte_tm_level_capabilities_get(i, j,
1103 					&caplevel, &error);
1104 			if (ret)
1105 				continue;
1106 
1107 			printf("  - Level %u\n", j);
1108 			printf("\t  -- node MAX: %u non leaf %u leaf %u\n",
1109 				caplevel.n_nodes_max,
1110 				caplevel.n_nodes_nonleaf_max,
1111 				caplevel.n_nodes_leaf_max);
1112 			printf("\t  -- indetical: non leaf %u leaf %u\n",
1113 				caplevel.non_leaf_nodes_identical,
1114 				caplevel.leaf_nodes_identical);
1115 
1116 			for (k = 0; k < caplevel.n_nodes_max; k++) {
1117 				ret = rte_tm_node_type_get(i, k,
1118 					&is_leaf, &error);
1119 				if (ret)
1120 					continue;
1121 
1122 				display_levelcap_info(is_leaf, &caplevel);
1123 			}
1124 		}
1125 
1126 		if (check_for_leaf) {
1127 			ret = rte_tm_get_number_of_leaf_nodes(i,
1128 					&n_leaf_nodes, &error);
1129 			if (ret == 0)
1130 				printf("  - leaf nodes (%u)\n", n_leaf_nodes);
1131 		}
1132 
1133 		for (j = 0; j < n_leaf_nodes; j++) {
1134 			struct rte_tm_node_stats stats;
1135 			memset(&stats, 0, sizeof(stats));
1136 
1137 			ret = rte_tm_node_stats_read(i, j,
1138 					&stats, &cap.stats_mask, 0, &error);
1139 			if (ret)
1140 				continue;
1141 
1142 			printf("  - STATS for node (%u)\n", j);
1143 			printf("  -- pkts (%"PRIu64") bytes (%"PRIu64")\n",
1144 				stats.n_pkts, stats.n_bytes);
1145 
1146 			ret = rte_tm_node_type_get(i, j, &is_leaf, &error);
1147 			if (ret || (!is_leaf))
1148 				continue;
1149 
1150 			printf("  -- leaf queued:"
1151 				" pkts (%"PRIu64") bytes (%"PRIu64")\n",
1152 				stats.leaf.n_pkts_queued,
1153 				stats.leaf.n_bytes_queued);
1154 			printf("  - dropped:\n"
1155 				"\t  -- GREEN:"
1156 				" pkts (%"PRIu64") bytes (%"PRIu64")\n"
1157 				"\t  -- YELLOW:"
1158 				" pkts (%"PRIu64") bytes (%"PRIu64")\n"
1159 				"\t  -- RED:"
1160 				" pkts (%"PRIu64") bytes (%"PRIu64")\n",
1161 				stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN],
1162 				stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN],
1163 				stats.leaf.n_pkts_dropped[RTE_COLOR_YELLOW],
1164 				stats.leaf.n_bytes_dropped[RTE_COLOR_YELLOW],
1165 				stats.leaf.n_pkts_dropped[RTE_COLOR_RED],
1166 				stats.leaf.n_bytes_dropped[RTE_COLOR_RED]);
1167 		}
1168 	}
1169 }
1170 
1171 static void
1172 display_crypto_feature_info(uint64_t x)
1173 {
1174 	if (x == 0)
1175 		return;
1176 
1177 	printf("\t  -- feature flags\n");
1178 	printf("\t\t  + symmetric (%c), asymmetric (%c)\n"
1179 		"\t\t  + symmetric operation chaining (%c)\n",
1180 		(x & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) ? 'y' : 'n',
1181 		(x & RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO) ? 'y' : 'n',
1182 		(x & RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING) ? 'y' : 'n');
1183 	printf("\t\t  + CPU: SSE (%c), AVX (%c), AVX2 (%c), AVX512 (%c)\n",
1184 		(x & RTE_CRYPTODEV_FF_CPU_SSE) ? 'y' : 'n',
1185 		(x & RTE_CRYPTODEV_FF_CPU_AVX) ? 'y' : 'n',
1186 		(x & RTE_CRYPTODEV_FF_CPU_AVX2) ? 'y' : 'n',
1187 		(x & RTE_CRYPTODEV_FF_CPU_AVX512) ? 'y' : 'n');
1188 	printf("\t\t  + AESNI: CPU (%c), HW (%c)\n",
1189 		(x & RTE_CRYPTODEV_FF_CPU_AESNI) ? 'y' : 'n',
1190 		(x & RTE_CRYPTODEV_FF_HW_ACCELERATED) ? 'y' : 'n');
1191 	printf("\t\t  + SECURITY OFFLOAD (%c)\n",
1192 		(x & RTE_CRYPTODEV_FF_SECURITY) ? 'y' : 'n');
1193 	printf("\t\t  + ARM: NEON (%c), CE (%c)\n",
1194 		(x & RTE_CRYPTODEV_FF_CPU_NEON) ? 'y' : 'n',
1195 		(x & RTE_CRYPTODEV_FF_CPU_ARM_CE) ? 'y' : 'n');
1196 	printf("\t  -- buffer offload\n");
1197 	printf("\t\t  + IN_PLACE_SGL (%c)\n",
1198 		(x & RTE_CRYPTODEV_FF_IN_PLACE_SGL) ? 'y' : 'n');
1199 	printf("\t\t  + OOP_SGL_IN_SGL_OUT (%c)\n",
1200 		(x & RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT) ? 'y' : 'n');
1201 	printf("\t\t  + OOP_SGL_IN_LB_OUT (%c)\n",
1202 		(x & RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT) ? 'y' : 'n');
1203 	printf("\t\t  + OOP_LB_IN_SGL_OUT (%c)\n",
1204 		(x & RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT) ? 'y' : 'n');
1205 	printf("\t\t  + OOP_LB_IN_LB_OUT (%c)\n",
1206 		(x & RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT) ? 'y' : 'n');
1207 }
1208 
1209 static void
1210 show_crypto(void)
1211 {
1212 	uint8_t crypto_dev_count = rte_cryptodev_count(), i;
1213 
1214 	snprintf(bdr_str, MAX_STRING_LEN, " show - CRYPTO PMD ");
1215 	STATS_BDR_STR(10, bdr_str);
1216 
1217 	for (i = 0; i < crypto_dev_count; i++) {
1218 		struct rte_cryptodev_info dev_info;
1219 		struct rte_cryptodev_stats stats;
1220 
1221 		rte_cryptodev_info_get(i, &dev_info);
1222 
1223 		printf("  - device (%u)\n", i);
1224 		printf("\t  -- name (%s)\n"
1225 		       "\t  -- driver (%s)\n"
1226 		       "\t  -- id (%u) on socket (%d)\n"
1227 		       "\t  -- queue pairs (%d)\n",
1228 		       rte_cryptodev_name_get(i),
1229 		       dev_info.driver_name,
1230 		       dev_info.driver_id,
1231 		       dev_info.device->numa_node,
1232 		       rte_cryptodev_queue_pair_count(i));
1233 
1234 		display_crypto_feature_info(dev_info.feature_flags);
1235 
1236 		if (rte_cryptodev_stats_get(i, &stats) == 0) {
1237 			printf("\t  -- stats\n");
1238 			printf("\t\t  + enqueue count (%"PRIu64")"
1239 			       " error (%"PRIu64")\n",
1240 			       stats.enqueued_count,
1241 			       stats.enqueue_err_count);
1242 			printf("\t\t  + dequeue count (%"PRIu64")"
1243 			       " error (%"PRIu64")\n",
1244 			       stats.dequeued_count,
1245 			       stats.dequeue_err_count);
1246 		}
1247 
1248 #ifdef RTE_LIB_SECURITY
1249 		show_security_context(i, false);
1250 #endif
1251 	}
1252 }
1253 
1254 static void
1255 show_ring(char *name)
1256 {
1257 	snprintf(bdr_str, MAX_STRING_LEN, " show - RING ");
1258 	STATS_BDR_STR(10, bdr_str);
1259 
1260 	if (name != NULL) {
1261 		struct rte_ring *ptr = rte_ring_lookup(name);
1262 		if (ptr != NULL) {
1263 			printf("  - Name (%s) on socket (%d)\n"
1264 				"  - flags:\n"
1265 				"\t  -- Single Producer Enqueue (%u)\n"
1266 				"\t  -- Single Consmer Dequeue (%u)\n",
1267 				ptr->name,
1268 				ptr->memzone->socket_id,
1269 				ptr->flags & RING_F_SP_ENQ,
1270 				ptr->flags & RING_F_SC_DEQ);
1271 			printf("  - size (%u) mask (0x%x) capacity (%u)\n",
1272 				ptr->size,
1273 				ptr->mask,
1274 				ptr->capacity);
1275 			printf("  - count (%u) free count (%u)\n",
1276 				rte_ring_count(ptr),
1277 				rte_ring_free_count(ptr));
1278 			printf("  - full (%d) empty (%d)\n",
1279 				rte_ring_full(ptr),
1280 				rte_ring_empty(ptr));
1281 
1282 			STATS_BDR_STR(50, "");
1283 			return;
1284 		}
1285 	}
1286 
1287 	rte_ring_list_dump(stdout);
1288 }
1289 
1290 static void
1291 show_mempool(char *name)
1292 {
1293 	snprintf(bdr_str, MAX_STRING_LEN, " show - MEMPOOL ");
1294 	STATS_BDR_STR(10, bdr_str);
1295 
1296 	if (name != NULL) {
1297 		struct rte_mempool *ptr = rte_mempool_lookup(name);
1298 		if (ptr != NULL) {
1299 			struct rte_mempool_ops *ops;
1300 			uint64_t flags = ptr->flags;
1301 
1302 			ops = rte_mempool_get_ops(ptr->ops_index);
1303 			printf("  - Name: %s on socket %d\n"
1304 				"  - flags:\n"
1305 				"\t  -- No spread (%c)\n"
1306 				"\t  -- No cache align (%c)\n"
1307 				"\t  -- SP put (%c), SC get (%c)\n"
1308 				"\t  -- Pool created (%c)\n"
1309 				"\t  -- No IOVA config (%c)\n"
1310 				"\t  -- Not used for IO (%c)\n",
1311 				ptr->name,
1312 				ptr->socket_id,
1313 				(flags & RTE_MEMPOOL_F_NO_SPREAD) ? 'y' : 'n',
1314 				(flags & RTE_MEMPOOL_F_NO_CACHE_ALIGN) ? 'y' : 'n',
1315 				(flags & RTE_MEMPOOL_F_SP_PUT) ? 'y' : 'n',
1316 				(flags & RTE_MEMPOOL_F_SC_GET) ? 'y' : 'n',
1317 				(flags & RTE_MEMPOOL_F_POOL_CREATED) ? 'y' : 'n',
1318 				(flags & RTE_MEMPOOL_F_NO_IOVA_CONTIG) ? 'y' : 'n',
1319 				(flags & RTE_MEMPOOL_F_NON_IO) ? 'y' : 'n');
1320 			printf("  - Size %u Cache %u element %u\n"
1321 				"  - header %u trailer %u\n"
1322 				"  - private data size %u\n",
1323 				ptr->size,
1324 				ptr->cache_size,
1325 				ptr->elt_size,
1326 				ptr->header_size,
1327 				ptr->trailer_size,
1328 				ptr->private_data_size);
1329 			printf("  - memezone - socket %d\n",
1330 				ptr->mz->socket_id);
1331 			printf("  - Count: avail (%u), in use (%u)\n",
1332 				rte_mempool_avail_count(ptr),
1333 				rte_mempool_in_use_count(ptr));
1334 			printf("  - ops_index %d ops_name %s\n",
1335 				ptr->ops_index, ops ? ops->name : "NA");
1336 
1337 			return;
1338 		}
1339 	}
1340 
1341 	rte_mempool_list_dump(stdout);
1342 }
1343 
1344 static void
1345 mempool_itr_obj(struct rte_mempool *mp, void *opaque,
1346 		void *obj, unsigned int obj_idx)
1347 {
1348 	printf("  - obj_idx %u opaque %p obj %p\n",
1349 			obj_idx, opaque, obj);
1350 
1351 	if (obj)
1352 		rte_hexdump(stdout, " Obj Content",
1353 				obj, (mp->elt_size > 256)?256:mp->elt_size);
1354 }
1355 
1356 static void
1357 iter_mempool(char *name)
1358 {
1359 	snprintf(bdr_str, MAX_STRING_LEN, " iter - MEMPOOL ");
1360 	STATS_BDR_STR(10, bdr_str);
1361 
1362 	if (name != NULL) {
1363 		struct rte_mempool *ptr = rte_mempool_lookup(name);
1364 		if (ptr != NULL) {
1365 			/* iterate each object */
1366 			uint32_t ret = rte_mempool_obj_iter(ptr,
1367 					mempool_itr_obj, NULL);
1368 			printf("\n  - iterated %u objects\n", ret);
1369 			return;
1370 		}
1371 	}
1372 }
1373 
1374 static void
1375 dump_regs(char *file_prefix)
1376 {
1377 #define MAX_FILE_NAME_SZ (MAX_LONG_OPT_SZ + 10)
1378 	char file_name[MAX_FILE_NAME_SZ];
1379 	struct rte_dev_reg_info reg_info;
1380 	struct rte_eth_dev_info dev_info;
1381 	unsigned char *buf_data;
1382 	size_t buf_size;
1383 	FILE *fp_regs;
1384 	uint16_t i;
1385 	int ret;
1386 
1387 	snprintf(bdr_str, MAX_STRING_LEN, " dump - Port REG");
1388 	STATS_BDR_STR(10, bdr_str);
1389 
1390 	RTE_ETH_FOREACH_DEV(i) {
1391 		/* Skip if port is not in mask */
1392 		if ((enabled_port_mask & (1ul << i)) == 0)
1393 			continue;
1394 
1395 		snprintf(bdr_str, MAX_STRING_LEN, " Port (%u)", i);
1396 		STATS_BDR_STR(5, bdr_str);
1397 
1398 		ret = rte_eth_dev_info_get(i, &dev_info);
1399 		if (ret) {
1400 			printf("Error getting device info: %d\n", ret);
1401 			continue;
1402 		}
1403 
1404 		memset(&reg_info, 0, sizeof(reg_info));
1405 		ret = rte_eth_dev_get_reg_info(i, &reg_info);
1406 		if (ret) {
1407 			printf("Error getting device reg info: %d\n", ret);
1408 			continue;
1409 		}
1410 
1411 		buf_size = reg_info.length * reg_info.width;
1412 		buf_data = malloc(buf_size);
1413 		if (buf_data == NULL) {
1414 			printf("Error allocating %zu bytes buffer\n", buf_size);
1415 			continue;
1416 		}
1417 
1418 		reg_info.data = buf_data;
1419 		reg_info.length = 0;
1420 		ret = rte_eth_dev_get_reg_info(i, &reg_info);
1421 		if (ret) {
1422 			printf("Error getting regs from device: %d\n", ret);
1423 			free(buf_data);
1424 			continue;
1425 		}
1426 
1427 		snprintf(file_name, MAX_FILE_NAME_SZ, "%s-port%u",
1428 				file_prefix, i);
1429 		fp_regs = fopen(file_name, "wb");
1430 		if (fp_regs == NULL) {
1431 			printf("Error during opening '%s' for writing: %s\n",
1432 					file_name, strerror(errno));
1433 		} else {
1434 			size_t nr_written;
1435 
1436 			nr_written = fwrite(buf_data, 1, buf_size, fp_regs);
1437 			if (nr_written != buf_size)
1438 				printf("Error during writing %s: %s\n",
1439 						file_prefix, strerror(errno));
1440 			else
1441 				printf("Device (%s) regs dumped successfully, "
1442 					"driver:%s version:0X%08X\n",
1443 					dev_info.device->name,
1444 					dev_info.driver_name, reg_info.version);
1445 
1446 			fclose(fp_regs);
1447 		}
1448 
1449 		free(buf_data);
1450 	}
1451 }
1452 
1453 int
1454 main(int argc, char **argv)
1455 {
1456 	int ret;
1457 	int i;
1458 	char c_flag[] = "-c1";
1459 	char n_flag[] = "-n4";
1460 	char mp_flag[] = "--proc-type=secondary";
1461 	char log_flag[] = "--log-level=6";
1462 	char *argp[argc + 4];
1463 	uint16_t nb_ports;
1464 
1465 	/* preparse app arguments */
1466 	ret = proc_info_preparse_args(argc, argv);
1467 	if (ret < 0) {
1468 		printf("Failed to parse arguments\n");
1469 		return -1;
1470 	}
1471 
1472 	argp[0] = argv[0];
1473 	argp[1] = c_flag;
1474 	argp[2] = n_flag;
1475 	argp[3] = mp_flag;
1476 	argp[4] = log_flag;
1477 
1478 	for (i = 1; i < argc; i++)
1479 		argp[i + 4] = argv[i];
1480 
1481 	argc += 4;
1482 
1483 	ret = rte_eal_init(argc, argp);
1484 	if (ret < 0)
1485 		rte_panic("Cannot init EAL\n");
1486 
1487 	argc -= ret;
1488 	argv += ret - 4;
1489 
1490 	if (!rte_eal_primary_proc_alive(NULL))
1491 		rte_exit(EXIT_FAILURE, "No primary DPDK process is running.\n");
1492 
1493 	/* parse app arguments */
1494 	ret = proc_info_parse_args(argc, argv);
1495 	if (ret < 0)
1496 		rte_exit(EXIT_FAILURE, "Invalid argument\n");
1497 
1498 	if (mem_info) {
1499 		meminfo_display();
1500 		return 0;
1501 	}
1502 
1503 	nb_ports = rte_eth_dev_count_avail();
1504 	if (nb_ports == 0)
1505 		rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
1506 
1507 	/* If no port mask was specified, then show non-owned ports */
1508 	if (enabled_port_mask == 0) {
1509 		RTE_ETH_FOREACH_DEV(i)
1510 			enabled_port_mask = 1ul << i;
1511 	}
1512 
1513 	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
1514 
1515 		/* Skip if port is not in mask */
1516 		if ((enabled_port_mask & (1ul << i)) == 0)
1517 			continue;
1518 
1519 		/* Skip if port is unused */
1520 		if (!rte_eth_dev_is_valid_port(i))
1521 			continue;
1522 
1523 		if (enable_stats)
1524 			nic_stats_display(i);
1525 		else if (enable_xstats)
1526 			nic_xstats_display(i);
1527 		else if (reset_stats)
1528 			nic_stats_clear(i);
1529 		else if (reset_xstats)
1530 			nic_xstats_clear(i);
1531 		else if (enable_xstats_name)
1532 			nic_xstats_by_name_display(i, xstats_name);
1533 		else if (nb_xstats_ids > 0)
1534 			nic_xstats_by_ids_display(i, xstats_ids,
1535 						  nb_xstats_ids);
1536 #ifdef RTE_LIB_METRICS
1537 		else if (enable_metrics)
1538 			metrics_display(i);
1539 #endif
1540 
1541 	}
1542 
1543 #ifdef RTE_LIB_METRICS
1544 	/* print port independent stats */
1545 	if (enable_metrics)
1546 		metrics_display(RTE_METRICS_GLOBAL);
1547 #endif
1548 
1549 	/* show information for PMD */
1550 	if (enable_shw_port)
1551 		show_port();
1552 	if (enable_shw_tm)
1553 		show_tm();
1554 	if (enable_shw_crypto)
1555 		show_crypto();
1556 	if (enable_shw_ring)
1557 		show_ring(ring_name);
1558 	if (enable_shw_mempool)
1559 		show_mempool(mempool_name);
1560 	if (enable_iter_mempool)
1561 		iter_mempool(mempool_iter_name);
1562 	if (enable_dump_regs)
1563 		dump_regs(dump_regs_file_prefix);
1564 
1565 	RTE_ETH_FOREACH_DEV(i)
1566 		rte_eth_dev_close(i);
1567 
1568 	ret = rte_eal_cleanup();
1569 	if (ret)
1570 		printf("Error from rte_eal_cleanup(), %d\n", ret);
1571 
1572 	return 0;
1573 }
1574