Commit 3f890923182aeebc572f3818dd51c9014827e0ec
Committed by
David S. Miller
1 parent
467aea0ddf
Exists in
master
and in
7 other branches
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>
Showing 1 changed file with 12 additions and 5 deletions Side-by-side Diff
net/bridge/br_fdb.c
... | ... | @@ -20,19 +20,24 @@ |
20 | 20 | #include <linux/netdevice.h> |
21 | 21 | #include <linux/etherdevice.h> |
22 | 22 | #include <linux/jhash.h> |
23 | +#include <linux/random.h> | |
23 | 24 | #include <asm/atomic.h> |
25 | +#include <asm/unaligned.h> | |
24 | 26 | #include "br_private.h" |
25 | 27 | |
26 | 28 | static struct kmem_cache *br_fdb_cache __read_mostly; |
27 | 29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
28 | 30 | const unsigned char *addr); |
29 | 31 | |
32 | +static u32 fdb_salt __read_mostly; | |
33 | + | |
30 | 34 | void __init br_fdb_init(void) |
31 | 35 | { |
32 | 36 | br_fdb_cache = kmem_cache_create("bridge_fdb_cache", |
33 | 37 | sizeof(struct net_bridge_fdb_entry), |
34 | 38 | 0, |
35 | 39 | SLAB_HWCACHE_ALIGN, NULL, NULL); |
40 | + get_random_bytes(&fdb_salt, sizeof(fdb_salt)); | |
36 | 41 | } |
37 | 42 | |
38 | 43 | void __exit br_fdb_fini(void) |
39 | 44 | |
40 | 45 | |
41 | 46 | |
42 | 47 | |
... | ... | @@ -44,24 +49,26 @@ |
44 | 49 | /* if topology_changing then use forward_delay (default 15 sec) |
45 | 50 | * otherwise keep longer (default 5 minutes) |
46 | 51 | */ |
47 | -static __inline__ unsigned long hold_time(const struct net_bridge *br) | |
52 | +static inline unsigned long hold_time(const struct net_bridge *br) | |
48 | 53 | { |
49 | 54 | return br->topology_change ? br->forward_delay : br->ageing_time; |
50 | 55 | } |
51 | 56 | |
52 | -static __inline__ int has_expired(const struct net_bridge *br, | |
57 | +static inline int has_expired(const struct net_bridge *br, | |
53 | 58 | const struct net_bridge_fdb_entry *fdb) |
54 | 59 | { |
55 | 60 | return !fdb->is_static |
56 | 61 | && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); |
57 | 62 | } |
58 | 63 | |
59 | -static __inline__ int br_mac_hash(const unsigned char *mac) | |
64 | +static inline int br_mac_hash(const unsigned char *mac) | |
60 | 65 | { |
61 | - return jhash(mac, ETH_ALEN, 0) & (BR_HASH_SIZE - 1); | |
66 | + /* use 1 byte of OUI cnd 3 bytes of NIC */ | |
67 | + u32 key = get_unaligned((u32 *)(mac + 2)); | |
68 | + return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1); | |
62 | 69 | } |
63 | 70 | |
64 | -static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f) | |
71 | +static inline void fdb_delete(struct net_bridge_fdb_entry *f) | |
65 | 72 | { |
66 | 73 | hlist_del_rcu(&f->hlist); |
67 | 74 | br_fdb_put(f); |