xref: /linux/net/dsa/netlink.c (revision e1c4c5436b4ad579762fbe78bfabc8aef59bd5b1)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2022 NXP
3  */
4 #include <linux/netdevice.h>
5 #include <net/rtnetlink.h>
6 
7 #include "dsa_priv.h"
8 
9 static const struct nla_policy dsa_policy[IFLA_DSA_MAX + 1] = {
10 	[IFLA_DSA_MASTER]	= { .type = NLA_U32 },
11 };
12 
13 static int dsa_changelink(struct net_device *dev, struct nlattr *tb[],
14 			  struct nlattr *data[],
15 			  struct netlink_ext_ack *extack)
16 {
17 	int err;
18 
19 	if (!data)
20 		return 0;
21 
22 	if (data[IFLA_DSA_MASTER]) {
23 		u32 ifindex = nla_get_u32(data[IFLA_DSA_MASTER]);
24 		struct net_device *master;
25 
26 		master = __dev_get_by_index(dev_net(dev), ifindex);
27 		if (!master)
28 			return -EINVAL;
29 
30 		err = dsa_slave_change_master(dev, master, extack);
31 		if (err)
32 			return err;
33 	}
34 
35 	return 0;
36 }
37 
38 static size_t dsa_get_size(const struct net_device *dev)
39 {
40 	return nla_total_size(sizeof(u32)) +	/* IFLA_DSA_MASTER  */
41 	       0;
42 }
43 
44 static int dsa_fill_info(struct sk_buff *skb, const struct net_device *dev)
45 {
46 	struct net_device *master = dsa_slave_to_master(dev);
47 
48 	if (nla_put_u32(skb, IFLA_DSA_MASTER, master->ifindex))
49 		return -EMSGSIZE;
50 
51 	return 0;
52 }
53 
54 struct rtnl_link_ops dsa_link_ops __read_mostly = {
55 	.kind			= "dsa",
56 	.priv_size		= sizeof(struct dsa_port),
57 	.maxtype		= IFLA_DSA_MAX,
58 	.policy			= dsa_policy,
59 	.changelink		= dsa_changelink,
60 	.get_size		= dsa_get_size,
61 	.fill_info		= dsa_fill_info,
62 	.netns_refund		= true,
63 };
64