aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_main.c60
-rw-r--r--drivers/net/bonding/bonding.h1
2 files changed, 50 insertions, 11 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index fb70c3e12927..ad6386671f28 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -865,18 +865,13 @@ static void bond_mc_del(struct bonding *bond, void *addr)
865} 865}
866 866
867 867
868/* 868static void __bond_resend_igmp_join_requests(struct net_device *dev)
869 * Retrieve the list of registered multicast addresses for the bonding
870 * device and retransmit an IGMP JOIN request to the current active
871 * slave.
872 */
873static void bond_resend_igmp_join_requests(struct bonding *bond)
874{ 869{
875 struct in_device *in_dev; 870 struct in_device *in_dev;
876 struct ip_mc_list *im; 871 struct ip_mc_list *im;
877 872
878 rcu_read_lock(); 873 rcu_read_lock();
879 in_dev = __in_dev_get_rcu(bond->dev); 874 in_dev = __in_dev_get_rcu(dev);
880 if (in_dev) { 875 if (in_dev) {
881 for (im = in_dev->mc_list; im; im = im->next) 876 for (im = in_dev->mc_list; im; im = im->next)
882 ip_mc_rejoin_group(im); 877 ip_mc_rejoin_group(im);
@@ -886,6 +881,41 @@ static void bond_resend_igmp_join_requests(struct bonding *bond)
886} 881}
887 882
888/* 883/*
884 * Retrieve the list of registered multicast addresses for the bonding
885 * device and retransmit an IGMP JOIN request to the current active
886 * slave.
887 */
888static void bond_resend_igmp_join_requests(struct bonding *bond)
889{
890 struct net_device *vlan_dev;
891 struct vlan_entry *vlan;
892
893 read_lock(&bond->lock);
894
895 /* rejoin all groups on bond device */
896 __bond_resend_igmp_join_requests(bond->dev);
897
898 /* rejoin all groups on vlan devices */
899 if (bond->vlgrp) {
900 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
901 vlan_dev = vlan_group_get_device(bond->vlgrp,
902 vlan->vlan_id);
903 if (vlan_dev)
904 __bond_resend_igmp_join_requests(vlan_dev);
905 }
906 }
907
908 read_unlock(&bond->lock);
909}
910
911void bond_resend_igmp_join_requests_delayed(struct work_struct *work)
912{
913 struct bonding *bond = container_of(work, struct bonding,
914 mcast_work.work);
915 bond_resend_igmp_join_requests(bond);
916}
917
918/*
889 * flush all members of flush->mc_list from device dev->mc_list 919 * flush all members of flush->mc_list from device dev->mc_list
890 */ 920 */
891static void bond_mc_list_flush(struct net_device *bond_dev, 921static void bond_mc_list_flush(struct net_device *bond_dev,
@@ -944,7 +974,6 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active,
944 974
945 netdev_for_each_mc_addr(ha, bond->dev) 975 netdev_for_each_mc_addr(ha, bond->dev)
946 dev_mc_add(new_active->dev, ha->addr); 976 dev_mc_add(new_active->dev, ha->addr);
947 bond_resend_igmp_join_requests(bond);
948 } 977 }
949} 978}
950 979
@@ -1180,9 +1209,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
1180 } 1209 }
1181 } 1210 }
1182 1211
1183 /* resend IGMP joins since all were sent on curr_active_slave */ 1212 /* resend IGMP joins since active slave has changed or
1184 if (bond->params.mode == BOND_MODE_ROUNDROBIN) { 1213 * all were sent on curr_active_slave */
1185 bond_resend_igmp_join_requests(bond); 1214 if ((USES_PRIMARY(bond->params.mode) && new_active) ||
1215 bond->params.mode == BOND_MODE_ROUNDROBIN) {
1216 queue_delayed_work(bond->wq, &bond->mcast_work, 0);
1186 } 1217 }
1187} 1218}
1188 1219
@@ -3744,6 +3775,8 @@ static int bond_open(struct net_device *bond_dev)
3744 3775
3745 bond->kill_timers = 0; 3776 bond->kill_timers = 0;
3746 3777
3778 INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
3779
3747 if (bond_is_lb(bond)) { 3780 if (bond_is_lb(bond)) {
3748 /* bond_alb_initialize must be called before the timer 3781 /* bond_alb_initialize must be called before the timer
3749 * is started. 3782 * is started.
@@ -3828,6 +3861,8 @@ static int bond_close(struct net_device *bond_dev)
3828 break; 3861 break;
3829 } 3862 }
3830 3863
3864 if (delayed_work_pending(&bond->mcast_work))
3865 cancel_delayed_work(&bond->mcast_work);
3831 3866
3832 if (bond_is_lb(bond)) { 3867 if (bond_is_lb(bond)) {
3833 /* Must be called only after all 3868 /* Must be called only after all
@@ -4703,6 +4738,9 @@ static void bond_work_cancel_all(struct bonding *bond)
4703 if (bond->params.mode == BOND_MODE_8023AD && 4738 if (bond->params.mode == BOND_MODE_8023AD &&
4704 delayed_work_pending(&bond->ad_work)) 4739 delayed_work_pending(&bond->ad_work))
4705 cancel_delayed_work(&bond->ad_work); 4740 cancel_delayed_work(&bond->ad_work);
4741
4742 if (delayed_work_pending(&bond->mcast_work))
4743 cancel_delayed_work(&bond->mcast_work);
4706} 4744}
4707 4745
4708/* 4746/*
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index c6fdd851579a..308ed10dca90 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -223,6 +223,7 @@ struct bonding {
223 struct delayed_work arp_work; 223 struct delayed_work arp_work;
224 struct delayed_work alb_work; 224 struct delayed_work alb_work;
225 struct delayed_work ad_work; 225 struct delayed_work ad_work;
226 struct delayed_work mcast_work;
226#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 227#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
227 struct in6_addr master_ipv6; 228 struct in6_addr master_ipv6;
228#endif 229#endif