Commit 060c642b authored by Mark Zhang's avatar Mark Zhang Committed by Leon Romanovsky
Browse files

RDMA/nldev: Add support to add/delete a sub IB device through netlink



Add new netlink commands and attributes to support adding and deleting
a sub IB device with admin privilege.

Examples:
$ rdma dev add smi1 type SMI parent ibp8s0f1
$ rdma dev del smi1

Signed-off-by: default avatarMark Zhang <markzhang@nvidia.com>
Link: https://lore.kernel.org/r/77cbf1b36359642be8a8d8c5c2f4e585b544282f.1718553901.git.leon@kernel.org


Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
parent 026a4259
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = {
	[RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC] = { .type = NLA_U8 },
	[RDMA_NLDEV_SYS_ATTR_PRIVILEGED_QKEY_MODE] = { .type = NLA_U8 },
	[RDMA_NLDEV_ATTR_DRIVER_DETAILS]	= { .type = NLA_U8 },
	[RDMA_NLDEV_ATTR_DEV_TYPE]		= { .type = NLA_U8 },
};

static int put_driver_name_print_type(struct sk_buff *msg, const char *name,
@@ -2548,6 +2549,56 @@ static int nldev_stat_get_counter_status_doit(struct sk_buff *skb,
	return ret;
}

static int nldev_newdev(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{
	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
	enum rdma_nl_dev_type type;
	struct ib_device *parent;
	char name[IFNAMSIZ] = {};
	u32 parentid;
	int ret;

	ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
			  nldev_policy, extack);
	if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
		!tb[RDMA_NLDEV_ATTR_DEV_NAME] || !tb[RDMA_NLDEV_ATTR_DEV_TYPE])
		return -EINVAL;

	nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME], sizeof(name));
	type = nla_get_u8(tb[RDMA_NLDEV_ATTR_DEV_TYPE]);
	parentid = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
	parent = ib_device_get_by_index(sock_net(skb->sk), parentid);
	if (!parent)
		return -EINVAL;

	ret = ib_add_sub_device(parent, type, name);
	ib_device_put(parent);

	return ret;
}

static int nldev_deldev(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{
	struct nlattr *tb[RDMA_NLDEV_ATTR_MAX];
	struct ib_device *device;
	u32 devid;
	int ret;

	ret = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
			  nldev_policy, extack);
	if (ret || !tb[RDMA_NLDEV_ATTR_DEV_INDEX])
		return -EINVAL;

	devid = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
	device = ib_device_get_by_index(sock_net(skb->sk), devid);
	if (!device)
		return -EINVAL;

	return ib_del_sub_device_and_put(device);
}

static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
	[RDMA_NLDEV_CMD_GET] = {
		.doit = nldev_get_doit,
@@ -2646,6 +2697,14 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = {
	[RDMA_NLDEV_CMD_STAT_GET_STATUS] = {
		.doit = nldev_stat_get_counter_status_doit,
	},
	[RDMA_NLDEV_CMD_NEWDEV] = {
		.doit = nldev_newdev,
		.flags = RDMA_NL_ADMIN_PERM,
	},
	[RDMA_NLDEV_CMD_DELDEV] = {
		.doit = nldev_deldev,
		.flags = RDMA_NL_ADMIN_PERM,
	},
};

void __init nldev_init(void)
+6 −0
Original line number Diff line number Diff line
@@ -301,6 +301,10 @@ enum rdma_nldev_command {

	RDMA_NLDEV_CMD_RES_SRQ_GET_RAW,

	RDMA_NLDEV_CMD_NEWDEV,

	RDMA_NLDEV_CMD_DELDEV,

	RDMA_NLDEV_NUM_OPS
};

@@ -564,6 +568,8 @@ enum rdma_nldev_attr {
	 */
	RDMA_NLDEV_ATTR_RES_SUBTYPE,		/* string */

	RDMA_NLDEV_ATTR_DEV_TYPE,		/* u8 */

	/*
	 * Always the end
	 */