summaryrefslogtreecommitdiff
path: root/net/bridge/br_fdb.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-03-21 23:42:33 +0300
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 09:28:46 +0400
commit3f890923182aeebc572f3818dd51c9014827e0ec (patch)
tree58831f297f8f8c6260d71b512176b7bd26dfe7db /net/bridge/br_fdb.c
parent467aea0ddfd1f0f1158c57cbef0e8941dd63374c (diff)
downloadlinux-3f890923182aeebc572f3818dd51c9014827e0ec.tar.xz
bridge: simpler hash with salt
Instead of hashing the whole Ethernet address, it should be faster to just use the last 4 bytes. Add a random salt value to the hash to make it more difficult to construct worst case DoS hash chains. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Diffstat (limited to 'net/bridge/br_fdb.c')
-rw-r--r--net/bridge/br_fdb.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 8d566c13cc73..dd5a5d5fb280 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -20,19 +20,24 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/jhash.h>
+#include <linux/random.h>
#include <asm/atomic.h>
+#include <asm/unaligned.h>
#include "br_private.h"
static struct kmem_cache *br_fdb_cache __read_mostly;
static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
const unsigned char *addr);
+static u32 fdb_salt __read_mostly;
+
void __init br_fdb_init(void)
{
br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
sizeof(struct net_bridge_fdb_entry),
0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
+ get_random_bytes(&fdb_salt, sizeof(fdb_salt));
}
void __exit br_fdb_fini(void)
@@ -44,24 +49,26 @@ void __exit br_fdb_fini(void)
/* if topology_changing then use forward_delay (default 15 sec)
* otherwise keep longer (default 5 minutes)
*/
-static __inline__ unsigned long hold_time(const struct net_bridge *br)
+static inline unsigned long hold_time(const struct net_bridge *br)
{
return br->topology_change ? br->forward_delay : br->ageing_time;
}
-static __inline__ int has_expired(const struct net_bridge *br,
+static inline int has_expired(const struct net_bridge *br,
const struct net_bridge_fdb_entry *fdb)
{
return !fdb->is_static
&& time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
}
-static __inline__ int br_mac_hash(const unsigned char *mac)
+static inline int br_mac_hash(const unsigned char *mac)
{
- return jhash(mac, ETH_ALEN, 0) & (BR_HASH_SIZE - 1);
+ /* use 1 byte of OUI cnd 3 bytes of NIC */
+ u32 key = get_unaligned((u32 *)(mac + 2));
+ return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1);
}
-static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f)
+static inline void fdb_delete(struct net_bridge_fdb_entry *f)
{
hlist_del_rcu(&f->hlist);
br_fdb_put(f);