|
@@ -880,6 +880,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
|
|
const struct rtnl_link_stats64 *stats;
|
|
|
struct nlattr *attr, *af_spec;
|
|
|
struct rtnl_af_ops *af_ops;
|
|
|
+ struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
|
|
|
|
|
|
ASSERT_RTNL();
|
|
|
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
|
|
@@ -908,8 +909,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
|
|
|
#endif
|
|
|
(dev->ifindex != dev->iflink &&
|
|
|
nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
|
|
|
- (dev->master &&
|
|
|
- nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
|
|
|
+ (upper_dev &&
|
|
|
+ nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
|
|
|
nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
|
|
|
(dev->qdisc &&
|
|
|
nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) ||
|
|
@@ -1273,16 +1274,16 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
|
|
|
|
|
|
static int do_set_master(struct net_device *dev, int ifindex)
|
|
|
{
|
|
|
- struct net_device *master_dev;
|
|
|
+ struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
|
|
|
const struct net_device_ops *ops;
|
|
|
int err;
|
|
|
|
|
|
- if (dev->master) {
|
|
|
- if (dev->master->ifindex == ifindex)
|
|
|
+ if (upper_dev) {
|
|
|
+ if (upper_dev->ifindex == ifindex)
|
|
|
return 0;
|
|
|
- ops = dev->master->netdev_ops;
|
|
|
+ ops = upper_dev->netdev_ops;
|
|
|
if (ops->ndo_del_slave) {
|
|
|
- err = ops->ndo_del_slave(dev->master, dev);
|
|
|
+ err = ops->ndo_del_slave(upper_dev, dev);
|
|
|
if (err)
|
|
|
return err;
|
|
|
} else {
|
|
@@ -1291,12 +1292,12 @@ static int do_set_master(struct net_device *dev, int ifindex)
|
|
|
}
|
|
|
|
|
|
if (ifindex) {
|
|
|
- master_dev = __dev_get_by_index(dev_net(dev), ifindex);
|
|
|
- if (!master_dev)
|
|
|
+ upper_dev = __dev_get_by_index(dev_net(dev), ifindex);
|
|
|
+ if (!upper_dev)
|
|
|
return -EINVAL;
|
|
|
- ops = master_dev->netdev_ops;
|
|
|
+ ops = upper_dev->netdev_ops;
|
|
|
if (ops->ndo_add_slave) {
|
|
|
- err = ops->ndo_add_slave(master_dev, dev);
|
|
|
+ err = ops->ndo_add_slave(upper_dev, dev);
|
|
|
if (err)
|
|
|
return err;
|
|
|
} else {
|
|
@@ -2048,7 +2049,6 @@ errout:
|
|
|
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
|
|
{
|
|
|
struct net *net = sock_net(skb->sk);
|
|
|
- struct net_device *master = NULL;
|
|
|
struct ndmsg *ndm;
|
|
|
struct nlattr *tb[NDA_MAX+1];
|
|
|
struct net_device *dev;
|
|
@@ -2090,10 +2090,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
|
|
/* Support fdb on master device the net/bridge default case */
|
|
|
if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
|
|
|
(dev->priv_flags & IFF_BRIDGE_PORT)) {
|
|
|
- master = dev->master;
|
|
|
- err = master->netdev_ops->ndo_fdb_add(ndm, tb,
|
|
|
- dev, addr,
|
|
|
- nlh->nlmsg_flags);
|
|
|
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
|
|
+ const struct net_device_ops *ops = br_dev->netdev_ops;
|
|
|
+
|
|
|
+ err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags);
|
|
|
if (err)
|
|
|
goto out;
|
|
|
else
|
|
@@ -2154,10 +2154,11 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
|
|
|
/* Support fdb on master device the net/bridge default case */
|
|
|
if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
|
|
|
(dev->priv_flags & IFF_BRIDGE_PORT)) {
|
|
|
- struct net_device *master = dev->master;
|
|
|
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
|
|
+ const struct net_device_ops *ops = br_dev->netdev_ops;
|
|
|
|
|
|
- if (master->netdev_ops->ndo_fdb_del)
|
|
|
- err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr);
|
|
|
+ if (ops->ndo_fdb_del)
|
|
|
+ err = ops->ndo_fdb_del(ndm, dev, addr);
|
|
|
|
|
|
if (err)
|
|
|
goto out;
|
|
@@ -2241,9 +2242,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
rcu_read_lock();
|
|
|
for_each_netdev_rcu(net, dev) {
|
|
|
if (dev->priv_flags & IFF_BRIDGE_PORT) {
|
|
|
- struct net_device *master = dev->master;
|
|
|
- const struct net_device_ops *ops = master->netdev_ops;
|
|
|
+ struct net_device *br_dev;
|
|
|
+ const struct net_device_ops *ops;
|
|
|
|
|
|
+ br_dev = netdev_master_upper_dev_get(dev);
|
|
|
+ ops = br_dev->netdev_ops;
|
|
|
if (ops->ndo_fdb_dump)
|
|
|
idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
|
|
|
}
|
|
@@ -2264,6 +2267,7 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|
|
struct ifinfomsg *ifm;
|
|
|
struct nlattr *br_afspec;
|
|
|
u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
|
|
|
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
|
|
|
|
|
nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
|
|
|
if (nlh == NULL)
|
|
@@ -2281,8 +2285,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
|
|
|
if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
|
|
|
nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
|
|
|
nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
|
|
|
- (dev->master &&
|
|
|
- nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
|
|
|
+ (br_dev &&
|
|
|
+ nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
|
|
|
(dev->addr_len &&
|
|
|
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
|
|
|
(dev->ifindex != dev->iflink &&
|
|
@@ -2318,11 +2322,11 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
|
|
|
rcu_read_lock();
|
|
|
for_each_netdev_rcu(net, dev) {
|
|
|
const struct net_device_ops *ops = dev->netdev_ops;
|
|
|
- struct net_device *master = dev->master;
|
|
|
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
|
|
|
|
|
- if (master && master->netdev_ops->ndo_bridge_getlink) {
|
|
|
+ if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
|
|
|
if (idx >= cb->args[0] &&
|
|
|
- master->netdev_ops->ndo_bridge_getlink(
|
|
|
+ br_dev->netdev_ops->ndo_bridge_getlink(
|
|
|
skb, portid, seq, dev) < 0)
|
|
|
break;
|
|
|
idx++;
|
|
@@ -2359,7 +2363,7 @@ static inline size_t bridge_nlmsg_size(void)
|
|
|
static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
|
|
|
{
|
|
|
struct net *net = dev_net(dev);
|
|
|
- struct net_device *master = dev->master;
|
|
|
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
|
|
struct sk_buff *skb;
|
|
|
int err = -EOPNOTSUPP;
|
|
|
|
|
@@ -2370,8 +2374,8 @@ static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
|
|
|
}
|
|
|
|
|
|
if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
|
|
|
- master && master->netdev_ops->ndo_bridge_getlink) {
|
|
|
- err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
|
|
|
+ br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
|
|
|
+ err = br_dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
|
|
|
if (err < 0)
|
|
|
goto errout;
|
|
|
}
|
|
@@ -2430,13 +2434,14 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
|
oflags = flags;
|
|
|
|
|
|
if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
|
|
|
- if (!dev->master ||
|
|
|
- !dev->master->netdev_ops->ndo_bridge_setlink) {
|
|
|
+ struct net_device *br_dev = netdev_master_upper_dev_get(dev);
|
|
|
+
|
|
|
+ if (!br_dev || !br_dev->netdev_ops->ndo_bridge_setlink) {
|
|
|
err = -EOPNOTSUPP;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
|
|
|
+ err = br_dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
|
|
|
if (err)
|
|
|
goto out;
|
|
|
|