aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/igmp.c
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2013-07-20 06:13:53 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-23 19:52:47 -0400
commit4aa5dee4d9997879adff858514844efab5a15a01 (patch)
treef3f3bf83f34dd832c8e163095c03e6aff29f20df /net/ipv4/igmp.c
parentfc423ff00df3a19554414eed80aef9de9b50313e (diff)
net: convert resend IGMP to notifier event
Until now, bond_resend_igmp_join_requests() looks for vlans attached to bonding device, bridge where bonding act as port manually. It does not care of other scenarios, like stacked bonds or team device above. Make this more generic and use netdev notifier to propagate the event to upper devices and to actually call ip_mc_rejoin_groups(). Signed-off-by: Jiri Pirko <jiri@resnulli.us> Acked-by: Veaceslav Falico <vfalico@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/igmp.c')
-rw-r--r--net/ipv4/igmp.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index cd71190d2962..375aca372250 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1323,16 +1323,17 @@ out:
1323EXPORT_SYMBOL(ip_mc_inc_group); 1323EXPORT_SYMBOL(ip_mc_inc_group);
1324 1324
1325/* 1325/*
1326 * Resend IGMP JOIN report; used for bonding. 1326 * Resend IGMP JOIN report; used by netdev notifier.
1327 * Called with rcu_read_lock()
1328 */ 1327 */
1329void ip_mc_rejoin_groups(struct in_device *in_dev) 1328static void ip_mc_rejoin_groups(struct in_device *in_dev)
1330{ 1329{
1331#ifdef CONFIG_IP_MULTICAST 1330#ifdef CONFIG_IP_MULTICAST
1332 struct ip_mc_list *im; 1331 struct ip_mc_list *im;
1333 int type; 1332 int type;
1334 1333
1335 for_each_pmc_rcu(in_dev, im) { 1334 ASSERT_RTNL();
1335
1336 for_each_pmc_rtnl(in_dev, im) {
1336 if (im->multiaddr == IGMP_ALL_HOSTS) 1337 if (im->multiaddr == IGMP_ALL_HOSTS)
1337 continue; 1338 continue;
1338 1339
@@ -1349,7 +1350,6 @@ void ip_mc_rejoin_groups(struct in_device *in_dev)
1349 } 1350 }
1350#endif 1351#endif
1351} 1352}
1352EXPORT_SYMBOL(ip_mc_rejoin_groups);
1353 1353
1354/* 1354/*
1355 * A socket has left a multicast group on device dev 1355 * A socket has left a multicast group on device dev
@@ -2735,8 +2735,42 @@ static struct pernet_operations igmp_net_ops = {
2735 .exit = igmp_net_exit, 2735 .exit = igmp_net_exit,
2736}; 2736};
2737 2737
2738static int igmp_netdev_event(struct notifier_block *this,
2739 unsigned long event, void *ptr)
2740{
2741 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2742 struct in_device *in_dev;
2743
2744 switch (event) {
2745 case NETDEV_RESEND_IGMP:
2746 in_dev = __in_dev_get_rtnl(dev);
2747 if (in_dev)
2748 ip_mc_rejoin_groups(in_dev);
2749 break;
2750 default:
2751 break;
2752 }
2753 return NOTIFY_DONE;
2754}
2755
2756static struct notifier_block igmp_notifier = {
2757 .notifier_call = igmp_netdev_event,
2758};
2759
2738int __init igmp_mc_proc_init(void) 2760int __init igmp_mc_proc_init(void)
2739{ 2761{
2740 return register_pernet_subsys(&igmp_net_ops); 2762 int err;
2763
2764 err = register_pernet_subsys(&igmp_net_ops);
2765 if (err)
2766 return err;
2767 err = register_netdevice_notifier(&igmp_notifier);
2768 if (err)
2769 goto reg_notif_fail;
2770 return 0;
2771
2772reg_notif_fail:
2773 unregister_pernet_subsys(&igmp_net_ops);
2774 return err;
2741} 2775}
2742#endif 2776#endif