/* A special optimized version that handles 1 or more of u_int32_ts. * The length parameter here is the number of u_int32_ts in the key. */ u_int32_t jhash2 (const u_int32_t *k, u_int32_t length, u_int32_t initval) { u_int32_t a, b, c, len; a = b = JHASH_GOLDEN_RATIO; c = initval; len = length; while (len >= 3) { a += k[0]; b += k[1]; c += k[2]; __jhash_mix (a, b, c); k += 3; len -= 3; } c += length * 4; switch (len) { case 2: b += k[1]; case 1: a += k[0]; }; __jhash_mix (a, b, c); return c; }
/* * callers should be careful not to use the hash value outside the ipfrag_lock * as doing so could race with ipfrag_hash_rnd being recalculated. */ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, struct in6_addr *daddr) { u32 a, b, c; a = (__force u32)saddr->s6_addr32[0]; b = (__force u32)saddr->s6_addr32[1]; c = (__force u32)saddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += ip6_frags.rnd; __jhash_mix(a, b, c); a += (__force u32)saddr->s6_addr32[3]; b += (__force u32)daddr->s6_addr32[0]; c += (__force u32)daddr->s6_addr32[1]; __jhash_mix(a, b, c); a += (__force u32)daddr->s6_addr32[2]; b += (__force u32)daddr->s6_addr32[3]; c += (__force u32)id; __jhash_mix(a, b, c); return c & (INETFRAGS_HASHSZ - 1); }
/* * callers should be careful not to use the hash value outside the ipfrag_lock * as doing so could race with ipfrag_hash_rnd being recalculated. */ unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, const struct in6_addr *daddr, u32 rnd) { u32 a, b, c; a = (__force u32)saddr->s6_addr32[0]; b = (__force u32)saddr->s6_addr32[1]; c = (__force u32)saddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += rnd; __jhash_mix(a, b, c); a += (__force u32)saddr->s6_addr32[3]; b += (__force u32)daddr->s6_addr32[0]; c += (__force u32)daddr->s6_addr32[1]; __jhash_mix(a, b, c); a += (__force u32)daddr->s6_addr32[2]; b += (__force u32)daddr->s6_addr32[3]; c += (__force u32)id; __jhash_mix(a, b, c); return c & (INETFRAGS_HASHSZ - 1); }
static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, struct in6_addr *daddr) { u32 a, b, c; a = saddr->s6_addr32[0]; b = saddr->s6_addr32[1]; c = saddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += nf_ct_frag6_hash_rnd; __jhash_mix(a, b, c); a += saddr->s6_addr32[3]; b += daddr->s6_addr32[0]; c += daddr->s6_addr32[1]; __jhash_mix(a, b, c); a += daddr->s6_addr32[2]; b += daddr->s6_addr32[3]; c += id; __jhash_mix(a, b, c); return c & (FRAG6Q_HASHSZ - 1); }
/* The most generic version, hashes an arbitrary sequence * of bytes. No alignment or length assumptions are made about * the input key. */ u_int32_t jhash (const void *key, u_int32_t length, u_int32_t initval) { u_int32_t a, b, c, len; const u_int8_t *k = key; len = length; a = b = JHASH_GOLDEN_RATIO; c = initval; while (len >= 12) { a += (k[0] + ((u_int32_t) k[1] << 8) + ((u_int32_t) k[2] << 16) + ((u_int32_t) k[3] << 24)); b += (k[4] + ((u_int32_t) k[5] << 8) + ((u_int32_t) k[6] << 16) + ((u_int32_t) k[7] << 24)); c += (k[8] + ((u_int32_t) k[9] << 8) + ((u_int32_t) k[10] << 16) + ((u_int32_t) k[11] << 24)); __jhash_mix (a, b, c); k += 12; len -= 12; } c += length; switch (len) { case 11: c += ((u_int32_t) k[10] << 24); case 10: c += ((u_int32_t) k[9] << 16); case 9: c += ((u_int32_t) k[8] << 8); case 8: b += ((u_int32_t) k[7] << 24); case 7: b += ((u_int32_t) k[6] << 16); case 6: b += ((u_int32_t) k[5] << 8); case 5: b += k[4]; case 4: a += ((u_int32_t) k[3] << 24); case 3: a += ((u_int32_t) k[2] << 16); case 2: a += ((u_int32_t) k[1] << 8); case 1: a += k[0]; }; __jhash_mix (a, b, c); return c; }
// The most generic version, hashes an arbitrary sequence // of bytes. No alignment or length assumptions are made about // the input key. uint32_t hash_jhash(const void* key, uint32_t length) { uint32_t a, b, c, len; const unsigned char* k = (const unsigned char*)key; len = length; a = b = JHASH_GOLDEN_RATIO; c = 99989; while (len >= 12) { a += (k[0] + ((uint32_t) k[1] << 8) + ((uint32_t) k[2] << 16) + ((uint32_t) k[3] << 24)); b += (k[4] + ((uint32_t) k[5] << 8) + ((uint32_t) k[6] << 16) + ((uint32_t) k[7] << 24)); c += (k[8] + ((uint32_t) k[9] << 8) + ((uint32_t) k[10] << 16) + ((uint32_t) k[11] << 24)); __jhash_mix(a, b, c); k += 12; len -= 12; } c += length; switch (len) { case 11: c += ((uint32_t) k[10] << 24); case 10: c += ((uint32_t) k[9] << 16); case 9: c += ((uint32_t) k[8] << 8); case 8: b += ((uint32_t) k[7] << 24); case 7: b += ((uint32_t) k[6] << 16); case 6: b += ((uint32_t) k[5] << 8); case 5: b += k[4]; case 4: a += ((uint32_t) k[3] << 24); case 3: a += ((uint32_t) k[2] << 16); case 2: a += ((uint32_t) k[1] << 8); case 1: a += k[0]; }; __jhash_mix(a, b, c); return c; }
/* jhash2 - hash an array of u32's * @k: the key which must be an array of u32's * @length: the number of u32's in the key * @initval: the previous hash, or an arbitray value * * Returns the hash value of the key. */ u32 jhash2(const u32 *k, u32 length, u32 initval) { u32 a, b, c; /* Set up the internal state */ a = b = c = JHASH_INITVAL + (length<<2) + initval; /* Handle most of the key */ while (length > 3) { a += k[0]; b += k[1]; c += k[2]; __jhash_mix(a, b, c); length -= 3; k += 3; } /* Handle the last 3 u32's: all the case statements fall through */ switch (length) { case 3: c += k[2]; case 2: b += k[1]; case 1: a += k[0]; __jhash_final(a, b, c); case 0: /* Nothing left to add */ break; } return c; }
static uint32_t jenkins_hash(const uint8_t *k, uint32_t length, uint32_t initval) { /* k: the key * length: length of the key * initval: the previous hash, or an arbitrary value */ uint32_t a, b, c, len; /* Set up the internal state */ len = length; a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ c = initval; /* the previous hash value */ /* handle most of the key */ while (len >= 12) { a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24)); b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24)); c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24)); __jhash_mix(a,b,c); k += 12; len -= 12; } c += length; switch(len) { case 11: c+=((uint32_t)k[10]<<24); case 10: c+=((uint32_t)k[9]<<16); case 9 : c+=((uint32_t)k[8]<<8); /* the first byte of c is reserved for the length */ case 8 : b+=((uint32_t)k[7]<<24); case 7 : b+=((uint32_t)k[6]<<16); case 6 : b+=((uint32_t)k[5]<<8); case 5 : b+=k[4]; case 4 : a+=((uint32_t)k[3]<<24); case 3 : a+=((uint32_t)k[2]<<16); case 2 : a+=((uint32_t)k[1]<<8); case 1 : a+=k[0]; } __jhash_mix(a,b,c); return c; }
/* A special ultra-optimized versions that knows they are hashing exactly * 3, 2 or 1 word(s). * * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally * done at the end is not done here. */ u_int32_t jhash_3words (u_int32_t a, u_int32_t b, u_int32_t c, u_int32_t initval) { a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += initval; __jhash_mix (a, b, c); return c; }
/* jhash - hash an arbitrary key * @k: sequence of bytes as key * @length: the length of the key * @initval: the previous hash, or an arbitray value * * The generic version, hashes an arbitrary sequence of bytes. * No alignment or length assumptions are made about the input key. * * Returns the hash value of the key. The result depends on endianness. */ u32 jhash(const void *key, u32 length, u32 initval) { u32 a, b, c; const u8 *k = key; /* Set up the internal state */ a = b = c = JHASH_INITVAL + length + initval; /* All but the last block: affect some 32 bits of (a,b,c) */ while (length > 12) { a += __get_unaligned_cpu32(k); b += __get_unaligned_cpu32(k + 4); c += __get_unaligned_cpu32(k + 8); __jhash_mix(a, b, c); length -= 12; k += 12; } /* Last block: affect all 32 bits of (c) */ /* All the case statements fall through */ switch (length) { case 12: c += (u32)k[11]<<24; case 11: c += (u32)k[10]<<16; case 10: c += (u32)k[9]<<8; case 9: c += k[8]; case 8: b += (u32)k[7]<<24; case 7: b += (u32)k[6]<<16; case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; __jhash_final(a, b, c); case 0: /* Nothing left to add */ break; } return c; }