Skip to content

Commit b195167

Browse files
herbertxdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 561f110 commit b195167

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

net/bridge/br_multicast.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/igmp.h>
1616
#include <linux/jhash.h>
1717
#include <linux/kernel.h>
18+
#include <linux/log2.h>
1819
#include <linux/netdevice.h>
1920
#include <linux/netfilter_bridge.h>
2021
#include <linux/random.h>
@@ -1261,3 +1262,43 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
12611262

12621263
return err;
12631264
}
1265+
1266+
int 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;
1289+
rollback:
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+
1300+
unlock:
1301+
spin_unlock(&br->multicast_lock);
1302+
1303+
return err;
1304+
}

net/bridge/br_private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val);
301301
extern int br_multicast_set_port_router(struct net_bridge_port *p,
302302
unsigned long val);
303303
extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
304+
extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
304305
#else
305306
static inline int br_multicast_rcv(struct net_bridge *br,
306307
struct net_bridge_port *port,

net/bridge/br_sysfs_br.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,43 @@ static ssize_t store_multicast_snooping(struct device *d,
378378
}
379379
static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR,
380380
show_multicast_snooping, store_multicast_snooping);
381+
382+
static 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+
389+
static int set_elasticity(struct net_bridge *br, unsigned long val)
390+
{
391+
br->hash_elasticity = val;
392+
return 0;
393+
}
394+
395+
static 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+
}
401+
static DEVICE_ATTR(hash_elasticity, S_IRUGO | S_IWUSR, show_hash_elasticity,
402+
store_hash_elasticity);
403+
404+
static 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+
411+
static 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+
}
416+
static DEVICE_ATTR(hash_max, S_IRUGO | S_IWUSR, show_hash_max,
417+
store_hash_max);
381418
#endif
382419

383420
static struct attribute *bridge_attrs[] = {
@@ -402,6 +439,8 @@ static struct attribute *bridge_attrs[] = {
402439
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
403440
&dev_attr_multicast_router.attr,
404441
&dev_attr_multicast_snooping.attr,
442+
&dev_attr_hash_elasticity.attr,
443+
&dev_attr_hash_max.attr,
405444
#endif
406445
NULL
407446
};

0 commit comments

Comments
 (0)