diff --git a/lib/ip.h b/lib/ip.h index 45e073d..2642813 100644 --- a/lib/ip.h +++ b/lib/ip.h @@ -216,23 +216,15 @@ static inline int ipa_nonzero2(ip_addr a) * Hash and compare functions */ -static inline uint ip4_hash(ip4_addr a) +static inline u32 ip4_hash(ip4_addr a) { - /* Returns a 16-bit value */ - u32 x = _I(a); - x ^= x >> 16; - x ^= x << 10; - return x & 0xffff; + u64 h = 2902958171u; + h *= _I(a); + h ^= h >> 32; + return h; } -static inline u32 ip4_hash32(ip4_addr a) -{ - /* Returns a 32-bit value, although low-order bits are not mixed */ - u32 x = _I(a); - x ^= x << 16; - x ^= x << 12; - return x; -} +#define ip4_hash32 ip4_hash static inline uint ip6_hash(ip6_addr a) { diff --git a/nest/rt-fib.c b/nest/rt-fib.c index b9c7d2a..4522968 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -43,7 +43,7 @@ #define HASH_DEF_ORDER 10 #define HASH_HI_MARK *4 #define HASH_HI_STEP 2 -#define HASH_HI_MAX 16 /* Must be at most 16 */ +#define HASH_HI_MAX 24 #define HASH_LO_MARK /5 #define HASH_LO_STEP 2 #define HASH_LO_MIN 10 @@ -52,7 +52,7 @@ static void fib_ht_alloc(struct fib *f) { f->hash_size = 1 << f->hash_order; - f->hash_shift = 16 - f->hash_order; + f->hash_shift = 32 - f->hash_order; if (f->hash_order > HASH_HI_MAX - HASH_HI_STEP) f->entries_max = ~0; else @@ -209,7 +209,7 @@ fib_get(struct fib *f, ip_addr *a, int len) unsigned int h = ipa_hash(*a); struct fib_node **ee = f->hash_table + (h >> f->hash_shift); struct fib_node *g, *e = *ee; - u32 uid = h << 16; + u32 uid = h << 8; while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix))) e = e->next; @@ -228,7 +228,7 @@ fib_get(struct fib *f, ip_addr *a, int len) uid++; } - if ((uid >> 16) != h) + if ((uid >> 8) != (h & 0xffffff)) log(L_ERR "FIB hash table chains are too long"); // log (L_WARN "FIB_GET %I %x %x", *a, h, uid);