-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
flow_hash(const struct flow *flow, uint32_t basis)
{
BUILD_ASSERT_DECL(!(sizeof *flow % sizeof(uint32_t)));
- return hash_lookup3((const uint32_t *) flow,
- sizeof *flow / sizeof(uint32_t), basis);
+ return hash_words((const uint32_t *) flow,
+ sizeof *flow / sizeof(uint32_t), basis);
}
#endif /* flow.h */
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
*/
#include <config.h>
#include "hash.h"
-
-uint32_t
-hash_fnv(const void *p_, size_t n, uint32_t basis)
-{
- const uint8_t *p = p_;
- uint32_t hash = basis;
- while (n--) {
- hash *= HASH_FNV_PRIME;
- hash ^= *p++;
- }
- return hash;
-}
+#include <string.h>
/* This is the public domain lookup3 hash by Bob Jenkins from
* http://burtleburtle.net/bob/c/lookup3.c, modified for style. */
c ^= b; c -= rot(b, 24); \
} while (0)
-/* Returns the hash of the 'n' uint32_t values at 'p', starting from 'basis'.
- * Note especially that 'n' is a count of 32-bit words, not bytes, and that
+/* Returns the hash of the 'n' 32-bit words at 'p', starting from 'basis'.
* 'p' must be properly aligned. */
uint32_t
-hash_lookup3(const uint32_t *p, size_t n, uint32_t basis)
+hash_words(const uint32_t *p, size_t n, uint32_t basis)
{
uint32_t a, b, c;
return c;
}
+/* Returns the hash of the 'n' bytes at 'p', starting from 'basis'. */
+uint32_t
+hash_bytes(const void *p_, size_t n, uint32_t basis)
+{
+ const uint8_t *p = p_;
+ uint32_t a, b, c;
+ uint32_t tmp[3];
+
+ a = b = c = 0xdeadbeef + n + basis;
+
+ while (n >= sizeof tmp) {
+ memcpy(tmp, p, sizeof tmp);
+ a += tmp[0];
+ b += tmp[1];
+ c += tmp[2];
+ mix(a, b, c);
+ n -= sizeof tmp;
+ p += sizeof tmp;
+ }
+
+ if (n) {
+ tmp[0] = tmp[1] = tmp[2] = 0;
+ memcpy(tmp, p, n);
+ a += tmp[0];
+ b += tmp[1];
+ c += tmp[2];
+ final(a, b, c);
+ }
+
+ return c;
+}
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
#include <stddef.h>
#include <stdint.h>
-#define HASH_FNV_BASIS UINT32_C(2166136261)
-#define HASH_FNV_PRIME UINT32_C(16777619)
-
-uint32_t hash_fnv(const void *, size_t, uint32_t basis);
-uint32_t hash_lookup3(const uint32_t *, size_t n, uint32_t basis);
+uint32_t hash_words(const uint32_t *, size_t n_word, uint32_t basis);
+uint32_t hash_bytes(const void *, size_t n_bytes, uint32_t basis);
#endif /* hash.h */
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
static uint32_t
mac_table_hash(const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan)
{
- return hash_fnv(mac, ETH_ADDR_LEN, HASH_FNV_BASIS) ^ vlan;
+ return hash_bytes(mac, ETH_ADDR_LEN, vlan);
}
static struct mac_entry *
make_unknown_mac_tag(const struct mac_learning *ml,
const uint8_t mac[ETH_ADDR_LEN], uint16_t vlan)
{
- return tag_create_deterministic(hash_fnv(&ml->secret, sizeof ml->secret,
- mac_table_hash(mac, vlan)));
+ uint32_t h = hash_bytes(&ml->secret, sizeof ml->secret,
+ mac_table_hash(mac, vlan));
+ return tag_create_deterministic(h);
}
static struct list *
-/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+/* Copyright (c) 2008, 2009 The Board of Trustees of The Leland Stanford
* Junior University
*
* We are making the OpenFlow specification and associated documentation
*
* 'seed' should have data in all of its bits; if it has data only in its
* low-order bits then the resulting tags will be poorly distributed. Use a
- * hash function such as hash_lookup3() to generate 'seed' if necessary. */
+ * hash function such as hash_bytes() to generate 'seed' if necessary. */
tag_type
tag_create_deterministic(uint32_t seed)
{
good_hash(int value)
{
const uint32_t x = value;
- return hash_lookup3(&x, 1, 0x1234abcd);
+ return hash_words(&x, 1, 0x1234abcd);
}
static size_t
static struct bond_entry *
lookup_bond_entry(const struct port *port, const uint8_t mac[ETH_ADDR_LEN])
{
- size_t h = hash_fnv(mac, ETH_ADDR_LEN, HASH_FNV_BASIS);
+ size_t h = hash_bytes(mac, ETH_ADDR_LEN, 0);
return &port->bond_hash[h & BOND_MASK];
}