aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_main.c76
-rw-r--r--include/linux/igmp.h2
-rw-r--r--net/ipv4/igmp.c23
3 files changed, 50 insertions, 51 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 1ca73b8c139b..e4724d874e7c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -60,6 +60,7 @@
60#include <linux/errno.h> 60#include <linux/errno.h>
61#include <linux/netdevice.h> 61#include <linux/netdevice.h>
62#include <linux/inetdevice.h> 62#include <linux/inetdevice.h>
63#include <linux/igmp.h>
63#include <linux/etherdevice.h> 64#include <linux/etherdevice.h>
64#include <linux/skbuff.h> 65#include <linux/skbuff.h>
65#include <net/sock.h> 66#include <net/sock.h>
@@ -861,6 +862,28 @@ static void bond_mc_delete(struct bonding *bond, void *addr, int alen)
861 } 862 }
862} 863}
863 864
865
866/*
867 * Retrieve the list of registered multicast addresses for the bonding
868 * device and retransmit an IGMP JOIN request to the current active
869 * slave.
870 */
871static void bond_resend_igmp_join_requests(struct bonding *bond)
872{
873 struct in_device *in_dev;
874 struct ip_mc_list *im;
875
876 rcu_read_lock();
877 in_dev = __in_dev_get_rcu(bond->dev);
878 if (in_dev) {
879 for (im = in_dev->mc_list; im; im = im->next) {
880 ip_mc_rejoin_group(im);
881 }
882 }
883
884 rcu_read_unlock();
885}
886
864/* 887/*
865 * Totally destroys the mc_list in bond 888 * Totally destroys the mc_list in bond
866 */ 889 */
@@ -874,6 +897,7 @@ static void bond_mc_list_destroy(struct bonding *bond)
874 kfree(dmi); 897 kfree(dmi);
875 dmi = bond->mc_list; 898 dmi = bond->mc_list;
876 } 899 }
900 bond->mc_list = NULL;
877} 901}
878 902
879/* 903/*
@@ -967,6 +991,7 @@ static void bond_mc_swap(struct bonding *bond, struct slave *new_active, struct
967 for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) { 991 for (dmi = bond->dev->mc_list; dmi; dmi = dmi->next) {
968 dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); 992 dev_mc_add(new_active->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
969 } 993 }
994 bond_resend_igmp_join_requests(bond);
970 } 995 }
971} 996}
972 997
@@ -4017,42 +4042,6 @@ out:
4017 return 0; 4042 return 0;
4018} 4043}
4019 4044
4020static void bond_activebackup_xmit_copy(struct sk_buff *skb,
4021 struct bonding *bond,
4022 struct slave *slave)
4023{
4024 struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
4025 struct ethhdr *eth_data;
4026 u8 *hwaddr;
4027 int res;
4028
4029 if (!skb2) {
4030 printk(KERN_ERR DRV_NAME ": Error: "
4031 "bond_activebackup_xmit_copy(): skb_copy() failed\n");
4032 return;
4033 }
4034
4035 skb2->mac.raw = (unsigned char *)skb2->data;
4036 eth_data = eth_hdr(skb2);
4037
4038 /* Pick an appropriate source MAC address
4039 * -- use slave's perm MAC addr, unless used by bond
4040 * -- otherwise, borrow active slave's perm MAC addr
4041 * since that will not be used
4042 */
4043 hwaddr = slave->perm_hwaddr;
4044 if (!memcmp(eth_data->h_source, hwaddr, ETH_ALEN))
4045 hwaddr = bond->curr_active_slave->perm_hwaddr;
4046
4047 /* Set source MAC address appropriately */
4048 memcpy(eth_data->h_source, hwaddr, ETH_ALEN);
4049
4050 res = bond_dev_queue_xmit(bond, skb2, slave->dev);
4051 if (res)
4052 dev_kfree_skb(skb2);
4053
4054 return;
4055}
4056 4045
4057/* 4046/*
4058 * in active-backup mode, we know that bond->curr_active_slave is always valid if 4047 * in active-backup mode, we know that bond->curr_active_slave is always valid if
@@ -4073,21 +4062,6 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d
4073 if (!bond->curr_active_slave) 4062 if (!bond->curr_active_slave)
4074 goto out; 4063 goto out;
4075 4064
4076 /* Xmit IGMP frames on all slaves to ensure rapid fail-over
4077 for multicast traffic on snooping switches */
4078 if (skb->protocol == __constant_htons(ETH_P_IP) &&
4079 skb->nh.iph->protocol == IPPROTO_IGMP) {
4080 struct slave *slave, *active_slave;
4081 int i;
4082
4083 active_slave = bond->curr_active_slave;
4084 bond_for_each_slave_from_to(bond, slave, i, active_slave->next,
4085 active_slave->prev)
4086 if (IS_UP(slave->dev) &&
4087 (slave->link == BOND_LINK_UP))
4088 bond_activebackup_xmit_copy(skb, bond, slave);
4089 }
4090
4091 res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); 4065 res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev);
4092 4066
4093out: 4067out:
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 9dbb525c5178..a113fe68d8a1 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -218,5 +218,7 @@ extern void ip_mc_up(struct in_device *);
218extern void ip_mc_down(struct in_device *); 218extern void ip_mc_down(struct in_device *);
219extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr); 219extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
220extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr); 220extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
221extern void ip_mc_rejoin_group(struct ip_mc_list *im);
222
221#endif 223#endif
222#endif 224#endif
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 063721302ebf..1c6a084b5fb7 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1251,6 +1251,28 @@ out:
1251} 1251}
1252 1252
1253/* 1253/*
1254 * Resend IGMP JOIN report; used for bonding.
1255 */
1256void ip_mc_rejoin_group(struct ip_mc_list *im)
1257{
1258 struct in_device *in_dev = im->interface;
1259
1260#ifdef CONFIG_IP_MULTICAST
1261 if (im->multiaddr == IGMP_ALL_HOSTS)
1262 return;
1263
1264 if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
1265 igmp_mod_timer(im, IGMP_Initial_Report_Delay);
1266 return;
1267 }
1268 /* else, v3 */
1269 im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
1270 IGMP_Unsolicited_Report_Count;
1271 igmp_ifc_event(in_dev);
1272#endif
1273}
1274
1275/*
1254 * A socket has left a multicast group on device dev 1276 * A socket has left a multicast group on device dev
1255 */ 1277 */
1256 1278
@@ -2596,3 +2618,4 @@ int __init igmp_mc_proc_init(void)
2596EXPORT_SYMBOL(ip_mc_dec_group); 2618EXPORT_SYMBOL(ip_mc_dec_group);
2597EXPORT_SYMBOL(ip_mc_inc_group); 2619EXPORT_SYMBOL(ip_mc_inc_group);
2598EXPORT_SYMBOL(ip_mc_join_group); 2620EXPORT_SYMBOL(ip_mc_join_group);
2621EXPORT_SYMBOL(ip_mc_rejoin_group);