diff options
Diffstat (limited to 'net/bridge')
-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 @@ | |||
20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
21 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
22 | #include <linux/jhash.h> | 22 | #include <linux/jhash.h> |
23 | #include <linux/random.h> | ||
23 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
25 | #include <asm/unaligned.h> | ||
24 | #include "br_private.h" | 26 | #include "br_private.h" |
25 | 27 | ||
26 | static struct kmem_cache *br_fdb_cache __read_mostly; | 28 | static struct kmem_cache *br_fdb_cache __read_mostly; |
27 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
28 | const unsigned char *addr); | 30 | const unsigned char *addr); |
29 | 31 | ||
32 | static u32 fdb_salt __read_mostly; | ||
33 | |||
30 | void __init br_fdb_init(void) | 34 | void __init br_fdb_init(void) |
31 | { | 35 | { |
32 | br_fdb_cache = kmem_cache_create("bridge_fdb_cache", | 36 | br_fdb_cache = kmem_cache_create("bridge_fdb_cache", |
33 | sizeof(struct net_bridge_fdb_entry), | 37 | sizeof(struct net_bridge_fdb_entry), |
34 | 0, | 38 | 0, |
35 | SLAB_HWCACHE_ALIGN, NULL, NULL); | 39 | SLAB_HWCACHE_ALIGN, NULL, NULL); |
40 | get_random_bytes(&fdb_salt, sizeof(fdb_salt)); | ||
36 | } | 41 | } |
37 | 42 | ||
38 | void __exit br_fdb_fini(void) | 43 | void __exit br_fdb_fini(void) |
@@ -44,24 +49,26 @@ void __exit br_fdb_fini(void) | |||
44 | /* if topology_changing then use forward_delay (default 15 sec) | 49 | /* if topology_changing then use forward_delay (default 15 sec) |
45 | * otherwise keep longer (default 5 minutes) | 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 | return br->topology_change ? br->forward_delay : br->ageing_time; | 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 | const struct net_bridge_fdb_entry *fdb) | 58 | const struct net_bridge_fdb_entry *fdb) |
54 | { | 59 | { |
55 | return !fdb->is_static | 60 | return !fdb->is_static |
56 | && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); | 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 | hlist_del_rcu(&f->hlist); | 73 | hlist_del_rcu(&f->hlist); |
67 | br_fdb_put(f); | 74 | br_fdb_put(f); |