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 "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)) + /* IFLA_DSA_CONDUIT */ 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 }; 65