Commit ba998906 authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by David S. Miller

rtnl/do_setlink(): notify when a netdev is modified

Depending on which parameters were updated, the changes were not propagated via
the notifier chain and netlink.

The new flag has been set only when the change did not cause a call to the
notifier chain and/or to the netlink notification functions.
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 90c325e3
...@@ -1482,6 +1482,8 @@ static int do_set_master(struct net_device *dev, int ifindex) ...@@ -1482,6 +1482,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
} }
#define DO_SETLINK_MODIFIED 0x01 #define DO_SETLINK_MODIFIED 0x01
/* notify flag means notify + modified. */
#define DO_SETLINK_NOTIFY 0x03
static int do_setlink(const struct sk_buff *skb, static int do_setlink(const struct sk_buff *skb,
struct net_device *dev, struct ifinfomsg *ifm, struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname, int status) struct nlattr **tb, char *ifname, int status)
...@@ -1532,7 +1534,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1532,7 +1534,7 @@ static int do_setlink(const struct sk_buff *skb,
if (err < 0) if (err < 0)
goto errout; goto errout;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
if (tb[IFLA_ADDRESS]) { if (tb[IFLA_ADDRESS]) {
...@@ -1564,7 +1566,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1564,7 +1566,7 @@ static int do_setlink(const struct sk_buff *skb,
if (tb[IFLA_GROUP]) { if (tb[IFLA_GROUP]) {
dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
/* /*
...@@ -1584,7 +1586,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1584,7 +1586,7 @@ static int do_setlink(const struct sk_buff *skb,
nla_len(tb[IFLA_IFALIAS])); nla_len(tb[IFLA_IFALIAS]));
if (err < 0) if (err < 0)
goto errout; goto errout;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
if (tb[IFLA_BROADCAST]) { if (tb[IFLA_BROADCAST]) {
...@@ -1616,7 +1618,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1616,7 +1618,7 @@ static int do_setlink(const struct sk_buff *skb,
unsigned long value = nla_get_u32(tb[IFLA_TXQLEN]); unsigned long value = nla_get_u32(tb[IFLA_TXQLEN]);
if (dev->tx_queue_len ^ value) if (dev->tx_queue_len ^ value)
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
dev->tx_queue_len = value; dev->tx_queue_len = value;
} }
...@@ -1629,7 +1631,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1629,7 +1631,7 @@ static int do_setlink(const struct sk_buff *skb,
write_lock_bh(&dev_base_lock); write_lock_bh(&dev_base_lock);
if (dev->link_mode ^ value) if (dev->link_mode ^ value)
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
dev->link_mode = value; dev->link_mode = value;
write_unlock_bh(&dev_base_lock); write_unlock_bh(&dev_base_lock);
} }
...@@ -1645,7 +1647,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1645,7 +1647,7 @@ static int do_setlink(const struct sk_buff *skb,
err = do_setvfinfo(dev, attr); err = do_setvfinfo(dev, attr);
if (err < 0) if (err < 0)
goto errout; goto errout;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
} }
err = 0; err = 0;
...@@ -1675,7 +1677,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1675,7 +1677,7 @@ static int do_setlink(const struct sk_buff *skb,
err = ops->ndo_set_vf_port(dev, vf, port); err = ops->ndo_set_vf_port(dev, vf, port);
if (err < 0) if (err < 0)
goto errout; goto errout;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
} }
err = 0; err = 0;
...@@ -1693,7 +1695,7 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1693,7 +1695,7 @@ static int do_setlink(const struct sk_buff *skb,
err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port);
if (err < 0) if (err < 0)
goto errout; goto errout;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
if (tb[IFLA_AF_SPEC]) { if (tb[IFLA_AF_SPEC]) {
...@@ -1710,15 +1712,20 @@ static int do_setlink(const struct sk_buff *skb, ...@@ -1710,15 +1712,20 @@ static int do_setlink(const struct sk_buff *skb,
if (err < 0) if (err < 0)
goto errout; goto errout;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
} }
err = 0; err = 0;
errout: errout:
if (err < 0 && status & DO_SETLINK_MODIFIED) if (status & DO_SETLINK_MODIFIED) {
if (status & DO_SETLINK_NOTIFY)
netdev_state_change(dev);
if (err < 0)
net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n", net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n",
dev->name); dev->name);
}
return err; return err;
} }
...@@ -2015,7 +2022,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -2015,7 +2022,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
err = ops->changelink(dev, tb, data); err = ops->changelink(dev, tb, data);
if (err < 0) if (err < 0)
return err; return err;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
if (linkinfo[IFLA_INFO_SLAVE_DATA]) { if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
...@@ -2026,7 +2033,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -2026,7 +2033,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
tb, slave_data); tb, slave_data);
if (err < 0) if (err < 0)
return err; return err;
status |= DO_SETLINK_MODIFIED; status |= DO_SETLINK_NOTIFY;
} }
return do_setlink(skb, dev, ifm, tb, ifname, status); return do_setlink(skb, dev, ifm, tb, ifname, status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment