|
@@ -706,45 +706,6 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Add a Multicast address to slaves
|
|
|
- * according to mode
|
|
|
- */
|
|
|
-static void bond_mc_add(struct bonding *bond, void *addr)
|
|
|
-{
|
|
|
- if (USES_PRIMARY(bond->params.mode)) {
|
|
|
- /* write lock already acquired */
|
|
|
- if (bond->curr_active_slave)
|
|
|
- dev_mc_add(bond->curr_active_slave->dev, addr);
|
|
|
- } else {
|
|
|
- struct slave *slave;
|
|
|
- int i;
|
|
|
-
|
|
|
- bond_for_each_slave(bond, slave, i)
|
|
|
- dev_mc_add(slave->dev, addr);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Remove a multicast address from slave
|
|
|
- * according to mode
|
|
|
- */
|
|
|
-static void bond_mc_del(struct bonding *bond, void *addr)
|
|
|
-{
|
|
|
- if (USES_PRIMARY(bond->params.mode)) {
|
|
|
- /* write lock already acquired */
|
|
|
- if (bond->curr_active_slave)
|
|
|
- dev_mc_del(bond->curr_active_slave->dev, addr);
|
|
|
- } else {
|
|
|
- struct slave *slave;
|
|
|
- int i;
|
|
|
- bond_for_each_slave(bond, slave, i) {
|
|
|
- dev_mc_del(slave->dev, addr);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
static void __bond_resend_igmp_join_requests(struct net_device *dev)
|
|
|
{
|
|
|
struct in_device *in_dev;
|
|
@@ -803,17 +764,15 @@ static void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
|
|
|
bond_resend_igmp_join_requests(bond);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * flush all members of flush->mc_list from device dev->mc_list
|
|
|
+/* Flush bond's hardware addresses from slave
|
|
|
*/
|
|
|
-static void bond_mc_list_flush(struct net_device *bond_dev,
|
|
|
+static void bond_hw_addr_flush(struct net_device *bond_dev,
|
|
|
struct net_device *slave_dev)
|
|
|
{
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
|
- struct netdev_hw_addr *ha;
|
|
|
|
|
|
- netdev_for_each_mc_addr(ha, bond_dev)
|
|
|
- dev_mc_del(slave_dev, ha->addr);
|
|
|
+ dev_uc_unsync(slave_dev, bond_dev);
|
|
|
+ dev_mc_unsync(slave_dev, bond_dev);
|
|
|
|
|
|
if (bond->params.mode == BOND_MODE_8023AD) {
|
|
|
/* del lacpdu mc addr from mc list */
|
|
@@ -825,22 +784,14 @@ static void bond_mc_list_flush(struct net_device *bond_dev,
|
|
|
|
|
|
/*--------------------------- Active slave change ---------------------------*/
|
|
|
|
|
|
-/*
|
|
|
- * Update the mc list and multicast-related flags for the new and
|
|
|
- * old active slaves (if any) according to the multicast mode, and
|
|
|
- * promiscuous flags unconditionally.
|
|
|
+/* Update the hardware address list and promisc/allmulti for the new and
|
|
|
+ * old active slaves (if any). Modes that are !USES_PRIMARY keep all
|
|
|
+ * slaves up date at all times; only the USES_PRIMARY modes need to call
|
|
|
+ * this function to swap these settings during a failover.
|
|
|
*/
|
|
|
-static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
|
|
|
- struct slave *old_active)
|
|
|
+static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
|
|
|
+ struct slave *old_active)
|
|
|
{
|
|
|
- struct netdev_hw_addr *ha;
|
|
|
-
|
|
|
- if (!USES_PRIMARY(bond->params.mode))
|
|
|
- /* nothing to do - mc list is already up-to-date on
|
|
|
- * all slaves
|
|
|
- */
|
|
|
- return;
|
|
|
-
|
|
|
if (old_active) {
|
|
|
if (bond->dev->flags & IFF_PROMISC)
|
|
|
dev_set_promiscuity(old_active->dev, -1);
|
|
@@ -848,10 +799,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
|
|
|
if (bond->dev->flags & IFF_ALLMULTI)
|
|
|
dev_set_allmulti(old_active->dev, -1);
|
|
|
|
|
|
- netif_addr_lock_bh(bond->dev);
|
|
|
- netdev_for_each_mc_addr(ha, bond->dev)
|
|
|
- dev_mc_del(old_active->dev, ha->addr);
|
|
|
- netif_addr_unlock_bh(bond->dev);
|
|
|
+ bond_hw_addr_flush(bond->dev, old_active->dev);
|
|
|
}
|
|
|
|
|
|
if (new_active) {
|
|
@@ -863,8 +811,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
|
|
|
dev_set_allmulti(new_active->dev, 1);
|
|
|
|
|
|
netif_addr_lock_bh(bond->dev);
|
|
|
- netdev_for_each_mc_addr(ha, bond->dev)
|
|
|
- dev_mc_add(new_active->dev, ha->addr);
|
|
|
+ dev_uc_sync(new_active->dev, bond->dev);
|
|
|
+ dev_mc_sync(new_active->dev, bond->dev);
|
|
|
netif_addr_unlock_bh(bond->dev);
|
|
|
}
|
|
|
}
|
|
@@ -1083,7 +1031,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
|
|
|
}
|
|
|
|
|
|
if (USES_PRIMARY(bond->params.mode))
|
|
|
- bond_mc_swap(bond, new_active, old_active);
|
|
|
+ bond_hw_addr_swap(bond, new_active, old_active);
|
|
|
|
|
|
if (bond_is_lb(bond)) {
|
|
|
bond_alb_handle_active_change(bond, new_active);
|
|
@@ -1526,7 +1474,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
|
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
|
|
|
struct slave *new_slave = NULL;
|
|
|
- struct netdev_hw_addr *ha;
|
|
|
struct sockaddr addr;
|
|
|
int link_reporting;
|
|
|
int res = 0;
|
|
@@ -1706,10 +1653,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
goto err_close;
|
|
|
}
|
|
|
|
|
|
- /* If the mode USES_PRIMARY, then the new slave gets the
|
|
|
- * master's promisc (and mc) settings only if it becomes the
|
|
|
- * curr_active_slave, and that is taken care of later when calling
|
|
|
- * bond_change_active()
|
|
|
+ /* If the mode USES_PRIMARY, then the following is handled by
|
|
|
+ * bond_change_active_slave().
|
|
|
*/
|
|
|
if (!USES_PRIMARY(bond->params.mode)) {
|
|
|
/* set promiscuity level to new slave */
|
|
@@ -1727,9 +1672,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
}
|
|
|
|
|
|
netif_addr_lock_bh(bond_dev);
|
|
|
- /* upload master's mc_list to new slave */
|
|
|
- netdev_for_each_mc_addr(ha, bond_dev)
|
|
|
- dev_mc_add(slave_dev, ha->addr);
|
|
|
+
|
|
|
+ dev_mc_sync_multiple(slave_dev, bond_dev);
|
|
|
+ dev_uc_sync_multiple(slave_dev, bond_dev);
|
|
|
+
|
|
|
netif_addr_unlock_bh(bond_dev);
|
|
|
}
|
|
|
|
|
@@ -1908,11 +1854,9 @@ err_dest_symlinks:
|
|
|
bond_destroy_slave_symlinks(bond_dev, slave_dev);
|
|
|
|
|
|
err_detach:
|
|
|
- if (!USES_PRIMARY(bond->params.mode)) {
|
|
|
- netif_addr_lock_bh(bond_dev);
|
|
|
- bond_mc_list_flush(bond_dev, slave_dev);
|
|
|
- netif_addr_unlock_bh(bond_dev);
|
|
|
- }
|
|
|
+ if (!USES_PRIMARY(bond->params.mode))
|
|
|
+ bond_hw_addr_flush(bond_dev, slave_dev);
|
|
|
+
|
|
|
bond_del_vlans_from_slave(bond, slave_dev);
|
|
|
write_lock_bh(&bond->lock);
|
|
|
bond_detach_slave(bond, new_slave);
|
|
@@ -2107,9 +2051,8 @@ static int __bond_release_one(struct net_device *bond_dev,
|
|
|
|
|
|
bond_del_vlans_from_slave(bond, slave_dev);
|
|
|
|
|
|
- /* If the mode USES_PRIMARY, then we should only remove its
|
|
|
- * promisc and mc settings if it was the curr_active_slave, but that was
|
|
|
- * already taken care of above when we detached the slave
|
|
|
+ /* If the mode USES_PRIMARY, then this cases was handled above by
|
|
|
+ * bond_change_active_slave(..., NULL)
|
|
|
*/
|
|
|
if (!USES_PRIMARY(bond->params.mode)) {
|
|
|
/* unset promiscuity level from slave */
|
|
@@ -2120,10 +2063,7 @@ static int __bond_release_one(struct net_device *bond_dev,
|
|
|
if (bond_dev->flags & IFF_ALLMULTI)
|
|
|
dev_set_allmulti(slave_dev, -1);
|
|
|
|
|
|
- /* flush master's mc_list from slave */
|
|
|
- netif_addr_lock_bh(bond_dev);
|
|
|
- bond_mc_list_flush(bond_dev, slave_dev);
|
|
|
- netif_addr_unlock_bh(bond_dev);
|
|
|
+ bond_hw_addr_flush(bond_dev, slave_dev);
|
|
|
}
|
|
|
|
|
|
bond_upper_dev_unlink(bond_dev, slave_dev);
|
|
@@ -3660,19 +3600,6 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
-static bool bond_addr_in_mc_list(unsigned char *addr,
|
|
|
- struct netdev_hw_addr_list *list,
|
|
|
- int addrlen)
|
|
|
-{
|
|
|
- struct netdev_hw_addr *ha;
|
|
|
-
|
|
|
- netdev_hw_addr_list_for_each(ha, list)
|
|
|
- if (!memcmp(ha->addr, addr, addrlen))
|
|
|
- return true;
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
static void bond_change_rx_flags(struct net_device *bond_dev, int change)
|
|
|
{
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
@@ -3686,35 +3613,29 @@ static void bond_change_rx_flags(struct net_device *bond_dev, int change)
|
|
|
bond_dev->flags & IFF_ALLMULTI ? 1 : -1);
|
|
|
}
|
|
|
|
|
|
-static void bond_set_multicast_list(struct net_device *bond_dev)
|
|
|
+static void bond_set_rx_mode(struct net_device *bond_dev)
|
|
|
{
|
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
|
- struct netdev_hw_addr *ha;
|
|
|
- bool found;
|
|
|
+ struct slave *slave;
|
|
|
+ int i;
|
|
|
|
|
|
read_lock(&bond->lock);
|
|
|
|
|
|
- /* looking for addresses to add to slaves' mc list */
|
|
|
- netdev_for_each_mc_addr(ha, bond_dev) {
|
|
|
- found = bond_addr_in_mc_list(ha->addr, &bond->mc_list,
|
|
|
- bond_dev->addr_len);
|
|
|
- if (!found)
|
|
|
- bond_mc_add(bond, ha->addr);
|
|
|
- }
|
|
|
-
|
|
|
- /* looking for addresses to delete from slaves' list */
|
|
|
- netdev_hw_addr_list_for_each(ha, &bond->mc_list) {
|
|
|
- found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc,
|
|
|
- bond_dev->addr_len);
|
|
|
- if (!found)
|
|
|
- bond_mc_del(bond, ha->addr);
|
|
|
+ if (USES_PRIMARY(bond->params.mode)) {
|
|
|
+ read_lock(&bond->curr_slave_lock);
|
|
|
+ slave = bond->curr_active_slave;
|
|
|
+ if (slave) {
|
|
|
+ dev_uc_sync(slave->dev, bond_dev);
|
|
|
+ dev_mc_sync(slave->dev, bond_dev);
|
|
|
+ }
|
|
|
+ read_unlock(&bond->curr_slave_lock);
|
|
|
+ } else {
|
|
|
+ bond_for_each_slave(bond, slave, i) {
|
|
|
+ dev_uc_sync_multiple(slave->dev, bond_dev);
|
|
|
+ dev_mc_sync_multiple(slave->dev, bond_dev);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- /* save master's multicast list */
|
|
|
- __hw_addr_flush(&bond->mc_list);
|
|
|
- __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc,
|
|
|
- bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST);
|
|
|
-
|
|
|
read_unlock(&bond->lock);
|
|
|
}
|
|
|
|
|
@@ -4321,7 +4242,7 @@ static const struct net_device_ops bond_netdev_ops = {
|
|
|
.ndo_get_stats64 = bond_get_stats,
|
|
|
.ndo_do_ioctl = bond_do_ioctl,
|
|
|
.ndo_change_rx_flags = bond_change_rx_flags,
|
|
|
- .ndo_set_rx_mode = bond_set_multicast_list,
|
|
|
+ .ndo_set_rx_mode = bond_set_rx_mode,
|
|
|
.ndo_change_mtu = bond_change_mtu,
|
|
|
.ndo_set_mac_address = bond_set_mac_address,
|
|
|
.ndo_neigh_setup = bond_neigh_setup,
|
|
@@ -4426,8 +4347,6 @@ static void bond_uninit(struct net_device *bond_dev)
|
|
|
|
|
|
bond_debug_unregister(bond);
|
|
|
|
|
|
- __hw_addr_flush(&bond->mc_list);
|
|
|
-
|
|
|
list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) {
|
|
|
list_del(&vlan->vlan_list);
|
|
|
kfree(vlan);
|
|
@@ -4838,7 +4757,6 @@ static int bond_init(struct net_device *bond_dev)
|
|
|
bond->dev_addr_from_first = true;
|
|
|
}
|
|
|
|
|
|
- __hw_addr_init(&bond->mc_list);
|
|
|
return 0;
|
|
|
}
|
|
|
|