diff options
author | David S. Miller <davem@davemloft.net> | 2014-09-02 15:58:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-02 15:58:36 -0400 |
commit | 29fea209f8333e2351710c14c19bf5358da63e39 (patch) | |
tree | a31001f42e367eac32e74c69ab2d48e571a14645 | |
parent | 219c5361e625186c21f3e1bc7bc67cd7dac50ca9 (diff) | |
parent | ba9989069f4e426b1e0ed7018eacc9e1ba607095 (diff) |
Merge branch 'netdev_modified'
Nicolas Dichtel says:
====================
rtnl: send notification in do_setlink()
This series ensures to call the notifier chain and to send a netlink
message when a change is done by do_setlink().
The three first patches mainly prepare the last one, which do this change.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/rtnetlink.c | 66 |
1 files changed, 42 insertions, 24 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f0493e3b7471..a6882686ca3a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1481,9 +1481,12 @@ static int do_set_master(struct net_device *dev, int ifindex) | |||
1481 | return 0; | 1481 | return 0; |
1482 | } | 1482 | } |
1483 | 1483 | ||
1484 | #define DO_SETLINK_MODIFIED 0x01 | ||
1485 | /* notify flag means notify + modified. */ | ||
1486 | #define DO_SETLINK_NOTIFY 0x03 | ||
1484 | static int do_setlink(const struct sk_buff *skb, | 1487 | static int do_setlink(const struct sk_buff *skb, |
1485 | struct net_device *dev, struct ifinfomsg *ifm, | 1488 | struct net_device *dev, struct ifinfomsg *ifm, |
1486 | struct nlattr **tb, char *ifname, int modified) | 1489 | struct nlattr **tb, char *ifname, int status) |
1487 | { | 1490 | { |
1488 | const struct net_device_ops *ops = dev->netdev_ops; | 1491 | const struct net_device_ops *ops = dev->netdev_ops; |
1489 | int err; | 1492 | int err; |
@@ -1502,7 +1505,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1502 | put_net(net); | 1505 | put_net(net); |
1503 | if (err) | 1506 | if (err) |
1504 | goto errout; | 1507 | goto errout; |
1505 | modified = 1; | 1508 | status |= DO_SETLINK_MODIFIED; |
1506 | } | 1509 | } |
1507 | 1510 | ||
1508 | if (tb[IFLA_MAP]) { | 1511 | if (tb[IFLA_MAP]) { |
@@ -1531,7 +1534,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1531 | if (err < 0) | 1534 | if (err < 0) |
1532 | goto errout; | 1535 | goto errout; |
1533 | 1536 | ||
1534 | modified = 1; | 1537 | status |= DO_SETLINK_NOTIFY; |
1535 | } | 1538 | } |
1536 | 1539 | ||
1537 | if (tb[IFLA_ADDRESS]) { | 1540 | if (tb[IFLA_ADDRESS]) { |
@@ -1551,19 +1554,19 @@ static int do_setlink(const struct sk_buff *skb, | |||
1551 | kfree(sa); | 1554 | kfree(sa); |
1552 | if (err) | 1555 | if (err) |
1553 | goto errout; | 1556 | goto errout; |
1554 | modified = 1; | 1557 | status |= DO_SETLINK_MODIFIED; |
1555 | } | 1558 | } |
1556 | 1559 | ||
1557 | if (tb[IFLA_MTU]) { | 1560 | if (tb[IFLA_MTU]) { |
1558 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); | 1561 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); |
1559 | if (err < 0) | 1562 | if (err < 0) |
1560 | goto errout; | 1563 | goto errout; |
1561 | modified = 1; | 1564 | status |= DO_SETLINK_MODIFIED; |
1562 | } | 1565 | } |
1563 | 1566 | ||
1564 | if (tb[IFLA_GROUP]) { | 1567 | if (tb[IFLA_GROUP]) { |
1565 | dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); | 1568 | dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP])); |
1566 | modified = 1; | 1569 | status |= DO_SETLINK_NOTIFY; |
1567 | } | 1570 | } |
1568 | 1571 | ||
1569 | /* | 1572 | /* |
@@ -1575,7 +1578,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1575 | err = dev_change_name(dev, ifname); | 1578 | err = dev_change_name(dev, ifname); |
1576 | if (err < 0) | 1579 | if (err < 0) |
1577 | goto errout; | 1580 | goto errout; |
1578 | modified = 1; | 1581 | status |= DO_SETLINK_MODIFIED; |
1579 | } | 1582 | } |
1580 | 1583 | ||
1581 | if (tb[IFLA_IFALIAS]) { | 1584 | if (tb[IFLA_IFALIAS]) { |
@@ -1583,7 +1586,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1583 | nla_len(tb[IFLA_IFALIAS])); | 1586 | nla_len(tb[IFLA_IFALIAS])); |
1584 | if (err < 0) | 1587 | if (err < 0) |
1585 | goto errout; | 1588 | goto errout; |
1586 | modified = 1; | 1589 | status |= DO_SETLINK_NOTIFY; |
1587 | } | 1590 | } |
1588 | 1591 | ||
1589 | if (tb[IFLA_BROADCAST]) { | 1592 | if (tb[IFLA_BROADCAST]) { |
@@ -1601,25 +1604,35 @@ static int do_setlink(const struct sk_buff *skb, | |||
1601 | err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER])); | 1604 | err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER])); |
1602 | if (err) | 1605 | if (err) |
1603 | goto errout; | 1606 | goto errout; |
1604 | modified = 1; | 1607 | status |= DO_SETLINK_MODIFIED; |
1605 | } | 1608 | } |
1606 | 1609 | ||
1607 | if (tb[IFLA_CARRIER]) { | 1610 | if (tb[IFLA_CARRIER]) { |
1608 | err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER])); | 1611 | err = dev_change_carrier(dev, nla_get_u8(tb[IFLA_CARRIER])); |
1609 | if (err) | 1612 | if (err) |
1610 | goto errout; | 1613 | goto errout; |
1611 | modified = 1; | 1614 | status |= DO_SETLINK_MODIFIED; |
1612 | } | 1615 | } |
1613 | 1616 | ||
1614 | if (tb[IFLA_TXQLEN]) | 1617 | if (tb[IFLA_TXQLEN]) { |
1615 | dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); | 1618 | unsigned long value = nla_get_u32(tb[IFLA_TXQLEN]); |
1619 | |||
1620 | if (dev->tx_queue_len ^ value) | ||
1621 | status |= DO_SETLINK_NOTIFY; | ||
1622 | |||
1623 | dev->tx_queue_len = value; | ||
1624 | } | ||
1616 | 1625 | ||
1617 | if (tb[IFLA_OPERSTATE]) | 1626 | if (tb[IFLA_OPERSTATE]) |
1618 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); | 1627 | set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); |
1619 | 1628 | ||
1620 | if (tb[IFLA_LINKMODE]) { | 1629 | if (tb[IFLA_LINKMODE]) { |
1630 | unsigned char value = nla_get_u8(tb[IFLA_LINKMODE]); | ||
1631 | |||
1621 | write_lock_bh(&dev_base_lock); | 1632 | write_lock_bh(&dev_base_lock); |
1622 | dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); | 1633 | if (dev->link_mode ^ value) |
1634 | status |= DO_SETLINK_NOTIFY; | ||
1635 | dev->link_mode = value; | ||
1623 | write_unlock_bh(&dev_base_lock); | 1636 | write_unlock_bh(&dev_base_lock); |
1624 | } | 1637 | } |
1625 | 1638 | ||
@@ -1634,7 +1647,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1634 | err = do_setvfinfo(dev, attr); | 1647 | err = do_setvfinfo(dev, attr); |
1635 | if (err < 0) | 1648 | if (err < 0) |
1636 | goto errout; | 1649 | goto errout; |
1637 | modified = 1; | 1650 | status |= DO_SETLINK_NOTIFY; |
1638 | } | 1651 | } |
1639 | } | 1652 | } |
1640 | err = 0; | 1653 | err = 0; |
@@ -1664,7 +1677,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1664 | err = ops->ndo_set_vf_port(dev, vf, port); | 1677 | err = ops->ndo_set_vf_port(dev, vf, port); |
1665 | if (err < 0) | 1678 | if (err < 0) |
1666 | goto errout; | 1679 | goto errout; |
1667 | modified = 1; | 1680 | status |= DO_SETLINK_NOTIFY; |
1668 | } | 1681 | } |
1669 | } | 1682 | } |
1670 | err = 0; | 1683 | err = 0; |
@@ -1682,7 +1695,7 @@ static int do_setlink(const struct sk_buff *skb, | |||
1682 | err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); | 1695 | err = ops->ndo_set_vf_port(dev, PORT_SELF_VF, port); |
1683 | if (err < 0) | 1696 | if (err < 0) |
1684 | goto errout; | 1697 | goto errout; |
1685 | modified = 1; | 1698 | status |= DO_SETLINK_NOTIFY; |
1686 | } | 1699 | } |
1687 | 1700 | ||
1688 | if (tb[IFLA_AF_SPEC]) { | 1701 | if (tb[IFLA_AF_SPEC]) { |
@@ -1699,15 +1712,20 @@ static int do_setlink(const struct sk_buff *skb, | |||
1699 | if (err < 0) | 1712 | if (err < 0) |
1700 | goto errout; | 1713 | goto errout; |
1701 | 1714 | ||
1702 | modified = 1; | 1715 | status |= DO_SETLINK_NOTIFY; |
1703 | } | 1716 | } |
1704 | } | 1717 | } |
1705 | err = 0; | 1718 | err = 0; |
1706 | 1719 | ||
1707 | errout: | 1720 | errout: |
1708 | if (err < 0 && modified) | 1721 | if (status & DO_SETLINK_MODIFIED) { |
1709 | 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", | 1722 | if (status & DO_SETLINK_NOTIFY) |
1710 | dev->name); | 1723 | netdev_state_change(dev); |
1724 | |||
1725 | if (err < 0) | ||
1726 | 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", | ||
1727 | dev->name); | ||
1728 | } | ||
1711 | 1729 | ||
1712 | return err; | 1730 | return err; |
1713 | } | 1731 | } |
@@ -1989,7 +2007,7 @@ replay: | |||
1989 | } | 2007 | } |
1990 | 2008 | ||
1991 | if (dev) { | 2009 | if (dev) { |
1992 | int modified = 0; | 2010 | int status = 0; |
1993 | 2011 | ||
1994 | if (nlh->nlmsg_flags & NLM_F_EXCL) | 2012 | if (nlh->nlmsg_flags & NLM_F_EXCL) |
1995 | return -EEXIST; | 2013 | return -EEXIST; |
@@ -2004,7 +2022,7 @@ replay: | |||
2004 | err = ops->changelink(dev, tb, data); | 2022 | err = ops->changelink(dev, tb, data); |
2005 | if (err < 0) | 2023 | if (err < 0) |
2006 | return err; | 2024 | return err; |
2007 | modified = 1; | 2025 | status |= DO_SETLINK_NOTIFY; |
2008 | } | 2026 | } |
2009 | 2027 | ||
2010 | if (linkinfo[IFLA_INFO_SLAVE_DATA]) { | 2028 | if (linkinfo[IFLA_INFO_SLAVE_DATA]) { |
@@ -2015,10 +2033,10 @@ replay: | |||
2015 | tb, slave_data); | 2033 | tb, slave_data); |
2016 | if (err < 0) | 2034 | if (err < 0) |
2017 | return err; | 2035 | return err; |
2018 | modified = 1; | 2036 | status |= DO_SETLINK_NOTIFY; |
2019 | } | 2037 | } |
2020 | 2038 | ||
2021 | return do_setlink(skb, dev, ifm, tb, ifname, modified); | 2039 | return do_setlink(skb, dev, ifm, tb, ifname, status); |
2022 | } | 2040 | } |
2023 | 2041 | ||
2024 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { | 2042 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { |