Commit 996304bb authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

bridge: Do not send queries on multicast group leaves

As it stands the bridge IGMP snooping system will respond to
group leave messages with queries for remaining membership.
This is both unnecessary and undesirable.  First of all any
multicast routers present should be doing this rather than us.
What's more the queries that we send may end up upsetting other
multicast snooping swithces in the system that are buggy.

In fact, we can simply remove the code that send these queries
because the existing membership expiry mechanism doesn't rely
on them anyway.

So this patch simply removes all code associated with group
queries in response to group leave messages.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 09d208ec
...@@ -241,7 +241,6 @@ static void br_multicast_group_expired(unsigned long data) ...@@ -241,7 +241,6 @@ static void br_multicast_group_expired(unsigned long data)
hlist_del_rcu(&mp->hlist[mdb->ver]); hlist_del_rcu(&mp->hlist[mdb->ver]);
mdb->size--; mdb->size--;
del_timer(&mp->query_timer);
call_rcu_bh(&mp->rcu, br_multicast_free_group); call_rcu_bh(&mp->rcu, br_multicast_free_group);
out: out:
...@@ -271,7 +270,6 @@ static void br_multicast_del_pg(struct net_bridge *br, ...@@ -271,7 +270,6 @@ static void br_multicast_del_pg(struct net_bridge *br,
rcu_assign_pointer(*pp, p->next); rcu_assign_pointer(*pp, p->next);
hlist_del_init(&p->mglist); hlist_del_init(&p->mglist);
del_timer(&p->timer); del_timer(&p->timer);
del_timer(&p->query_timer);
call_rcu_bh(&p->rcu, br_multicast_free_pg); call_rcu_bh(&p->rcu, br_multicast_free_pg);
if (!mp->ports && !mp->mglist && if (!mp->ports && !mp->mglist &&
...@@ -507,74 +505,6 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, ...@@ -507,74 +505,6 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
return NULL; return NULL;
} }
static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp)
{
struct net_bridge *br = mp->br;
struct sk_buff *skb;
skb = br_multicast_alloc_query(br, &mp->addr);
if (!skb)
goto timer;
netif_rx(skb);
timer:
if (++mp->queries_sent < br->multicast_last_member_count)
mod_timer(&mp->query_timer,
jiffies + br->multicast_last_member_interval);
}
static void br_multicast_group_query_expired(unsigned long data)
{
struct net_bridge_mdb_entry *mp = (void *)data;
struct net_bridge *br = mp->br;
spin_lock(&br->multicast_lock);
if (!netif_running(br->dev) || !mp->mglist ||
mp->queries_sent >= br->multicast_last_member_count)
goto out;
br_multicast_send_group_query(mp);
out:
spin_unlock(&br->multicast_lock);
}
static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg)
{
struct net_bridge_port *port = pg->port;
struct net_bridge *br = port->br;
struct sk_buff *skb;
skb = br_multicast_alloc_query(br, &pg->addr);
if (!skb)
goto timer;
br_deliver(port, skb);
timer:
if (++pg->queries_sent < br->multicast_last_member_count)
mod_timer(&pg->query_timer,
jiffies + br->multicast_last_member_interval);
}
static void br_multicast_port_group_query_expired(unsigned long data)
{
struct net_bridge_port_group *pg = (void *)data;
struct net_bridge_port *port = pg->port;
struct net_bridge *br = port->br;
spin_lock(&br->multicast_lock);
if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) ||
pg->queries_sent >= br->multicast_last_member_count)
goto out;
br_multicast_send_port_group_query(pg);
out:
spin_unlock(&br->multicast_lock);
}
static struct net_bridge_mdb_entry *br_multicast_get_group( static struct net_bridge_mdb_entry *br_multicast_get_group(
struct net_bridge *br, struct net_bridge_port *port, struct net_bridge *br, struct net_bridge_port *port,
struct br_ip *group, int hash) struct br_ip *group, int hash)
...@@ -690,8 +620,6 @@ static struct net_bridge_mdb_entry *br_multicast_new_group( ...@@ -690,8 +620,6 @@ static struct net_bridge_mdb_entry *br_multicast_new_group(
mp->addr = *group; mp->addr = *group;
setup_timer(&mp->timer, br_multicast_group_expired, setup_timer(&mp->timer, br_multicast_group_expired,
(unsigned long)mp); (unsigned long)mp);
setup_timer(&mp->query_timer, br_multicast_group_query_expired,
(unsigned long)mp);
hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
mdb->size++; mdb->size++;
...@@ -746,8 +674,6 @@ static int br_multicast_add_group(struct net_bridge *br, ...@@ -746,8 +674,6 @@ static int br_multicast_add_group(struct net_bridge *br,
hlist_add_head(&p->mglist, &port->mglist); hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired, setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p); (unsigned long)p);
setup_timer(&p->query_timer, br_multicast_port_group_query_expired,
(unsigned long)p);
rcu_assign_pointer(*pp, p); rcu_assign_pointer(*pp, p);
...@@ -1291,9 +1217,6 @@ static void br_multicast_leave_group(struct net_bridge *br, ...@@ -1291,9 +1217,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
time_after(mp->timer.expires, time) : time_after(mp->timer.expires, time) :
try_to_del_timer_sync(&mp->timer) >= 0)) { try_to_del_timer_sync(&mp->timer) >= 0)) {
mod_timer(&mp->timer, time); mod_timer(&mp->timer, time);
mp->queries_sent = 0;
mod_timer(&mp->query_timer, now);
} }
goto out; goto out;
...@@ -1310,9 +1233,6 @@ static void br_multicast_leave_group(struct net_bridge *br, ...@@ -1310,9 +1233,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
time_after(p->timer.expires, time) : time_after(p->timer.expires, time) :
try_to_del_timer_sync(&p->timer) >= 0)) { try_to_del_timer_sync(&p->timer) >= 0)) {
mod_timer(&p->timer, time); mod_timer(&p->timer, time);
p->queries_sent = 0;
mod_timer(&p->query_timer, now);
} }
break; break;
...@@ -1681,7 +1601,6 @@ void br_multicast_stop(struct net_bridge *br) ...@@ -1681,7 +1601,6 @@ void br_multicast_stop(struct net_bridge *br)
hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i],
hlist[ver]) { hlist[ver]) {
del_timer(&mp->timer); del_timer(&mp->timer);
del_timer(&mp->query_timer);
call_rcu_bh(&mp->rcu, br_multicast_free_group); call_rcu_bh(&mp->rcu, br_multicast_free_group);
} }
} }
......
...@@ -82,9 +82,7 @@ struct net_bridge_port_group { ...@@ -82,9 +82,7 @@ struct net_bridge_port_group {
struct hlist_node mglist; struct hlist_node mglist;
struct rcu_head rcu; struct rcu_head rcu;
struct timer_list timer; struct timer_list timer;
struct timer_list query_timer;
struct br_ip addr; struct br_ip addr;
u32 queries_sent;
}; };
struct net_bridge_mdb_entry struct net_bridge_mdb_entry
...@@ -94,10 +92,8 @@ struct net_bridge_mdb_entry ...@@ -94,10 +92,8 @@ struct net_bridge_mdb_entry
struct net_bridge_port_group __rcu *ports; struct net_bridge_port_group __rcu *ports;
struct rcu_head rcu; struct rcu_head rcu;
struct timer_list timer; struct timer_list timer;
struct timer_list query_timer;
struct br_ip addr; struct br_ip addr;
bool mglist; bool mglist;
u32 queries_sent;
}; };
struct net_bridge_mdb_htable struct net_bridge_mdb_htable
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment