aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeon Romanovsky <leonro@mellanox.com>2018-01-28 04:17:24 -0500
committerJason Gunthorpe <jgg@mellanox.com>2018-01-29 22:21:40 -0500
commitbf3c5a93c52368410a521af34ed3bff91a99df44 (patch)
treee8a43619c4c4682f45a93616806d8af01847ae9e
parent9d5f8c209b3f29259e6aa9595ea2dc2dfa27549a (diff)
RDMA/nldev: Provide global resource utilization
Expose through the netlink interface the global per-device utilization of the supported object types. Provide both dumpit and doit callbacks. As an example of possible output from rdmatool for system with 5 mlx5 cards: $ rdma res 1: mlx5_0: qp 4 cq 5 pd 3 2: mlx5_1: qp 4 cq 5 pd 3 3: mlx5_2: qp 4 cq 5 pd 3 4: mlx5_3: qp 2 cq 3 pd 2 5: mlx5_4: qp 4 cq 5 pd 3 Reviewed-by: Mark Bloch <markb@mellanox.com> Signed-off-by: Leon Romanovsky <leonro@mellanox.com> Reviewed-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r--drivers/infiniband/core/nldev.c147
-rw-r--r--include/uapi/rdma/rdma_netlink.h7
2 files changed, 154 insertions, 0 deletions
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 5d790c507c7e..c37bb041f647 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -31,6 +31,8 @@
31 */ 31 */
32 32
33#include <linux/module.h> 33#include <linux/module.h>
34#include <linux/pid.h>
35#include <linux/pid_namespace.h>
34#include <net/netlink.h> 36#include <net/netlink.h>
35#include <rdma/rdma_netlink.h> 37#include <rdma/rdma_netlink.h>
36 38
@@ -52,6 +54,11 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
52 [RDMA_NLDEV_ATTR_PORT_STATE] = { .type = NLA_U8 }, 54 [RDMA_NLDEV_ATTR_PORT_STATE] = { .type = NLA_U8 },
53 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = { .type = NLA_U8 }, 55 [RDMA_NLDEV_ATTR_PORT_PHYS_STATE] = { .type = NLA_U8 },
54 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = { .type = NLA_U8 }, 56 [RDMA_NLDEV_ATTR_DEV_NODE_TYPE] = { .type = NLA_U8 },
57 [RDMA_NLDEV_ATTR_RES_SUMMARY] = { .type = NLA_NESTED },
58 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY] = { .type = NLA_NESTED },
59 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME] = { .type = NLA_NUL_STRING,
60 .len = 16 },
61 [RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR] = { .type = NLA_U64 },
55}; 62};
56 63
57static int fill_nldev_handle(struct sk_buff *msg, struct ib_device *device) 64static int fill_nldev_handle(struct sk_buff *msg, struct ib_device *device)
@@ -134,6 +141,65 @@ static int fill_port_info(struct sk_buff *msg,
134 return 0; 141 return 0;
135} 142}
136 143
144static int fill_res_info_entry(struct sk_buff *msg,
145 const char *name, u64 curr)
146{
147 struct nlattr *entry_attr;
148
149 entry_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY);
150 if (!entry_attr)
151 return -EMSGSIZE;
152
153 if (nla_put_string(msg, RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME, name))
154 goto err;
155 if (nla_put_u64_64bit(msg,
156 RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR, curr, 0))
157 goto err;
158
159 nla_nest_end(msg, entry_attr);
160 return 0;
161
162err:
163 nla_nest_cancel(msg, entry_attr);
164 return -EMSGSIZE;
165}
166
167static int fill_res_info(struct sk_buff *msg, struct ib_device *device)
168{
169 static const char * const names[RDMA_RESTRACK_MAX] = {
170 [RDMA_RESTRACK_PD] = "pd",
171 [RDMA_RESTRACK_CQ] = "cq",
172 [RDMA_RESTRACK_QP] = "qp",
173 };
174
175 struct rdma_restrack_root *res = &device->res;
176 struct nlattr *table_attr;
177 int ret, i, curr;
178
179 if (fill_nldev_handle(msg, device))
180 return -EMSGSIZE;
181
182 table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_SUMMARY);
183 if (!table_attr)
184 return -EMSGSIZE;
185
186 for (i = 0; i < RDMA_RESTRACK_MAX; i++) {
187 if (!names[i])
188 continue;
189 curr = rdma_restrack_count(res, i, task_active_pid_ns(current));
190 ret = fill_res_info_entry(msg, names[i], curr);
191 if (ret)
192 goto err;
193 }
194
195 nla_nest_end(msg, table_attr);
196 return 0;
197
198err:
199 nla_nest_cancel(msg, table_attr);
200 return ret;
201}
202
137static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh, 203static int nldev_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
138 struct netlink_ext_ack *extack) 204 struct netlink_ext_ack *extack)
139{ 205{
@@ -329,6 +395,83 @@ out:
329 return skb->len; 395 return skb->len;
330} 396}
331 397
398static int nldev_res_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
399 struct netlink_ext_ack *extack)
400{
401 struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
402 struct ib_device *device;
403 struct sk_buff *msg;
404 u32 index;
405 int ret;
406
407 ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
408 nldev_policy, extack);
409 if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
410 return -EINVAL;
411
412 index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
413 device = ib_device_get_by_index(index);
414 if (!device)
415 return -EINVAL;
416
417 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
418 if (!msg)
419 goto err;
420
421 nlh = nlmsg_put(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq,
422 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_RES_GET),
423 0, 0);
424
425 ret = fill_res_info(msg, device);
426 if (ret)
427 goto err_free;
428
429 nlmsg_end(msg, nlh);
430 put_device(&device->dev);
431 return rdma_nl_unicast(msg, NETLINK_CB(skb).portid);
432
433err_free:
434 nlmsg_free(msg);
435err:
436 put_device(&device->dev);
437 return ret;
438}
439
440static int _nldev_res_get_dumpit(struct ib_device *device,
441 struct sk_buff *skb,
442 struct netlink_callback *cb,
443 unsigned int idx)
444{
445 int start = cb->args[0];
446 struct nlmsghdr *nlh;
447
448 if (idx < start)
449 return 0;
450
451 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
452 RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_RES_GET),
453 0, NLM_F_MULTI);
454
455 if (fill_res_info(skb, device)) {
456 nlmsg_cancel(skb, nlh);
457 goto out;
458 }
459
460 nlmsg_end(skb, nlh);
461
462 idx++;
463
464out:
465 cb->args[0] = idx;
466 return skb->len;
467}
468
469static int nldev_res_get_dumpit(struct sk_buff *skb,
470 struct netlink_callback *cb)
471{
472 return ib_enum_all_devs(_nldev_res_get_dumpit, skb, cb);
473}
474
332static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { 475static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
333 [RDMA_NLDEV_CMD_GET] = { 476 [RDMA_NLDEV_CMD_GET] = {
334 .doit = nldev_get_doit, 477 .doit = nldev_get_doit,
@@ -338,6 +481,10 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
338 .doit = nldev_port_get_doit, 481 .doit = nldev_port_get_doit,
339 .dump = nldev_port_get_dumpit, 482 .dump = nldev_port_get_dumpit,
340 }, 483 },
484 [RDMA_NLDEV_CMD_RES_GET] = {
485 .doit = nldev_res_get_doit,
486 .dump = nldev_res_get_dumpit,
487 },
341}; 488};
342 489
343void __init nldev_init(void) 490void __init nldev_init(void)
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index cc002e316d09..22c39532c411 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -236,6 +236,8 @@ enum rdma_nldev_command {
236 RDMA_NLDEV_CMD_PORT_NEW, 236 RDMA_NLDEV_CMD_PORT_NEW,
237 RDMA_NLDEV_CMD_PORT_DEL, 237 RDMA_NLDEV_CMD_PORT_DEL,
238 238
239 RDMA_NLDEV_CMD_RES_GET, /* can dump */
240
239 RDMA_NLDEV_NUM_OPS 241 RDMA_NLDEV_NUM_OPS
240}; 242};
241 243
@@ -303,6 +305,11 @@ enum rdma_nldev_attr {
303 305
304 RDMA_NLDEV_ATTR_DEV_NODE_TYPE, /* u8 */ 306 RDMA_NLDEV_ATTR_DEV_NODE_TYPE, /* u8 */
305 307
308 RDMA_NLDEV_ATTR_RES_SUMMARY, /* nested table */
309 RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY, /* nested table */
310 RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME, /* string */
311 RDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR, /* u64 */
312
306 RDMA_NLDEV_ATTR_MAX 313 RDMA_NLDEV_ATTR_MAX
307}; 314};
308#endif /* _UAPI_RDMA_NETLINK_H */ 315#endif /* _UAPI_RDMA_NETLINK_H */