aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_main.c
diff options
context:
space:
mode:
authorPeter Pan(潘卫平) <panweiping3@gmail.com>2012-03-17 13:23:27 -0400
committerDavid S. Miller <davem@davemloft.net>2012-03-19 18:02:05 -0400
commit1c3ac4289a0e4d60cbd4787b4a91de4a0c785df1 (patch)
tree01a3a0806e24d869b2e0df5e8e8fb0aaeb91bd4e /drivers/net/bonding/bond_main.c
parentba568335b089e0a27829e3a6117a7e1bf957ad07 (diff)
bonding: send igmp report for its master
Liang Zheng(lzheng@redhat.com) found that in the following topo, bonding does not send igmp report when we trigger a fail-over of bonding. eth0-- |-- bond0 -- br0 eth1-- modprobe bonding mode=1 miimon=100 resend_igmp=10 ifconfig bond0 up ifenslave bond0 eth0 eth1 brctl addbr br0 ifconfig br0 192.168.100.2/24 up brctl addif br0 bond0 Add 192.168.100.2(br0) into a multicast group, like 224.10.10.10, then trigger a fali-over in bonding. You can see that parameter "resend_igmp" does not work. The reason is that when we add br0 into a multicast group, it does not propagate multicast knowledge down to its ports. If we choose to propagate multicast knowledge down to all ports for bridge, then we have to track every change that is done to bridge, and keep a backup for all ports. It is hard to track, I think. Instead I choose to modify bonding to send igmp report for its master. Changelog: V2: correct comments V3: move this check into bond_resend_igmp_join_requests() V4: only send igmp reports if bond is enslaved to a bridge Signed-off-by: Weiping Pan <panweiping3@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r--drivers/net/bonding/bond_main.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 435984ad8b2f..0730203a19f2 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -766,18 +766,30 @@ static void __bond_resend_igmp_join_requests(struct net_device *dev)
766 */ 766 */
767static void bond_resend_igmp_join_requests(struct bonding *bond) 767static void bond_resend_igmp_join_requests(struct bonding *bond)
768{ 768{
769 struct net_device *vlan_dev; 769 struct net_device *bond_dev, *vlan_dev, *master_dev;
770 struct vlan_entry *vlan; 770 struct vlan_entry *vlan;
771 771
772 read_lock(&bond->lock); 772 read_lock(&bond->lock);
773 773
774 bond_dev = bond->dev;
775
774 /* rejoin all groups on bond device */ 776 /* rejoin all groups on bond device */
775 __bond_resend_igmp_join_requests(bond->dev); 777 __bond_resend_igmp_join_requests(bond_dev);
778
779 /*
780 * if bond is enslaved to a bridge,
781 * then rejoin all groups on its master
782 */
783 master_dev = bond_dev->master;
784 if (master_dev)
785 if ((master_dev->priv_flags & IFF_EBRIDGE)
786 && (bond_dev->priv_flags & IFF_BRIDGE_PORT))
787 __bond_resend_igmp_join_requests(master_dev);
776 788
777 /* rejoin all groups on vlan devices */ 789 /* rejoin all groups on vlan devices */
778 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { 790 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
779 rcu_read_lock(); 791 rcu_read_lock();
780 vlan_dev = __vlan_find_dev_deep(bond->dev, 792 vlan_dev = __vlan_find_dev_deep(bond_dev,
781 vlan->vlan_id); 793 vlan->vlan_id);
782 rcu_read_unlock(); 794 rcu_read_unlock();
783 if (vlan_dev) 795 if (vlan_dev)