Previously, when using the 128-bit hash in conjunction with the 32-bit hash tables, we would ignore the upper 96 bits rather than attempting to redistribute the hash across the 32-bit output space. This patch adds a new function to translate the hash down from 128 bits to 32 bits for this use case.
XXX: Also modify the u64 accessors for ovs_u128 on big_endian systems. XXX: Also don't exit immediately on hash test failure. Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- Resend due to GMail wrapping long lines. --- include/openvswitch/types.h | 4 ++++ lib/dpif-netdev.c | 2 +- lib/hash.h | 11 +++++++++++ ofproto/ofproto-dpif-upcall.c | 2 +- tests/test-hash.c | 5 ++--- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/openvswitch/types.h b/include/openvswitch/types.h index 2afb7b7..efd44fc 100644 --- a/include/openvswitch/types.h +++ b/include/openvswitch/types.h @@ -84,7 +84,11 @@ typedef struct { typedef union { uint32_t u32[4]; struct { +#ifdef WORDS_BIGENDIAN + uint64_t hi, lo; +#else uint64_t lo, hi; +#endif } u64; } ovs_u128; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 890870c..e07cb80 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1162,7 +1162,7 @@ static void dp_netdev_flow_unref(struct dp_netdev_flow *flow) static uint32_t dp_netdev_flow_hash(const ovs_u128 *ufid) { - return ufid->u32[0]; + return hash128_to_32(ufid); } static void diff --git a/lib/hash.h b/lib/hash.h index c2820dd..818fcca 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -35,6 +35,7 @@ hash_rot(uint32_t x, int k) uint32_t hash_bytes(const void *, size_t n_bytes, uint32_t basis); void hash_bytes128(const void *_, size_t n_bytes, uint32_t basis, ovs_u128 *out); +uint32_t hash128_to_32(const ovs_u128 *hash); static inline uint32_t hash_int(uint32_t x, uint32_t basis); static inline uint32_t hash_2words(uint32_t, uint32_t); @@ -84,6 +85,16 @@ static inline uint32_t mhash_finish(uint32_t hash) return hash; } +static inline uint32_t hash128_to_32(const ovs_u128 *hash) +{ + uint32_t h1, h2; + + h1 = mhash_add(hash->u32[0], hash->u32[1]); + h2 = mhash_add(hash->u32[2], hash->u32[3]); + + return mhash_finish(mhash_add(h1, h2)); +} + #if !(defined(__SSE4_2__) && defined(__x86_64__)) /* Mhash-based implementation. */ diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 4a7a829..8b2a38d 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -1247,7 +1247,7 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls, static uint32_t get_ufid_hash(const ovs_u128 *ufid) { - return ufid->u32[0]; + return hash128_to_32(ufid); } static struct udpif_key * diff --git a/tests/test-hash.c b/tests/test-hash.c index d7e2e6b..80d24ed 100644 --- a/tests/test-hash.c +++ b/tests/test-hash.c @@ -74,8 +74,8 @@ hash_bytes128_cb(uint32_t input) { ovs_u128 hash; - hash_bytes128(&input, sizeof input, 0, &hash); - return hash.u64.lo; + hash_bytes128(&input, sizeof input, 233, &hash); + return hash128_to_32(&hash); } static void @@ -101,7 +101,6 @@ check_word_hash(uint32_t (*hash)(uint32_t), const char *name, printf("%s(%08"PRIx32") = %08"PRIx32"\n", name, in2, out2); printf("%d bits of output starting at bit %d " "are both 0x%"PRIx32"\n", min_unique, ofs, bits1); - exit(1); } } } -- 1.7.10.4 _______________________________________________ discuss mailing list discuss@openvswitch.org http://openvswitch.org/mailman/listinfo/discuss