Skip to content

Commit 4aa5dee

Browse files
jpirkodavem330
authored andcommitted
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 <[email protected]> Acked-by: Veaceslav Falico <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fc423ff commit 4aa5dee

File tree

7 files changed

+60
-42
lines changed

7 files changed

+60
-42
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -715,49 +715,19 @@ static int bond_set_allmulti(struct bonding *bond, int inc)
715715
return err;
716716
}
717717

718-
static void __bond_resend_igmp_join_requests(struct net_device *dev)
719-
{
720-
struct in_device *in_dev;
721-
722-
in_dev = __in_dev_get_rcu(dev);
723-
if (in_dev)
724-
ip_mc_rejoin_groups(in_dev);
725-
}
726-
727718
/*
728719
* Retrieve the list of registered multicast addresses for the bonding
729720
* device and retransmit an IGMP JOIN request to the current active
730721
* slave.
731722
*/
732723
static void bond_resend_igmp_join_requests(struct bonding *bond)
733724
{
734-
struct net_device *bond_dev, *vlan_dev, *upper_dev;
735-
struct vlan_entry *vlan;
736-
737-
read_lock(&bond->lock);
738-
rcu_read_lock();
739-
740-
bond_dev = bond->dev;
741-
742-
/* rejoin all groups on bond device */
743-
__bond_resend_igmp_join_requests(bond_dev);
744-
745-
/*
746-
* if bond is enslaved to a bridge,
747-
* then rejoin all groups on its master
748-
*/
749-
upper_dev = netdev_master_upper_dev_get_rcu(bond_dev);
750-
if (upper_dev && upper_dev->priv_flags & IFF_EBRIDGE)
751-
__bond_resend_igmp_join_requests(upper_dev);
752-
753-
/* rejoin all groups on vlan devices */
754-
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
755-
vlan_dev = __vlan_find_dev_deep(bond_dev, htons(ETH_P_8021Q),
756-
vlan->vlan_id);
757-
if (vlan_dev)
758-
__bond_resend_igmp_join_requests(vlan_dev);
725+
if (!rtnl_trylock()) {
726+
queue_delayed_work(bond->wq, &bond->mcast_work, 0);
727+
return;
759728
}
760-
rcu_read_unlock();
729+
call_netdevice_notifiers(NETDEV_RESEND_IGMP, bond->dev);
730+
rtnl_unlock();
761731

762732
/* We use curr_slave_lock to protect against concurrent access to
763733
* igmp_retrans from multiple running instances of this function and
@@ -3234,6 +3204,10 @@ static int bond_slave_netdev_event(unsigned long event,
32343204
case NETDEV_FEAT_CHANGE:
32353205
bond_compute_features(bond);
32363206
break;
3207+
case NETDEV_RESEND_IGMP:
3208+
/* Propagate to master device */
3209+
call_netdevice_notifiers(event, slave->bond->dev);
3210+
break;
32373211
default:
32383212
break;
32393213
}

drivers/net/team/team.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2785,6 +2785,10 @@ static int team_device_event(struct notifier_block *unused,
27852785
case NETDEV_PRE_TYPE_CHANGE:
27862786
/* Forbid to change type of underlaying device */
27872787
return NOTIFY_BAD;
2788+
case NETDEV_RESEND_IGMP:
2789+
/* Propagate to master device */
2790+
call_netdevice_notifiers(event, port->team->dev);
2791+
break;
27882792
}
27892793
return NOTIFY_DONE;
27902794
}

include/linux/igmp.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,5 @@ extern void ip_mc_unmap(struct in_device *);
129129
extern void ip_mc_remap(struct in_device *);
130130
extern void ip_mc_dec_group(struct in_device *in_dev, __be32 addr);
131131
extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
132-
extern void ip_mc_rejoin_groups(struct in_device *in_dev);
133132

134133
#endif

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,7 @@ struct packet_offload {
16331633
#define NETDEV_NOTIFY_PEERS 0x0013
16341634
#define NETDEV_JOIN 0x0014
16351635
#define NETDEV_CHANGEUPPER 0x0015
1636+
#define NETDEV_RESEND_IGMP 0x0016
16361637

16371638
extern int register_netdevice_notifier(struct notifier_block *nb);
16381639
extern int unregister_netdevice_notifier(struct notifier_block *nb);

net/8021q/vlan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
459459

460460
case NETDEV_NOTIFY_PEERS:
461461
case NETDEV_BONDING_FAILOVER:
462+
case NETDEV_RESEND_IGMP:
462463
/* Propagate to vlan devices */
463464
vlan_group_for_each_dev(grp, i, vlandev)
464465
call_netdevice_notifiers(event, vlandev);

net/bridge/br_notify.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
102102
case NETDEV_PRE_TYPE_CHANGE:
103103
/* Forbid underlaying device to change its type. */
104104
return NOTIFY_BAD;
105+
106+
case NETDEV_RESEND_IGMP:
107+
/* Propagate to master device */
108+
call_netdevice_notifiers(event, br->dev);
109+
break;
105110
}
106111

107112
/* Events that may cause spanning tree to refresh */

net/ipv4/igmp.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,16 +1323,17 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
13231323
EXPORT_SYMBOL(ip_mc_inc_group);
13241324

13251325
/*
1326-
* Resend IGMP JOIN report; used for bonding.
1327-
* Called with rcu_read_lock()
1326+
* Resend IGMP JOIN report; used by netdev notifier.
13281327
*/
1329-
void ip_mc_rejoin_groups(struct in_device *in_dev)
1328+
static void ip_mc_rejoin_groups(struct in_device *in_dev)
13301329
{
13311330
#ifdef CONFIG_IP_MULTICAST
13321331
struct ip_mc_list *im;
13331332
int type;
13341333

1335-
for_each_pmc_rcu(in_dev, im) {
1334+
ASSERT_RTNL();
1335+
1336+
for_each_pmc_rtnl(in_dev, im) {
13361337
if (im->multiaddr == IGMP_ALL_HOSTS)
13371338
continue;
13381339

@@ -1349,7 +1350,6 @@ void ip_mc_rejoin_groups(struct in_device *in_dev)
13491350
}
13501351
#endif
13511352
}
1352-
EXPORT_SYMBOL(ip_mc_rejoin_groups);
13531353

13541354
/*
13551355
* A socket has left a multicast group on device dev
@@ -2735,8 +2735,42 @@ static struct pernet_operations igmp_net_ops = {
27352735
.exit = igmp_net_exit,
27362736
};
27372737

2738+
static 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+
2756+
static struct notifier_block igmp_notifier = {
2757+
.notifier_call = igmp_netdev_event,
2758+
};
2759+
27382760
int __init igmp_mc_proc_init(void)
27392761
{
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+
2772+
reg_notif_fail:
2773+
unregister_pernet_subsys(&igmp_net_ops);
2774+
return err;
27412775
}
27422776
#endif

0 commit comments

Comments
 (0)