diff options
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 22 | ||||
-rw-r--r-- | drivers/net/bonding/bond_3ad.h | 1 | ||||
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 2 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 159 | ||||
-rw-r--r-- | drivers/net/bonding/bond_options.c | 3 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 47 |
6 files changed, 157 insertions, 77 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cce1f1bf90b4..dcde56057fe1 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -181,7 +181,7 @@ static inline int __agg_has_partner(struct aggregator *agg) | |||
181 | */ | 181 | */ |
182 | static inline void __disable_port(struct port *port) | 182 | static inline void __disable_port(struct port *port) |
183 | { | 183 | { |
184 | bond_set_slave_inactive_flags(port->slave); | 184 | bond_set_slave_inactive_flags(port->slave, BOND_SLAVE_NOTIFY_LATER); |
185 | } | 185 | } |
186 | 186 | ||
187 | /** | 187 | /** |
@@ -193,7 +193,7 @@ static inline void __enable_port(struct port *port) | |||
193 | struct slave *slave = port->slave; | 193 | struct slave *slave = port->slave; |
194 | 194 | ||
195 | if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) | 195 | if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) |
196 | bond_set_slave_active_flags(slave); | 196 | bond_set_slave_active_flags(slave, BOND_SLAVE_NOTIFY_LATER); |
197 | } | 197 | } |
198 | 198 | ||
199 | /** | 199 | /** |
@@ -1796,8 +1796,6 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) | |||
1796 | BOND_AD_INFO(bond).agg_select_timer = timeout; | 1796 | BOND_AD_INFO(bond).agg_select_timer = timeout; |
1797 | } | 1797 | } |
1798 | 1798 | ||
1799 | static u16 aggregator_identifier; | ||
1800 | |||
1801 | /** | 1799 | /** |
1802 | * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures | 1800 | * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures |
1803 | * @bond: bonding struct to work on | 1801 | * @bond: bonding struct to work on |
@@ -1811,7 +1809,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) | |||
1811 | if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), | 1809 | if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), |
1812 | bond->dev->dev_addr)) { | 1810 | bond->dev->dev_addr)) { |
1813 | 1811 | ||
1814 | aggregator_identifier = 0; | 1812 | BOND_AD_INFO(bond).aggregator_identifier = 0; |
1815 | 1813 | ||
1816 | BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; | 1814 | BOND_AD_INFO(bond).system.sys_priority = 0xFFFF; |
1817 | BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); | 1815 | BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr); |
@@ -1880,7 +1878,7 @@ void bond_3ad_bind_slave(struct slave *slave) | |||
1880 | ad_initialize_agg(aggregator); | 1878 | ad_initialize_agg(aggregator); |
1881 | 1879 | ||
1882 | aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr); | 1880 | aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr); |
1883 | aggregator->aggregator_identifier = (++aggregator_identifier); | 1881 | aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier; |
1884 | aggregator->slave = slave; | 1882 | aggregator->slave = slave; |
1885 | aggregator->is_active = 0; | 1883 | aggregator->is_active = 0; |
1886 | aggregator->num_of_ports = 0; | 1884 | aggregator->num_of_ports = 0; |
@@ -2064,6 +2062,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2064 | struct list_head *iter; | 2062 | struct list_head *iter; |
2065 | struct slave *slave; | 2063 | struct slave *slave; |
2066 | struct port *port; | 2064 | struct port *port; |
2065 | bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; | ||
2067 | 2066 | ||
2068 | read_lock(&bond->lock); | 2067 | read_lock(&bond->lock); |
2069 | rcu_read_lock(); | 2068 | rcu_read_lock(); |
@@ -2121,8 +2120,19 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2121 | } | 2120 | } |
2122 | 2121 | ||
2123 | re_arm: | 2122 | re_arm: |
2123 | bond_for_each_slave_rcu(bond, slave, iter) { | ||
2124 | if (slave->should_notify) { | ||
2125 | should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW; | ||
2126 | break; | ||
2127 | } | ||
2128 | } | ||
2124 | rcu_read_unlock(); | 2129 | rcu_read_unlock(); |
2125 | read_unlock(&bond->lock); | 2130 | read_unlock(&bond->lock); |
2131 | |||
2132 | if (should_notify_rtnl && rtnl_trylock()) { | ||
2133 | bond_slave_state_notify(bond); | ||
2134 | rtnl_unlock(); | ||
2135 | } | ||
2126 | queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); | 2136 | queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks); |
2127 | } | 2137 | } |
2128 | 2138 | ||
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h index 13dc9d3c5e34..f4dd9592ac62 100644 --- a/drivers/net/bonding/bond_3ad.h +++ b/drivers/net/bonding/bond_3ad.h | |||
@@ -253,6 +253,7 @@ struct ad_system { | |||
253 | struct ad_bond_info { | 253 | struct ad_bond_info { |
254 | struct ad_system system; /* 802.3ad system structure */ | 254 | struct ad_system system; /* 802.3ad system structure */ |
255 | u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes | 255 | u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes |
256 | u16 aggregator_identifier; | ||
256 | }; | 257 | }; |
257 | 258 | ||
258 | struct ad_slave_info { | 259 | struct ad_slave_info { |
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index a2c47476804d..e8f133e926aa 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
@@ -730,7 +730,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon | |||
730 | client_info->ntt = 0; | 730 | client_info->ntt = 0; |
731 | } | 731 | } |
732 | 732 | ||
733 | if (!vlan_get_tag(skb, &client_info->vlan_id)) | 733 | if (vlan_get_tag(skb, &client_info->vlan_id)) |
734 | client_info->vlan_id = 0; | 734 | client_info->vlan_id = 0; |
735 | 735 | ||
736 | if (!client_info->assigned) { | 736 | if (!client_info->assigned) { |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 4c08018d7333..e5628fc725c3 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -829,21 +829,25 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
829 | if (bond_is_lb(bond)) { | 829 | if (bond_is_lb(bond)) { |
830 | bond_alb_handle_active_change(bond, new_active); | 830 | bond_alb_handle_active_change(bond, new_active); |
831 | if (old_active) | 831 | if (old_active) |
832 | bond_set_slave_inactive_flags(old_active); | 832 | bond_set_slave_inactive_flags(old_active, |
833 | BOND_SLAVE_NOTIFY_NOW); | ||
833 | if (new_active) | 834 | if (new_active) |
834 | bond_set_slave_active_flags(new_active); | 835 | bond_set_slave_active_flags(new_active, |
836 | BOND_SLAVE_NOTIFY_NOW); | ||
835 | } else { | 837 | } else { |
836 | rcu_assign_pointer(bond->curr_active_slave, new_active); | 838 | rcu_assign_pointer(bond->curr_active_slave, new_active); |
837 | } | 839 | } |
838 | 840 | ||
839 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { | 841 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { |
840 | if (old_active) | 842 | if (old_active) |
841 | bond_set_slave_inactive_flags(old_active); | 843 | bond_set_slave_inactive_flags(old_active, |
844 | BOND_SLAVE_NOTIFY_NOW); | ||
842 | 845 | ||
843 | if (new_active) { | 846 | if (new_active) { |
844 | bool should_notify_peers = false; | 847 | bool should_notify_peers = false; |
845 | 848 | ||
846 | bond_set_slave_active_flags(new_active); | 849 | bond_set_slave_active_flags(new_active, |
850 | BOND_SLAVE_NOTIFY_NOW); | ||
847 | 851 | ||
848 | if (bond->params.fail_over_mac) | 852 | if (bond->params.fail_over_mac) |
849 | bond_do_fail_over_mac(bond, new_active, | 853 | bond_do_fail_over_mac(bond, new_active, |
@@ -1193,6 +1197,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1193 | return -EBUSY; | 1197 | return -EBUSY; |
1194 | } | 1198 | } |
1195 | 1199 | ||
1200 | if (bond_dev == slave_dev) { | ||
1201 | pr_err("%s: cannot enslave bond to itself.\n", bond_dev->name); | ||
1202 | return -EPERM; | ||
1203 | } | ||
1204 | |||
1196 | /* vlan challenged mutual exclusion */ | 1205 | /* vlan challenged mutual exclusion */ |
1197 | /* no need to lock since we're protected by rtnl_lock */ | 1206 | /* no need to lock since we're protected by rtnl_lock */ |
1198 | if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { | 1207 | if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { |
@@ -1270,9 +1279,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1270 | 1279 | ||
1271 | if (slave_ops->ndo_set_mac_address == NULL) { | 1280 | if (slave_ops->ndo_set_mac_address == NULL) { |
1272 | if (!bond_has_slaves(bond)) { | 1281 | if (!bond_has_slaves(bond)) { |
1273 | pr_warning("%s: Warning: The first slave device specified does not support setting the MAC address. Setting fail_over_mac to active.", | 1282 | pr_warn("%s: Warning: The first slave device specified does not support setting the MAC address.\n", |
1274 | bond_dev->name); | 1283 | bond_dev->name); |
1275 | bond->params.fail_over_mac = BOND_FOM_ACTIVE; | 1284 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { |
1285 | bond->params.fail_over_mac = BOND_FOM_ACTIVE; | ||
1286 | pr_warn("%s: Setting fail_over_mac to active for active-backup mode.\n", | ||
1287 | bond_dev->name); | ||
1288 | } | ||
1276 | } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { | 1289 | } else if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { |
1277 | pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n", | 1290 | pr_err("%s: Error: The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active.\n", |
1278 | bond_dev->name); | 1291 | bond_dev->name); |
@@ -1315,7 +1328,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1315 | */ | 1328 | */ |
1316 | memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); | 1329 | memcpy(new_slave->perm_hwaddr, slave_dev->dev_addr, ETH_ALEN); |
1317 | 1330 | ||
1318 | if (!bond->params.fail_over_mac) { | 1331 | if (!bond->params.fail_over_mac || |
1332 | bond->params.mode != BOND_MODE_ACTIVEBACKUP) { | ||
1319 | /* | 1333 | /* |
1320 | * Set slave to master's mac address. The application already | 1334 | * Set slave to master's mac address. The application already |
1321 | * set the master's mac address to that of the first slave | 1335 | * set the master's mac address to that of the first slave |
@@ -1458,14 +1472,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1458 | 1472 | ||
1459 | switch (bond->params.mode) { | 1473 | switch (bond->params.mode) { |
1460 | case BOND_MODE_ACTIVEBACKUP: | 1474 | case BOND_MODE_ACTIVEBACKUP: |
1461 | bond_set_slave_inactive_flags(new_slave); | 1475 | bond_set_slave_inactive_flags(new_slave, |
1476 | BOND_SLAVE_NOTIFY_NOW); | ||
1462 | break; | 1477 | break; |
1463 | case BOND_MODE_8023AD: | 1478 | case BOND_MODE_8023AD: |
1464 | /* in 802.3ad mode, the internal mechanism | 1479 | /* in 802.3ad mode, the internal mechanism |
1465 | * will activate the slaves in the selected | 1480 | * will activate the slaves in the selected |
1466 | * aggregator | 1481 | * aggregator |
1467 | */ | 1482 | */ |
1468 | bond_set_slave_inactive_flags(new_slave); | 1483 | bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); |
1469 | /* if this is the first slave */ | 1484 | /* if this is the first slave */ |
1470 | if (!prev_slave) { | 1485 | if (!prev_slave) { |
1471 | SLAVE_AD_INFO(new_slave).id = 1; | 1486 | SLAVE_AD_INFO(new_slave).id = 1; |
@@ -1483,7 +1498,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1483 | case BOND_MODE_TLB: | 1498 | case BOND_MODE_TLB: |
1484 | case BOND_MODE_ALB: | 1499 | case BOND_MODE_ALB: |
1485 | bond_set_active_slave(new_slave); | 1500 | bond_set_active_slave(new_slave); |
1486 | bond_set_slave_inactive_flags(new_slave); | 1501 | bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); |
1487 | break; | 1502 | break; |
1488 | default: | 1503 | default: |
1489 | pr_debug("This slave is always active in trunk mode\n"); | 1504 | pr_debug("This slave is always active in trunk mode\n"); |
@@ -1505,7 +1520,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1505 | slave_dev->npinfo = bond->dev->npinfo; | 1520 | slave_dev->npinfo = bond->dev->npinfo; |
1506 | if (slave_dev->npinfo) { | 1521 | if (slave_dev->npinfo) { |
1507 | if (slave_enable_netpoll(new_slave)) { | 1522 | if (slave_enable_netpoll(new_slave)) { |
1508 | read_unlock(&bond->lock); | ||
1509 | pr_info("Error, %s: master_dev is using netpoll, " | 1523 | pr_info("Error, %s: master_dev is using netpoll, " |
1510 | "but new slave device does not support netpoll.\n", | 1524 | "but new slave device does not support netpoll.\n", |
1511 | bond_dev->name); | 1525 | bond_dev->name); |
@@ -1539,9 +1553,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1539 | bond_set_carrier(bond); | 1553 | bond_set_carrier(bond); |
1540 | 1554 | ||
1541 | if (USES_PRIMARY(bond->params.mode)) { | 1555 | if (USES_PRIMARY(bond->params.mode)) { |
1556 | block_netpoll_tx(); | ||
1542 | write_lock_bh(&bond->curr_slave_lock); | 1557 | write_lock_bh(&bond->curr_slave_lock); |
1543 | bond_select_active_slave(bond); | 1558 | bond_select_active_slave(bond); |
1544 | write_unlock_bh(&bond->curr_slave_lock); | 1559 | write_unlock_bh(&bond->curr_slave_lock); |
1560 | unblock_netpoll_tx(); | ||
1545 | } | 1561 | } |
1546 | 1562 | ||
1547 | pr_info("%s: enslaving %s as a%s interface with a%s link.\n", | 1563 | pr_info("%s: enslaving %s as a%s interface with a%s link.\n", |
@@ -1567,10 +1583,12 @@ err_detach: | |||
1567 | if (bond->primary_slave == new_slave) | 1583 | if (bond->primary_slave == new_slave) |
1568 | bond->primary_slave = NULL; | 1584 | bond->primary_slave = NULL; |
1569 | if (bond->curr_active_slave == new_slave) { | 1585 | if (bond->curr_active_slave == new_slave) { |
1586 | block_netpoll_tx(); | ||
1570 | write_lock_bh(&bond->curr_slave_lock); | 1587 | write_lock_bh(&bond->curr_slave_lock); |
1571 | bond_change_active_slave(bond, NULL); | 1588 | bond_change_active_slave(bond, NULL); |
1572 | bond_select_active_slave(bond); | 1589 | bond_select_active_slave(bond); |
1573 | write_unlock_bh(&bond->curr_slave_lock); | 1590 | write_unlock_bh(&bond->curr_slave_lock); |
1591 | unblock_netpoll_tx(); | ||
1574 | } | 1592 | } |
1575 | slave_disable_netpoll(new_slave); | 1593 | slave_disable_netpoll(new_slave); |
1576 | 1594 | ||
@@ -1579,7 +1597,8 @@ err_close: | |||
1579 | dev_close(slave_dev); | 1597 | dev_close(slave_dev); |
1580 | 1598 | ||
1581 | err_restore_mac: | 1599 | err_restore_mac: |
1582 | if (!bond->params.fail_over_mac) { | 1600 | if (!bond->params.fail_over_mac || |
1601 | bond->params.mode != BOND_MODE_ACTIVEBACKUP) { | ||
1583 | /* XXX TODO - fom follow mode needs to change master's | 1602 | /* XXX TODO - fom follow mode needs to change master's |
1584 | * MAC if this slave's MAC is in use by the bond, or at | 1603 | * MAC if this slave's MAC is in use by the bond, or at |
1585 | * least print a warning. | 1604 | * least print a warning. |
@@ -1645,9 +1664,6 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1645 | return -EINVAL; | 1664 | return -EINVAL; |
1646 | } | 1665 | } |
1647 | 1666 | ||
1648 | /* release the slave from its bond */ | ||
1649 | bond->slave_cnt--; | ||
1650 | |||
1651 | bond_sysfs_slave_del(slave); | 1667 | bond_sysfs_slave_del(slave); |
1652 | 1668 | ||
1653 | bond_upper_dev_unlink(bond_dev, slave_dev); | 1669 | bond_upper_dev_unlink(bond_dev, slave_dev); |
@@ -1672,7 +1688,8 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1672 | 1688 | ||
1673 | bond->current_arp_slave = NULL; | 1689 | bond->current_arp_slave = NULL; |
1674 | 1690 | ||
1675 | if (!all && !bond->params.fail_over_mac) { | 1691 | if (!all && (!bond->params.fail_over_mac || |
1692 | bond->params.mode != BOND_MODE_ACTIVEBACKUP)) { | ||
1676 | if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && | 1693 | if (ether_addr_equal_64bits(bond_dev->dev_addr, slave->perm_hwaddr) && |
1677 | bond_has_slaves(bond)) | 1694 | bond_has_slaves(bond)) |
1678 | pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n", | 1695 | pr_warn("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n", |
@@ -1728,6 +1745,7 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1728 | 1745 | ||
1729 | unblock_netpoll_tx(); | 1746 | unblock_netpoll_tx(); |
1730 | synchronize_rcu(); | 1747 | synchronize_rcu(); |
1748 | bond->slave_cnt--; | ||
1731 | 1749 | ||
1732 | if (!bond_has_slaves(bond)) { | 1750 | if (!bond_has_slaves(bond)) { |
1733 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); | 1751 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); |
@@ -1769,7 +1787,8 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1769 | /* close slave before restoring its mac address */ | 1787 | /* close slave before restoring its mac address */ |
1770 | dev_close(slave_dev); | 1788 | dev_close(slave_dev); |
1771 | 1789 | ||
1772 | if (bond->params.fail_over_mac != BOND_FOM_ACTIVE) { | 1790 | if (bond->params.fail_over_mac != BOND_FOM_ACTIVE || |
1791 | bond->params.mode != BOND_MODE_ACTIVEBACKUP) { | ||
1773 | /* restore original ("permanent") mac address */ | 1792 | /* restore original ("permanent") mac address */ |
1774 | memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); | 1793 | memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN); |
1775 | addr.sa_family = slave_dev->type; | 1794 | addr.sa_family = slave_dev->type; |
@@ -2004,7 +2023,8 @@ static void bond_miimon_commit(struct bonding *bond) | |||
2004 | 2023 | ||
2005 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || | 2024 | if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || |
2006 | bond->params.mode == BOND_MODE_8023AD) | 2025 | bond->params.mode == BOND_MODE_8023AD) |
2007 | bond_set_slave_inactive_flags(slave); | 2026 | bond_set_slave_inactive_flags(slave, |
2027 | BOND_SLAVE_NOTIFY_NOW); | ||
2008 | 2028 | ||
2009 | pr_info("%s: link status definitely down for interface %s, disabling it\n", | 2029 | pr_info("%s: link status definitely down for interface %s, disabling it\n", |
2010 | bond->dev->name, slave->dev->name); | 2030 | bond->dev->name, slave->dev->name); |
@@ -2551,7 +2571,8 @@ static void bond_ab_arp_commit(struct bonding *bond) | |||
2551 | slave->link = BOND_LINK_UP; | 2571 | slave->link = BOND_LINK_UP; |
2552 | if (bond->current_arp_slave) { | 2572 | if (bond->current_arp_slave) { |
2553 | bond_set_slave_inactive_flags( | 2573 | bond_set_slave_inactive_flags( |
2554 | bond->current_arp_slave); | 2574 | bond->current_arp_slave, |
2575 | BOND_SLAVE_NOTIFY_NOW); | ||
2555 | bond->current_arp_slave = NULL; | 2576 | bond->current_arp_slave = NULL; |
2556 | } | 2577 | } |
2557 | 2578 | ||
@@ -2571,7 +2592,8 @@ static void bond_ab_arp_commit(struct bonding *bond) | |||
2571 | slave->link_failure_count++; | 2592 | slave->link_failure_count++; |
2572 | 2593 | ||
2573 | slave->link = BOND_LINK_DOWN; | 2594 | slave->link = BOND_LINK_DOWN; |
2574 | bond_set_slave_inactive_flags(slave); | 2595 | bond_set_slave_inactive_flags(slave, |
2596 | BOND_SLAVE_NOTIFY_NOW); | ||
2575 | 2597 | ||
2576 | pr_info("%s: link status definitely down for interface %s, disabling it\n", | 2598 | pr_info("%s: link status definitely down for interface %s, disabling it\n", |
2577 | bond->dev->name, slave->dev->name); | 2599 | bond->dev->name, slave->dev->name); |
@@ -2604,17 +2626,17 @@ do_failover: | |||
2604 | 2626 | ||
2605 | /* | 2627 | /* |
2606 | * Send ARP probes for active-backup mode ARP monitor. | 2628 | * Send ARP probes for active-backup mode ARP monitor. |
2629 | * | ||
2630 | * Called with rcu_read_lock hold. | ||
2607 | */ | 2631 | */ |
2608 | static bool bond_ab_arp_probe(struct bonding *bond) | 2632 | static bool bond_ab_arp_probe(struct bonding *bond) |
2609 | { | 2633 | { |
2610 | struct slave *slave, *before = NULL, *new_slave = NULL, | 2634 | struct slave *slave, *before = NULL, *new_slave = NULL, |
2611 | *curr_arp_slave, *curr_active_slave; | 2635 | *curr_arp_slave = rcu_dereference(bond->current_arp_slave), |
2636 | *curr_active_slave = rcu_dereference(bond->curr_active_slave); | ||
2612 | struct list_head *iter; | 2637 | struct list_head *iter; |
2613 | bool found = false; | 2638 | bool found = false; |
2614 | 2639 | bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER; | |
2615 | rcu_read_lock(); | ||
2616 | curr_arp_slave = rcu_dereference(bond->current_arp_slave); | ||
2617 | curr_active_slave = rcu_dereference(bond->curr_active_slave); | ||
2618 | 2640 | ||
2619 | if (curr_arp_slave && curr_active_slave) | 2641 | if (curr_arp_slave && curr_active_slave) |
2620 | pr_info("PROBE: c_arp %s && cas %s BAD\n", | 2642 | pr_info("PROBE: c_arp %s && cas %s BAD\n", |
@@ -2623,32 +2645,23 @@ static bool bond_ab_arp_probe(struct bonding *bond) | |||
2623 | 2645 | ||
2624 | if (curr_active_slave) { | 2646 | if (curr_active_slave) { |
2625 | bond_arp_send_all(bond, curr_active_slave); | 2647 | bond_arp_send_all(bond, curr_active_slave); |
2626 | rcu_read_unlock(); | 2648 | return should_notify_rtnl; |
2627 | return true; | ||
2628 | } | 2649 | } |
2629 | rcu_read_unlock(); | ||
2630 | 2650 | ||
2631 | /* if we don't have a curr_active_slave, search for the next available | 2651 | /* if we don't have a curr_active_slave, search for the next available |
2632 | * backup slave from the current_arp_slave and make it the candidate | 2652 | * backup slave from the current_arp_slave and make it the candidate |
2633 | * for becoming the curr_active_slave | 2653 | * for becoming the curr_active_slave |
2634 | */ | 2654 | */ |
2635 | 2655 | ||
2636 | if (!rtnl_trylock()) | ||
2637 | return false; | ||
2638 | /* curr_arp_slave might have gone away */ | ||
2639 | curr_arp_slave = ACCESS_ONCE(bond->current_arp_slave); | ||
2640 | |||
2641 | if (!curr_arp_slave) { | 2656 | if (!curr_arp_slave) { |
2642 | curr_arp_slave = bond_first_slave(bond); | 2657 | curr_arp_slave = bond_first_slave_rcu(bond); |
2643 | if (!curr_arp_slave) { | 2658 | if (!curr_arp_slave) |
2644 | rtnl_unlock(); | 2659 | return should_notify_rtnl; |
2645 | return true; | ||
2646 | } | ||
2647 | } | 2660 | } |
2648 | 2661 | ||
2649 | bond_set_slave_inactive_flags(curr_arp_slave); | 2662 | bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER); |
2650 | 2663 | ||
2651 | bond_for_each_slave(bond, slave, iter) { | 2664 | bond_for_each_slave_rcu(bond, slave, iter) { |
2652 | if (!found && !before && IS_UP(slave->dev)) | 2665 | if (!found && !before && IS_UP(slave->dev)) |
2653 | before = slave; | 2666 | before = slave; |
2654 | 2667 | ||
@@ -2666,7 +2679,8 @@ static bool bond_ab_arp_probe(struct bonding *bond) | |||
2666 | if (slave->link_failure_count < UINT_MAX) | 2679 | if (slave->link_failure_count < UINT_MAX) |
2667 | slave->link_failure_count++; | 2680 | slave->link_failure_count++; |
2668 | 2681 | ||
2669 | bond_set_slave_inactive_flags(slave); | 2682 | bond_set_slave_inactive_flags(slave, |
2683 | BOND_SLAVE_NOTIFY_LATER); | ||
2670 | 2684 | ||
2671 | pr_info("%s: backup interface %s is now down.\n", | 2685 | pr_info("%s: backup interface %s is now down.\n", |
2672 | bond->dev->name, slave->dev->name); | 2686 | bond->dev->name, slave->dev->name); |
@@ -2678,26 +2692,31 @@ static bool bond_ab_arp_probe(struct bonding *bond) | |||
2678 | if (!new_slave && before) | 2692 | if (!new_slave && before) |
2679 | new_slave = before; | 2693 | new_slave = before; |
2680 | 2694 | ||
2681 | if (!new_slave) { | 2695 | if (!new_slave) |
2682 | rtnl_unlock(); | 2696 | goto check_state; |
2683 | return true; | ||
2684 | } | ||
2685 | 2697 | ||
2686 | new_slave->link = BOND_LINK_BACK; | 2698 | new_slave->link = BOND_LINK_BACK; |
2687 | bond_set_slave_active_flags(new_slave); | 2699 | bond_set_slave_active_flags(new_slave, BOND_SLAVE_NOTIFY_LATER); |
2688 | bond_arp_send_all(bond, new_slave); | 2700 | bond_arp_send_all(bond, new_slave); |
2689 | new_slave->jiffies = jiffies; | 2701 | new_slave->jiffies = jiffies; |
2690 | rcu_assign_pointer(bond->current_arp_slave, new_slave); | 2702 | rcu_assign_pointer(bond->current_arp_slave, new_slave); |
2691 | rtnl_unlock(); | ||
2692 | 2703 | ||
2693 | return true; | 2704 | check_state: |
2705 | bond_for_each_slave_rcu(bond, slave, iter) { | ||
2706 | if (slave->should_notify) { | ||
2707 | should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW; | ||
2708 | break; | ||
2709 | } | ||
2710 | } | ||
2711 | return should_notify_rtnl; | ||
2694 | } | 2712 | } |
2695 | 2713 | ||
2696 | static void bond_activebackup_arp_mon(struct work_struct *work) | 2714 | static void bond_activebackup_arp_mon(struct work_struct *work) |
2697 | { | 2715 | { |
2698 | struct bonding *bond = container_of(work, struct bonding, | 2716 | struct bonding *bond = container_of(work, struct bonding, |
2699 | arp_work.work); | 2717 | arp_work.work); |
2700 | bool should_notify_peers = false, should_commit = false; | 2718 | bool should_notify_peers = false; |
2719 | bool should_notify_rtnl = false; | ||
2701 | int delta_in_ticks; | 2720 | int delta_in_ticks; |
2702 | 2721 | ||
2703 | delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); | 2722 | delta_in_ticks = msecs_to_jiffies(bond->params.arp_interval); |
@@ -2706,11 +2725,12 @@ static void bond_activebackup_arp_mon(struct work_struct *work) | |||
2706 | goto re_arm; | 2725 | goto re_arm; |
2707 | 2726 | ||
2708 | rcu_read_lock(); | 2727 | rcu_read_lock(); |
2728 | |||
2709 | should_notify_peers = bond_should_notify_peers(bond); | 2729 | should_notify_peers = bond_should_notify_peers(bond); |
2710 | should_commit = bond_ab_arp_inspect(bond); | ||
2711 | rcu_read_unlock(); | ||
2712 | 2730 | ||
2713 | if (should_commit) { | 2731 | if (bond_ab_arp_inspect(bond)) { |
2732 | rcu_read_unlock(); | ||
2733 | |||
2714 | /* Race avoidance with bond_close flush of workqueue */ | 2734 | /* Race avoidance with bond_close flush of workqueue */ |
2715 | if (!rtnl_trylock()) { | 2735 | if (!rtnl_trylock()) { |
2716 | delta_in_ticks = 1; | 2736 | delta_in_ticks = 1; |
@@ -2719,23 +2739,28 @@ static void bond_activebackup_arp_mon(struct work_struct *work) | |||
2719 | } | 2739 | } |
2720 | 2740 | ||
2721 | bond_ab_arp_commit(bond); | 2741 | bond_ab_arp_commit(bond); |
2742 | |||
2722 | rtnl_unlock(); | 2743 | rtnl_unlock(); |
2744 | rcu_read_lock(); | ||
2723 | } | 2745 | } |
2724 | 2746 | ||
2725 | if (!bond_ab_arp_probe(bond)) { | 2747 | should_notify_rtnl = bond_ab_arp_probe(bond); |
2726 | /* rtnl locking failed, re-arm */ | 2748 | rcu_read_unlock(); |
2727 | delta_in_ticks = 1; | ||
2728 | should_notify_peers = false; | ||
2729 | } | ||
2730 | 2749 | ||
2731 | re_arm: | 2750 | re_arm: |
2732 | if (bond->params.arp_interval) | 2751 | if (bond->params.arp_interval) |
2733 | queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); | 2752 | queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks); |
2734 | 2753 | ||
2735 | if (should_notify_peers) { | 2754 | if (should_notify_peers || should_notify_rtnl) { |
2736 | if (!rtnl_trylock()) | 2755 | if (!rtnl_trylock()) |
2737 | return; | 2756 | return; |
2738 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); | 2757 | |
2758 | if (should_notify_peers) | ||
2759 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, | ||
2760 | bond->dev); | ||
2761 | if (should_notify_rtnl) | ||
2762 | bond_slave_state_notify(bond); | ||
2763 | |||
2739 | rtnl_unlock(); | 2764 | rtnl_unlock(); |
2740 | } | 2765 | } |
2741 | } | 2766 | } |
@@ -2857,9 +2882,12 @@ static int bond_slave_netdev_event(unsigned long event, | |||
2857 | pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", | 2882 | pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", |
2858 | bond->dev->name, bond->primary_slave ? slave_dev->name : | 2883 | bond->dev->name, bond->primary_slave ? slave_dev->name : |
2859 | "none"); | 2884 | "none"); |
2885 | |||
2886 | block_netpoll_tx(); | ||
2860 | write_lock_bh(&bond->curr_slave_lock); | 2887 | write_lock_bh(&bond->curr_slave_lock); |
2861 | bond_select_active_slave(bond); | 2888 | bond_select_active_slave(bond); |
2862 | write_unlock_bh(&bond->curr_slave_lock); | 2889 | write_unlock_bh(&bond->curr_slave_lock); |
2890 | unblock_netpoll_tx(); | ||
2863 | break; | 2891 | break; |
2864 | case NETDEV_FEAT_CHANGE: | 2892 | case NETDEV_FEAT_CHANGE: |
2865 | bond_compute_features(bond); | 2893 | bond_compute_features(bond); |
@@ -3032,9 +3060,11 @@ static int bond_open(struct net_device *bond_dev) | |||
3032 | bond_for_each_slave(bond, slave, iter) { | 3060 | bond_for_each_slave(bond, slave, iter) { |
3033 | if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) | 3061 | if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) |
3034 | && (slave != bond->curr_active_slave)) { | 3062 | && (slave != bond->curr_active_slave)) { |
3035 | bond_set_slave_inactive_flags(slave); | 3063 | bond_set_slave_inactive_flags(slave, |
3064 | BOND_SLAVE_NOTIFY_NOW); | ||
3036 | } else { | 3065 | } else { |
3037 | bond_set_slave_active_flags(slave); | 3066 | bond_set_slave_active_flags(slave, |
3067 | BOND_SLAVE_NOTIFY_NOW); | ||
3038 | } | 3068 | } |
3039 | } | 3069 | } |
3040 | read_unlock(&bond->curr_slave_lock); | 3070 | read_unlock(&bond->curr_slave_lock); |
@@ -3431,7 +3461,8 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr) | |||
3431 | /* If fail_over_mac is enabled, do nothing and return success. | 3461 | /* If fail_over_mac is enabled, do nothing and return success. |
3432 | * Returning an error causes ifenslave to fail. | 3462 | * Returning an error causes ifenslave to fail. |
3433 | */ | 3463 | */ |
3434 | if (bond->params.fail_over_mac) | 3464 | if (bond->params.fail_over_mac && |
3465 | bond->params.mode == BOND_MODE_ACTIVEBACKUP) | ||
3435 | return 0; | 3466 | return 0; |
3436 | 3467 | ||
3437 | if (!is_valid_ether_addr(sa->sa_data)) | 3468 | if (!is_valid_ether_addr(sa->sa_data)) |
@@ -3692,7 +3723,7 @@ static inline int bond_slave_override(struct bonding *bond, | |||
3692 | 3723 | ||
3693 | 3724 | ||
3694 | static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb, | 3725 | static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb, |
3695 | void *accel_priv) | 3726 | void *accel_priv, select_queue_fallback_t fallback) |
3696 | { | 3727 | { |
3697 | /* | 3728 | /* |
3698 | * This helper function exists to help dev_pick_tx get the correct | 3729 | * This helper function exists to help dev_pick_tx get the correct |
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index 11cb943222d5..298c26509095 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/if.h> | 15 | #include <linux/if.h> |
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include <linux/rwlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
19 | #include <linux/ctype.h> | 19 | #include <linux/ctype.h> |
20 | #include <linux/inet.h> | 20 | #include <linux/inet.h> |
@@ -121,6 +121,7 @@ static struct bond_opt_value bond_resend_igmp_tbl[] = { | |||
121 | static struct bond_opt_value bond_lp_interval_tbl[] = { | 121 | static struct bond_opt_value bond_lp_interval_tbl[] = { |
122 | { "minval", 1, BOND_VALFLAG_MIN | BOND_VALFLAG_DEFAULT}, | 122 | { "minval", 1, BOND_VALFLAG_MIN | BOND_VALFLAG_DEFAULT}, |
123 | { "maxval", INT_MAX, BOND_VALFLAG_MAX}, | 123 | { "maxval", INT_MAX, BOND_VALFLAG_MAX}, |
124 | { NULL, -1, 0}, | ||
124 | }; | 125 | }; |
125 | 126 | ||
126 | static struct bond_option bond_opts[] = { | 127 | static struct bond_option bond_opts[] = { |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 86ccfb9f71cc..2b0fdec695f7 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -195,7 +195,8 @@ struct slave { | |||
195 | s8 new_link; | 195 | s8 new_link; |
196 | u8 backup:1, /* indicates backup slave. Value corresponds with | 196 | u8 backup:1, /* indicates backup slave. Value corresponds with |
197 | BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ | 197 | BOND_STATE_ACTIVE and BOND_STATE_BACKUP */ |
198 | inactive:1; /* indicates inactive slave */ | 198 | inactive:1, /* indicates inactive slave */ |
199 | should_notify:1; /* indicateds whether the state changed */ | ||
199 | u8 duplex; | 200 | u8 duplex; |
200 | u32 original_mtu; | 201 | u32 original_mtu; |
201 | u32 link_failure_count; | 202 | u32 link_failure_count; |
@@ -303,6 +304,24 @@ static inline void bond_set_backup_slave(struct slave *slave) | |||
303 | } | 304 | } |
304 | } | 305 | } |
305 | 306 | ||
307 | static inline void bond_set_slave_state(struct slave *slave, | ||
308 | int slave_state, bool notify) | ||
309 | { | ||
310 | if (slave->backup == slave_state) | ||
311 | return; | ||
312 | |||
313 | slave->backup = slave_state; | ||
314 | if (notify) { | ||
315 | rtmsg_ifinfo(RTM_NEWLINK, slave->dev, 0, GFP_KERNEL); | ||
316 | slave->should_notify = 0; | ||
317 | } else { | ||
318 | if (slave->should_notify) | ||
319 | slave->should_notify = 0; | ||
320 | else | ||
321 | slave->should_notify = 1; | ||
322 | } | ||
323 | } | ||
324 | |||
306 | static inline void bond_slave_state_change(struct bonding *bond) | 325 | static inline void bond_slave_state_change(struct bonding *bond) |
307 | { | 326 | { |
308 | struct list_head *iter; | 327 | struct list_head *iter; |
@@ -316,6 +335,19 @@ static inline void bond_slave_state_change(struct bonding *bond) | |||
316 | } | 335 | } |
317 | } | 336 | } |
318 | 337 | ||
338 | static inline void bond_slave_state_notify(struct bonding *bond) | ||
339 | { | ||
340 | struct list_head *iter; | ||
341 | struct slave *tmp; | ||
342 | |||
343 | bond_for_each_slave(bond, tmp, iter) { | ||
344 | if (tmp->should_notify) { | ||
345 | rtmsg_ifinfo(RTM_NEWLINK, tmp->dev, 0, GFP_KERNEL); | ||
346 | tmp->should_notify = 0; | ||
347 | } | ||
348 | } | ||
349 | } | ||
350 | |||
319 | static inline int bond_slave_state(struct slave *slave) | 351 | static inline int bond_slave_state(struct slave *slave) |
320 | { | 352 | { |
321 | return slave->backup; | 353 | return slave->backup; |
@@ -343,6 +375,9 @@ static inline bool bond_is_active_slave(struct slave *slave) | |||
343 | #define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \ | 375 | #define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \ |
344 | BOND_ARP_VALIDATE_BACKUP) | 376 | BOND_ARP_VALIDATE_BACKUP) |
345 | 377 | ||
378 | #define BOND_SLAVE_NOTIFY_NOW true | ||
379 | #define BOND_SLAVE_NOTIFY_LATER false | ||
380 | |||
346 | static inline int slave_do_arp_validate(struct bonding *bond, | 381 | static inline int slave_do_arp_validate(struct bonding *bond, |
347 | struct slave *slave) | 382 | struct slave *slave) |
348 | { | 383 | { |
@@ -394,17 +429,19 @@ static inline void bond_netpoll_send_skb(const struct slave *slave, | |||
394 | } | 429 | } |
395 | #endif | 430 | #endif |
396 | 431 | ||
397 | static inline void bond_set_slave_inactive_flags(struct slave *slave) | 432 | static inline void bond_set_slave_inactive_flags(struct slave *slave, |
433 | bool notify) | ||
398 | { | 434 | { |
399 | if (!bond_is_lb(slave->bond)) | 435 | if (!bond_is_lb(slave->bond)) |
400 | bond_set_backup_slave(slave); | 436 | bond_set_slave_state(slave, BOND_STATE_BACKUP, notify); |
401 | if (!slave->bond->params.all_slaves_active) | 437 | if (!slave->bond->params.all_slaves_active) |
402 | slave->inactive = 1; | 438 | slave->inactive = 1; |
403 | } | 439 | } |
404 | 440 | ||
405 | static inline void bond_set_slave_active_flags(struct slave *slave) | 441 | static inline void bond_set_slave_active_flags(struct slave *slave, |
442 | bool notify) | ||
406 | { | 443 | { |
407 | bond_set_active_slave(slave); | 444 | bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify); |
408 | slave->inactive = 0; | 445 | slave->inactive = 0; |
409 | } | 446 | } |
410 | 447 | ||