diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2012-04-03 21:01:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-04-11 09:43:13 -0400 |
commit | 996304bbea3d2a094b7ba54c3bd65d3fffeac57b (patch) | |
tree | e015e32637366870b52882e95759d5f2d4c95ba5 /net | |
parent | 09d208ec74b804b9dcd0b1cd9c21dfd592760807 (diff) |
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: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_multicast.c | 81 | ||||
-rw-r--r-- | net/bridge/br_private.h | 4 |
2 files changed, 0 insertions, 85 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 702a1ae9220b..27ca25ed7021 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -241,7 +241,6 @@ static void br_multicast_group_expired(unsigned long data) | |||
241 | hlist_del_rcu(&mp->hlist[mdb->ver]); | 241 | hlist_del_rcu(&mp->hlist[mdb->ver]); |
242 | mdb->size--; | 242 | mdb->size--; |
243 | 243 | ||
244 | del_timer(&mp->query_timer); | ||
245 | call_rcu_bh(&mp->rcu, br_multicast_free_group); | 244 | call_rcu_bh(&mp->rcu, br_multicast_free_group); |
246 | 245 | ||
247 | out: | 246 | out: |
@@ -271,7 +270,6 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
271 | rcu_assign_pointer(*pp, p->next); | 270 | rcu_assign_pointer(*pp, p->next); |
272 | hlist_del_init(&p->mglist); | 271 | hlist_del_init(&p->mglist); |
273 | del_timer(&p->timer); | 272 | del_timer(&p->timer); |
274 | del_timer(&p->query_timer); | ||
275 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 273 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
276 | 274 | ||
277 | if (!mp->ports && !mp->mglist && | 275 | if (!mp->ports && !mp->mglist && |
@@ -507,74 +505,6 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | |||
507 | return NULL; | 505 | return NULL; |
508 | } | 506 | } |
509 | 507 | ||
510 | static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) | ||
511 | { | ||
512 | struct net_bridge *br = mp->br; | ||
513 | struct sk_buff *skb; | ||
514 | |||
515 | skb = br_multicast_alloc_query(br, &mp->addr); | ||
516 | if (!skb) | ||
517 | goto timer; | ||
518 | |||
519 | netif_rx(skb); | ||
520 | |||
521 | timer: | ||
522 | if (++mp->queries_sent < br->multicast_last_member_count) | ||
523 | mod_timer(&mp->query_timer, | ||
524 | jiffies + br->multicast_last_member_interval); | ||
525 | } | ||
526 | |||
527 | static void br_multicast_group_query_expired(unsigned long data) | ||
528 | { | ||
529 | struct net_bridge_mdb_entry *mp = (void *)data; | ||
530 | struct net_bridge *br = mp->br; | ||
531 | |||
532 | spin_lock(&br->multicast_lock); | ||
533 | if (!netif_running(br->dev) || !mp->mglist || | ||
534 | mp->queries_sent >= br->multicast_last_member_count) | ||
535 | goto out; | ||
536 | |||
537 | br_multicast_send_group_query(mp); | ||
538 | |||
539 | out: | ||
540 | spin_unlock(&br->multicast_lock); | ||
541 | } | ||
542 | |||
543 | static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) | ||
544 | { | ||
545 | struct net_bridge_port *port = pg->port; | ||
546 | struct net_bridge *br = port->br; | ||
547 | struct sk_buff *skb; | ||
548 | |||
549 | skb = br_multicast_alloc_query(br, &pg->addr); | ||
550 | if (!skb) | ||
551 | goto timer; | ||
552 | |||
553 | br_deliver(port, skb); | ||
554 | |||
555 | timer: | ||
556 | if (++pg->queries_sent < br->multicast_last_member_count) | ||
557 | mod_timer(&pg->query_timer, | ||
558 | jiffies + br->multicast_last_member_interval); | ||
559 | } | ||
560 | |||
561 | static void br_multicast_port_group_query_expired(unsigned long data) | ||
562 | { | ||
563 | struct net_bridge_port_group *pg = (void *)data; | ||
564 | struct net_bridge_port *port = pg->port; | ||
565 | struct net_bridge *br = port->br; | ||
566 | |||
567 | spin_lock(&br->multicast_lock); | ||
568 | if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) || | ||
569 | pg->queries_sent >= br->multicast_last_member_count) | ||
570 | goto out; | ||
571 | |||
572 | br_multicast_send_port_group_query(pg); | ||
573 | |||
574 | out: | ||
575 | spin_unlock(&br->multicast_lock); | ||
576 | } | ||
577 | |||
578 | static struct net_bridge_mdb_entry *br_multicast_get_group( | 508 | static struct net_bridge_mdb_entry *br_multicast_get_group( |
579 | struct net_bridge *br, struct net_bridge_port *port, | 509 | struct net_bridge *br, struct net_bridge_port *port, |
580 | struct br_ip *group, int hash) | 510 | struct br_ip *group, int hash) |
@@ -690,8 +620,6 @@ rehash: | |||
690 | mp->addr = *group; | 620 | mp->addr = *group; |
691 | setup_timer(&mp->timer, br_multicast_group_expired, | 621 | setup_timer(&mp->timer, br_multicast_group_expired, |
692 | (unsigned long)mp); | 622 | (unsigned long)mp); |
693 | setup_timer(&mp->query_timer, br_multicast_group_query_expired, | ||
694 | (unsigned long)mp); | ||
695 | 623 | ||
696 | hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); | 624 | hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); |
697 | mdb->size++; | 625 | mdb->size++; |
@@ -746,8 +674,6 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
746 | hlist_add_head(&p->mglist, &port->mglist); | 674 | hlist_add_head(&p->mglist, &port->mglist); |
747 | setup_timer(&p->timer, br_multicast_port_group_expired, | 675 | setup_timer(&p->timer, br_multicast_port_group_expired, |
748 | (unsigned long)p); | 676 | (unsigned long)p); |
749 | setup_timer(&p->query_timer, br_multicast_port_group_query_expired, | ||
750 | (unsigned long)p); | ||
751 | 677 | ||
752 | rcu_assign_pointer(*pp, p); | 678 | rcu_assign_pointer(*pp, p); |
753 | 679 | ||
@@ -1291,9 +1217,6 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
1291 | time_after(mp->timer.expires, time) : | 1217 | time_after(mp->timer.expires, time) : |
1292 | try_to_del_timer_sync(&mp->timer) >= 0)) { | 1218 | try_to_del_timer_sync(&mp->timer) >= 0)) { |
1293 | mod_timer(&mp->timer, time); | 1219 | mod_timer(&mp->timer, time); |
1294 | |||
1295 | mp->queries_sent = 0; | ||
1296 | mod_timer(&mp->query_timer, now); | ||
1297 | } | 1220 | } |
1298 | 1221 | ||
1299 | goto out; | 1222 | goto out; |
@@ -1310,9 +1233,6 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
1310 | time_after(p->timer.expires, time) : | 1233 | time_after(p->timer.expires, time) : |
1311 | try_to_del_timer_sync(&p->timer) >= 0)) { | 1234 | try_to_del_timer_sync(&p->timer) >= 0)) { |
1312 | mod_timer(&p->timer, time); | 1235 | mod_timer(&p->timer, time); |
1313 | |||
1314 | p->queries_sent = 0; | ||
1315 | mod_timer(&p->query_timer, now); | ||
1316 | } | 1236 | } |
1317 | 1237 | ||
1318 | break; | 1238 | break; |
@@ -1681,7 +1601,6 @@ void br_multicast_stop(struct net_bridge *br) | |||
1681 | hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], | 1601 | hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], |
1682 | hlist[ver]) { | 1602 | hlist[ver]) { |
1683 | del_timer(&mp->timer); | 1603 | del_timer(&mp->timer); |
1684 | del_timer(&mp->query_timer); | ||
1685 | call_rcu_bh(&mp->rcu, br_multicast_free_group); | 1604 | call_rcu_bh(&mp->rcu, br_multicast_free_group); |
1686 | } | 1605 | } |
1687 | } | 1606 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 0b67a63ad7a8..e1d882257877 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -82,9 +82,7 @@ struct net_bridge_port_group { | |||
82 | struct hlist_node mglist; | 82 | struct hlist_node mglist; |
83 | struct rcu_head rcu; | 83 | struct rcu_head rcu; |
84 | struct timer_list timer; | 84 | struct timer_list timer; |
85 | struct timer_list query_timer; | ||
86 | struct br_ip addr; | 85 | struct br_ip addr; |
87 | u32 queries_sent; | ||
88 | }; | 86 | }; |
89 | 87 | ||
90 | struct net_bridge_mdb_entry | 88 | struct net_bridge_mdb_entry |
@@ -94,10 +92,8 @@ struct net_bridge_mdb_entry | |||
94 | struct net_bridge_port_group __rcu *ports; | 92 | struct net_bridge_port_group __rcu *ports; |
95 | struct rcu_head rcu; | 93 | struct rcu_head rcu; |
96 | struct timer_list timer; | 94 | struct timer_list timer; |
97 | struct timer_list query_timer; | ||
98 | struct br_ip addr; | 95 | struct br_ip addr; |
99 | bool mglist; | 96 | bool mglist; |
100 | u32 queries_sent; | ||
101 | }; | 97 | }; |
102 | 98 | ||
103 | struct net_bridge_mdb_htable | 99 | struct net_bridge_mdb_htable |