Skip to contentSkip to conversation

RDMA resource tracking

PATCH In review Leon Romanovsky 4 participants 16 messages Jan 2, 2018 – Jan 3, 2018 5 messages not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover RDMA resource tracking

From: Leon Romanovsky <[email protected]>

Hi,

This is supplementary (user-space) part of RDMA resource tracking posted to the RDMA mailing list for the review [1].

The main goal of this new functionality in RDMAtool is to provide debug visibility of running applications in RDMA stack.

The current series adds new command object (resource) which provides short summary if it is called without arguments or more detailed information while it is called with request to present QPs.

1) Summary information:

$ rdma res
1: mlx5_0: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
2: mlx5_1: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
3: mlx5_2: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
4: mlx5_3: curr/max: pd 2/16777216 cq 3/16777216 qp 2/262144
5: mlx5_4: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144

2) Summary information of specific device:

$ rdma res show mlx5_4
5: mlx5_4: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144

3) Detailed information of specific device:

$ rdma res show qp link mlx5_4
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/-  8          UD    RESET  0          [ipoib-verbs]
mlx5_4/1  7          UD    RTS    0          [mlx5-gsi]
mlx5_4/1  1          GSI   RTS    0          [rdma-mad]
mlx5_4/1  0          SMI   RTS    0          [rdma-mad]
$ rdma res show qp link mlx5_4/
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/-  8          UD    RESET  0          [ipoib-verbs]
mlx5_4/1  7          UD    RTS    0          [mlx5-gsi]
mlx5_4/1  1          GSI   RTS    0          [rdma-mad]
mlx5_4/1  0          SMI   RTS    0          [rdma-mad]

4) Wrong port (it can be 1 or 2):

$ rdma res show qp link mlx5_4/0
Wrong device name

5) Detailed information of specific device and port:

$ rdma res show qp link mlx5_4/1
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/1  7          UD    RTS    0          [mlx5-gsi]
mlx5_4/1  1          GSI   RTS    0          [rdma-mad]
mlx5_4/1  0          SMI   RTS    0          [rdma-mad]

6) Detailed information of QPs not-connected to port yet:

$ rdma res show qp link mlx5_4/-
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/-  8          UD    RESET  0          [ipoib-verbs]

7) Very detailed view:

$ rdma res show qp link mlx5_4/- -d
DEV/PORT  LQPN       RQPN       TYPE  STATE  PID        COMM            SQ-PSN     RQ-PSN     PATH-MIG
mlx5_4/-  8          ---        UD    RESET  0          [ipoib-verbs]   0          ---        ---

8) Limit display to specific columns:

$ rdma res show qp link mlx5_4/1 display pid,lqpn,comm
DEV/PORT  LQPN       PID        COMM
mlx5_4/1  7          0          [mlx5-gsi]
mlx5_4/1  1          0          [rdma-mad]
mlx5_4/1  0          0          [rdma-mad]

9) Filter specific processes:

$ rdma res show qp link mlx5_4/1 display pid,lqpn,comm pid 0-2000
DEV/PORT  LQPN       PID        COMM
mlx5_4/1  7          0          [mlx5-gsi]
mlx5_4/1  1          0          [rdma-mad]
mlx5_4/1  0          0          [rdma-mad]

Thanks

[1] https://marc.info/?l=linux-rdma&m=151488112032562&w=2

Leon Romanovsky (9):
rdam: Add option to provide "-" sign for the port number
rdma: Make visible the number of arguments
rdma: Add filtering infrastructure
rdma: Set pointer to device name position
rdma: Allow external usage of compare string routine
rdma: Update kernel header file
rdma: Add resource tracking summary
rdma: Add QP resource tracking information
rdma: Document resource tracking

 include/uapi/rdma/rdma_netlink.h |  58 +++++-
 man/man8/rdma-resource.8         |  91 +++++++++
 rdma/Makefile                    |   2 +-
 rdma/link.c                      |   2 +-
 rdma/rdma.c                      |   4 +-
 rdma/rdma.h                      |  23 ++-
 rdma/res.c                       | 411 +++++++++++++++++++++++++++++++++++++++
 rdma/utils.c                     | 300 +++++++++++++++++++++++++++-
 8 files changed, 874 insertions(+), 17 deletions(-)
 create mode 100644 man/man8/rdma-resource.8
 create mode 100644 rdma/res.c

A message that is not in the archive (sent off-list or not yet received): 20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

#2 lore raw

PATCH 1/9 rdam: Add option to provide "-" sign for the port number

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

According to the IBTA spec [1], the physical connected port is provided for the QP in RTR-to-INIT stage performed by modify_qp(). It causes to do not have port number for newly created QPs.

The following patch adds "-" sign to present absence of port, because QPs are going to be associated with rdmatool link object, which needs port number as an index.

[1] InfiniBand Architecture Release 1.3 -
"Table 96 QP State Transition Properties"

---
 rdma/link.c  |  2 +-
 rdma/rdma.h  |  3 +--
 rdma/utils.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
 3 files changed, 43 insertions(+), 11 deletions(-)
rdma/link.c +1 -1
index 676cb21d..66bcd50e 100644
@@ -285,7 +285,7 @@ static int link_one_show(struct rd *rd)
 
 static int link_show(struct rd *rd)
 {
-	return rd_exec_link(rd, link_one_show);
+	return rd_exec_link(rd, link_one_show, true);
 }
 
 int cmd_link(struct rd *rd)
rdma/rdma.h +1 -2
index 8d53d3a0..cbd9aa89 100644
@@ -64,7 +64,6 @@ bool rd_no_arg(struct rd *rd);
 void rd_arg_inc(struct rd *rd);
 
 char *rd_argv(struct rd *rd);
-uint32_t get_port_from_argv(struct rd *rd);
 
 /*
  * Commands interface
@@ -73,7 +72,7 @@ int cmd_dev(struct rd *rd);
 int cmd_link(struct rd *rd);
 int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str);
 int rd_exec_dev(struct rd *rd, int (*cb)(struct rd *rd));
-int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd));
+int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port);
 void rd_free(struct rd *rd);
 
 /*
rdma/utils.c +41 -8

95 lines not on this page · raw message

Signature · 6 lines
2.15.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 20180102093725.6172-2-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

#4 lore raw

Re: [PATCH iproute2-next 1/9] rdam: Add option to provide "-" sign for the port number

a couple of nits

Quoted 30 lines · Leon Romanovsky
rdma/utils.c +14 -1
index 7b2001e2..7c920a5c 100644
@@ -10,6 +10,7 @@
  */
 
 #include "rdma.h"
+#include <ctype.h>
 
 static int rd_argc(struct rd *rd)
 {
@@ -50,13 +51,43 @@ bool rd_no_arg(struct rd *rd)
 	return rd_argc(rd) == 0;
 }
 
-uint32_t get_port_from_argv(struct rd *rd)
+/*
+ * Possible input:output
+ * dev/port    | first port | is_dump_all
+ * mlx5_1      | 0          | true
+ * mlx5_1/     | 0          | true
+ * mlx5_1/0    | 0          | false
+ * mlx5_1/1    | 1          | false
+ * mlx5_1/-    | 0          | false
+ *
+ * In strict mode, /- will return error.
+ */
+static int get_port_from_argv(struct rd *rd, uint32_t *port,
+			      bool *is_dump_all, bool strict_port)

rdma/utils.c bool rd_no_arg(struct rd *rd) · line 75

Quoted 10 lines
rdma/utils.c +4 -1
 {
 	char *slash;
 
+	*port = 0;
+	*is_dump_all = true;
+
 	slash = strchr(rd_argv(rd), '/');
 	/* if no port found, return 0 */
-	return slash ? atoi(slash + 1) : 0;
+	if (slash) {

++slash here would alleviate the need for all of the +1's.

Quoted 38 lines
rdma/utils.c +18 -2
+		if (*(slash + 1) == '-') {
+			if (strict_port)
+				return -EINVAL;
+			*is_dump_all = false;
+			return 0;
+		}
+
+		if (isdigit(*(slash + 1))) {
+			*is_dump_all = false;
+			*port = atoi(slash + 1);
+		}
+		if (!*port && strlen(slash + 1))
+			return -EINVAL;
+	}
+	return 0;
 }
 
 static struct dev_map *dev_map_alloc(const char *dev_name)
@@ -152,7 +183,7 @@ void rd_free(struct rd *rd)
 	dev_map_cleanup(rd);
 }
 
-int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd))
+int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port)
 {
 	struct dev_map *dev_map;
 	uint32_t port;
@@ -163,7 +194,8 @@ int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd))
 	if (rd_no_arg(rd)) {
 		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
 			rd->dev_idx = dev_map->idx;
-			for (port = 1; port < dev_map->num_ports + 1; port++) {
+			port = (strict_port) ? 1 : 0;
+			for (; port < dev_map->num_ports + 1; port++) {
 				rd->port_idx = port;
 				ret = cb(rd);
 				if (ret)

rdma/utils.c int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd)) · line 208

Quoted 5 lines
rdma/utils.c +1 -0
@@ -172,21 +204,22 @@ int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd))
 		}
 
 	} else {
+		bool is_dump_all;
 		dev_map = dev_map_lookup(rd, true);

newline between declarations and code.

Quoted 12 lines
rdma/utils.c +2 -3
-		port = get_port_from_argv(rd);
-		if (!dev_map || port > dev_map->num_ports) {
+		ret = get_port_from_argv(rd, &port, &is_dump_all, strict_port);
+		if (!dev_map || port > dev_map->num_ports || (!port && ret)) {
 			pr_err("Wrong device name\n");
 			ret = -ENOENT;
 			goto out;
 		}
 		rd_arg_inc(rd);
 		rd->dev_idx = dev_map->idx;
-		rd->port_idx = port ? : 1;

rdma/utils.c int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd)) · line 225

Quoted 10 lines
rdma/utils.c +2 -1
+		rd->port_idx = port;
 		for (; rd->port_idx < dev_map->num_ports + 1; rd->port_idx++) {
 			ret = cb(rd);
 			if (ret)
 				goto out;
-			if (port)
+			if (!is_dump_all)
 				/*
 				 * We got request to show link for devname
 				 * with port index.

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#5 lore raw

PATCH 2/9 rdma: Make visible the number of arguments

In reply to a message not in the archive

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

---
 rdma/rdma.h  | 1 +
 rdma/utils.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
rdma/rdma.h +1 -0
index cbd9aa89..1b66ae04 100644
@@ -74,6 +74,7 @@ int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str);
 int rd_exec_dev(struct rd *rd, int (*cb)(struct rd *rd));
 int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port);
 void rd_free(struct rd *rd);
+int rd_argc(struct rd *rd);
 
 /*
  * Device manipulation
rdma/utils.c +1 -1
index 7c920a5c..9184f455 100644
@@ -12,7 +12,7 @@
 #include "rdma.h"
 #include <ctype.h>
 
-static int rd_argc(struct rd *rd)
+int rd_argc(struct rd *rd)
 {
 	return rd->argc;
 }
Signature · 6 lines
2.15.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#6 lore raw

PATCH 6/9 rdma: Update kernel header file

In reply to a message not in the archive

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

Synchronize iporute2 package with latest kernel
RDMA netlink header file.

---
 include/uapi/rdma/rdma_netlink.h | 58 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)
include/uapi/rdma/rdma_netlink.h +56 -2
index 48fbf3c3..a6f60c22 100644
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _RDMA_NETLINK_H
-#define _RDMA_NETLINK_H
+#ifndef _UAPI_RDMA_NETLINK_H
+#define _UAPI_RDMA_NETLINK_H
 
 #include <linux/types.h>
 
@@ -236,6 +236,16 @@ enum rdma_nldev_command {
 	RDMA_NLDEV_CMD_PORT_NEW,
 	RDMA_NLDEV_CMD_PORT_DEL,
 
+	RDMA_NLDEV_CMD_RES_GET, /* can dump */
+	RDMA_NLDEV_CMD_RES_SET,
+	RDMA_NLDEV_CMD_RES_NEW,
+	RDMA_NLDEV_CMD_RES_DEL,
+
+	RDMA_NLDEV_CMD_RES_QP_GET, /* can dump */
+	RDMA_NLDEV_CMD_RES_QP_SET,
+	RDMA_NLDEV_CMD_RES_QP_NEW,
+	RDMA_NLDEV_CMD_RES_QP_DEL,
+
 	RDMA_NLDEV_NUM_OPS
 };
 
@@ -303,6 +313,50 @@ enum rdma_nldev_attr {
 
 	RDMA_NLDEV_ATTR_DEV_NODE_TYPE,		/* u8 */
 
+	RDMA_NLDEV_ATTR_RES_SUMMARY,		/* nested table */
+	RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY,	/* nested table */
+	RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME,	/* string */
+	RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR,	/* u64 */
+	RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_MAX,	/* u64 */
+
+	RDMA_NLDEV_ATTR_RES_QP,			/* nested table */
+	RDMA_NLDEV_ATTR_RES_QP_ENTRY,		/* nested table */
+	/*
+	 * Local QPN
+	 */
+	RDMA_NLDEV_ATTR_RES_LQPN,		/* u32 */
+	/*
+	 * Remote QPN,
+	 * Applicable for RC and UC only IBTA 11.2.5.3 QUERY QUEUE PAIR
+	 */
+	RDMA_NLDEV_ATTR_RES_RQPN,		/* u32 */
+	/*
+	 * Receive Queue PSN,
+	 * Applicable for RC and UC only 11.2.5.3 QUERY QUEUE PAIR
+	 */
+	RDMA_NLDEV_ATTR_RES_RQ_PSN,		/* u32 */
+	/*
+	 * Send Queue PSN
+	 */
+	RDMA_NLDEV_ATTR_RES_SQ_PSN,		/* u32 */
+	RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE,	/* u8 */
+	/*
+	 * QP types as visible to RDMA/core, the reserved QPT
+	 * are not exported through this interface.
+	 */
+	RDMA_NLDEV_ATTR_RES_TYPE,		/* u8 */
+	RDMA_NLDEV_ATTR_RES_STATE,		/* u8 */
+	/*
+	 * Process ID created QP, in case of kernel PID is equal to 0
+	 * and this field won't be set, so user will distinguish user/kernel
+	 * processes without relying on PID number.
+	 */
+	RDMA_NLDEV_ATTR_RES_PID,		/* u32 */
+	/*
+	 * The name of process created following resource.
+	 */
+	RDMA_NLDEV_ATTR_RES_PID_COMM,		/* string */
+
 	RDMA_NLDEV_ATTR_MAX
 };
 #endif /* _RDMA_NETLINK_H */
Signature · 6 lines
2.15.1

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 20180102093725.6172-7-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

#8 lore raw

Re: [PATCH iproute2-next 6/9] rdma: Update kernel header file

Quoted 9 lines · Leon Romanovsky

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

Synchronize iporute2 package with latest kernel
RDMA netlink header file.

---
 include/uapi/rdma/rdma_netlink.h | 58 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

FYI: uapi headers are updated separately. Once the patches hit net-next, I will update the headers and drop this patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): 8dc793ba-abf7-900b-02b9-0f9f468fd49f-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org

#10 lore raw

Re: [PATCH iproute2-next 6/9] rdma: Update kernel header file

Quoted 6 lines · David Ahern
Quoted 5 lines · Leon Romanovsky

From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/[email protected]>

Synchronize iporute2 package with latest kernel
RDMA netlink header file.

Quoted 7 lines
Quoted 4 lines
---
 include/uapi/rdma/rdma_netlink.h | 58 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 2 deletions(-)

FYI: uapi headers are updated separately. Once the patches hit net-next, I will update the headers and drop this patch.

No problem, just wanted to raise your attention that this header will be updated in rdma-next and it will appear in net-next in delay of one cycle, after merge cycle will complete.

Thanks

#12 lore raw

PATCH 3/9 rdma: Add filtering infrastructure

In reply to Leon Romanovsky

From: Leon Romanovsky <[email protected]>

This patch adds general infrastructure to RDMAtool to handle various filtering options needed for the downstream resource tracking patches.

The infrastructure is generic and stores filters in list of key<->value entries. There are three types of filters:

1. Numeric - the values are intended to be digits combined with '-' to mark range and ',' to mark multiple entries, e.g. pid 1-100,234,400-401 is perfectly legit filter to limit process ids.

2. String - the values are consist from strings and "," as a denominator. Currently only "display" option is opened for the users and it will be used to hide/unhide table columns in resource tracking patches.

3. Link - special case to allow '/' in string to provide link name, e.g. link mlx4_1/2.

---
 rdma/rdma.c  |   1 +
 rdma/rdma.h  |  15 +++++
 rdma/utils.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 228 insertions(+)
rdma/rdma.c +1 -0
index 0e8fd688..a21ba440 100644
@@ -47,6 +47,7 @@ static int rd_init(struct rd *rd, int argc, char **argv, char *filename)
 	rd->argc = argc;
 	rd->argv = argv;
 	INIT_LIST_HEAD(&rd->dev_map_list);
+	INIT_LIST_HEAD(&rd->filter_list);
 
 	if (rd->json_output) {
 		rd->jw = jsonw_new(stdout);
rdma/rdma.h +15 -0
index 1b66ae04..cd415670 100644
@@ -29,6 +29,12 @@
 #define RDMA_BITMAP_ENUM(name, bit_no) RDMA_BITMAP_##name = BIT(bit_no),
 #define RDMA_BITMAP_NAMES(name, bit_no) [bit_no] = #name,
 
+struct filter_entry {
+	struct list_head list;
+	char *key;
+	char *value;
+};
+
 struct dev_map {
 	struct list_head list;
 	char *dev_name;
@@ -50,6 +56,7 @@ struct rd {
 	json_writer_t *jw;
 	bool json_output;
 	bool pretty_output;
+	struct list_head filter_list;
 };
 
 struct rd_cmd {
@@ -81,6 +88,14 @@ int rd_argc(struct rd *rd);
  */
 struct dev_map *dev_map_lookup(struct rd *rd, bool allow_port_index);
 
+/*
+ * Filter manipulation
+ */
+int rd_build_filter(struct rd *rd, const char * const valid_filters[]);
+bool rd_check_is_filtered(struct rd *rd, const char *key,
+			  uint32_t val, bool ignore_val);
+bool rd_check_is_string_filtered(struct rd *rd, const char *key, char *val);
+bool rd_check_is_key_exist(struct rd *rd, const char *key);
 /*
  * Netlink
  */
rdma/utils.c +212 -0

224 lines not on this page · raw message

Signature · 1 line
2.15.1
#13 lore raw

Re: [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure

Quoted 5 lines · Leon Romanovsky
rdma/utils.c +5 -0
+/*
+ * Check if string entry is filtered:
+ *  * key doesn't exist -> user didn't request -> not filtered
+ */
+bool rd_check_is_string_filtered(struct rd *rd, const char *key, char *val)

rdma/utils.c static void dev_map_cleanup(struct rd *rd) · line 233

Quoted 10 lines
rdma/utils.c +10 -0
+{
+	bool key_is_filtered = false;
+	struct filter_entry *fe;
+	char *p = NULL;
+	char *str;
+
+	list_for_each_entry(fe, &rd->filter_list, list) {
+		if (!strcmpx(fe->key, key)) {
+			/* We found the key */
+			p = strdup(fe->value);

if (p == NULL) ...

Quoted 25 lines
rdma/utils.c +25 -0
+
+			/*
+			 * Need to check if value in range
+			 * It can come in the following formats
+			 * and their permutations:
+			 * str
+			 * str1,str2
+			 */
+			str = strtok(p, ",");
+			while (str) {
+				if (!strcmpx(str, val)) {
+					key_is_filtered = true;
+					goto out;
+				}
+				str = strtok(NULL, ",");
+			}
+			goto out;
+		}
+	}
+
+out:
+	free(p);
+	return key_is_filtered;
+}
+
#14 lore raw

PATCH 4/9 rdma: Set pointer to device name position

In reply to Leon Romanovsky

From: Leon Romanovsky <[email protected]>

The dev and link execution callbacks expects that next command line argument is device or port name.

Set pointer to device or port name position prior calls to rd_exec_dev()/rd_exec_link().

---
 rdma/rdma.h  |  1 +
 rdma/utils.c | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)
rdma/rdma.h +1 -0
index cd415670..e842d076 100644
@@ -81,6 +81,7 @@ int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str);
 int rd_exec_dev(struct rd *rd, int (*cb)(struct rd *rd));
 int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port);
 void rd_free(struct rd *rd);
+int rd_set_arg_to_devname(struct rd *rd);
 int rd_argc(struct rd *rd);
 
 /*
rdma/utils.c +19 -0
index dc9f4f01..fbeffa08 100644
@@ -395,6 +395,25 @@ void rd_free(struct rd *rd)
 	filters_cleanup(rd);
 }
 
+int rd_set_arg_to_devname(struct rd *rd)
+{
+	int ret = 0;
+
+	while (!rd_no_arg(rd)) {
+		if (rd_argv_match(rd, "dev") || rd_argv_match(rd, "link")) {
+			rd_arg_inc(rd);
+			if (rd_no_arg(rd)) {
+				pr_err("No device name was supplied\n");
+				ret = -EINVAL;
+			}
+			goto out;
+		}
+		rd_arg_inc(rd);
+	}
+out:
+	return ret;
+}
+
 int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port)
 {
 	struct dev_map *dev_map;
Signature · 1 line
2.15.1
#15 lore raw

PATCH 5/9 rdma: Allow external usage of compare string routine

In reply to Leon Romanovsky

From: Leon Romanovsky <[email protected]>

---
 rdma/rdma.h  | 2 ++
 rdma/utils.c | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)
rdma/rdma.h +2 -0
index e842d076..816c8ddd 100644
@@ -84,6 +84,8 @@ void rd_free(struct rd *rd);
 int rd_set_arg_to_devname(struct rd *rd);
 int rd_argc(struct rd *rd);
 
+int strcmpx(const char *str1, const char *str2);
+
 /*
  * Device manipulation
  */
rdma/utils.c +1 -1
index fbeffa08..a63a7c2f 100644
@@ -24,7 +24,7 @@ char *rd_argv(struct rd *rd)
 	return *rd->argv;
 }
 
-static int strcmpx(const char *str1, const char *str2)
+int strcmpx(const char *str1, const char *str2)
 {
 	if (strlen(str1) > strlen(str2))
 		return -1;
Signature · 1 line
2.15.1
#16 lore raw

PATCH 7/9 rdma: Add resource tracking summary

In reply to Leon Romanovsky

From: Leon Romanovsky <[email protected]>

The global resource summary information. The object names, current utilization and maximum numbers are received as is from the kernel.

$ rdma res
1: mlx5_0: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
2: mlx5_1: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
3: mlx5_2: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
4: mlx5_3: curr/max: pd 2/16777216 cq 3/16777216 qp 2/262144
5: mlx5_4: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
$ rdma res show mlx5_4
5: mlx5_4: curr/max: pd 3/16777216 cq 5/16777216 qp 4/262144
---
 rdma/Makefile |   2 +-
 rdma/rdma.c   |   3 +-
 rdma/rdma.h   |   1 +
 rdma/res.c    | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rdma/utils.c  |   5 ++
 5 files changed, 177 insertions(+), 2 deletions(-)
 create mode 100644 rdma/res.c
rdma/Makefile +1 -1
index c8966bfd..875fe53c 100644
@@ -3,7 +3,7 @@ include ../config.mk
 
 ifeq ($(HAVE_MNL),y)
 
-RDMA_OBJ = rdma.o utils.o dev.o link.o
+RDMA_OBJ = rdma.o utils.o dev.o link.o res.o
 
 TARGETS=rdma
 endif
rdma/rdma.c +2 -1
index a21ba440..19608f41 100644
@@ -15,7 +15,7 @@
 static void help(char *name)
 {
 	pr_out("Usage: %s [ OPTIONS ] OBJECT { COMMAND | help }\n"
-	       "where  OBJECT := { dev | link | help }\n"
+	       "where  OBJECT := { dev | link | resource | help }\n"
 	       "       OPTIONS := { -V[ersion] | -d[etails] | -j[son] | -p[retty]}\n", name);
 }
 
@@ -32,6 +32,7 @@ static int rd_cmd(struct rd *rd)
 		{ "help",	cmd_help },
 		{ "dev",	cmd_dev },
 		{ "link",	cmd_link },
+		{ "resource",	cmd_res },
 		{ 0 }
 	};
 
rdma/rdma.h +1 -0
index 816c8ddd..f1ddedd2 100644
@@ -77,6 +77,7 @@ char *rd_argv(struct rd *rd);
  */
 int cmd_dev(struct rd *rd);
 int cmd_link(struct rd *rd);
+int cmd_res(struct rd *rd);
 int rd_exec_cmd(struct rd *rd, const struct rd_cmd *c, const char *str);
 int rd_exec_dev(struct rd *rd, int (*cb)(struct rd *rd));
 int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port);
rdma/res.c new file +168 -0

168 lines not on this page · raw message

rdma/utils.c +5 -0
index a63a7c2f..859ad7ab 100644
@@ -339,6 +339,11 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
 	[RDMA_NLDEV_ATTR_PORT_STATE] = MNL_TYPE_U8,
 	[RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = MNL_TYPE_U8,
 	[RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = MNL_TYPE_U8,
+	[RDMA_NLDEV_ATTR_RES_SUMMARY]	= MNL_TYPE_NESTED,
+	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY]	= MNL_TYPE_NESTED,
+	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME] = MNL_TYPE_NUL_STRING,
+	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR] = MNL_TYPE_U64,
+	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_MAX]	= MNL_TYPE_U64,
 };
 
 int rd_attr_cb(const struct nlattr *attr, void *data)
Signature · 1 line
2.15.1
#17 lore raw

PATCH 8/9 rdma: Add QP resource tracking information

In reply to Leon Romanovsky

From: Leon Romanovsky <[email protected]>

This patch adds ss-similar interface to view various resource tracked objects. At this stage, only QP is presented.

1. Get all QPs for the specific device:

$ rdma res show qp link mlx5_4
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/-  8          UD    RESET  0          [ipoib-verbs]
mlx5_4/1  7          UD    RTS    0          [mlx5-gsi]
mlx5_4/1  1          GSI   RTS    0          [rdma-mad]
mlx5_4/1  0          SMI   RTS    0          [rdma-mad]
$ rdma res show qp link mlx5_4/
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/-  8          UD    RESET  0          [ipoib-verbs]
mlx5_4/1  7          UD    RTS    0          [mlx5-gsi]
mlx5_4/1  1          GSI   RTS    0          [rdma-mad]
mlx5_4/1  0          SMI   RTS    0          [rdma-mad]

2. Provide illegal port number (0 is illegal):

$ rdma res show qp link mlx5_4/0
Wrong device name

3. Get QPs of specific port:

$ rdma res show qp link mlx5_4/1
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/1  7          UD    RTS    0          [mlx5-gsi]
mlx5_4/1  1          GSI   RTS    0          [rdma-mad]
mlx5_4/1  0          SMI   RTS    0          [rdma-mad]

4. Get QPs which have not assigned port yet:

$ rdma res show qp link mlx5_4/-
DEV/PORT  LQPN       TYPE  STATE  PID        COMM
mlx5_4/-  8          UD    RESET  0          [ipoib-verbs]

5. Detailed view:

$ rdma res show qp link mlx5_4/- -d
DEV/PORT  LQPN       RQPN       TYPE  STATE  PID        COMM            SQ-PSN     RQ-PSN     PATH-MIG
mlx5_4/-  8          ---        UD    RESET  0          [ipoib-verbs]   0          ---        ---

6. Limit to specific columns (dev/port is always available):

$ rdma res show qp link mlx5_4/1 display pid,lqpn,comm
DEV/PORT  LQPN       PID        COMM
mlx5_4/1  7          0          [mlx5-gsi]
mlx5_4/1  1          0          [rdma-mad]
mlx5_4/1  0          0          [rdma-mad]

7. Detailed view (no change, due to "display" option):

$ rdma res show qp link mlx5_4/1 display pid,lqpn,comm -d
DEV/PORT  LQPN       PID        COMM
mlx5_4/1  7          0          [mlx5-gsi]
mlx5_4/1  1          0          [rdma-mad]
mlx5_4/1  0          0          [rdma-mad]

8. Limit to specific Local QPNs:

$ rdma res show qp link mlx5_4/1 display pid,lqpn,comm lqpn 0-6
DEV/PORT  LQPN       PID        COMM
mlx5_4/1  1          0          [rdma-mad]
mlx5_4/1  0          0          [rdma-mad]
---
 rdma/res.c   | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rdma/utils.c |  11 +++
 2 files changed, 254 insertions(+)
rdma/res.c +243 -0
index a70e87dd..184a3a02 100644
@@ -16,6 +16,9 @@ static int res_help(struct rd *rd)
 {
 	pr_out("Usage: %s resource\n", rd->filename);
 	pr_out("          resource show [DEV]\n");
+	pr_out("          resource show [qp]\n");
+	pr_out("          resource show qp link [DEV/PORT]\n");
+	pr_out("          resource show qp link [DEV/PORT] [FILTER-NAME FILTER-VALUE]\n");
 	return 0;
 }
 
@@ -136,12 +139,252 @@ static int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback)
 		return rd_exec_link(rd, _##name, strict_port); \
 	}
 
+struct column {
+	char filter_name[32];
+	char column_name[32];
+	bool in_simple_view;
+};
+
+static bool show_column(struct rd *rd, struct column *c)
+{
+	if (rd_check_is_key_exist(rd, "display"))
+		return rd_check_is_string_filtered(rd, "display", c->filter_name);
+
+	if (!rd->show_details)
+		return c->in_simple_view;
+	return true;
+}
+
+static const char *path_mig_to_str(uint8_t idx)
+{
+	static const char * const path_mig_str[] = { "MIGRATED",
+						     "REARM", "ARMED" };
+
+	if (idx < ARRAY_SIZE(path_mig_str))
+		return path_mig_str[idx];
+	return "UNKNOWN";
+}
+
+static const char *qp_states_to_str(uint8_t idx)
+{
+	static const char * const qp_states_str[] = { "RESET", "INIT",
+						      "RTR", "RTS", "SQD",
+						      "SQE", "ERR" };
+
+	if (idx < ARRAY_SIZE(qp_states_str))
+		return qp_states_str[idx];
+	return "UNKNOWN";
+}
+
+static const char *qp_types_to_str(uint8_t idx)
+{
+	static const char * const qp_types_str[] = { "SMI", "GSI", "RC",
+						     "UC", "UD", "RAW_IPV6",
+						     "RAW_ETHERTYPE",
+						     "UNKNOWN", "RAW_PACKET",
+						     "XRC_INI", "XRC_TGT" };
+
+	if (idx < ARRAY_SIZE(qp_types_str))
+		return qp_types_str[idx];
+	return "UNKNOWN";
+}
+
+static int res_qp_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+	static struct column c[] = { { .filter_name = "lqpn",
+				       .column_name = "LQPN       ",
+				       .in_simple_view = true },
+				     { .filter_name = "rqpn",
+				       .column_name = "RQPN       " },
+				     { .filter_name = "type",
+				       .column_name = "TYPE  ",
+					.in_simple_view = true },
+				     { .filter_name = "state",
+				       .column_name = "STATE  ",
+				       .in_simple_view = true },
+				     { .filter_name = "pid",
+				       .column_name = "PID        ",
+				       .in_simple_view = true },
+				     { .filter_name = "comm",
+				       .column_name = "COMM            ",
+				       .in_simple_view = true },
+				     { .filter_name = "sq-psn",
+				       .column_name = "SQ-PSN     " },
+				     { .filter_name = "rq-psn",
+				       .column_name = "RQ-PSN     " },
+				     { .filter_name = "path-mig",
+				       .column_name = "PATH-MIG        " } };
+
+	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+	struct nlattr *nla_table, *nla_entry;
+	static bool print_header = true;
+	struct rd *rd = data;
+	uint32_t cidx, idx;
+	const char *name;
+
+	mnl_attr_parse(nlh, 0, rd_attr_cb, tb);
+	if (!tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
+	    !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
+	    !tb[RDMA_NLDEV_ATTR_RES_QP])
+		return MNL_CB_ERROR;
+
+	name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+	idx =  mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+	nla_table = tb[RDMA_NLDEV_ATTR_RES_QP];
+	if (!rd->json_output && print_header) {
+		pr_out("DEV/PORT  ");
+		for (cidx = 0; cidx < ARRAY_SIZE(c); cidx++)
+			if (show_column(rd, &c[cidx]))
+				pr_out("%s", c[cidx].column_name);
+		pr_out("\n");
+		print_header = false;
+	}
+
+	mnl_attr_for_each_nested(nla_entry, nla_table) {
+		struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+		uint32_t lqpn, rqpn = 0, rq_psn = 0, sq_psn;
+		uint8_t type, state, path_mig_state = 0;
+		uint32_t port = 0, pid = 0;
+		bool ignore_value = false;
+		char port_name[32];
+		const char *comm;
+		int err;
+
+		err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
+		if (err != MNL_CB_OK)
+			return -EINVAL;
+
+		if (!nla_line[RDMA_NLDEV_ATTR_RES_LQPN] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_TYPE] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_PID_COMM]) {
+			return -EINVAL;
+		}
+
+		if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+			port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
+
+		if (port != rd->port_idx)
+			continue;
+
+		if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+			snprintf(port_name, 32, "%s/%u", name, port);
+		else
+			snprintf(port_name, 32, "%s/-", name);
+
+		lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
+		if (rd_check_is_filtered(rd, "lqpn", lqpn, false))
+			continue;
+
+		if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
+			rqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQPN]);
+		else
+			ignore_value = true;
+
+		if (rd_check_is_filtered(rd, "rqpn", rqpn, ignore_value))
+			continue;
+
+		if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
+			rq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]);
+
+		sq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]);
+		if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
+			path_mig_state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]);
+		type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
+		state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
+
+		if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+			pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
+
+		if (rd_check_is_filtered(rd, "pid", pid, false))
+			continue;
+
+		comm = mnl_attr_get_str(nla_line[RDMA_NLDEV_ATTR_RES_PID_COMM]);
+
+		if (rd->json_output) {
+			jsonw_start_array(rd->jw);
+			jsonw_uint_field(rd->jw, "ifindex", idx);
+			if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+				jsonw_uint_field(rd->jw, "port", port);
+			jsonw_string_field(rd->jw, "ifname", port_name);
+			jsonw_uint_field(rd->jw, "lqpn", lqpn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
+				jsonw_uint_field(rd->jw, "rqpn", rqpn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
+				jsonw_uint_field(rd->jw, "rq-psn", rq_psn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN])
+				jsonw_uint_field(rd->jw, "sq-psn", sq_psn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
+				jsonw_string_field(rd->jw, "path-mig-state",
+						   path_mig_to_str(path_mig_state));
+
+			jsonw_string_field(rd->jw, "type", qp_types_to_str(type));
+			jsonw_string_field(rd->jw, "state", qp_states_to_str(state));
+			if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+				jsonw_uint_field(rd->jw, "pid", pid);
+			jsonw_string_field(rd->jw, "comm", comm);
+			jsonw_end_array(rd->jw);
+		} else {
+			pr_out("%-10s", port_name);
+			for (cidx = 0; cidx < ARRAY_SIZE(c); cidx++)
+				if (show_column(rd, &c[cidx])) {
+					if (!strcmpx(c[cidx].filter_name, "lqpn"))
+						pr_out("%-11u", lqpn);
+					if (!strcmpx(c[cidx].filter_name, "rqpn")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
+							pr_out("%-11u", rqpn);
+						else
+							pr_out("%-11s", "---");
+					}
+					if (!strcmpx(c[cidx].filter_name, "type"))
+						pr_out("%-6s", qp_types_to_str(type));
+					if (!strcmpx(c[cidx].filter_name, "state"))
+						pr_out("%-7s", qp_states_to_str(state));
+					if (!strcmpx(c[cidx].filter_name, "rq-psn")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
+							pr_out("%-11d", rq_psn);
+						else
+							pr_out("%-11s", "---");
+					}
+					if (!strcmpx(c[cidx].filter_name, "sq-psn"))
+						pr_out("%-11d", sq_psn);
+					if (!strcmpx(c[cidx].filter_name, "path-mig")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
+							pr_out("%-16s", path_mig_to_str(path_mig_state));
+						else
+							pr_out("%-16s", "---");
+					}
+					if (!strcmpx(c[cidx].filter_name, "pid"))
+						pr_out("%-11d", pid);
+					if (!strcmpx(c[cidx].filter_name, "comm")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
+							pr_out("%-16s ", comm);
+						} else {
+							char tmp[18];
+
+							snprintf(tmp, sizeof(tmp), "[%s]", comm);
+							pr_out("%-16s", tmp);
+						}
+					}
+			}
+			pr_out("\n");
+		}
+	}
+	return MNL_CB_OK;
+}
+
 RES_FUNC(res_no_args,	RDMA_NLDEV_CMD_RES_GET,	NULL, true);
 
+static const char * const qp_valid_filters[] = { "link", "lqpn", "rqpn",
+						 "pid", "display", NULL };
+RES_FUNC(res_qp,	RDMA_NLDEV_CMD_RES_QP_GET, qp_valid_filters, false);
+
 static int res_show(struct rd *rd)
 {
 	const struct rd_cmd cmds[] = {
 		{ NULL,		res_no_args	},
+		{ "qp",		res_qp		},
 		{ 0 }
 	};
 
rdma/utils.c +11 -0
index 859ad7ab..65bb6657 100644
@@ -344,6 +344,17 @@ static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
 	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME] = MNL_TYPE_NUL_STRING,
 	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR] = MNL_TYPE_U64,
 	[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_MAX]	= MNL_TYPE_U64,
+	[RDMA_NLDEV_ATTR_RES_QP]		= MNL_TYPE_NESTED,
+	[RDMA_NLDEV_ATTR_RES_QP_ENTRY]		= MNL_TYPE_NESTED,
+	[RDMA_NLDEV_ATTR_RES_LQPN]	= MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_RES_RQPN]	= MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_RES_RQ_PSN]		= MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_RES_SQ_PSN]		= MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]	= MNL_TYPE_U8,
+	[RDMA_NLDEV_ATTR_RES_TYPE]		= MNL_TYPE_U8,
+	[RDMA_NLDEV_ATTR_RES_STATE]		= MNL_TYPE_U8,
+	[RDMA_NLDEV_ATTR_RES_PID]		= MNL_TYPE_U32,
+	[RDMA_NLDEV_ATTR_RES_PID_COMM]	= MNL_TYPE_NUL_STRING,
 };
 
 int rd_attr_cb(const struct nlattr *attr, void *data)
Signature · 1 line
2.15.1

A message that is not in the archive (sent off-list or not yet received): 20180102093725.6172-9-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org

#19 lore raw

Re: [PATCH iproute2-next 8/9] rdma: Add QP resource tracking information

Quoted 75 lines · Leon Romanovsky
rdma/res.c +75 -0
+	mnl_attr_for_each_nested(nla_entry, nla_table) {
+		struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+		uint32_t lqpn, rqpn = 0, rq_psn = 0, sq_psn;
+		uint8_t type, state, path_mig_state = 0;
+		uint32_t port = 0, pid = 0;
+		bool ignore_value = false;
+		char port_name[32];
+		const char *comm;
+		int err;
+
+		err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, nla_line);
+		if (err != MNL_CB_OK)
+			return -EINVAL;
+
+		if (!nla_line[RDMA_NLDEV_ATTR_RES_LQPN] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_TYPE] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_STATE] ||
+		    !nla_line[RDMA_NLDEV_ATTR_RES_PID_COMM]) {
+			return -EINVAL;
+		}
+
+		if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+			port = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_PORT_INDEX]);
+
+		if (port != rd->port_idx)
+			continue;
+
+		if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+			snprintf(port_name, 32, "%s/%u", name, port);
+		else
+			snprintf(port_name, 32, "%s/-", name);
+
+		lqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_LQPN]);
+		if (rd_check_is_filtered(rd, "lqpn", lqpn, false))
+			continue;
+
+		if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
+			rqpn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQPN]);
+		else
+			ignore_value = true;
+
+		if (rd_check_is_filtered(rd, "rqpn", rqpn, ignore_value))
+			continue;
+
+		if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
+			rq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN]);
+
+		sq_psn = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN]);
+		if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
+			path_mig_state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE]);
+		type = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_TYPE]);
+		state = mnl_attr_get_u8(nla_line[RDMA_NLDEV_ATTR_RES_STATE]);
+
+		if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+			pid = mnl_attr_get_u32(nla_line[RDMA_NLDEV_ATTR_RES_PID]);
+
+		if (rd_check_is_filtered(rd, "pid", pid, false))
+			continue;
+
+		comm = mnl_attr_get_str(nla_line[RDMA_NLDEV_ATTR_RES_PID_COMM]);
+
+		if (rd->json_output) {
+			jsonw_start_array(rd->jw);
+			jsonw_uint_field(rd->jw, "ifindex", idx);
+			if (nla_line[RDMA_NLDEV_ATTR_PORT_INDEX])
+				jsonw_uint_field(rd->jw, "port", port);
+			jsonw_string_field(rd->jw, "ifname", port_name);
+			jsonw_uint_field(rd->jw, "lqpn", lqpn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
+				jsonw_uint_field(rd->jw, "rqpn", rqpn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
+				jsonw_uint_field(rd->jw, "rq-psn", rq_psn);
+			if (nla_line[RDMA_NLDEV_ATTR_RES_SQ_PSN])
+				jsonw_uint_field(rd->jw, "sq-psn", sq_psn);

rdma/res.c static int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback) · line 327

Quoted 10 lines
rdma/res.c +10 -0
+			if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
+				jsonw_string_field(rd->jw, "path-mig-state",
+						   path_mig_to_str(path_mig_state));
+
+			jsonw_string_field(rd->jw, "type", qp_types_to_str(type));
+			jsonw_string_field(rd->jw, "state", qp_states_to_str(state));
+			if (nla_line[RDMA_NLDEV_ATTR_RES_PID])
+				jsonw_uint_field(rd->jw, "pid", pid);
+			jsonw_string_field(rd->jw, "comm", comm);
+			jsonw_end_array(rd->jw);

Some newlines separating common fields goes a long way to make that readable.

Quoted 32 lines
rdma/res.c +32 -0
+		} else {
+			pr_out("%-10s", port_name);
+			for (cidx = 0; cidx < ARRAY_SIZE(c); cidx++)
+				if (show_column(rd, &c[cidx])) {
+					if (!strcmpx(c[cidx].filter_name, "lqpn"))
+						pr_out("%-11u", lqpn);
+					if (!strcmpx(c[cidx].filter_name, "rqpn")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_RQPN])
+							pr_out("%-11u", rqpn);
+						else
+							pr_out("%-11s", "---");
+					}
+					if (!strcmpx(c[cidx].filter_name, "type"))
+						pr_out("%-6s", qp_types_to_str(type));
+					if (!strcmpx(c[cidx].filter_name, "state"))
+						pr_out("%-7s", qp_states_to_str(state));
+					if (!strcmpx(c[cidx].filter_name, "rq-psn")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_RQ_PSN])
+							pr_out("%-11d", rq_psn);
+						else
+							pr_out("%-11s", "---");
+					}
+					if (!strcmpx(c[cidx].filter_name, "sq-psn"))
+						pr_out("%-11d", sq_psn);
+					if (!strcmpx(c[cidx].filter_name, "path-mig")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_PATH_MIG_STATE])
+							pr_out("%-16s", path_mig_to_str(path_mig_state));
+						else
+							pr_out("%-16s", "---");
+					}
+					if (!strcmpx(c[cidx].filter_name, "pid"))
+						pr_out("%-11d", pid);

rdma/res.c static int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback) · line 369

Quoted 10 lines
rdma/res.c +10 -0
+					if (!strcmpx(c[cidx].filter_name, "comm")) {
+						if (nla_line[RDMA_NLDEV_ATTR_RES_PID]) {
+							pr_out("%-16s ", comm);
+						} else {
+							char tmp[18];
+
+							snprintf(tmp, sizeof(tmp), "[%s]", comm);
+							pr_out("%-16s", tmp);
+						}
+					}

same with this block. Can each be put into helpers to decrease the indentation and then some newlines to put some whitespace on all the strcmp's?

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#20 lore raw

PATCH 9/9 rdma: Document resource tracking

In reply to Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Spartan version of resource tracking documentation.

---
 man/man8/rdma-resource.8 | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)
 create mode 100644 man/man8/rdma-resource.8
man/man8/rdma-resource.8 new file +91 -0
new file mode 100644
index 00000000..e3c83b94
@@ -0,0 +1,91 @@
+.TH RDMA\-RESOURCE 8 "26 Dec 2017" "iproute2" "Linux"
+.SH NAME
+rdma-resource \- rdma resource configuration
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+.ti -8
+.B rdma
+.RI "[ " OPTIONS " ]"
+.B resource
+.RI  " { " COMMAND " | "
+.BR help " }"
+.sp
+
+.ti -8
+.IR OPTIONS " := { "
+\fB\-j\fR[\fIson\fR] |
+\fB\-d\fR[\fIetails\fR] }
+
+.ti -8
+.B rdma resource show
+.RI "[ " DEV/PORT_INDEX " ]"
+
+.ti -8
+.B rdma resource help
+
+.SH "DESCRIPTION"
+.SS rdma resource show - display rdma resource tracking information
+
+.PP
+.I "DEV/PORT_INDEX"
+- specifies the RDMA link to show.
+If this argument is omitted all links are listed.
+
+.SH "EXAMPLES"
+.PP
+rdma resource show
+.RS 4
+Shows summary for all devices on the system.
+.RE
+.PP
+rdma resource show mlx5_2
+.RS 4
+Shows the state of specified rdma device.
+.RE
+.PP
+rdma res show qp link mlx5_4
+.RS 4
+Get all QPs for the specific device.
+.RE
+.PP
+rdma res show qp link mlx5_4/1
+.RS 4
+Get QPs of specific port.
+.RE
+.PP
+rdma res show qp link mlx5_4/0
+.RS 4
+Provide illegal port number (0 is illegal).
+.RE
+.PP
+rdma res show qp link mlx5_4/-
+.RS 4
+Get QPs which have not assigned port yet.
+.RE
+.PP
+rdma res show qp link mlx5_4/- -d
+.RS 4
+Detailed view.
+.RE
+.PP
+rdma res show qp link mlx5_4/1 display pid,lqpn,comm
+.RS 4
+Limit to specific columns (dev/port is always available)
+.RE
+.PP
+rdma res show qp link mlx5_4/1 display pid,lqpn,comm lqpn 0-6
+.RS 4
+Limit to specific Local QPNs.
+.RE
+.PP
+
+.SH SEE ALSO
+.BR rdma (8),
+.BR rdma-dev (8),
+.BR rdma-link (8),
+.br
+
+.SH AUTHOR
+Leon Romanovsky <[email protected]>
Signature · 1 line
2.15.1