diff options
author | Nir Muchtar <nirm@voltaire.com> | 2011-01-03 15:33:53 +0000 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-05-25 13:46:23 -0700 |
commit | 753f618ae03a699cc30044d64eea84165016dc6e (patch) | |
tree | 145bbd73eef824f047affe79ee0570a6bb0940b1 /drivers/infiniband | |
parent | b26f9b9949013fec31b23c426fc463164ae08891 (diff) |
RDMA/cma: Add support for netlink statistics export
Add callbacks and data types for statistics export of all current
devices/ids. The schema for RDMA CM is a series of netlink messages.
Each one contains an rdma_cm_stat struct. Additionally, two netlink
attributes are created for the addresses for each message (if
applicable).
Their types used are:
RDMA_NL_RDMA_CM_ATTR_SRC_ADDR (The source address for this ID)
RDMA_NL_RDMA_CM_ATTR_DST_ADDR (The destination address for this ID)
sockaddr_* structs are encapsulated within these attributes.
In other words, every transaction contains a series of messages like:
-------message 1-------
struct rdma_cm_id_stats {
__u32 qp_num;
__u32 bound_dev_if;
__u32 port_space;
__s32 pid;
__u8 cm_state;
__u8 node_type;
__u8 port_num;
__u8 reserved;
}
RDMA_NL_RDMA_CM_ATTR_SRC_ADDR attribute - contains the source address
RDMA_NL_RDMA_CM_ATTR_DST_ADDR attribute - contains the destination address
-------end 1-------
-------message 2-------
struct rdma_cm_id_stats
RDMA_NL_RDMA_CM_ATTR_SRC_ADDR attribute
RDMA_NL_RDMA_CM_ATTR_DST_ADDR attribute
-------end 2-------
Signed-off-by: Nir Muchtar <nirm@voltaire.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/core/cma.c | 99 |
1 files changed, 99 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 @@ #include <rdma/rdma_cm.h> #include <rdma/rdma_cm_ib.h> +#include <rdma/rdma_netlink.h> #include <rdma/ib_cache.h> #include <rdma/ib_cm.h> #include <rdma/ib_sa.h> @@ -3315,6 +3316,99 @@ static void cma_remove_one(struct ib_device *device) kfree(cma_dev); } +static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct nlmsghdr *nlh; + struct rdma_cm_id_stats *id_stats; + struct rdma_id_private *id_priv; + struct rdma_cm_id *id = NULL; + struct cma_device *cma_dev; + int i_dev = 0, i_id = 0; + + /* + * We export all of the IDs as a sequence of messages. Each + * ID gets its own netlink message. + */ + mutex_lock(&lock); + + list_for_each_entry(cma_dev, &dev_list, list) { + if (i_dev < cb->args[0]) { + i_dev++; + continue; + } + + i_id = 0; + list_for_each_entry(id_priv, &cma_dev->id_list, list) { + if (i_id < cb->args[1]) { + i_id++; + continue; + } + + id_stats = ibnl_put_msg(skb, &nlh, cb->nlh->nlmsg_seq, + sizeof *id_stats, RDMA_NL_RDMA_CM, + RDMA_NL_RDMA_CM_ID_STATS); + if (!id_stats) + goto out; + + memset(id_stats, 0, sizeof *id_stats); + id = &id_priv->id; + id_stats->node_type = id->route.addr.dev_addr.dev_type; + id_stats->port_num = id->port_num; + id_stats->bound_dev_if = + id->route.addr.dev_addr.bound_dev_if; + + if (id->route.addr.src_addr.ss_family == AF_INET) { + if (ibnl_put_attr(skb, nlh, + sizeof(struct sockaddr_in), + &id->route.addr.src_addr, + RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { + goto out; + } + if (ibnl_put_attr(skb, nlh, + sizeof(struct sockaddr_in), + &id->route.addr.dst_addr, + RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { + goto out; + } + } else if (id->route.addr.src_addr.ss_family == AF_INET6) { + if (ibnl_put_attr(skb, nlh, + sizeof(struct sockaddr_in6), + &id->route.addr.src_addr, + RDMA_NL_RDMA_CM_ATTR_SRC_ADDR)) { + goto out; + } + if (ibnl_put_attr(skb, nlh, + sizeof(struct sockaddr_in6), + &id->route.addr.dst_addr, + RDMA_NL_RDMA_CM_ATTR_DST_ADDR)) { + goto out; + } + } + + id_stats->port_space = id->ps; + id_stats->cm_state = id_priv->state; + id_stats->qp_num = id_priv->qp_num; + id_stats->qp_type = id->qp_type; + + i_id++; + } + + cb->args[1] = 0; + i_dev++; + } + +out: + mutex_unlock(&lock); + cb->args[0] = i_dev; + cb->args[1] = i_id; + + return skb->len; +} + +static const struct ibnl_client_cbs cma_cb_table[] = { + [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats }, +}; + static int __init cma_init(void) { int ret; @@ -3330,6 +3424,10 @@ static int __init cma_init(void) ret = ib_register_client(&cma_client); if (ret) goto err; + + if (ibnl_add_client(RDMA_NL_RDMA_CM, RDMA_NL_RDMA_CM_NUM_OPS, cma_cb_table)) + printk(KERN_WARNING "RDMA CMA: failed to add netlink callback\n"); + return 0; err: @@ -3342,6 +3440,7 @@ err: static void __exit cma_cleanup(void) { + ibnl_remove_client(RDMA_NL_RDMA_CM); ib_unregister_client(&cma_client); unregister_netdevice_notifier(&cma_nb); rdma_addr_unregister_client(&addr_client); |