diff options
-rw-r--r-- | drivers/net/bonding/bond_main.c | 60 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 1 |
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 | /* | 868 | static 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 | */ | ||
873 | static 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 | */ | ||
888 | static 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 | |||
911 | void 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 | */ |
891 | static void bond_mc_list_flush(struct net_device *bond_dev, | 921 | static 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 |