Commit 3f890923182aeebc572f3818dd51c9014827e0ec

Authored by Stephen Hemminger
Committed by David S. Miller
1 parent 467aea0ddf

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

... ... @@ -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);