diff options
author | Satish Ashok <sashok@cumulusnetworks.com> | 2015-07-28 06:28:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-07-29 17:57:05 -0400 |
commit | 544586f742b43c6fd5fcb74c794d33b2ef189e64 (patch) | |
tree | 09b81a555a01a17aa21f3ff61545ececed53875d | |
parent | df356d5e81b04dd51dd9f23f2bce7d73dd929899 (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.c | 50 |
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; |