aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/br_multicast.c41
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/bridge/br_sysfs_br.c39
3 files changed, 81 insertions, 0 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index c7a1095ed84a..2559fb539836 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -15,6 +15,7 @@
15#include <linux/igmp.h> 15#include <linux/igmp.h>
16#include <linux/jhash.h> 16#include <linux/jhash.h>
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/log2.h>
18#include <linux/netdevice.h> 19#include <linux/netdevice.h>
19#include <linux/netfilter_bridge.h> 20#include <linux/netfilter_bridge.h>
20#include <linux/random.h> 21#include <linux/random.h>
@@ -1261,3 +1262,43 @@ unlock:
1261 1262
1262 return err; 1263 return err;
1263} 1264}
1265
1266int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
1267{
1268 int err = -ENOENT;
1269 u32 old;
1270
1271 spin_lock(&br->multicast_lock);
1272 if (!netif_running(br->dev))
1273 goto unlock;
1274
1275 err = -EINVAL;
1276 if (!is_power_of_2(val))
1277 goto unlock;
1278 if (br->mdb && val < br->mdb->size)
1279 goto unlock;
1280
1281 err = 0;
1282
1283 old = br->hash_max;
1284 br->hash_max = val;
1285
1286 if (br->mdb) {
1287 if (br->mdb->old) {
1288 err = -EEXIST;
1289rollback:
1290 br->hash_max = old;
1291 goto unlock;
1292 }
1293
1294 err = br_mdb_rehash(&br->mdb, br->hash_max,
1295 br->hash_elasticity);
1296 if (err)
1297 goto rollback;
1298 }
1299
1300unlock:
1301 spin_unlock(&br->multicast_lock);
1302
1303 return err;
1304}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bf162fa6b23b..9191198c4f1b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -301,6 +301,7 @@ extern 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); 303extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
304extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
304#else 305#else
305static inline int br_multicast_rcv(struct net_bridge *br, 306static inline int br_multicast_rcv(struct net_bridge *br,
306 struct net_bridge_port *port, 307 struct net_bridge_port *port,
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 0ab288332fc5..d2ee53b3ad7d 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -378,6 +378,43 @@ static ssize_t store_multicast_snooping(struct device *d,
378} 378}
379static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, 379static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
380 show_multicast_snooping, store_multicast_snooping); 380 show_multicast_snooping, store_multicast_snooping);
381
382static ssize_t show_hash_elasticity(struct device *d,
383 struct device_attribute *attr, char *buf)
384{
385 struct net_bridge *br = to_bridge(d);
386 return sprintf(buf, "%u\n", br->hash_elasticity);
387}
388
389static int set_elasticity(struct net_bridge *br, unsigned long val)
390{
391 br->hash_elasticity = val;
392 return 0;
393}
394
395static ssize_t store_hash_elasticity(struct device *d,
396 struct device_attribute *attr,
397 const char *buf, size_t len)
398{
399 return store_bridge_parm(d, buf, len, set_elasticity);
400}
401static DEVICE_ATTR(hash_elasticity, S_IRUGO | S_IWUSR, show_hash_elasticity,
402 store_hash_elasticity);
403
404static ssize_t show_hash_max(struct device *d, struct device_attribute *attr,
405 char *buf)
406{
407 struct net_bridge *br = to_bridge(d);
408 return sprintf(buf, "%u\n", br->hash_max);
409}
410
411static ssize_t store_hash_max(struct device *d, struct device_attribute *attr,
412 const char *buf, size_t len)
413{
414 return store_bridge_parm(d, buf, len, br_multicast_set_hash_max);
415}
416static DEVICE_ATTR(hash_max, S_IRUGO | S_IWUSR, show_hash_max,
417 store_hash_max);
381#endif 418#endif
382 419
383static struct attribute *bridge_attrs[] = { 420static struct attribute *bridge_attrs[] = {
@@ -402,6 +439,8 @@ static struct attribute *bridge_attrs[] = {
402#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 439#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
403 &dev_attr_multicast_router.attr, 440 &dev_attr_multicast_router.attr,
404 &dev_attr_multicast_snooping.attr, 441 &dev_attr_multicast_snooping.attr,
442 &dev_attr_hash_elasticity.attr,
443 &dev_attr_hash_max.attr,
405#endif 444#endif
406 NULL 445 NULL
407}; 446};