summaryrefslogtreecommitdiffstats
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
authorHerbert Xu2010-02-27 20:41:51 +0100
committerDavid S. Miller2010-02-28 09:49:46 +0100
commitb195167fcf089dbdc650bb874084555035f07f98 (patch)
tree9b0c491bd1e6e13472d074986869a9aafcb3ae3f /net/bridge/br_multicast.c
parentbridge: Add multicast_snooping sysfs toggle (diff)
downloadkernel-qcow2-linux-b195167fcf089dbdc650bb874084555035f07f98.tar.gz
kernel-qcow2-linux-b195167fcf089dbdc650bb874084555035f07f98.tar.xz
kernel-qcow2-linux-b195167fcf089dbdc650bb874084555035f07f98.zip
bridge: Add hash elasticity/max sysfs entries
This patch allows the user to control the hash elasticity/max parameters. The elasticity setting does not take effect until the next new multicast group is added. At which point it is checked and if after rehashing it still can't be satisfied then snooping will be disabled. The max setting on the other hand takes effect immediately. It must be a power of two and cannot be set to a value less than the current number of multicast group entries. This is the only way to shrink the multicast hash. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r--net/bridge/br_multicast.c41
1 files changed, 41 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 @@
#include <linux/igmp.h>
#include <linux/jhash.h>
#include <linux/kernel.h>
+#include <linux/log2.h>
#include <linux/netdevice.h>
#include <linux/netfilter_bridge.h>
#include <linux/random.h>
@@ -1261,3 +1262,43 @@ unlock:
return err;
}
+
+int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
+{
+ int err = -ENOENT;
+ u32 old;
+
+ spin_lock(&br->multicast_lock);
+ if (!netif_running(br->dev))
+ goto unlock;
+
+ err = -EINVAL;
+ if (!is_power_of_2(val))
+ goto unlock;
+ if (br->mdb && val < br->mdb->size)
+ goto unlock;
+
+ err = 0;
+
+ old = br->hash_max;
+ br->hash_max = val;
+
+ if (br->mdb) {
+ if (br->mdb->old) {
+ err = -EEXIST;
+rollback:
+ br->hash_max = old;
+ goto unlock;
+ }
+
+ err = br_mdb_rehash(&br->mdb, br->hash_max,
+ br->hash_elasticity);
+ if (err)
+ goto rollback;
+ }
+
+unlock:
+ spin_unlock(&br->multicast_lock);
+
+ return err;
+}