[v17] app/procinfo: display eventdev xstats

Message ID 20230525184731.3056328-1-abdullah.sevincer@intel.com (mailing list archive)
State Accepted, archived
Delegated to: Thomas Monjalon
Headers
Series [v17] app/procinfo: display eventdev xstats |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/iol-unit-testing success Testing PASS
ci/iol-abi-testing success Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-aarch64-compile-testing success Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/github-robot: build success github build: passed
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS

Commit Message

Sevincer, Abdullah May 25, 2023, 6:47 p.m. UTC
  This commit extends proc-info application to
display xstats for the eventdev devices.

New command line arguments are introduced to
display xstats for eventdev devices. The command
example is like:

For displaying a specific port stats (e.g. port 1):
./dpdk-proc-info -- --show-edev-port-xstats=1:0

If any xstats parameters for eventdev passed through
proc-info command line, proc-info will only display
requested eventdev data and exit.

Users should not pass any eventdev xstats parameters
if they desire to dump other proc-info data such as
Rx/Tx descriptor dump.
More information can be found in proc-info app doc.

Signed-off-by: Abdullah Sevincer <abdullah.sevincer@intel.com>
---
 app/proc-info/main.c           | 375 ++++++++++++++++++++++++++++++++-
 app/proc-info/meson.build      |   2 +-
 doc/guides/tools/proc_info.rst |  26 ++-
 3 files changed, 400 insertions(+), 3 deletions(-)
  

Comments

Stephen Hemminger May 25, 2023, 8:07 p.m. UTC | #1
On Thu, 25 May 2023 13:47:31 -0500
Abdullah Sevincer <abdullah.sevincer@intel.com> wrote:

> This commit extends proc-info application to
> display xstats for the eventdev devices.
> 
> New command line arguments are introduced to
> display xstats for eventdev devices. The command
> example is like:
> 
> For displaying a specific port stats (e.g. port 1):
> ./dpdk-proc-info -- --show-edev-port-xstats=1:0
> 
> If any xstats parameters for eventdev passed through
> proc-info command line, proc-info will only display
> requested eventdev data and exit.
> 
> Users should not pass any eventdev xstats parameters
> if they desire to dump other proc-info data such as
> Rx/Tx descriptor dump.
> More information can be found in proc-info app doc.
> 
> Signed-off-by: Abdullah Sevincer <abdullah.sevincer@intel.com>

Acked-by: Stephen Hemminger <stephen@networkplumber.org>
  
Pattan, Reshma May 26, 2023, 8:32 a.m. UTC | #2
> -----Original Message-----
> From: Sevincer, Abdullah <abdullah.sevincer@intel.com>
> Signed-off-by: Abdullah Sevincer <abdullah.sevincer@intel.com>

Acked-by: Reshma Pattan <reshma.pattan@intel.com>
  
Sevincer, Abdullah June 8, 2023, 5:35 p.m. UTC | #3
>+Acked-by: Reshma Pattan <reshma.pattan@intel.com>
>+Acked-by: Stephen Hemminger <stephen@networkplumber.org>

Reminder!
What's the plan to merge this patch?
  
Thomas Monjalon July 7, 2023, 9:15 a.m. UTC | #4
25/05/2023 22:07, Stephen Hemminger:
> On Thu, 25 May 2023 13:47:31 -0500
> Abdullah Sevincer <abdullah.sevincer@intel.com> wrote:
> 
> > This commit extends proc-info application to
> > display xstats for the eventdev devices.
> > 
> > New command line arguments are introduced to
> > display xstats for eventdev devices. The command
> > example is like:
> > 
> > For displaying a specific port stats (e.g. port 1):
> > ./dpdk-proc-info -- --show-edev-port-xstats=1:0
> > 
> > If any xstats parameters for eventdev passed through
> > proc-info command line, proc-info will only display
> > requested eventdev data and exit.
> > 
> > Users should not pass any eventdev xstats parameters
> > if they desire to dump other proc-info data such as
> > Rx/Tx descriptor dump.
> > More information can be found in proc-info app doc.
> > 
> > Signed-off-by: Abdullah Sevincer <abdullah.sevincer@intel.com>
> 
> Acked-by: Stephen Hemminger <stephen@networkplumber.org>

Applied, thanks.
  
Stephen Hemminger July 7, 2023, 2:55 p.m. UTC | #5
On Fri, 07 Jul 2023 11:15:22 +0200
Thomas Monjalon <thomas@monjalon.net> wrote:

> 25/05/2023 22:07, Stephen Hemminger:
> > On Thu, 25 May 2023 13:47:31 -0500
> > Abdullah Sevincer <abdullah.sevincer@intel.com> wrote:
> >   
> > > This commit extends proc-info application to
> > > display xstats for the eventdev devices.
> > > 
> > > New command line arguments are introduced to
> > > display xstats for eventdev devices. The command
> > > example is like:
> > > 
> > > For displaying a specific port stats (e.g. port 1):
> > > ./dpdk-proc-info -- --show-edev-port-xstats=1:0
> > > 
> > > If any xstats parameters for eventdev passed through
> > > proc-info command line, proc-info will only display
> > > requested eventdev data and exit.
> > > 
> > > Users should not pass any eventdev xstats parameters
> > > if they desire to dump other proc-info data such as
> > > Rx/Tx descriptor dump.
> > > More information can be found in proc-info app doc.
> > > 
> > > Signed-off-by: Abdullah Sevincer <abdullah.sevincer@intel.com>  
> > 
> > Acked-by: Stephen Hemminger <stephen@networkplumber.org>  
> 
> Applied, thanks.

Has new coverity issue.
The reason is the boolean is set every time because it gets every time.

Looks like code goes over eventdev_var[] even if no eventdevs are present.
Should only look for the number of eventdevs

*** CID 395458:  Control flow issues  (DEADCODE)
/app/proc-info/main.c: 2114 in process_eventdev_xstats()
2108     		}
2109     	}
2110     
2111     	if (processing_eventdev_xstats)
2112     		return 1;
2113     
>>>     CID 395458:  Control flow issues  (DEADCODE)
>>>     Execution cannot reach this statement: "return 0;".  
2114     	return 0;
2115     }
2116     
2117     int
2118     main(int argc, char **argv)
2119     {
  
Sevincer, Abdullah July 8, 2023, 3:11 p.m. UTC | #6
>+Has new coverity issue.
>+The reason is the boolean is set every time because it gets every time.

>+Looks like code goes over eventdev_var[] even if no eventdevs are present.
>+Should only look for the number of eventdevs

Thanks Stephen, I will add a condition at the top of the function like:

evdevs = rte_event_dev_count();
	if (!evdevs)
		return 0;

This will ensure if there is no eventdev device function returns.

I will also change the for loop to iterate only with the count of evdevs like:
for (i = 0; i < evdevs; i++) {....... instead of for (i = 0; i < RTE_EVENT_MAX_DEVS; i++) {.

I still need that flag to be set when a user sets a value from command line for a queue or port.
The flag is needed to display and exit from the program.  

if (process_eventdev_xstats())
		return 0;
  
Stephen Hemminger July 8, 2023, 3:26 p.m. UTC | #7
On Sat, 8 Jul 2023 15:11:45 +0000
"Sevincer, Abdullah" <abdullah.sevincer@intel.com> wrote:

> >+Has new coverity issue.
> >+The reason is the boolean is set every time because it gets every time.  
> 
> >+Looks like code goes over eventdev_var[] even if no eventdevs are present.
> >+Should only look for the number of eventdevs  
> 
> Thanks Stephen, I will add a condition at the top of the function like:
> 
> evdevs = rte_event_dev_count();
> 	if (!evdevs)
> 		return 0;
> 
> This will ensure if there is no eventdev device function returns.
> 
> I will also change the for loop to iterate only with the count of evdevs like:
> for (i = 0; i < evdevs; i++) {....... instead of for (i = 0; i < RTE_EVENT_MAX_DEVS; i++) {.
> 
> I still need that flag to be set when a user sets a value from command line for a queue or port.
> The flag is needed to display and exit from the program.  
> 
> if (process_eventdev_xstats())
> 		return 0;
> 

Maybe something like this:

PS: also shortened variable names for clarity

diff --git a/app/proc-info/main.c b/app/proc-info/main.c
index be63eace6909..e3d2578c39dc 100644
--- a/app/proc-info/main.c
+++ b/app/proc-info/main.c
@@ -2045,18 +2045,13 @@ xstats_reset(uint8_t dev_id,
 
 }
 
-static int
-process_eventdev_xstats(void)
+static unsigned int
+eventdev_xstats(void)
 {
-	int i;
-	int j;
-	int processing_eventdev_xstats = 0;
-
-	for (i = 0; i < RTE_EVENT_MAX_DEVS; i++) {
-
-		if (!processing_eventdev_xstats)
-			processing_eventdev_xstats = 1;
+	unsigned int count = 0;
+	int i, j;
 
+	for (i = 0; i < rte_event_dev_count(); i++) {
 		if (eventdev_var[i].dump_xstats) {
 			int ret = rte_event_dev_dump(i, stdout);
 
@@ -2106,12 +2101,10 @@ process_eventdev_xstats(void)
 							eventdev_var[i].queues[j]);
 			}
 		}
+		++count;
 	}
 
-	if (processing_eventdev_xstats)
-		return 1;
-
-	return 0;
+	return count;
 }
 
 int
@@ -2164,7 +2157,7 @@ main(int argc, char **argv)
 		return 0;
 	}
 
-	if (process_eventdev_xstats())
+	if (eventdev_xstats() > 0)
 		return 0;
 
 	nb_ports = rte_eth_dev_count_avail();
  

Patch

diff --git a/app/proc-info/main.c b/app/proc-info/main.c
index 53e852a07c..be63eace69 100644
--- a/app/proc-info/main.c
+++ b/app/proc-info/main.c
@@ -40,6 +40,7 @@ 
 #include <rte_tm.h>
 #include <rte_hexdump.h>
 #include <rte_version.h>
+#include <rte_eventdev.h>
 
 /* Maximum long option length for option parsing. */
 #define MAX_LONG_OPT_SZ 64
@@ -121,6 +122,25 @@  static uint32_t enable_shw_module_eeprom;
 static uint32_t enable_shw_rx_desc_dump;
 static uint32_t enable_shw_tx_desc_dump;
 
+/* Note: Port_queue_id in xstats APIs is 8 bits, so we have a maximum of
+ * 256 ports and queues for event_Dev
+ */
+#define MAX_PORTS_QUEUES 256
+
+struct eventdev_params {
+	uint16_t ports[MAX_PORTS_QUEUES];
+	uint16_t queues[MAX_PORTS_QUEUES];
+	uint16_t num_queues;
+	uint16_t num_ports;
+	uint8_t shw_all_queues:1,
+		shw_all_ports:1,
+		dump_xstats:1,
+		reset_xstats:1,
+		shw_device_xstats:1;
+};
+
+static struct eventdev_params eventdev_var[RTE_EVENT_MAX_DEVS];
+
 #define DESC_PARAM_NUM 3
 
 struct desc_param {
@@ -172,7 +192,12 @@  proc_info_usage(const char *prgname)
 			"offset: The offset of the descriptor starting from tail. "
 			"num: The number of the descriptors to dump.\n"
 		"  --iter-mempool=name: iterate mempool elements to display content\n"
-		"  --dump-regs=file-prefix: dump registers to file with the file-prefix\n",
+		"  --dump-regs=file-prefix: dump registers to file with the file-prefix\n"
+		"  --show-edev-queue-xstats=queue_num:evdev_id or *:evdev_id to get queue xstats for specified queue or all queues;\n"
+		"  --show-edev-port-xstats=port_num:evdev_id or *:evdev_id to get queue xstats for specified port or all ports;\n"
+		"  --edev-dump-xstats=evdev_id to dump all event_dev xstats for specified eventdev device;\n"
+		"  --edev-reset-xstats=evdev_id to reset event_dev xstats after reading;\n"
+		"  --show-edev-device-xstats=evdev_id to get event_dev device xstats for specified eventdev device;\n",
 		prgname);
 }
 
@@ -236,6 +261,125 @@  parse_descriptor_param(char *list, struct desc_param *desc)
 	return 0;
 }
 
+static int
+parse_eventdev_id(const char *str)
+{
+	unsigned long evdev_id;
+	char *endp;
+
+	evdev_id = strtoul(str, &endp, 0);
+
+	if (*str == '\0' || *endp != '\0' || evdev_id >= rte_event_dev_count()) {
+		fprintf(stderr, "Invalid eventdev id: %s\n", str);
+		return -1;
+	}
+
+	return evdev_id;
+}
+
+static int
+parse_eventdev_dump_xstats_params(const char *list)
+{
+	int evdev_id = parse_eventdev_id(list);
+
+	if (evdev_id < 0)
+		return -EINVAL;
+
+	eventdev_var[evdev_id].dump_xstats = 1;
+
+	return 0;
+}
+
+static int
+parse_eventdev_reset_xstats_params(const char *list)
+{
+	int evdev_id = parse_eventdev_id(list);
+
+	if (evdev_id < 0)
+		return -EINVAL;
+
+	eventdev_var[evdev_id].reset_xstats = 1;
+
+	return 0;
+}
+
+static int
+parse_eventdev_device_xstats_params(const char *list)
+{
+	int evdev_id = parse_eventdev_id(list);
+
+	if (evdev_id < 0)
+		return -EINVAL;
+
+	eventdev_var[evdev_id].shw_device_xstats = 1;
+
+	return 0;
+}
+
+static int
+parse_eventdev_queue_xstats_params(const char *list)
+{
+	uint16_t queue_id;
+	uint16_t evdev_id;
+
+	if (sscanf(list, "*:%hu", &evdev_id) == 1) {
+		if (evdev_id >= rte_event_dev_count()) {
+			printf("Invalid eventdev id: %hu\n", evdev_id);
+			return -EINVAL;
+		}
+		eventdev_var[evdev_id].shw_all_queues = 1;
+	} else if (sscanf(list, "%hu:%hu", &queue_id, &evdev_id) == 2) {
+		if (evdev_id >= rte_event_dev_count()) {
+			printf("Invalid eventdev id: %hu\n", evdev_id);
+			return -EINVAL;
+		}
+
+		if (queue_id >= MAX_PORTS_QUEUES) {
+			printf("Invalid queue_id: %hu\n", queue_id);
+			return -EINVAL;
+		}
+
+		eventdev_var[evdev_id].queues[eventdev_var[evdev_id].num_queues] = queue_id;
+		eventdev_var[evdev_id].num_queues++;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_eventdev_port_xstats_params(const char *list)
+{
+	uint16_t port_id;
+	uint16_t evdev_id;
+
+	if (sscanf(list, "*:%hu", &evdev_id) == 1) {
+		if (evdev_id >= rte_event_dev_count()) {
+			printf("Invalid eventdev id: %hu\n", evdev_id);
+			return -EINVAL;
+		}
+		eventdev_var[evdev_id].shw_all_ports = 1;
+	} else if (sscanf(list, "%hu:%hu", &port_id, &evdev_id) == 2) {
+		if (evdev_id >= rte_event_dev_count()) {
+			printf("Invalid eventdev id: %hu\n", evdev_id);
+			return -EINVAL;
+		}
+
+		if (port_id >= MAX_PORTS_QUEUES) {
+			printf("Invalid port_id: %hu\n", port_id);
+			return -EINVAL;
+		}
+
+		eventdev_var[evdev_id].ports[eventdev_var[evdev_id].num_ports] = port_id;
+		eventdev_var[evdev_id].num_ports++;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int
 proc_info_preparse_args(int argc, char **argv)
 {
@@ -302,6 +446,11 @@  proc_info_parse_args(int argc, char **argv)
 		{"show-module-eeprom", 0, NULL, 0},
 		{"show-rx-descriptor", required_argument, NULL, 1},
 		{"show-tx-descriptor", required_argument, NULL, 1},
+		{"show-edev-queue-xstats", required_argument, NULL, 0},
+		{"show-edev-port-xstats", required_argument, NULL, 0},
+		{"edev-dump-xstats", required_argument, NULL, 0},
+		{"edev-reset-xstats", required_argument, NULL, 0},
+		{"show-edev-device-xstats", required_argument, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
 
@@ -385,6 +534,47 @@  proc_info_parse_args(int argc, char **argv)
 			else if (!strncmp(long_option[option_index].name,
 					"show-module-eeprom", MAX_LONG_OPT_SZ))
 				enable_shw_module_eeprom = 1;
+			else if (!strncmp(long_option[option_index].name,
+					"edev-dump-xstats", MAX_LONG_OPT_SZ)) {
+				int ret = parse_eventdev_dump_xstats_params(optarg);
+				if (ret < 0) {
+					fprintf(stderr, "Error parsing eventdev dump xstats params: %s\n",
+						strerror(-ret));
+					return -1;
+				}
+			} else if (!strncmp(long_option[option_index].name,
+					"edev-reset-xstats", MAX_LONG_OPT_SZ)) {
+				int ret = parse_eventdev_reset_xstats_params(optarg);
+				if (ret < 0) {
+					fprintf(stderr, "Error parsing eventdev reset xstats params: %s\n",
+						strerror(-ret));
+					return -1;
+				}
+			} else if (!strncmp(long_option[option_index].name,
+					"show-edev-device-xstats", MAX_LONG_OPT_SZ)) {
+				int ret = parse_eventdev_device_xstats_params(optarg);
+				if (ret < 0) {
+					fprintf(stderr, "Error parsing eventdev reset xstats params: %s\n",
+						strerror(-ret));
+					return -1;
+				}
+			} else if (!strncmp(long_option[option_index].name,
+					"show-edev-queue-xstats", MAX_LONG_OPT_SZ)) {
+				int ret = parse_eventdev_queue_xstats_params(optarg);
+				if (ret < 0) {
+					fprintf(stderr, "Error parsing eventdev queue xstats params: %s\n",
+						strerror(-ret));
+					return -1;
+				}
+			} else if (!strncmp(long_option[option_index].name,
+					"show-edev-port-xstats", MAX_LONG_OPT_SZ)) {
+				int ret = parse_eventdev_port_xstats_params(optarg);
+				if (ret < 0) {
+					fprintf(stderr, "Error parsing eventdev port xstats params: %s\n",
+						strerror(-ret));
+					return -1;
+				}
+			}
 			break;
 		case 1:
 			/* Print xstat single value given by name*/
@@ -1744,6 +1934,186 @@  nic_tx_descriptor_display(uint16_t port_id, struct desc_param *desc)
 			strerror(-ret));
 }
 
+static void
+xstats_display(uint8_t dev_id,
+	  enum rte_event_dev_xstats_mode mode,
+	  uint8_t queue_port_id)
+{
+	int ret;
+	struct rte_event_dev_xstats_name *xstats_names;
+	uint64_t *ids;
+	uint64_t *values;
+	int size;
+	int i;
+
+	size = rte_event_dev_xstats_names_get(dev_id,
+					     mode,
+					     queue_port_id,
+					     NULL, /* names */
+					     NULL, /* ids */
+					     0);   /* num */
+
+	if (size < 0)
+		rte_panic("rte_event_dev_xstats_names_get err %d\n", size);
+
+	if (size == 0) {
+		printf(
+		"No stats available for this item, mode=%d, queue_port_id=%d\n",
+			mode, queue_port_id);
+		return;
+	}
+
+	/* Get memory to hold stat names, IDs, and values */
+	xstats_names = malloc(sizeof(struct rte_event_dev_xstats_name) * (unsigned int)size);
+	ids = malloc(sizeof(unsigned int) * size);
+
+	if (!xstats_names || !ids)
+		rte_panic("unable to alloc memory for stats retrieval\n");
+
+	ret = rte_event_dev_xstats_names_get(dev_id, mode, queue_port_id,
+					     xstats_names, ids,
+					     (unsigned int)size);
+	if (ret != size)
+		rte_panic("rte_event_dev_xstats_names_get err %d\n", ret);
+
+	values = malloc(sizeof(uint64_t) * size);
+	if (!values)
+		rte_panic("unable to alloc memory for stats retrieval\n");
+
+	ret = rte_event_dev_xstats_get(dev_id, mode, queue_port_id,
+					    ids, values, size);
+
+	if (ret != size)
+		rte_panic("rte_event_dev_xstats_get err %d\n", ret);
+
+	for (i = 0; i < size; i++) {
+		printf("id %"PRIu64"  %s = %"PRIu64"\n",
+			ids[i], &xstats_names[i].name[0], values[i]);
+	}
+
+	free(values);
+	free(xstats_names);
+	free(ids);
+
+}
+
+static void
+xstats_reset(uint8_t dev_id,
+	  enum rte_event_dev_xstats_mode mode,
+	  uint8_t queue_port_id)
+{
+	int ret;
+	struct rte_event_dev_xstats_name *xstats_names;
+	uint64_t *ids;
+	int size;
+
+	size = rte_event_dev_xstats_names_get(dev_id,
+					     mode,
+					     queue_port_id,
+					     NULL, /* names */
+					     NULL, /* ids */
+					     0);   /* num */
+
+	if (size < 0)
+		rte_panic("rte_event_dev_xstats_names_get err %d\n", size);
+
+	if (size == 0) {
+		printf(
+		"No stats available for this item, mode=%d, queue_port_id=%d\n",
+			mode, queue_port_id);
+		return;
+	}
+
+	/* Get memory to hold stat names, IDs, and values */
+	xstats_names = malloc(sizeof(struct rte_event_dev_xstats_name) * (unsigned int)size);
+	ids = malloc(sizeof(unsigned int) * size);
+
+	if (!xstats_names || !ids)
+		rte_panic("unable to alloc memory for stats retrieval\n");
+
+	ret = rte_event_dev_xstats_names_get(dev_id, mode, queue_port_id,
+					     xstats_names, ids,
+					     (unsigned int)size);
+	if (ret != size)
+		rte_panic("rte_event_dev_xstats_names_get err %d\n", ret);
+
+	rte_event_dev_xstats_reset(dev_id, mode, queue_port_id,
+					   ids, size);
+
+	free(xstats_names);
+	free(ids);
+
+}
+
+static int
+process_eventdev_xstats(void)
+{
+	int i;
+	int j;
+	int processing_eventdev_xstats = 0;
+
+	for (i = 0; i < RTE_EVENT_MAX_DEVS; i++) {
+
+		if (!processing_eventdev_xstats)
+			processing_eventdev_xstats = 1;
+
+		if (eventdev_var[i].dump_xstats) {
+			int ret = rte_event_dev_dump(i, stdout);
+
+			if (ret)
+				rte_panic("dump failed with err=%d\n", ret);
+		}
+
+		if (eventdev_var[i].shw_device_xstats == 1) {
+			xstats_display(i, RTE_EVENT_DEV_XSTATS_DEVICE, 0);
+
+			if (eventdev_var[i].reset_xstats == 1)
+				xstats_reset(i, RTE_EVENT_DEV_XSTATS_DEVICE, 0);
+		}
+
+		if (eventdev_var[i].shw_all_ports == 1) {
+			for (j = 0; j < MAX_PORTS_QUEUES; j++) {
+				xstats_display(i, RTE_EVENT_DEV_XSTATS_PORT, j);
+
+				if (eventdev_var[i].reset_xstats == 1)
+					xstats_reset(i, RTE_EVENT_DEV_XSTATS_PORT, j);
+			}
+		} else {
+			for (j = 0; j < eventdev_var[i].num_ports; j++) {
+				xstats_display(i, RTE_EVENT_DEV_XSTATS_PORT,
+					eventdev_var[i].ports[j]);
+
+				if (eventdev_var[i].reset_xstats == 1)
+					xstats_reset(i, RTE_EVENT_DEV_XSTATS_PORT,
+							eventdev_var[i].ports[j]);
+			}
+		}
+
+		if (eventdev_var[i].shw_all_queues == 1) {
+			for (j = 0; j < MAX_PORTS_QUEUES; j++) {
+				xstats_display(i, RTE_EVENT_DEV_XSTATS_QUEUE, j);
+
+				if (eventdev_var[i].reset_xstats == 1)
+					xstats_reset(i, RTE_EVENT_DEV_XSTATS_QUEUE, j);
+			}
+		} else {
+			for (j = 0; j < eventdev_var[i].num_queues; j++) {
+				xstats_display(i, RTE_EVENT_DEV_XSTATS_QUEUE,
+						eventdev_var[i].queues[j]);
+
+				if (eventdev_var[i].reset_xstats == 1)
+					xstats_reset(i, RTE_EVENT_DEV_XSTATS_QUEUE,
+							eventdev_var[i].queues[j]);
+			}
+		}
+	}
+
+	if (processing_eventdev_xstats)
+		return 1;
+
+	return 0;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -1794,6 +2164,9 @@  main(int argc, char **argv)
 		return 0;
 	}
 
+	if (process_eventdev_xstats())
+		return 0;
+
 	nb_ports = rte_eth_dev_count_avail();
 	if (nb_ports == 0)
 		rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
diff --git a/app/proc-info/meson.build b/app/proc-info/meson.build
index 1563ce656a..4f83f29a64 100644
--- a/app/proc-info/meson.build
+++ b/app/proc-info/meson.build
@@ -8,7 +8,7 @@  if is_windows
 endif
 
 sources = files('main.c')
-deps += ['ethdev', 'security']
+deps += ['ethdev', 'security', 'eventdev']
 if dpdk_conf.has('RTE_LIB_METRICS')
     deps += 'metrics'
 endif
diff --git a/doc/guides/tools/proc_info.rst b/doc/guides/tools/proc_info.rst
index cf3502a8cb..bb483afbce 100644
--- a/doc/guides/tools/proc_info.rst
+++ b/doc/guides/tools/proc_info.rst
@@ -22,7 +22,9 @@  The application has a number of command line options:
    --show-ring[=name] | --show-mempool[=name] | --iter-mempool=name |
    --show-port-private | --version | --firmware-version | --show-rss-reta |
    --show-module-eeprom | --show-rx-descriptor queue_id:offset:num |
-   --show-tx-descriptor queue_id:offset:num ]
+   --show-tx-descriptor queue_id:offset:num | --show-edev-queue-xstats=queue_num:evdev_id |
+   --show-edev-port-xstats=port_num :evdev_id | --edev-dump-xstats=evdev_id |
+   --edev-reset-xstats=evdev_id | --show-edev-device-xstats=evdev_id]
 
 Parameters
 ~~~~~~~~~~
@@ -101,6 +103,28 @@  queue_id: A Tx queue identifier on this port.
 offset: The offset of the descriptor starting from tail.
 num: The number of the descriptors to dump.
 
+**--show-edev-queue-xstats queue_num:evdev_id**
+The show-edev-queue-xstats parameter enables stats for specified queue or all queues.
+queue_num: The queue number to get queue xstats for this specified queue or * for all queues.
+evdev_id: Id of the eventdev device to display xstats.
+
+**--show-edev-port-xstats port_num:evdev_id**
+The show-edev-port-xstats parameter enables stats for specified port or all ports.
+port_num: The port number to get port xstats for this specified port or * for all ports.
+evdev_id: Id of the eventdev device to display xstats.
+
+**--edev-dump-xstats evdev_id**
+The edev-dump-xstats parameter dumps all eventdev stats.
+evdev_id: Id of the eventdev device to display xstats.
+
+**--edev-reset-xstats evdev_id**
+The edev-reset-xstats parameter resets eventdev xstats after reading.
+evdev_id: Id of the eventdev device to display xstats.
+
+**--show-edev-device-xstats evdev_id**
+The show-edev-device-xstats parameter displays eventdev device xstats.
+evdev_id: Id of the eventdev device to display xstats.
+
 Limitations
 -----------