Re: [RFC WIP 1/2] RDMA/Core: add RDMA_NLDEV_CMD_NEWLINK/DELLLINK support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Sep 13, 2018 at 12:16:20PM -0700, Steve Wise wrote:
> Add support for new LINK messages to allow adding and deleting rdma
> interfaces.  This will be used initially for soft rdma drivers which
> instantiate device instances dynamically by the admin specifying a netdev
> device to use.  The rdma_rxe module will be the first user of these
> messages.
>
> The design is modeled after RTNL_NEWLINK/DELLINK:  rdma drivers
> register with the rdma core if they provide link add/delete functions.
> Each driver registers with a unique "type" string, that is used to
> dispatch messages coming from user space.  A new RDMA_NLDEV_ATTR is
> defined for the "type" string.  User mode will pass 3 attributes in a
> NEWLINK message: RDMA_NLDEV_ATTR_IBDEV_NAME for the desired rdma device
> name to be created, RDMA_NLDEV_ATTR_LINK_TYPE for the "type" of link
> being added, and RDMA_NLDEV_ATTR_NDEV_NAME for the net_device interface
> to use for this link. The DELLINK message will contain the IBDEV_NAME
> and LINK_TYPE attributes.
>
> Signed-off-by: Steve Wise <swise@xxxxxxxxxxxxxxxxxxxxx>
> ---
>  drivers/infiniband/core/nldev.c  | 113 +++++++++++++++++++++++++++++++++++++++
>  include/rdma/rdma_netlink.h      |  11 ++++
>  include/uapi/rdma/rdma_netlink.h |   9 ++++
>  3 files changed, 133 insertions(+)
>
> diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
> index 0385ab438320..d107b982c210 100644
> --- a/drivers/infiniband/core/nldev.c
> +++ b/drivers/infiniband/core/nldev.c
> @@ -33,6 +33,7 @@
>  #include <linux/module.h>
>  #include <linux/pid.h>
>  #include <linux/pid_namespace.h>
> +#include <linux/mutex.h>
>  #include <net/netlink.h>
>  #include <rdma/rdma_cm.h>
>  #include <rdma/rdma_netlink.h>
> @@ -107,6 +108,8 @@
>  	[RDMA_NLDEV_ATTR_DRIVER_U32]		= { .type = NLA_U32 },
>  	[RDMA_NLDEV_ATTR_DRIVER_S64]		= { .type = NLA_S64 },
>  	[RDMA_NLDEV_ATTR_DRIVER_U64]		= { .type = NLA_U64 },
> +	[RDMA_NLDEV_ATTR_LINK_TYPE]		= { .type = NLA_NUL_STRING,
> +						    .len = IFNAMSIZ },

In case, we are continuing this path, better to use our define RDMA_NLDEV_ATTR_ENTRY_STRLEN.

>  };
>
>  static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
> @@ -1072,6 +1075,110 @@ static int nldev_res_get_pd_dumpit(struct sk_buff *skb,
>  	return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_PD);
>  }
>
> +static LIST_HEAD(link_ops);
> +static DEFINE_MUTEX(link_ops_mutex);
> +
> +void rdma_link_register(struct rdma_link_ops *ops)
> +{
> +	mutex_lock(&link_ops_mutex);
> +	list_add(&ops->list, &link_ops);
> +	mutex_unlock(&link_ops_mutex);
> +}
> +EXPORT_SYMBOL(rdma_link_register);
> +
> +void rdma_link_unregister(struct rdma_link_ops *ops)
> +{
> +	mutex_lock(&link_ops_mutex);
> +	list_del_init(&ops->list);

Why did you use list_del_init and not list_del?

And in case we will use device_type, we won't need manage list at all :)

> +	mutex_unlock(&link_ops_mutex);
> +}
> +EXPORT_SYMBOL(rdma_link_unregister);
> +
> +static const struct rdma_link_ops *link_ops_get(const char *type)
> +{
> +	const struct rdma_link_ops *ops;
> +
> +	mutex_lock(&link_ops_mutex);
> +	list_for_each_entry(ops, &link_ops, list) {
> +		if (!strncmp(ops->type, type, IFNAMSIZ))
> +			goto out;
> +	}
> +	ops = NULL;
> +out:
> +	mutex_unlock(&link_ops_mutex);
> +	return ops;
> +}
> +
> +static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
> +			  struct netlink_ext_ack *extack)
> +{
> +	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
> +	char ibdev_name[IB_DEVICE_NAME_MAX];
> +	const struct rdma_link_ops *ops;
> +	char ndev_name[IFNAMSIZ];
> +	char type[IFNAMSIZ];
> +	int err;
> +
> +	err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
> +			  nldev_policy, extack);
> +	if (err || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
> +	    !tb[RDMA_NLDEV_ATTR_LINK_TYPE] || !tb[RDMA_NLDEV_ATTR_NDEV_NAME]) {
> +		err = -EINVAL;
> +		goto err_out;
> +	}
> +
> +	nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
> +		    sizeof(ibdev_name));

Query from userspace should be done RDMA_NLDEV_ATTR_DEV_INDEX, because
it is our handle and not device name.

> +	nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));

Will it mean that type should be unique?

> +	nla_strlcpy(ndev_name, tb[RDMA_NLDEV_ATTR_NDEV_NAME],
> +		    sizeof(ndev_name));
> +	pr_debug("ibdev_name |%s| type |%s| ndev_name |%s|\n", ibdev_name,
> +		 type, ndev_name);
> +
> +	ops = link_ops_get(type);
> +	if (!ops) {
> +		err = -ENODEV;
> +		goto err_out;
> +	}
> +
> +	err = ops->newlink(ibdev_name, ndev_name);
> +err_out:
> +	return err;
> +}
> +
> +static int nldev_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
> +			  struct netlink_ext_ack *extack)
> +{
> +	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
> +	char ibdev_name[IB_DEVICE_NAME_MAX];
> +	const struct rdma_link_ops *ops;
> +	char type[IFNAMSIZ];
> +	int err;
> +
> +	err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
> +			  nldev_policy, extack);
> +	if (err || !tb[RDMA_NLDEV_ATTR_DEV_NAME] ||
> +	    !tb[RDMA_NLDEV_ATTR_LINK_TYPE]) {
> +		err = !err ? -EINVAL : err;
> +		goto err_out;
> +	}
> +
> +	nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
> +		    sizeof(ibdev_name));
> +	nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));
> +	pr_debug("ibdev_name |%s| type |%s|\n", ibdev_name, type);

The same comments,

> +
> +	ops = link_ops_get(type);
> +	if (!ops) {
> +		err = -ENODEV;
> +		goto err_out;
> +	}
> +
> +	err = ops->dellink(ibdev_name);
> +err_out:
> +	return err;
> +}
> +
>  static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
>  	[RDMA_NLDEV_CMD_GET] = {
>  		.doit = nldev_get_doit,
> @@ -1110,6 +1217,12 @@ static int nldev_res_get_pd_dumpit(struct sk_buff *skb,
>  	[RDMA_NLDEV_CMD_RES_PD_GET] = {
>  		.dump = nldev_res_get_pd_dumpit,
>  	},
> +	[RDMA_NLDEV_CMD_NEWLINK] = {
> +		.doit = nldev_newlink,
> +	},
> +	[RDMA_NLDEV_CMD_DELLINK] = {
> +		.doit = nldev_dellink,
> +	},
>  };
>
>  void __init nldev_init(void)
> diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h
> index c369703fcd69..b5a5a1a7cddc 100644
> --- a/include/rdma/rdma_netlink.h
> +++ b/include/rdma/rdma_netlink.h
> @@ -99,4 +99,15 @@ int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh,
>   * Returns 0 on success or a negative for no listeners.
>   */
>  int rdma_nl_chk_listeners(unsigned int group);
> +
> +struct rdma_link_ops {
> +	struct list_head list;
> +	const char *type;
> +	int (*newlink)(char *ibdev_name, char *ndev_name);
> +	int (*dellink)(char *ibdev_name);
> +};
> +
> +void rdma_link_register(struct rdma_link_ops *ops);
> +void rdma_link_unregister(struct rdma_link_ops *ops);
> +
>  #endif /* _RDMA_NETLINK_H */
> diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
> index edba6351ac13..025172d41fa7 100644
> --- a/include/uapi/rdma/rdma_netlink.h
> +++ b/include/uapi/rdma/rdma_netlink.h
> @@ -246,6 +246,10 @@ enum rdma_nldev_command {
>
>  	RDMA_NLDEV_CMD_RES_PD_GET, /* can dump */
>
> +	RDMA_NLDEV_CMD_NEWLINK,
> +
> +	RDMA_NLDEV_CMD_DELLINK,
> +

Let's reuse 3 and 4 indexes, which are not occupied.

>  	RDMA_NLDEV_NUM_OPS
>  };
>
> @@ -427,6 +431,11 @@ enum rdma_nldev_attr {
>  	RDMA_NLDEV_ATTR_DRIVER_U64,		/* u64 */
>
>  	/*
> +	 * Identifies the rdma driver. eg: "rxe" or "siw"
> +	 */
> +	RDMA_NLDEV_ATTR_LINK_TYPE,		/* string */
> +
> +	/*
>  	 * Always the end
>  	 */
>  	RDMA_NLDEV_ATTR_MAX
> --
> 1.8.3.1
>

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux