diff options
| -rw-r--r-- | net/bridge/br_if.c | 1 | ||||
| -rw-r--r-- | net/bridge/br_multicast.c | 29 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 1 |
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 | ||
| 915 | void br_multicast_del_port(struct net_bridge_port *port) | 917 | void 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 | ||
| 1731 | void br_multicast_stop(struct net_bridge *br) | 1743 | void 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 | |||
| 1754 | void 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); | |||
| 466 | void br_multicast_init(struct net_bridge *br); | 466 | void br_multicast_init(struct net_bridge *br); |
| 467 | void br_multicast_open(struct net_bridge *br); | 467 | void br_multicast_open(struct net_bridge *br); |
| 468 | void br_multicast_stop(struct net_bridge *br); | 468 | void br_multicast_stop(struct net_bridge *br); |
| 469 | void br_multicast_dev_del(struct net_bridge *br); | ||
| 469 | void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, | 470 | void br_multicast_deliver(struct net_bridge_mdb_entry *mdst, |
| 470 | struct sk_buff *skb); | 471 | struct sk_buff *skb); |
| 471 | void br_multicast_forward(struct net_bridge_mdb_entry *mdst, | 472 | void br_multicast_forward(struct net_bridge_mdb_entry *mdst, |
