diff options
| -rw-r--r-- | net/bridge/br_mdb.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_multicast.c | 47 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 1 |
3 files changed, 28 insertions, 22 deletions
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 85a09bb5ca51..b7b1914dfa25 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
| @@ -453,7 +453,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) | |||
| 453 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 453 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
| 454 | err = 0; | 454 | err = 0; |
| 455 | 455 | ||
| 456 | if (!mp->ports && !mp->mglist && mp->timer_armed && | 456 | if (!mp->ports && !mp->mglist && |
| 457 | netif_running(br->dev)) | 457 | netif_running(br->dev)) |
| 458 | mod_timer(&mp->timer, jiffies); | 458 | mod_timer(&mp->timer, jiffies); |
| 459 | break; | 459 | break; |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 1085f2180f3a..8b0b610ca2c9 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -272,7 +272,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
| 272 | del_timer(&p->timer); | 272 | del_timer(&p->timer); |
| 273 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 273 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
| 274 | 274 | ||
| 275 | if (!mp->ports && !mp->mglist && mp->timer_armed && | 275 | if (!mp->ports && !mp->mglist && |
| 276 | netif_running(br->dev)) | 276 | netif_running(br->dev)) |
| 277 | mod_timer(&mp->timer, jiffies); | 277 | mod_timer(&mp->timer, jiffies); |
| 278 | 278 | ||
| @@ -611,9 +611,6 @@ rehash: | |||
| 611 | break; | 611 | break; |
| 612 | 612 | ||
| 613 | default: | 613 | default: |
| 614 | /* If we have an existing entry, update it's expire timer */ | ||
| 615 | mod_timer(&mp->timer, | ||
| 616 | jiffies + br->multicast_membership_interval); | ||
| 617 | goto out; | 614 | goto out; |
| 618 | } | 615 | } |
| 619 | 616 | ||
| @@ -623,7 +620,6 @@ rehash: | |||
| 623 | 620 | ||
| 624 | mp->br = br; | 621 | mp->br = br; |
| 625 | mp->addr = *group; | 622 | mp->addr = *group; |
| 626 | |||
| 627 | setup_timer(&mp->timer, br_multicast_group_expired, | 623 | setup_timer(&mp->timer, br_multicast_group_expired, |
| 628 | (unsigned long)mp); | 624 | (unsigned long)mp); |
| 629 | 625 | ||
| @@ -663,6 +659,7 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 663 | struct net_bridge_mdb_entry *mp; | 659 | struct net_bridge_mdb_entry *mp; |
| 664 | struct net_bridge_port_group *p; | 660 | struct net_bridge_port_group *p; |
| 665 | struct net_bridge_port_group __rcu **pp; | 661 | struct net_bridge_port_group __rcu **pp; |
| 662 | unsigned long now = jiffies; | ||
| 666 | int err; | 663 | int err; |
| 667 | 664 | ||
| 668 | spin_lock(&br->multicast_lock); | 665 | spin_lock(&br->multicast_lock); |
| @@ -677,18 +674,15 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 677 | 674 | ||
| 678 | if (!port) { | 675 | if (!port) { |
| 679 | mp->mglist = true; | 676 | mp->mglist = true; |
| 677 | mod_timer(&mp->timer, now + br->multicast_membership_interval); | ||
| 680 | goto out; | 678 | goto out; |
| 681 | } | 679 | } |
| 682 | 680 | ||
| 683 | for (pp = &mp->ports; | 681 | for (pp = &mp->ports; |
| 684 | (p = mlock_dereference(*pp, br)) != NULL; | 682 | (p = mlock_dereference(*pp, br)) != NULL; |
| 685 | pp = &p->next) { | 683 | pp = &p->next) { |
| 686 | if (p->port == port) { | 684 | if (p->port == port) |
| 687 | /* We already have a portgroup, update the timer. */ | 685 | goto found; |
| 688 | mod_timer(&p->timer, | ||
| 689 | jiffies + br->multicast_membership_interval); | ||
| 690 | goto out; | ||
| 691 | } | ||
| 692 | if ((unsigned long)p->port < (unsigned long)port) | 686 | if ((unsigned long)p->port < (unsigned long)port) |
| 693 | break; | 687 | break; |
| 694 | } | 688 | } |
| @@ -699,6 +693,8 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
| 699 | rcu_assign_pointer(*pp, p); | 693 | rcu_assign_pointer(*pp, p); |
| 700 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB); | 694 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB); |
| 701 | 695 | ||
| 696 | found: | ||
| 697 | mod_timer(&p->timer, now + br->multicast_membership_interval); | ||
| 702 | out: | 698 | out: |
| 703 | err = 0; | 699 | err = 0; |
| 704 | 700 | ||
| @@ -1198,9 +1194,6 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
| 1198 | if (!mp) | 1194 | if (!mp) |
| 1199 | goto out; | 1195 | goto out; |
| 1200 | 1196 | ||
| 1201 | mod_timer(&mp->timer, now + br->multicast_membership_interval); | ||
| 1202 | mp->timer_armed = true; | ||
| 1203 | |||
| 1204 | max_delay *= br->multicast_last_member_count; | 1197 | max_delay *= br->multicast_last_member_count; |
| 1205 | 1198 | ||
| 1206 | if (mp->mglist && | 1199 | if (mp->mglist && |
| @@ -1277,9 +1270,6 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
| 1277 | if (!mp) | 1270 | if (!mp) |
| 1278 | goto out; | 1271 | goto out; |
| 1279 | 1272 | ||
| 1280 | mod_timer(&mp->timer, now + br->multicast_membership_interval); | ||
| 1281 | mp->timer_armed = true; | ||
| 1282 | |||
| 1283 | max_delay *= br->multicast_last_member_count; | 1273 | max_delay *= br->multicast_last_member_count; |
| 1284 | if (mp->mglist && | 1274 | if (mp->mglist && |
| 1285 | (timer_pending(&mp->timer) ? | 1275 | (timer_pending(&mp->timer) ? |
| @@ -1365,7 +1355,7 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
| 1365 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 1355 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
| 1366 | br_mdb_notify(br->dev, port, group, RTM_DELMDB); | 1356 | br_mdb_notify(br->dev, port, group, RTM_DELMDB); |
| 1367 | 1357 | ||
| 1368 | if (!mp->ports && !mp->mglist && mp->timer_armed && | 1358 | if (!mp->ports && !mp->mglist && |
| 1369 | netif_running(br->dev)) | 1359 | netif_running(br->dev)) |
| 1370 | mod_timer(&mp->timer, jiffies); | 1360 | mod_timer(&mp->timer, jiffies); |
| 1371 | } | 1361 | } |
| @@ -1377,12 +1367,30 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
| 1377 | br->multicast_last_member_interval; | 1367 | br->multicast_last_member_interval; |
| 1378 | 1368 | ||
| 1379 | if (!port) { | 1369 | if (!port) { |
| 1380 | if (mp->mglist && mp->timer_armed && | 1370 | if (mp->mglist && |
| 1381 | (timer_pending(&mp->timer) ? | 1371 | (timer_pending(&mp->timer) ? |
| 1382 | time_after(mp->timer.expires, time) : | 1372 | time_after(mp->timer.expires, time) : |
| 1383 | try_to_del_timer_sync(&mp->timer) >= 0)) { | 1373 | try_to_del_timer_sync(&mp->timer) >= 0)) { |
| 1384 | mod_timer(&mp->timer, time); | 1374 | mod_timer(&mp->timer, time); |
| 1385 | } | 1375 | } |
| 1376 | |||
| 1377 | goto out; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | for (p = mlock_dereference(mp->ports, br); | ||
| 1381 | p != NULL; | ||
| 1382 | p = mlock_dereference(p->next, br)) { | ||
| 1383 | if (p->port != port) | ||
| 1384 | continue; | ||
| 1385 | |||
| 1386 | if (!hlist_unhashed(&p->mglist) && | ||
| 1387 | (timer_pending(&p->timer) ? | ||
| 1388 | time_after(p->timer.expires, time) : | ||
| 1389 | try_to_del_timer_sync(&p->timer) >= 0)) { | ||
| 1390 | mod_timer(&p->timer, time); | ||
| 1391 | } | ||
| 1392 | |||
| 1393 | break; | ||
| 1386 | } | 1394 | } |
| 1387 | out: | 1395 | out: |
| 1388 | spin_unlock(&br->multicast_lock); | 1396 | spin_unlock(&br->multicast_lock); |
| @@ -1805,7 +1813,6 @@ void br_multicast_stop(struct net_bridge *br) | |||
| 1805 | hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], | 1813 | hlist_for_each_entry_safe(mp, n, &mdb->mhash[i], |
| 1806 | hlist[ver]) { | 1814 | hlist[ver]) { |
| 1807 | del_timer(&mp->timer); | 1815 | del_timer(&mp->timer); |
| 1808 | mp->timer_armed = false; | ||
| 1809 | call_rcu_bh(&mp->rcu, br_multicast_free_group); | 1816 | call_rcu_bh(&mp->rcu, br_multicast_free_group); |
| 1810 | } | 1817 | } |
| 1811 | } | 1818 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 7ca2ae45b2d5..e14c33b42f75 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -126,7 +126,6 @@ struct net_bridge_mdb_entry | |||
| 126 | struct timer_list timer; | 126 | struct timer_list timer; |
| 127 | struct br_ip addr; | 127 | struct br_ip addr; |
| 128 | bool mglist; | 128 | bool mglist; |
| 129 | bool timer_armed; | ||
| 130 | }; | 129 | }; |
| 131 | 130 | ||
| 132 | struct net_bridge_mdb_htable | 131 | struct net_bridge_mdb_htable |
