GNU Linux-libre 6.1.90-gnu
[releases.git] / net / dsa / netlink.c
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 };