aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/core/rtnetlink.c66
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
1484static int do_setlink(const struct sk_buff *skb, 1487static 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
1707errout: 1720errout:
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)) {