* [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure
2018-01-02 9:37 [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
2018-01-03 2:47 ` David Ahern
2018-01-02 9:37 ` [PATCH iproute2-next 4/9] rdma: Set pointer to device name position Leon Romanovsky
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro@mellanox.com>
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.
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/rdma.c | 1 +
rdma/rdma.h | 15 +++++
rdma/utils.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 228 insertions(+)
diff --git a/rdma/rdma.c b/rdma/rdma.c
index 0e8fd688..a21ba440 100644
--- a/rdma/rdma.c
+++ b/rdma/rdma.c
@@ -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);
diff --git a/rdma/rdma.h b/rdma/rdma.h
index 1b66ae04..cd415670 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -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
*/
diff --git a/rdma/utils.c b/rdma/utils.c
index 9184f455..dc9f4f01 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -114,6 +114,217 @@ static void dev_map_cleanup(struct rd *rd)
}
}
+static int add_filter(struct rd *rd, char *key, char *value,
+ const char * const valid_filters[])
+{
+ char cset[] = "1234567890,-";
+ struct filter_entry *fe;
+ bool key_found = false;
+ int idx = 0;
+ int ret;
+
+ fe = calloc(1, sizeof(*fe));
+ if (!fe)
+ return -ENOMEM;
+
+ while (valid_filters[idx]) {
+ if (!strcmpx(key, valid_filters[idx])) {
+ key_found = true;
+ break;
+ }
+ idx++;
+ }
+ if (!key_found) {
+ pr_err("Unsupported filter option: %s\n", key);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /*
+ * Check the filter validity, not optimal, but works
+ *
+ * Actually, there are three types of filters
+ * numeric - for example PID or QPN
+ * string - for example states, currently only "display"
+ * is from this type
+ * link - user requested to filter on specific link
+ * e.g. mlx5_1/1, mlx5_1/-, mlx5_1 ...
+ */
+ if (strcmpx(key, "link") && strcmpx(key, "display") &&
+ strspn(value, cset) != strlen(value)) {
+ pr_err("%s filter accepts \"%s\" characters only\n", key, cset);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ fe->key = strdup(key);
+ fe->value = strdup(value);
+
+ list_add_tail(&fe->list, &rd->filter_list);
+ return 0;
+
+err:
+ free(fe);
+ return ret;
+}
+
+int rd_build_filter(struct rd *rd, const char * const valid_filters[])
+{
+ int ret = 0;
+ int idx = 0;
+
+ if (!valid_filters || !rd_argc(rd))
+ goto out;
+
+ if (rd_argc(rd) == 1) {
+ pr_err("No filter data was supplied to filter option %s\n", rd_argv(rd));
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (rd_argc(rd) % 2) {
+ pr_err("There is filter option without data\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ while (idx != rd_argc(rd)) {
+ /*
+ * We can do micro-optimization and skip "dev"
+ * and "link" filters, but it is not worth of it.
+ */
+ ret = add_filter(rd, *(rd->argv + idx),
+ *(rd->argv + idx + 1), valid_filters);
+ if (ret)
+ goto out;
+ idx += 2;
+ }
+
+out:
+ return ret;
+}
+
+bool rd_check_is_key_exist(struct rd *rd, const char *key)
+{
+ struct filter_entry *fe;
+
+ list_for_each_entry(fe, &rd->filter_list, list) {
+ if (!strcmpx(fe->key, key))
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * 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)
+{
+ 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);
+
+ /*
+ * 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;
+}
+
+/*
+ * Check if key is filtered:
+ * key doesn't exist -> user didn't request -> not filtered
+ */
+bool rd_check_is_filtered(struct rd *rd, const char *key,
+ uint32_t val, bool ignore_val)
+{
+ bool key_is_filtered = false;
+ struct filter_entry *fe;
+
+ list_for_each_entry(fe, &rd->filter_list, list) {
+ uint32_t left_val = 0, fe_value = 0;
+ bool range_check = false;
+ char *p = fe->value;
+
+ if (!strcmpx(fe->key, key)) {
+ /* We found the key */
+ key_is_filtered = true;
+ if (ignore_val)
+ goto out;
+ /*
+ * Need to check if value in range
+ * It can come in the following formats
+ * (and their permutations):
+ * numb
+ * numb1,numb2
+ * ,numb1,numb2
+ * numb1-numb2
+ * numb1,numb2-numb3,numb4-numb5
+ */
+ while (*p) {
+ if (isdigit(*p)) {
+ fe_value = strtol(p, &p, 10);
+ if (fe_value == val ||
+ (range_check && left_val < val &&
+ val < fe_value)) {
+ key_is_filtered = false;
+ goto out;
+ }
+ range_check = false;
+ } else {
+ if (*p == '-') {
+ left_val = fe_value;
+ range_check = true;
+ }
+ p++;
+ }
+ }
+ goto out;
+ }
+ }
+
+out:
+ return key_is_filtered;
+}
+
+static void filters_cleanup(struct rd *rd)
+{
+ struct filter_entry *fe, *tmp;
+
+ list_for_each_entry_safe(fe, tmp,
+ &rd->filter_list, list) {
+ list_del(&fe->list);
+ free(fe->key);
+ free(fe->value);
+ free(fe);
+ }
+}
+
static const enum mnl_attr_data_type nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
[RDMA_NLDEV_ATTR_DEV_INDEX] = MNL_TYPE_U32,
[RDMA_NLDEV_ATTR_DEV_NAME] = MNL_TYPE_NUL_STRING,
@@ -181,6 +392,7 @@ void rd_free(struct rd *rd)
return;
free(rd->buff);
dev_map_cleanup(rd);
+ filters_cleanup(rd);
}
int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port)
--
2.15.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure
2018-01-02 9:37 ` [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure Leon Romanovsky
@ 2018-01-03 2:47 ` David Ahern
0 siblings, 0 replies; 16+ messages in thread
From: David Ahern @ 2018-01-03 2:47 UTC (permalink / raw)
To: Leon Romanovsky, Doug Ledford, Jason Gunthorpe
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
On 1/2/18 2:37 AM, Leon Romanovsky wrote:
> +/*
> + * 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)
> +{
> + 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) ...
> +
> + /*
> + * 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;
> +}
> +
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH iproute2-next 4/9] rdma: Set pointer to device name position
2018-01-02 9:37 [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 5/9] rdma: Allow external usage of compare string routine Leon Romanovsky
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro@mellanox.com>
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().
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/rdma.h | 1 +
rdma/utils.c | 19 +++++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/rdma/rdma.h b/rdma/rdma.h
index cd415670..e842d076 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -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);
/*
diff --git a/rdma/utils.c b/rdma/utils.c
index dc9f4f01..fbeffa08 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -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;
--
2.15.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH iproute2-next 5/9] rdma: Allow external usage of compare string routine
2018-01-02 9:37 [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 4/9] rdma: Set pointer to device name position Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
[not found] ` <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/rdma.h | 2 ++
rdma/utils.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/rdma/rdma.h b/rdma/rdma.h
index e842d076..816c8ddd 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -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
*/
diff --git a/rdma/utils.c b/rdma/utils.c
index fbeffa08..a63a7c2f 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -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;
--
2.15.1
^ permalink raw reply related [flat|nested] 16+ messages in thread[parent not found: <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>]
* [PATCH iproute2-next 1/9] rdam: Add option to provide "-" sign for the port number
[not found] ` <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2018-01-02 9:37 ` Leon Romanovsky
[not found] ` <20180102093725.6172-2-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2018-01-02 9:37 ` [PATCH iproute2-next 2/9] rdma: Make visible the number of arguments Leon Romanovsky
` (2 subsequent siblings)
3 siblings, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
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"
Signed-off-by: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
rdma/link.c | 2 +-
rdma/rdma.h | 3 +--
rdma/utils.c | 49 +++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/rdma/link.c b/rdma/link.c
index 676cb21d..66bcd50e 100644
--- a/rdma/link.c
+++ b/rdma/link.c
@@ -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)
diff --git a/rdma/rdma.h b/rdma/rdma.h
index 8d53d3a0..cbd9aa89 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -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);
/*
diff --git a/rdma/utils.c b/rdma/utils.c
index 7b2001e2..7c920a5c 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -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)
{
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) {
+ 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)
@@ -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);
- 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;
+ 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.
--
2.15.1
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH iproute2-next 2/9] rdma: Make visible the number of arguments
[not found] ` <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2018-01-02 9:37 ` [PATCH iproute2-next 1/9] rdam: Add option to provide "-" sign for the port number Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 6/9] rdma: Update kernel header file Leon Romanovsky
2018-01-03 5:40 ` [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
3 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Signed-off-by: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
rdma/rdma.h | 1 +
rdma/utils.c | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/rdma/rdma.h b/rdma/rdma.h
index cbd9aa89..1b66ae04 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -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
diff --git a/rdma/utils.c b/rdma/utils.c
index 7c920a5c..9184f455 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -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;
}
--
2.15.1
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH iproute2-next 6/9] rdma: Update kernel header file
[not found] ` <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2018-01-02 9:37 ` [PATCH iproute2-next 1/9] rdam: Add option to provide "-" sign for the port number Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 2/9] rdma: Make visible the number of arguments Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
[not found] ` <20180102093725.6172-7-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2018-01-03 5:40 ` [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
3 siblings, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
Synchronize iporute2 package with latest kernel
RDMA netlink header file.
Signed-off-by: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
include/uapi/rdma/rdma_netlink.h | 58 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 56 insertions(+), 2 deletions(-)
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index 48fbf3c3..a6f60c22 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -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 */
--
2.15.1
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [PATCH iproute2-next 0/9] RDMA resource tracking
[not found] ` <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
` (2 preceding siblings ...)
2018-01-02 9:37 ` [PATCH iproute2-next 6/9] rdma: Update kernel header file Leon Romanovsky
@ 2018-01-03 5:40 ` Leon Romanovsky
3 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-03 5:40 UTC (permalink / raw)
To: David Ahern
Cc: Doug Ledford, Jason Gunthorpe, RDMA mailing list, netdev,
Stephen Hemminger
[-- Attachment #1: Type: text/plain, Size: 332 bytes --]
On Tue, Jan 02, 2018 at 11:37:16AM +0200, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
>
....
David,
Thanks for the review, I'll fix everything you mentioned and will send
new version a little bit later this week to give time to other reviewers
to finish their reviews.
Thanks
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH iproute2-next 7/9] rdma: Add resource tracking summary
2018-01-02 9:37 [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
` (3 preceding siblings ...)
[not found] ` <20180102093725.6172-1-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2018-01-02 9:37 ` Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 8/9] rdma: Add QP resource tracking information Leon Romanovsky
2018-01-02 9:37 ` [PATCH iproute2-next 9/9] rdma: Document resource tracking Leon Romanovsky
6 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro@mellanox.com>
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
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
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
diff --git a/rdma/Makefile b/rdma/Makefile
index c8966bfd..875fe53c 100644
--- a/rdma/Makefile
+++ b/rdma/Makefile
@@ -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
diff --git a/rdma/rdma.c b/rdma/rdma.c
index a21ba440..19608f41 100644
--- a/rdma/rdma.c
+++ b/rdma/rdma.c
@@ -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 }
};
diff --git a/rdma/rdma.h b/rdma/rdma.h
index 816c8ddd..f1ddedd2 100644
--- a/rdma/rdma.h
+++ b/rdma/rdma.h
@@ -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);
diff --git a/rdma/res.c b/rdma/res.c
new file mode 100644
index 00000000..a70e87dd
--- /dev/null
+++ b/rdma/res.c
@@ -0,0 +1,168 @@
+/*
+ * res.c RDMA tool
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Leon Romanovsky <leonro@mellanox.com>
+ */
+
+#include "rdma.h"
+#include <inttypes.h>
+
+static int res_help(struct rd *rd)
+{
+ pr_out("Usage: %s resource\n", rd->filename);
+ pr_out(" resource show [DEV]\n");
+ return 0;
+}
+
+static int res_print_summary(struct rd *rd, struct nlattr **tb)
+{
+ struct nlattr *nla_table = tb[RDMA_NLDEV_ATTR_RES_SUMMARY];
+ struct nlattr *nla_entry;
+ uint64_t max, curr;
+ const char *name;
+ int err;
+
+ if (!rd->json_output)
+ pr_out("curr/max: ");
+
+ mnl_attr_for_each_nested(nla_entry, nla_table) {
+ struct nlattr *nla_line[RDMA_NLDEV_ATTR_MAX] = {};
+ char json_name[32];
+
+ 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_SUMMARY_ENTRY_NAME] ||
+ !nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR] ||
+ !nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_MAX]) {
+ return -EINVAL;
+ }
+
+ name = mnl_attr_get_str(nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME]);
+ curr = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR]);
+ if (rd->json_output) {
+ snprintf(json_name, 32, "curr_%s", name);
+ jsonw_lluint_field(rd->jw, json_name, curr);
+ }
+
+ max = mnl_attr_get_u64(nla_line[RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_MAX]);
+ if (rd->json_output) {
+ snprintf(json_name, 32, "max_%s", name);
+ jsonw_lluint_field(rd->jw, json_name, max);
+ } else {
+ pr_out("%s %"PRId64 "/%"PRId64 " ", name, curr, max);
+ }
+ }
+ return 0;
+}
+
+static int res_no_args_parse_cb(const struct nlmsghdr *nlh, void *data)
+{
+ struct nlattr *tb[RDMA_NLDEV_ATTR_MAX] = {};
+ struct rd *rd = data;
+ const char *name;
+ uint32_t idx;
+
+ 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_SUMMARY])
+ return MNL_CB_ERROR;
+
+ idx = mnl_attr_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
+ name = mnl_attr_get_str(tb[RDMA_NLDEV_ATTR_DEV_NAME]);
+ if (rd->json_output) {
+ jsonw_uint_field(rd->jw, "ifindex", idx);
+ jsonw_string_field(rd->jw, "ifname", name);
+ } else {
+ pr_out("%u: %s: ", idx, name);
+ }
+
+ res_print_summary(rd, tb);
+
+ if (!rd->json_output)
+ pr_out("\n");
+ return MNL_CB_OK;
+}
+
+static int _res_send_msg(struct rd *rd, uint32_t command, mnl_cb_t callback)
+{
+ uint32_t flags = NLM_F_REQUEST | NLM_F_ACK;
+ uint32_t seq;
+ int ret;
+
+ if (command != RDMA_NLDEV_CMD_RES_GET)
+ flags |= NLM_F_DUMP;
+
+ rd_prepare_msg(rd, command, &seq, flags);
+ mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx);
+ if (rd->port_idx)
+ mnl_attr_put_u32(rd->nlh,
+ RDMA_NLDEV_ATTR_PORT_INDEX, rd->port_idx);
+
+ ret = rd_send_msg(rd);
+ if (ret)
+ return ret;
+
+ if (rd->json_output)
+ jsonw_start_object(rd->jw);
+ ret = rd_recv_msg(rd, callback, rd, seq);
+ if (rd->json_output)
+ jsonw_end_object(rd->jw);
+ return ret;
+}
+
+#define RES_FUNC(name, command, valid_filters, strict_port) \
+ static int _##name(struct rd *rd)\
+ { \
+ return _res_send_msg(rd, command, name##_parse_cb); \
+ } \
+ static int name(struct rd *rd) \
+ {\
+ int ret = rd_build_filter(rd, valid_filters); \
+ if (ret) \
+ return ret; \
+ if ((uintptr_t)valid_filters != (uintptr_t)NULL) { \
+ ret = rd_set_arg_to_devname(rd); \
+ if (ret) \
+ return ret;\
+ } \
+ return rd_exec_link(rd, _##name, strict_port); \
+ }
+
+RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true);
+
+static int res_show(struct rd *rd)
+{
+ const struct rd_cmd cmds[] = {
+ { NULL, res_no_args },
+ { 0 }
+ };
+
+ /*
+ * Special case to support "rdma res show DEV_NAME"
+ */
+ if (rd_argc(rd) == 1 && dev_map_lookup(rd, false))
+ return rd_exec_dev(rd, _res_no_args);
+
+ return rd_exec_cmd(rd, cmds, "parameter");
+}
+
+int cmd_res(struct rd *rd)
+{
+ const struct rd_cmd cmds[] = {
+ { NULL, res_show },
+ { "show", res_show },
+ { "list", res_show },
+ { "help", res_help },
+ { 0 }
+ };
+
+ return rd_exec_cmd(rd, cmds, "resource command");
+}
diff --git a/rdma/utils.c b/rdma/utils.c
index a63a7c2f..859ad7ab 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -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)
--
2.15.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH iproute2-next 8/9] rdma: Add QP resource tracking information
2018-01-02 9:37 [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
` (4 preceding siblings ...)
2018-01-02 9:37 ` [PATCH iproute2-next 7/9] rdma: Add resource tracking summary Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
[not found] ` <20180102093725.6172-9-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2018-01-02 9:37 ` [PATCH iproute2-next 9/9] rdma: Document resource tracking Leon Romanovsky
6 siblings, 1 reply; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro@mellanox.com>
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]
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
rdma/res.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
rdma/utils.c | 11 +++
2 files changed, 254 insertions(+)
diff --git a/rdma/res.c b/rdma/res.c
index a70e87dd..184a3a02 100644
--- a/rdma/res.c
+++ b/rdma/res.c
@@ -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 }
};
diff --git a/rdma/utils.c b/rdma/utils.c
index 859ad7ab..65bb6657 100644
--- a/rdma/utils.c
+++ b/rdma/utils.c
@@ -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)
--
2.15.1
^ permalink raw reply related [flat|nested] 16+ messages in thread* [PATCH iproute2-next 9/9] rdma: Document resource tracking
2018-01-02 9:37 [PATCH iproute2-next 0/9] RDMA resource tracking Leon Romanovsky
` (5 preceding siblings ...)
2018-01-02 9:37 ` [PATCH iproute2-next 8/9] rdma: Add QP resource tracking information Leon Romanovsky
@ 2018-01-02 9:37 ` Leon Romanovsky
6 siblings, 0 replies; 16+ messages in thread
From: Leon Romanovsky @ 2018-01-02 9:37 UTC (permalink / raw)
To: Doug Ledford, Jason Gunthorpe, David Ahern
Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
From: Leon Romanovsky <leonro@mellanox.com>
Spartan version of resource tracking documentation.
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
man/man8/rdma-resource.8 | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
create mode 100644 man/man8/rdma-resource.8
diff --git a/man/man8/rdma-resource.8 b/man/man8/rdma-resource.8
new file mode 100644
index 00000000..e3c83b94
--- /dev/null
+++ b/man/man8/rdma-resource.8
@@ -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 <leonro@mellanox.com>
--
2.15.1
^ permalink raw reply related [flat|nested] 16+ messages in thread