aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSatish Ashok <sashok@cumulusnetworks.com>2015-07-28 06:28:27 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-29 17:57:05 -0400
commit544586f742b43c6fd5fcb74c794d33b2ef189e64 (patch)
tree09b81a555a01a17aa21f3ff61545ececed53875d
parentdf356d5e81b04dd51dd9f23f2bce7d73dd929899 (diff)
bridge: mcast: give fast leave precedence over multicast router and querier
When fast leave is configured on a bridge port and an IGMP leave is received for a group, the group is not deleted immediately if there is a router detected or if multicast querier is configured. Ideally the group should be deleted immediately when fast leave is configured. Signed-off-by: Satish Ashok <sashok@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/br_multicast.c50
1 files changed, 26 insertions, 24 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 79db489cdade..0b39dcc65b94 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1416,8 +1416,7 @@ br_multicast_leave_group(struct net_bridge *br,
1416 1416
1417 spin_lock(&br->multicast_lock); 1417 spin_lock(&br->multicast_lock);
1418 if (!netif_running(br->dev) || 1418 if (!netif_running(br->dev) ||
1419 (port && port->state == BR_STATE_DISABLED) || 1419 (port && port->state == BR_STATE_DISABLED))
1420 timer_pending(&other_query->timer))
1421 goto out; 1420 goto out;
1422 1421
1423 mdb = mlock_dereference(br->mdb, br); 1422 mdb = mlock_dereference(br->mdb, br);
@@ -1425,6 +1424,31 @@ br_multicast_leave_group(struct net_bridge *br,
1425 if (!mp) 1424 if (!mp)
1426 goto out; 1425 goto out;
1427 1426
1427 if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
1428 struct net_bridge_port_group __rcu **pp;
1429
1430 for (pp = &mp->ports;
1431 (p = mlock_dereference(*pp, br)) != NULL;
1432 pp = &p->next) {
1433 if (p->port != port)
1434 continue;
1435
1436 rcu_assign_pointer(*pp, p->next);
1437 hlist_del_init(&p->mglist);
1438 del_timer(&p->timer);
1439 call_rcu_bh(&p->rcu, br_multicast_free_pg);
1440 br_mdb_notify(br->dev, port, group, RTM_DELMDB);
1441
1442 if (!mp->ports && !mp->mglist &&
1443 netif_running(br->dev))
1444 mod_timer(&mp->timer, jiffies);
1445 }
1446 goto out;
1447 }
1448
1449 if (timer_pending(&other_query->timer))
1450 goto out;
1451
1428 if (br->multicast_querier) { 1452 if (br->multicast_querier) {
1429 __br_multicast_send_query(br, port, &mp->addr); 1453 __br_multicast_send_query(br, port, &mp->addr);
1430 1454
@@ -1450,28 +1474,6 @@ br_multicast_leave_group(struct net_bridge *br,
1450 } 1474 }
1451 } 1475 }
1452 1476
1453 if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
1454 struct net_bridge_port_group __rcu **pp;
1455
1456 for (pp = &mp->ports;
1457 (p = mlock_dereference(*pp, br)) != NULL;
1458 pp = &p->next) {
1459 if (p->port != port)
1460 continue;
1461
1462 rcu_assign_pointer(*pp, p->next);
1463 hlist_del_init(&p->mglist);
1464 del_timer(&p->timer);
1465 call_rcu_bh(&p->rcu, br_multicast_free_pg);
1466 br_mdb_notify(br->dev, port, group, RTM_DELMDB);
1467
1468 if (!mp->ports && !mp->mglist &&
1469 netif_running(br->dev))
1470 mod_timer(&mp->timer, jiffies);
1471 }
1472 goto out;
1473 }
1474
1475 now = jiffies; 1477 now = jiffies;
1476 time = now + br->multicast_last_member_count * 1478 time = now + br->multicast_last_member_count *
1477 br->multicast_last_member_interval; 1479 br->multicast_last_member_interval;