Commit 3f890923 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

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: default avatarStephen Hemminger <shemminger@linux-foundation.org>
parent 467aea0d
...@@ -20,19 +20,24 @@ ...@@ -20,19 +20,24 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/jhash.h> #include <linux/jhash.h>
#include <linux/random.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/unaligned.h>
#include "br_private.h" #include "br_private.h"
static struct kmem_cache *br_fdb_cache __read_mostly; static struct kmem_cache *br_fdb_cache __read_mostly;
static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
const unsigned char *addr); const unsigned char *addr);
static u32 fdb_salt __read_mostly;
void __init br_fdb_init(void) void __init br_fdb_init(void)
{ {
br_fdb_cache = kmem_cache_create("bridge_fdb_cache", br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
sizeof(struct net_bridge_fdb_entry), sizeof(struct net_bridge_fdb_entry),
0, 0,
SLAB_HWCACHE_ALIGN, NULL, NULL); SLAB_HWCACHE_ALIGN, NULL, NULL);
get_random_bytes(&fdb_salt, sizeof(fdb_salt));
} }
void __exit br_fdb_fini(void) void __exit br_fdb_fini(void)
...@@ -44,24 +49,26 @@ 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) /* if topology_changing then use forward_delay (default 15 sec)
* otherwise keep longer (default 5 minutes) * 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; 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) const struct net_bridge_fdb_entry *fdb)
{ {
return !fdb->is_static return !fdb->is_static
&& time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); && 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); hlist_del_rcu(&f->hlist);
br_fdb_put(f); br_fdb_put(f);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment