diff options
-rw-r--r-- | drivers/net/bonding/bond_main.c | 76 | ||||
-rw-r--r-- | include/linux/igmp.h | 2 | ||||
-rw-r--r-- | net/ipv4/igmp.c | 23 |
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 | */ | ||
871 | static 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 | ||
4020 | static 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 | ||
4093 | out: | 4067 | out: |
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 *); | |||
218 | extern void ip_mc_down(struct in_device *); | 218 | extern void ip_mc_down(struct in_device *); |
219 | extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr); | 219 | extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr); |
220 | extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr); | 220 | extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr); |
221 | extern 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 | */ | ||
1256 | void 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) | |||
2596 | EXPORT_SYMBOL(ip_mc_dec_group); | 2618 | EXPORT_SYMBOL(ip_mc_dec_group); |
2597 | EXPORT_SYMBOL(ip_mc_inc_group); | 2619 | EXPORT_SYMBOL(ip_mc_inc_group); |
2598 | EXPORT_SYMBOL(ip_mc_join_group); | 2620 | EXPORT_SYMBOL(ip_mc_join_group); |
2621 | EXPORT_SYMBOL(ip_mc_rejoin_group); | ||