Add callbacks and data types for statistics export. One callback is implemented that exports all of the current devices/ids. Add/remove the callback to IB Netlink on init/cleanup.
Signed-off-by: Nir Muchtar <[email protected]> --- drivers/infiniband/core/cma.c | 91 +++++++++++++++++++++++++++++++++++++++++ include/rdma/ib_netlink.h | 15 +++++++ include/rdma/rdma_cm.h | 11 +++++ 3 files changed, 117 insertions(+), 0 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 5821f93..6436995 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -51,6 +51,7 @@ #include <rdma/ib_cm.h> #include <rdma/ib_sa.h> #include <rdma/iw_cm.h> +#include <rdma/ib_netlink.h> MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("Generic RDMA CM Agent"); @@ -3243,6 +3244,93 @@ 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 id's 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, IBNL_RDMA_CM, + IBNL_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, + IBNL_RDMA_CM_ATTR_SRC_ADDR)) { + goto out; + } + if (ibnl_put_attr(skb, nlh, + sizeof(struct sockaddr_in), + &id->route.addr.dst_addr, + IBNL_RDMA_CM_ATTR_DST_ADDR)) { + goto out; + } + } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + 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, + IBNL_RDMA_CM_ATTR_SRC_ADDR)) { + goto out; + } + if (ibnl_put_attr(skb, nlh, + sizeof(struct sockaddr_in6), + &id->route.addr.dst_addr, + IBNL_RDMA_CM_ATTR_DST_ADDR)) { + goto out; + } + } +#endif + id_stats->port_space = id->ps; + id_stats->cm_state = id_priv->state; + id_stats->qp_num = id_priv->qp_num; + + 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[] = { + [IBNL_RDMA_CM_ID_STATS] = {.dump = cma_get_id_stats}, +}; + static int __init cma_init(void) { int ret; @@ -3258,6 +3346,8 @@ static int __init cma_init(void) ret = ib_register_client(&cma_client); if (ret) goto err; + if (ibnl_add_client(IBNL_RDMA_CM, IBNL_RDMA_CM_NUM_OPS, cma_cb_table)) + printk(KERN_WARNING "RDMA CM failed to add netlink callback\n"); return 0; err: @@ -3270,6 +3360,7 @@ err: static void __exit cma_cleanup(void) { + ibnl_remove_client(IBNL_RDMA_CM); ib_unregister_client(&cma_client); unregister_netdevice_notifier(&cma_nb); rdma_addr_unregister_client(&addr_client); diff --git a/include/rdma/ib_netlink.h b/include/rdma/ib_netlink.h index 1ef76d0..1ce6ed8 100644 --- a/include/rdma/ib_netlink.h +++ b/include/rdma/ib_netlink.h @@ -1,6 +1,21 @@ #ifndef _IBNETLINK_H #define _IBNETLINK_H +enum { + IBNL_RDMA_CM = 1 +}; + +enum { + IBNL_RDMA_CM_ID_STATS = 0, + IBNL_RDMA_CM_NUM_OPS +}; + +enum { + IBNL_RDMA_CM_ATTR_SRC_ADDR = 1, + IBNL_RDMA_CM_ATTR_DST_ADDR, + IBNL_RDMA_CM_NUM_ATTR, +}; + #define IBNL_GET_CLIENT(type) ((type & (((1 << 6) - 1) << 10)) >> 10) #define IBNL_GET_OP(type) (type & ((1 << 10) - 1)) #define IBNL_GET_TYPE(client, op) ((client << 10) + op) diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h index c766da9..66b776e 100644 --- a/include/rdma/rdma_cm.h +++ b/include/rdma/rdma_cm.h @@ -147,6 +147,17 @@ struct rdma_cm_id { u8 port_num; }; +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_create_id - Create an RDMA identifier. * -- 1.7.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
