mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
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>
This commit is contained in:
parent
467aea0ddf
commit
3f89092318
@ -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)
|
|||||||
/* 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);
|
||||||
|
Loading…
Reference in New Issue
Block a user