aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/cma.c99
-rw-r--r--include/rdma/rdma_netlink.h28
2 files changed, 127 insertions, 0 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 44be1c9ed05b..5dd9acb92c3a 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -47,6 +47,7 @@
47 47
48#include <rdma/rdma_cm.h> 48#include <rdma/rdma_cm.h>
49#include <rdma/rdma_cm_ib.h> 49#include <rdma/rdma_cm_ib.h>
50#include <rdma/rdma_netlink.h>
50#include <rdma/ib_cache.h> 51#include <rdma/ib_cache.h>
51#include <rdma/ib_cm.h> 52#include <rdma/ib_cm.h>
52#include <rdma/ib_sa.h> 53#include <rdma/ib_sa.h>
@@ -3315,6 +3316,99 @@ static void cma_remove_one(struct ib_device *device)
3315 kfree(cma_dev); 3316 kfree(cma_dev);
3316} 3317}
3317 3318
3319static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb)
3320{
3321 struct nlmsghdr *nlh;
3322 struct rdma_cm_id_stats *id_stats;
3323 struct rdma_id_private *id_priv;
3324 struct rdma_cm_id *id = NULL;
3325 struct cma_device *cma_dev;
3326 int i_dev = 0, i_id = 0;
3327
3328 /*
3329 * We export all of the IDs as a sequence of messages. Each
3330 * ID gets its own netlink message.
3331 */
3332 mutex_lock(&lock);
3333
3334 list_for_each_entry(cma_dev, &dev_list, list) {
3335 if (i_dev < cb->args[0]) {
3336 i_dev++;
3337 continue;
3338 }
3339
3340 i_id = 0;
3341 list_for_each_entry(id_priv, &cma_dev->id_list, list) {
3342 if (i_id < cb->args[1]) {
3343 i_id++;
3344 continue;
3345 }
3346
3347 id_stats = ibnl_put_msg(skb, &nlh, cb->nlh->nlmsg_seq,
3348 sizeof *id_stats, RDMA_NL_RDMA_CM,
3349 RDMA_NL_RDMA_CM_ID_STATS);
3350 if (!id_stats)
3351 goto out;
3352
3353 memset(id_stats, 0, sizeof *id_stats);
3354 id = &id_priv->id;
3355 id_stats->node_type = id->route.addr.dev_addr.dev_type;
3356 id_stats->port_num = id->port_num;
3357 id_stats->bound_dev_if =
3358 id->route.addr.dev_addr.bound_dev_if;
3359
3360 if (id->route.addr.src_addr.ss_family == AF_INET) {
3361 if (ibnl_put_attr(skb, nlh,
3362 sizeof(struct sockaddr_in),
3363 &id->route.addr.src_addr,
3364 RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) {
3365 goto out;
3366 }
3367 if (ibnl_put_attr(skb, nlh,
3368 sizeof(struct sockaddr_in),
3369 &id->route.addr.dst_addr,
3370 RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) {
3371 goto out;
3372 }
3373 } else if (id->route.addr.src_addr.ss_family == AF_INET6) {
3374 if (ibnl_put_attr(skb, nlh,
3375 sizeof(struct sockaddr_in6),
3376 &id->route.addr.src_addr,
3377 RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) {
3378 goto out;
3379 }
3380 if (ibnl_put_attr(skb, nlh,
3381 sizeof(struct sockaddr_in6),
3382 &id->route.addr.dst_addr,
3383 RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) {
3384 goto out;
3385 }
3386 }
3387
3388 id_stats->port_space = id->ps;
3389 id_stats->cm_state = id_priv->state;
3390 id_stats->qp_num = id_priv->qp_num;
3391 id_stats->qp_type = id->qp_type;
3392
3393 i_id++;
3394 }
3395
3396 cb->args[1] = 0;
3397 i_dev++;
3398 }
3399
3400out:
3401 mutex_unlock(&lock);
3402 cb->args[0] = i_dev;
3403 cb->args[1] = i_id;
3404
3405 return skb->len;
3406}
3407
3408static const struct ibnl_client_cbs cma_cb_table[] = {
3409 [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats },
3410};
3411
3318static int __init cma_init(void) 3412static int __init cma_init(void)
3319{ 3413{
3320 int ret; 3414 int ret;
@@ -3330,6 +3424,10 @@ static int __init cma_init(void)
3330 ret = ib_register_client(&cma_client); 3424 ret = ib_register_client(&cma_client);
3331 if (ret) 3425 if (ret)
3332 goto err; 3426 goto err;
3427
3428 if (ibnl_add_client(RDMA_NL_RDMA_CM, RDMA_NL_RDMA_CM_NUM_OPS, cma_cb_table))
3429 printk(KERN_WARNING "RDMA CMA: failed to add netlink callback\n");
3430
3333 return 0; 3431 return 0;
3334 3432
3335err: 3433err:
@@ -3342,6 +3440,7 @@ err:
3342 3440
3343static void __exit cma_cleanup(void) 3441static void __exit cma_cleanup(void)
3344{ 3442{
3443 ibnl_remove_client(RDMA_NL_RDMA_CM);
3345 ib_unregister_client(&cma_client); 3444 ib_unregister_client(&cma_client);
3346 unregister_netdevice_notifier(&cma_nb); 3445 unregister_netdevice_notifier(&cma_nb);
3347 rdma_addr_unregister_client(&addr_client); 3446 rdma_addr_unregister_client(&addr_client);
diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h
index c983a193cecf..3c5363ab867b 100644
--- a/include/rdma/rdma_netlink.h
+++ b/include/rdma/rdma_netlink.h
@@ -1,10 +1,38 @@
1#ifndef _RDMA_NETLINK_H 1#ifndef _RDMA_NETLINK_H
2#define _RDMA_NETLINK_H 2#define _RDMA_NETLINK_H
3 3
4#include <linux/types.h>
5
6enum {
7 RDMA_NL_RDMA_CM = 1
8};
9
4#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10) 10#define RDMA_NL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10)
5#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1)) 11#define RDMA_NL_GET_OP(type) (type & ((1 << 10) - 1))
6#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op) 12#define RDMA_NL_GET_TYPE(client, op) ((client << 10) + op)
7 13
14enum {
15 RDMA_NL_RDMA_CM_ID_STATS = 0,
16 RDMA_NL_RDMA_CM_NUM_OPS
17};
18
19enum {
20 RDMA_NL_RDMA_CM_ATTR_SRC_ADDR = 1,
21 RDMA_NL_RDMA_CM_ATTR_DST_ADDR,
22 RDMA_NL_RDMA_CM_NUM_ATTR,
23};
24
25struct rdma_cm_id_stats {
26 __u32 qp_num;
27 __u32 bound_dev_if;
28 __u32 port_space;
29 __s32 pid;
30 __u8 cm_state;
31 __u8 node_type;
32 __u8 port_num;
33 __u8 qp_type;
34};
35
8#ifdef __KERNEL__ 36#ifdef __KERNEL__
9 37
10#include <linux/netlink.h> 38#include <linux/netlink.h>