aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_multicast.c29
-rw-r--r--net/bridge/br_private.h1
3 files changed, 24 insertions, 7 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a538cb1199a3..45e4757c6fd2 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -281,6 +281,7 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
281 br_fdb_delete_by_port(br, NULL, 0, 1); 281 br_fdb_delete_by_port(br, NULL, 0, 1);
282 282
283 br_vlan_flush(br); 283 br_vlan_flush(br);
284 br_multicast_dev_del(br);
284 del_timer_sync(&br->gc_timer); 285 del_timer_sync(&br->gc_timer);
285 286
286 br_sysfs_delbr(br->dev); 287 br_sysfs_delbr(br->dev);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 5a44cd9473f2..0dd3cd90962c 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -273,6 +273,8 @@ static void br_multicast_del_pg(struct net_bridge *br,
273 rcu_assign_pointer(*pp, p->next); 273 rcu_assign_pointer(*pp, p->next);
274 hlist_del_init(&p->mglist); 274 hlist_del_init(&p->mglist);
275 del_timer(&p->timer); 275 del_timer(&p->timer);
276 br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB,
277 p->state);
276 call_rcu_bh(&p->rcu, br_multicast_free_pg); 278 call_rcu_bh(&p->rcu, br_multicast_free_pg);
277 279
278 if (!mp->ports && !mp->mglist && 280 if (!mp->ports && !mp->mglist &&
@@ -914,6 +916,15 @@ void br_multicast_add_port(struct net_bridge_port *port)
914 916
915void br_multicast_del_port(struct net_bridge_port *port) 917void br_multicast_del_port(struct net_bridge_port *port)
916{ 918{
919 struct net_bridge *br = port->br;
920 struct net_bridge_port_group *pg;
921 struct hlist_node *n;
922
923 /* Take care of the remaining groups, only perm ones should be left */
924 spin_lock_bh(&br->multicast_lock);
925 hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
926 br_multicast_del_pg(br, pg);
927 spin_unlock_bh(&br->multicast_lock);
917 del_timer_sync(&port->multicast_router_timer); 928 del_timer_sync(&port->multicast_router_timer);
918} 929}
919 930
@@ -953,7 +964,8 @@ void br_multicast_disable_port(struct net_bridge_port *port)
953 964
954 spin_lock(&br->multicast_lock); 965 spin_lock(&br->multicast_lock);
955 hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) 966 hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
956 br_multicast_del_pg(br, pg); 967 if (pg->state == MDB_TEMPORARY)
968 br_multicast_del_pg(br, pg);
957 969
958 if (!hlist_unhashed(&port->rlist)) 970 if (!hlist_unhashed(&port->rlist))
959 hlist_del_init_rcu(&port->rlist); 971 hlist_del_init_rcu(&port->rlist);
@@ -1730,12 +1742,6 @@ void br_multicast_open(struct net_bridge *br)
1730 1742
1731void br_multicast_stop(struct net_bridge *br) 1743void br_multicast_stop(struct net_bridge *br)
1732{ 1744{
1733 struct net_bridge_mdb_htable *mdb;
1734 struct net_bridge_mdb_entry *mp;
1735 struct hlist_node *n;
1736 u32 ver;
1737 int i;
1738
1739 del_timer_sync(&br->multicast_router_timer); 1745 del_timer_sync(&br->multicast_router_timer);
1740 del_timer_sync(&br->ip4_other_query.timer); 1746 del_timer_sync(&br->ip4_other_query.timer);
1741 del_timer_sync(&br->ip4_own_query.timer); 1747 del_timer_sync(&br->ip4_own_query.timer);
@@ -1743,6 +1749,15 @@ void br_multicast_stop(struct net_bridge *br)
1743 del_timer_sync(&br->ip6_other_query.timer); 1749 del_timer_sync(&br->ip6_other_query.timer);
1744 del_timer_sync(&br->ip6_own_query.timer); 1750 del_timer_sync(&br->ip6_own_query.timer);
1745#endif 1751#endif
1752}
1753
1754void br_multicast_dev_del(struct net_bridge *br)
1755{
1756 struct net_bridge_mdb_htable *mdb;
1757 struct net_bridge_mdb_entry *mp;
1758 struct hlist_node *n;
1759 u32 ver;
1760 int i;
1746 1761
1747 spin_lock_bh(&br->multicast_lock); 1762 spin_lock_bh(&br->multicast_lock);
1748 mdb = mlock_dereference(br->mdb, br); 1763 mdb = mlock_dereference(br->mdb, br);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c73fd785654d..2bada2279721 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -466,6 +466,7 @@ void br_multicast_disable_port(struct net_bridge_port *port);
466void br_multicast_init(struct net_bridge *br); 466void br_multicast_init(struct net_bridge *br);
467void br_multicast_open(struct net_bridge *br); 467void br_multicast_open(struct net_bridge *br);
468void br_multicast_stop(struct net_bridge *br); 468void br_multicast_stop(struct net_bridge *br);
469void br_multicast_dev_del(struct net_bridge *br);
469void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, 470void br_multicast_deliver(struct net_bridge_mdb_entry *mdst,
470 struct sk_buff *skb); 471 struct sk_buff *skb);
471void br_multicast_forward(struct net_bridge_mdb_entry *mdst, 472void br_multicast_forward(struct net_bridge_mdb_entry *mdst,