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