Skip to content

Commit

Permalink
rtnl/do_setlink(): notify when a netdev is modified
Browse files Browse the repository at this point in the history
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: Nicolas Dichtel <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
NicolasDichtel authored and davem330 committed Sep 2, 2014
1 parent 90c325e commit ba99890
Showing 1 changed file with 21 additions and 14 deletions.
35 changes: 21 additions & 14 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,8 @@ static int do_set_master(struct net_device *dev, int ifindex)
}

#define DO_SETLINK_MODIFIED 0x01
/* notify flag means notify + modified. */
#define DO_SETLINK_NOTIFY 0x03
static int do_setlink(const struct sk_buff *skb,
struct net_device *dev, struct ifinfomsg *ifm,
struct nlattr **tb, char *ifname, int status)
Expand Down Expand Up @@ -1532,7 +1534,7 @@ static int do_setlink(const struct sk_buff *skb,
if (err < 0)
goto errout;

status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}

if (tb[IFLA_ADDRESS]) {
Expand Down Expand Up @@ -1564,7 +1566,7 @@ static int do_setlink(const struct sk_buff *skb,

if (tb[IFLA_GROUP]) {
dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}

/*
Expand All @@ -1584,7 +1586,7 @@ static int do_setlink(const struct sk_buff *skb,
nla_len(tb[IFLA_IFALIAS]));
if (err < 0)
goto errout;
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}

if (tb[IFLA_BROADCAST]) {
Expand Down Expand Up @@ -1616,7 +1618,7 @@ static int do_setlink(const struct sk_buff *skb,
unsigned long value = nla_get_u32(tb[IFLA_TXQLEN]);

if (dev->tx_queue_len ^ value)
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;

dev->tx_queue_len = value;
}
Expand All @@ -1629,7 +1631,7 @@ static int do_setlink(const struct sk_buff *skb,

write_lock_bh(&dev_base_lock);
if (dev->link_mode ^ value)
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
dev->link_mode = value;
write_unlock_bh(&dev_base_lock);
}
Expand All @@ -1645,7 +1647,7 @@ static int do_setlink(const struct sk_buff *skb,
err = do_setvfinfo(dev, attr);
if (err < 0)
goto errout;
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}
}
err = 0;
Expand Down Expand Up @@ -1675,7 +1677,7 @@ static int do_setlink(const struct sk_buff *skb,
err = ops->ndo_set_vf_port(dev, vf, port);
if (err < 0)
goto errout;
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}
}
err = 0;
Expand All @@ -1693,7 +1695,7 @@ static int do_setlink(const struct sk_buff *skb,
err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port);
if (err < 0)
goto errout;
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}

if (tb[IFLA_AF_SPEC]) {
Expand All @@ -1710,15 +1712,20 @@ static int do_setlink(const struct sk_buff *skb,
if (err < 0)
goto errout;

status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}
}
err = 0;

errout:
if (err < 0 && status & DO_SETLINK_MODIFIED)
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);
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",
dev->name);
}

return err;
}
Expand Down Expand Up @@ -2015,7 +2022,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
err = ops->changelink(dev, tb, data);
if (err < 0)
return err;
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}

if (linkinfo[IFLA_INFO_SLAVE_DATA]) {
Expand All @@ -2026,7 +2033,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh)
tb, slave_data);
if (err < 0)
return err;
status |= DO_SETLINK_MODIFIED;
status |= DO_SETLINK_NOTIFY;
}

return do_setlink(skb, dev, ifm, tb, ifname, status);
Expand Down

0 comments on commit ba99890

Please sign in to comment.