diff options
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r-- | net/bridge/br_multicast.c | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 674224b6729d..c7a1095ed84a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -656,6 +656,15 @@ void br_multicast_del_port(struct net_bridge_port *port) | |||
656 | del_timer_sync(&port->multicast_router_timer); | 656 | del_timer_sync(&port->multicast_router_timer); |
657 | } | 657 | } |
658 | 658 | ||
659 | static void __br_multicast_enable_port(struct net_bridge_port *port) | ||
660 | { | ||
661 | port->multicast_startup_queries_sent = 0; | ||
662 | |||
663 | if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 || | ||
664 | del_timer(&port->multicast_query_timer)) | ||
665 | mod_timer(&port->multicast_query_timer, jiffies); | ||
666 | } | ||
667 | |||
659 | void br_multicast_enable_port(struct net_bridge_port *port) | 668 | void br_multicast_enable_port(struct net_bridge_port *port) |
660 | { | 669 | { |
661 | struct net_bridge *br = port->br; | 670 | struct net_bridge *br = port->br; |
@@ -664,11 +673,7 @@ void br_multicast_enable_port(struct net_bridge_port *port) | |||
664 | if (br->multicast_disabled || !netif_running(br->dev)) | 673 | if (br->multicast_disabled || !netif_running(br->dev)) |
665 | goto out; | 674 | goto out; |
666 | 675 | ||
667 | port->multicast_startup_queries_sent = 0; | 676 | __br_multicast_enable_port(port); |
668 | |||
669 | if (try_to_del_timer_sync(&port->multicast_query_timer) >= 0 || | ||
670 | del_timer(&port->multicast_query_timer)) | ||
671 | mod_timer(&port->multicast_query_timer, jiffies); | ||
672 | 677 | ||
673 | out: | 678 | out: |
674 | spin_unlock(&br->multicast_lock); | 679 | spin_unlock(&br->multicast_lock); |
@@ -1210,3 +1215,49 @@ unlock: | |||
1210 | 1215 | ||
1211 | return err; | 1216 | return err; |
1212 | } | 1217 | } |
1218 | |||
1219 | int br_multicast_toggle(struct net_bridge *br, unsigned long val) | ||
1220 | { | ||
1221 | struct net_bridge_port *port; | ||
1222 | int err = -ENOENT; | ||
1223 | |||
1224 | spin_lock(&br->multicast_lock); | ||
1225 | if (!netif_running(br->dev)) | ||
1226 | goto unlock; | ||
1227 | |||
1228 | err = 0; | ||
1229 | if (br->multicast_disabled == !val) | ||
1230 | goto unlock; | ||
1231 | |||
1232 | br->multicast_disabled = !val; | ||
1233 | if (br->multicast_disabled) | ||
1234 | goto unlock; | ||
1235 | |||
1236 | if (br->mdb) { | ||
1237 | if (br->mdb->old) { | ||
1238 | err = -EEXIST; | ||
1239 | rollback: | ||
1240 | br->multicast_disabled = !!val; | ||
1241 | goto unlock; | ||
1242 | } | ||
1243 | |||
1244 | err = br_mdb_rehash(&br->mdb, br->mdb->max, | ||
1245 | br->hash_elasticity); | ||
1246 | if (err) | ||
1247 | goto rollback; | ||
1248 | } | ||
1249 | |||
1250 | br_multicast_open(br); | ||
1251 | list_for_each_entry(port, &br->port_list, list) { | ||
1252 | if (port->state == BR_STATE_DISABLED || | ||
1253 | port->state == BR_STATE_BLOCKING) | ||
1254 | continue; | ||
1255 | |||
1256 | __br_multicast_enable_port(port); | ||
1257 | } | ||
1258 | |||
1259 | unlock: | ||
1260 | spin_unlock(&br->multicast_lock); | ||
1261 | |||
1262 | return err; | ||
1263 | } | ||