diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-03-21 13:42:33 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-25 22:28:46 -0700 |
commit | 3f890923182aeebc572f3818dd51c9014827e0ec (patch) | |
tree | 58831f297f8f8c6260d71b512176b7bd26dfe7db /net/bridge/br_fdb.c | |
parent | 467aea0ddfd1f0f1158c57cbef0e8941dd63374c (diff) | |
download | lwn-3f890923182aeebc572f3818dd51c9014827e0ec.tar.gz lwn-3f890923182aeebc572f3818dd51c9014827e0ec.zip |
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.c | 17 |
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); |