aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_multicast.c61
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/bridge/br_sysfs_br.c18
3 files changed, 75 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
659static 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
659void br_multicast_enable_port(struct net_bridge_port *port) 668void 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
673out: 678out:
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
1219int 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;
1239rollback:
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
1259unlock:
1260 spin_unlock(&br->multicast_lock);
1261
1262 return err;
1263}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index dcdfafbe4b17..bf162fa6b23b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -300,6 +300,7 @@ extern void br_multicast_forward(struct net_bridge_mdb_entry *mdst,
300extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); 300extern int br_multicast_set_router(struct net_bridge *br, unsigned long val);
301extern int br_multicast_set_port_router(struct net_bridge_port *p, 301extern int br_multicast_set_port_router(struct net_bridge_port *p,
302 unsigned long val); 302 unsigned long val);
303extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
303#else 304#else
304static inline int br_multicast_rcv(struct net_bridge *br, 305static inline int br_multicast_rcv(struct net_bridge *br,
305 struct net_bridge_port *port, 306 struct net_bridge_port *port,
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index cb742016db21..0ab288332fc5 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -361,6 +361,23 @@ static ssize_t store_multicast_router(struct device *d,
361} 361}
362static DEVICE_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, 362static DEVICE_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
363 store_multicast_router); 363 store_multicast_router);
364
365static ssize_t show_multicast_snooping(struct device *d,
366 struct device_attribute *attr,
367 char *buf)
368{
369 struct net_bridge *br = to_bridge(d);
370 return sprintf(buf, "%d\n", !br->multicast_disabled);
371}
372
373static ssize_t store_multicast_snooping(struct device *d,
374 struct device_attribute *attr,
375 const char *buf, size_t len)
376{
377 return store_bridge_parm(d, buf, len, br_multicast_toggle);
378}
379static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
380 show_multicast_snooping, store_multicast_snooping);
364#endif 381#endif
365 382
366static struct attribute *bridge_attrs[] = { 383static struct attribute *bridge_attrs[] = {
@@ -384,6 +401,7 @@ static struct attribute *bridge_attrs[] = {
384 &dev_attr_flush.attr, 401 &dev_attr_flush.attr,
385#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 402#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
386 &dev_attr_multicast_router.attr, 403 &dev_attr_multicast_router.attr,
404 &dev_attr_multicast_snooping.attr,
387#endif 405#endif
388 NULL 406 NULL
389}; 407};