Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 50426b59 authored by Amerigo Wang's avatar Amerigo Wang Committed by David S. Miller
Browse files

bridge: implement multicast fast leave



V2: make the toggle per-port

Fast leave allows bridge to immediately stops the multicast
traffic on the port receives IGMP Leave when IGMP snooping is enabled,
no timeouts are observed.

Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: default avatarCong Wang <amwang@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a573ea56
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1225,6 +1225,27 @@ static void br_multicast_leave_group(struct net_bridge *br,
	if (!mp)
		goto out;

	if (port && port->multicast_fast_leave) {
		struct net_bridge_port_group __rcu **pp;

		for (pp = &mp->ports;
		     (p = mlock_dereference(*pp, br)) != NULL;
		     pp = &p->next) {
			if (p->port != port)
				continue;

			rcu_assign_pointer(*pp, p->next);
			hlist_del_init(&p->mglist);
			del_timer(&p->timer);
			call_rcu_bh(&p->rcu, br_multicast_free_pg);

			if (!mp->ports && !mp->mglist &&
			    netif_running(br->dev))
				mod_timer(&mp->timer, jiffies);
		}
		goto out;
	}

	now = jiffies;
	time = now + br->multicast_last_member_count *
		     br->multicast_last_member_interval;
+1 −0
Original line number Diff line number Diff line
@@ -141,6 +141,7 @@ struct net_bridge_port
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	u32				multicast_startup_queries_sent;
	unsigned char			multicast_router;
	unsigned char			multicast_fast_leave;
	struct timer_list		multicast_router_timer;
	struct timer_list		multicast_query_timer;
	struct hlist_head		mglist;
+20 −0
Original line number Diff line number Diff line
@@ -172,6 +172,25 @@ static int store_multicast_router(struct net_bridge_port *p,
}
static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
		   store_multicast_router);

static ssize_t show_multicast_fast_leave(struct net_bridge_port *p,
					 char *buf)
{
	return sprintf(buf, "%d\n", p->multicast_fast_leave);
}

static int store_multicast_fast_leave(struct net_bridge_port *p,
				      unsigned long v)
{
	if (p->br->multicast_disabled)
		return -EINVAL;

	p->multicast_fast_leave = !!v;
	return 0;
}

static BRPORT_ATTR(multicast_fast_leave, S_IRUGO | S_IWUSR,
		   show_multicast_fast_leave, store_multicast_fast_leave);
#endif

static const struct brport_attribute *brport_attrs[] = {
@@ -195,6 +214,7 @@ static const struct brport_attribute *brport_attrs[] = {
	&brport_attr_root_block,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	&brport_attr_multicast_router,
	&brport_attr_multicast_fast_leave,
#endif
	NULL
};