diff options
-rw-r--r-- | net/bridge/br_mdb.c | 10 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 50 | ||||
-rw-r--r-- | net/bridge/br_private.h | 3 |
3 files changed, 28 insertions, 35 deletions
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index da5ed4cf9233..9a975e2a2489 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -764,16 +764,8 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (p->port->state == BR_STATE_DISABLED) goto unlock; - __mdb_entry_fill_flags(entry, p->flags); - rcu_assign_pointer(*pp, p->next); - hlist_del_init(&p->mglist); - del_timer(&p->timer); - kfree_rcu(p, rcu); + br_multicast_del_pg(mp, p, pp); err = 0; - - if (!mp->ports && !mp->host_joined && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); break; } diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 4c4a93abde68..e1739652f859 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -163,8 +163,24 @@ out: spin_unlock(&br->multicast_lock); } -static void br_multicast_del_pg(struct net_bridge *br, - struct net_bridge_port_group *pg) +void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, + struct net_bridge_port_group __rcu **pp) +{ + struct net_bridge *br = pg->port->br; + + rcu_assign_pointer(*pp, pg->next); + hlist_del_init(&pg->mglist); + del_timer(&pg->timer); + br_mdb_notify(br->dev, pg->port, &pg->addr, RTM_DELMDB, pg->flags); + kfree_rcu(pg, rcu); + + if (!mp->ports && !mp->host_joined && netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); +} + +static void br_multicast_find_del_pg(struct net_bridge *br, + struct net_bridge_port_group *pg) { struct net_bridge_mdb_entry *mp; struct net_bridge_port_group *p; @@ -180,17 +196,7 @@ static void br_multicast_del_pg(struct net_bridge *br, if (p != pg) continue; - rcu_assign_pointer(*pp, p->next); - hlist_del_init(&p->mglist); - del_timer(&p->timer); - br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB, - p->flags); - kfree_rcu(p, rcu); - - if (!mp->ports && !mp->host_joined && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); - + br_multicast_del_pg(mp, pg, pp); return; } @@ -207,7 +213,7 @@ static void br_multicast_port_group_expired(struct timer_list *t) hlist_unhashed(&pg->mglist) || pg->flags & MDB_PG_FLAGS_PERMANENT) goto out; - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); out: spin_unlock(&br->multicast_lock); @@ -852,7 +858,7 @@ void br_multicast_del_port(struct net_bridge_port *port) /* Take care of the remaining groups, only perm ones should be left */ spin_lock_bh(&br->multicast_lock); hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); spin_unlock_bh(&br->multicast_lock); del_timer_sync(&port->multicast_router_timer); free_percpu(port->mcast_stats); @@ -901,7 +907,7 @@ void br_multicast_disable_port(struct net_bridge_port *port) spin_lock(&br->multicast_lock); hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) if (!(pg->flags & MDB_PG_FLAGS_PERMANENT)) - br_multicast_del_pg(br, pg); + br_multicast_find_del_pg(br, pg); __del_port_router(port); @@ -1407,16 +1413,8 @@ br_multicast_leave_group(struct net_bridge *br, if (p->flags & MDB_PG_FLAGS_PERMANENT) break; - rcu_assign_pointer(*pp, p->next); - hlist_del_init(&p->mglist); - del_timer(&p->timer); - kfree_rcu(p, rcu); - br_mdb_notify(br->dev, port, group, RTM_DELMDB, - p->flags | MDB_PG_FLAGS_FAST_LEAVE); - - if (!mp->ports && !mp->host_joined && - netif_running(br->dev)) - mod_timer(&mp->timer, jiffies); + p->flags |= MDB_PG_FLAGS_FAST_LEAVE; + br_multicast_del_pg(mp, p, pp); } goto out; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 357b6905ecef..800e9b91483c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -777,6 +777,9 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, struct br_ip *group, int type, u8 flags); void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, int type); +void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, + struct net_bridge_port_group *pg, + struct net_bridge_port_group __rcu **pp); void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p, const struct sk_buff *skb, u8 type, u8 dir); int br_multicast_init_stats(struct net_bridge *br); |