diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2013-05-31 07:57:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-07 18:05:51 -0400 |
commit | 303d1cbf610eef31e039efc2e8da30cf94cf5ebc (patch) | |
tree | 5b7d13ea626dd0eda7122efa93afb7a4013a257a | |
parent | ca162a82f56921442f5db72a3a472010e5a62c4b (diff) |
bonding: Convert hw addr handling to sync/unsync, support ucast addresses
This patch converts bonding to use the dev_uc/mc_sync and
dev_uc/mc_sync_multiple functions for updating the hardware addresses
of bonding slaves.
The existing functions to add or remove addresses are removed,
and their functionality is replaced with calls to dev_mc_sync or
dev_mc_sync_multiple, depending upon the bonding mode.
Calls to dev_uc_sync and dev_uc_sync_multiple are also added,
so that unicast addresses added to a bond will be properly synced with
its slaves.
Various functions are renamed to better reflect the new
situation, and relevant comments are updated.
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Cc: Vlad Yasevich <vyasevic@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/bonding/bond_main.c | 168 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 1 |
2 files changed, 43 insertions, 126 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f4489d65bf33..4953f66a29a4 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -706,45 +706,6 @@ static int bond_set_allmulti(struct bonding *bond, int inc) | |||
706 | return err; | 706 | return err; |
707 | } | 707 | } |
708 | 708 | ||
709 | /* | ||
710 | * Add a Multicast address to slaves | ||
711 | * according to mode | ||
712 | */ | ||
713 | static void bond_mc_add(struct bonding *bond, void *addr) | ||
714 | { | ||
715 | if (USES_PRIMARY(bond->params.mode)) { | ||
716 | /* write lock already acquired */ | ||
717 | if (bond->curr_active_slave) | ||
718 | dev_mc_add(bond->curr_active_slave->dev, addr); | ||
719 | } else { | ||
720 | struct slave *slave; | ||
721 | int i; | ||
722 | |||
723 | bond_for_each_slave(bond, slave, i) | ||
724 | dev_mc_add(slave->dev, addr); | ||
725 | } | ||
726 | } | ||
727 | |||
728 | /* | ||
729 | * Remove a multicast address from slave | ||
730 | * according to mode | ||
731 | */ | ||
732 | static void bond_mc_del(struct bonding *bond, void *addr) | ||
733 | { | ||
734 | if (USES_PRIMARY(bond->params.mode)) { | ||
735 | /* write lock already acquired */ | ||
736 | if (bond->curr_active_slave) | ||
737 | dev_mc_del(bond->curr_active_slave->dev, addr); | ||
738 | } else { | ||
739 | struct slave *slave; | ||
740 | int i; | ||
741 | bond_for_each_slave(bond, slave, i) { | ||
742 | dev_mc_del(slave->dev, addr); | ||
743 | } | ||
744 | } | ||
745 | } | ||
746 | |||
747 | |||
748 | static void __bond_resend_igmp_join_requests(struct net_device *dev) | 709 | static void __bond_resend_igmp_join_requests(struct net_device *dev) |
749 | { | 710 | { |
750 | struct in_device *in_dev; | 711 | struct in_device *in_dev; |
@@ -803,17 +764,15 @@ static void bond_resend_igmp_join_requests_delayed(struct work_struct *work) | |||
803 | bond_resend_igmp_join_requests(bond); | 764 | bond_resend_igmp_join_requests(bond); |
804 | } | 765 | } |
805 | 766 | ||
806 | /* | 767 | /* Flush bond's hardware addresses from slave |
807 | * flush all members of flush->mc_list from device dev->mc_list | ||
808 | */ | 768 | */ |
809 | static void bond_mc_list_flush(struct net_device *bond_dev, | 769 | static void bond_hw_addr_flush(struct net_device *bond_dev, |
810 | struct net_device *slave_dev) | 770 | struct net_device *slave_dev) |
811 | { | 771 | { |
812 | struct bonding *bond = netdev_priv(bond_dev); | 772 | struct bonding *bond = netdev_priv(bond_dev); |
813 | struct netdev_hw_addr *ha; | ||
814 | 773 | ||
815 | netdev_for_each_mc_addr(ha, bond_dev) | 774 | dev_uc_unsync(slave_dev, bond_dev); |
816 | dev_mc_del(slave_dev, ha->addr); | 775 | dev_mc_unsync(slave_dev, bond_dev); |
817 | 776 | ||
818 | if (bond->params.mode == BOND_MODE_8023AD) { | 777 | if (bond->params.mode == BOND_MODE_8023AD) { |
819 | /* del lacpdu mc addr from mc list */ | 778 | /* del lacpdu mc addr from mc list */ |
@@ -825,22 +784,14 @@ static void bond_mc_list_flush(struct net_device *bond_dev, | |||
825 | 784 | ||
826 | /*--------------------------- Active slave change ---------------------------*/ | 785 | /*--------------------------- Active slave change ---------------------------*/ |
827 | 786 | ||
828 | /* | 787 | /* Update the hardware address list and promisc/allmulti for the new and |
829 | * Update the mc list and multicast-related flags for the new and | 788 | * old active slaves (if any). Modes that are !USES_PRIMARY keep all |
830 | * old active slaves (if any) according to the multicast mode, and | 789 | * slaves up date at all times; only the USES_PRIMARY modes need to call |
831 | * promiscuous flags unconditionally. | 790 | * this function to swap these settings during a failover. |
832 | */ | 791 | */ |
833 | static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | 792 | static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, |
834 | struct slave *old_active) | 793 | struct slave *old_active) |
835 | { | 794 | { |
836 | struct netdev_hw_addr *ha; | ||
837 | |||
838 | if (!USES_PRIMARY(bond->params.mode)) | ||
839 | /* nothing to do - mc list is already up-to-date on | ||
840 | * all slaves | ||
841 | */ | ||
842 | return; | ||
843 | |||
844 | if (old_active) { | 795 | if (old_active) { |
845 | if (bond->dev->flags & IFF_PROMISC) | 796 | if (bond->dev->flags & IFF_PROMISC) |
846 | dev_set_promiscuity(old_active->dev, -1); | 797 | dev_set_promiscuity(old_active->dev, -1); |
@@ -848,10 +799,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | |||
848 | if (bond->dev->flags & IFF_ALLMULTI) | 799 | if (bond->dev->flags & IFF_ALLMULTI) |
849 | dev_set_allmulti(old_active->dev, -1); | 800 | dev_set_allmulti(old_active->dev, -1); |
850 | 801 | ||
851 | netif_addr_lock_bh(bond->dev); | 802 | bond_hw_addr_flush(bond->dev, old_active->dev); |
852 | netdev_for_each_mc_addr(ha, bond->dev) | ||
853 | dev_mc_del(old_active->dev, ha->addr); | ||
854 | netif_addr_unlock_bh(bond->dev); | ||
855 | } | 803 | } |
856 | 804 | ||
857 | if (new_active) { | 805 | if (new_active) { |
@@ -863,8 +811,8 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, | |||
863 | dev_set_allmulti(new_active->dev, 1); | 811 | dev_set_allmulti(new_active->dev, 1); |
864 | 812 | ||
865 | netif_addr_lock_bh(bond->dev); | 813 | netif_addr_lock_bh(bond->dev); |
866 | netdev_for_each_mc_addr(ha, bond->dev) | 814 | dev_uc_sync(new_active->dev, bond->dev); |
867 | dev_mc_add(new_active->dev, ha->addr); | 815 | dev_mc_sync(new_active->dev, bond->dev); |
868 | netif_addr_unlock_bh(bond->dev); | 816 | netif_addr_unlock_bh(bond->dev); |
869 | } | 817 | } |
870 | } | 818 | } |
@@ -1083,7 +1031,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
1083 | } | 1031 | } |
1084 | 1032 | ||
1085 | if (USES_PRIMARY(bond->params.mode)) | 1033 | if (USES_PRIMARY(bond->params.mode)) |
1086 | bond_mc_swap(bond, new_active, old_active); | 1034 | bond_hw_addr_swap(bond, new_active, old_active); |
1087 | 1035 | ||
1088 | if (bond_is_lb(bond)) { | 1036 | if (bond_is_lb(bond)) { |
1089 | bond_alb_handle_active_change(bond, new_active); | 1037 | 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) | |||
1526 | struct bonding *bond = netdev_priv(bond_dev); | 1474 | struct bonding *bond = netdev_priv(bond_dev); |
1527 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; | 1475 | const struct net_device_ops *slave_ops = slave_dev->netdev_ops; |
1528 | struct slave *new_slave = NULL; | 1476 | struct slave *new_slave = NULL; |
1529 | struct netdev_hw_addr *ha; | ||
1530 | struct sockaddr addr; | 1477 | struct sockaddr addr; |
1531 | int link_reporting; | 1478 | int link_reporting; |
1532 | int res = 0; | 1479 | int res = 0; |
@@ -1706,10 +1653,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1706 | goto err_close; | 1653 | goto err_close; |
1707 | } | 1654 | } |
1708 | 1655 | ||
1709 | /* If the mode USES_PRIMARY, then the new slave gets the | 1656 | /* If the mode USES_PRIMARY, then the following is handled by |
1710 | * master's promisc (and mc) settings only if it becomes the | 1657 | * bond_change_active_slave(). |
1711 | * curr_active_slave, and that is taken care of later when calling | ||
1712 | * bond_change_active() | ||
1713 | */ | 1658 | */ |
1714 | if (!USES_PRIMARY(bond->params.mode)) { | 1659 | if (!USES_PRIMARY(bond->params.mode)) { |
1715 | /* set promiscuity level to new slave */ | 1660 | /* set promiscuity level to new slave */ |
@@ -1727,9 +1672,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1727 | } | 1672 | } |
1728 | 1673 | ||
1729 | netif_addr_lock_bh(bond_dev); | 1674 | netif_addr_lock_bh(bond_dev); |
1730 | /* upload master's mc_list to new slave */ | 1675 | |
1731 | netdev_for_each_mc_addr(ha, bond_dev) | 1676 | dev_mc_sync_multiple(slave_dev, bond_dev); |
1732 | dev_mc_add(slave_dev, ha->addr); | 1677 | dev_uc_sync_multiple(slave_dev, bond_dev); |
1678 | |||
1733 | netif_addr_unlock_bh(bond_dev); | 1679 | netif_addr_unlock_bh(bond_dev); |
1734 | } | 1680 | } |
1735 | 1681 | ||
@@ -1908,11 +1854,9 @@ err_dest_symlinks: | |||
1908 | bond_destroy_slave_symlinks(bond_dev, slave_dev); | 1854 | bond_destroy_slave_symlinks(bond_dev, slave_dev); |
1909 | 1855 | ||
1910 | err_detach: | 1856 | err_detach: |
1911 | if (!USES_PRIMARY(bond->params.mode)) { | 1857 | if (!USES_PRIMARY(bond->params.mode)) |
1912 | netif_addr_lock_bh(bond_dev); | 1858 | bond_hw_addr_flush(bond_dev, slave_dev); |
1913 | bond_mc_list_flush(bond_dev, slave_dev); | 1859 | |
1914 | netif_addr_unlock_bh(bond_dev); | ||
1915 | } | ||
1916 | bond_del_vlans_from_slave(bond, slave_dev); | 1860 | bond_del_vlans_from_slave(bond, slave_dev); |
1917 | write_lock_bh(&bond->lock); | 1861 | write_lock_bh(&bond->lock); |
1918 | bond_detach_slave(bond, new_slave); | 1862 | bond_detach_slave(bond, new_slave); |
@@ -2107,9 +2051,8 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
2107 | 2051 | ||
2108 | bond_del_vlans_from_slave(bond, slave_dev); | 2052 | bond_del_vlans_from_slave(bond, slave_dev); |
2109 | 2053 | ||
2110 | /* If the mode USES_PRIMARY, then we should only remove its | 2054 | /* If the mode USES_PRIMARY, then this cases was handled above by |
2111 | * promisc and mc settings if it was the curr_active_slave, but that was | 2055 | * bond_change_active_slave(..., NULL) |
2112 | * already taken care of above when we detached the slave | ||
2113 | */ | 2056 | */ |
2114 | if (!USES_PRIMARY(bond->params.mode)) { | 2057 | if (!USES_PRIMARY(bond->params.mode)) { |
2115 | /* unset promiscuity level from slave */ | 2058 | /* unset promiscuity level from slave */ |
@@ -2120,10 +2063,7 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
2120 | if (bond_dev->flags & IFF_ALLMULTI) | 2063 | if (bond_dev->flags & IFF_ALLMULTI) |
2121 | dev_set_allmulti(slave_dev, -1); | 2064 | dev_set_allmulti(slave_dev, -1); |
2122 | 2065 | ||
2123 | /* flush master's mc_list from slave */ | 2066 | bond_hw_addr_flush(bond_dev, slave_dev); |
2124 | netif_addr_lock_bh(bond_dev); | ||
2125 | bond_mc_list_flush(bond_dev, slave_dev); | ||
2126 | netif_addr_unlock_bh(bond_dev); | ||
2127 | } | 2067 | } |
2128 | 2068 | ||
2129 | bond_upper_dev_unlink(bond_dev, slave_dev); | 2069 | 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 | |||
3660 | return res; | 3600 | return res; |
3661 | } | 3601 | } |
3662 | 3602 | ||
3663 | static bool bond_addr_in_mc_list(unsigned char *addr, | ||
3664 | struct netdev_hw_addr_list *list, | ||
3665 | int addrlen) | ||
3666 | { | ||
3667 | struct netdev_hw_addr *ha; | ||
3668 | |||
3669 | netdev_hw_addr_list_for_each(ha, list) | ||
3670 | if (!memcmp(ha->addr, addr, addrlen)) | ||
3671 | return true; | ||
3672 | |||
3673 | return false; | ||
3674 | } | ||
3675 | |||
3676 | static void bond_change_rx_flags(struct net_device *bond_dev, int change) | 3603 | static void bond_change_rx_flags(struct net_device *bond_dev, int change) |
3677 | { | 3604 | { |
3678 | struct bonding *bond = netdev_priv(bond_dev); | 3605 | struct bonding *bond = netdev_priv(bond_dev); |
@@ -3686,35 +3613,29 @@ static void bond_change_rx_flags(struct net_device *bond_dev, int change) | |||
3686 | bond_dev->flags & IFF_ALLMULTI ? 1 : -1); | 3613 | bond_dev->flags & IFF_ALLMULTI ? 1 : -1); |
3687 | } | 3614 | } |
3688 | 3615 | ||
3689 | static void bond_set_multicast_list(struct net_device *bond_dev) | 3616 | static void bond_set_rx_mode(struct net_device *bond_dev) |
3690 | { | 3617 | { |
3691 | struct bonding *bond = netdev_priv(bond_dev); | 3618 | struct bonding *bond = netdev_priv(bond_dev); |
3692 | struct netdev_hw_addr *ha; | 3619 | struct slave *slave; |
3693 | bool found; | 3620 | int i; |
3694 | 3621 | ||
3695 | read_lock(&bond->lock); | 3622 | read_lock(&bond->lock); |
3696 | 3623 | ||
3697 | /* looking for addresses to add to slaves' mc list */ | 3624 | if (USES_PRIMARY(bond->params.mode)) { |
3698 | netdev_for_each_mc_addr(ha, bond_dev) { | 3625 | read_lock(&bond->curr_slave_lock); |
3699 | found = bond_addr_in_mc_list(ha->addr, &bond->mc_list, | 3626 | slave = bond->curr_active_slave; |
3700 | bond_dev->addr_len); | 3627 | if (slave) { |
3701 | if (!found) | 3628 | dev_uc_sync(slave->dev, bond_dev); |
3702 | bond_mc_add(bond, ha->addr); | 3629 | dev_mc_sync(slave->dev, bond_dev); |
3703 | } | 3630 | } |
3704 | 3631 | read_unlock(&bond->curr_slave_lock); | |
3705 | /* looking for addresses to delete from slaves' list */ | 3632 | } else { |
3706 | netdev_hw_addr_list_for_each(ha, &bond->mc_list) { | 3633 | bond_for_each_slave(bond, slave, i) { |
3707 | found = bond_addr_in_mc_list(ha->addr, &bond_dev->mc, | 3634 | dev_uc_sync_multiple(slave->dev, bond_dev); |
3708 | bond_dev->addr_len); | 3635 | dev_mc_sync_multiple(slave->dev, bond_dev); |
3709 | if (!found) | 3636 | } |
3710 | bond_mc_del(bond, ha->addr); | ||
3711 | } | 3637 | } |
3712 | 3638 | ||
3713 | /* save master's multicast list */ | ||
3714 | __hw_addr_flush(&bond->mc_list); | ||
3715 | __hw_addr_add_multiple(&bond->mc_list, &bond_dev->mc, | ||
3716 | bond_dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST); | ||
3717 | |||
3718 | read_unlock(&bond->lock); | 3639 | read_unlock(&bond->lock); |
3719 | } | 3640 | } |
3720 | 3641 | ||
@@ -4321,7 +4242,7 @@ static const struct net_device_ops bond_netdev_ops = { | |||
4321 | .ndo_get_stats64 = bond_get_stats, | 4242 | .ndo_get_stats64 = bond_get_stats, |
4322 | .ndo_do_ioctl = bond_do_ioctl, | 4243 | .ndo_do_ioctl = bond_do_ioctl, |
4323 | .ndo_change_rx_flags = bond_change_rx_flags, | 4244 | .ndo_change_rx_flags = bond_change_rx_flags, |
4324 | .ndo_set_rx_mode = bond_set_multicast_list, | 4245 | .ndo_set_rx_mode = bond_set_rx_mode, |
4325 | .ndo_change_mtu = bond_change_mtu, | 4246 | .ndo_change_mtu = bond_change_mtu, |
4326 | .ndo_set_mac_address = bond_set_mac_address, | 4247 | .ndo_set_mac_address = bond_set_mac_address, |
4327 | .ndo_neigh_setup = bond_neigh_setup, | 4248 | .ndo_neigh_setup = bond_neigh_setup, |
@@ -4426,8 +4347,6 @@ static void bond_uninit(struct net_device *bond_dev) | |||
4426 | 4347 | ||
4427 | bond_debug_unregister(bond); | 4348 | bond_debug_unregister(bond); |
4428 | 4349 | ||
4429 | __hw_addr_flush(&bond->mc_list); | ||
4430 | |||
4431 | list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) { | 4350 | list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) { |
4432 | list_del(&vlan->vlan_list); | 4351 | list_del(&vlan->vlan_list); |
4433 | kfree(vlan); | 4352 | kfree(vlan); |
@@ -4838,7 +4757,6 @@ static int bond_init(struct net_device *bond_dev) | |||
4838 | bond->dev_addr_from_first = true; | 4757 | bond->dev_addr_from_first = true; |
4839 | } | 4758 | } |
4840 | 4759 | ||
4841 | __hw_addr_init(&bond->mc_list); | ||
4842 | return 0; | 4760 | return 0; |
4843 | } | 4761 | } |
4844 | 4762 | ||
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 2baec24388b1..b38609b967b7 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -231,7 +231,6 @@ struct bonding { | |||
231 | char proc_file_name[IFNAMSIZ]; | 231 | char proc_file_name[IFNAMSIZ]; |
232 | #endif /* CONFIG_PROC_FS */ | 232 | #endif /* CONFIG_PROC_FS */ |
233 | struct list_head bond_list; | 233 | struct list_head bond_list; |
234 | struct netdev_hw_addr_list mc_list; | ||
235 | int (*xmit_hash_policy)(struct sk_buff *, int); | 234 | int (*xmit_hash_policy)(struct sk_buff *, int); |
236 | u16 rr_tx_counter; | 235 | u16 rr_tx_counter; |
237 | struct ad_bond_info ad_info; | 236 | struct ad_bond_info ad_info; |