mirror of
https://github.com/openvswitch/ovs
synced 2025-10-19 14:37:21 +00:00
lib/hash: Abstract hash interface.
Use generic names hash_add() and hash_finish() instead of mhash_* equivalents. This makes future changes to hash implentations more localized. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
@@ -214,10 +214,10 @@ flow_hash_in_minimask(const struct flow *flow, const struct minimask *mask,
|
|||||||
|
|
||||||
hash = basis;
|
hash = basis;
|
||||||
for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
|
for (map = mask->masks.map; map; map = zero_rightmost_1bit(map)) {
|
||||||
hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p++);
|
hash = hash_add(hash, flow_u32[raw_ctz(map)] & *p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mhash_finish(hash, (p - mask_values) * 4);
|
return hash_finish(hash, (p - mask_values) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a hash value for the bits of 'flow' where there are 1-bits in
|
/* Returns a hash value for the bits of 'flow' where there are 1-bits in
|
||||||
@@ -235,10 +235,10 @@ miniflow_hash_in_minimask(const struct miniflow *flow,
|
|||||||
uint32_t flow_u32;
|
uint32_t flow_u32;
|
||||||
|
|
||||||
MINIFLOW_FOR_EACH_IN_MAP(flow_u32, flow, mask->masks.map) {
|
MINIFLOW_FOR_EACH_IN_MAP(flow_u32, flow, mask->masks.map) {
|
||||||
hash = mhash_add(hash, flow_u32 & *p++);
|
hash = hash_add(hash, flow_u32 & *p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mhash_finish(hash, (p - mask_values) * 4);
|
return hash_finish(hash, (p - mask_values) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a hash value for the bits of range [start, end) in 'flow',
|
/* Returns a hash value for the bits of range [start, end) in 'flow',
|
||||||
@@ -260,11 +260,11 @@ flow_hash_in_minimask_range(const struct flow *flow,
|
|||||||
uint32_t hash = *basis;
|
uint32_t hash = *basis;
|
||||||
|
|
||||||
for (; map; map = zero_rightmost_1bit(map)) {
|
for (; map; map = zero_rightmost_1bit(map)) {
|
||||||
hash = mhash_add(hash, flow_u32[raw_ctz(map)] & *p++);
|
hash = hash_add(hash, flow_u32[raw_ctz(map)] & *p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
*basis = hash; /* Allow continuation from the unfinished value. */
|
*basis = hash; /* Allow continuation from the unfinished value. */
|
||||||
return mhash_finish(hash, (p - mask_values) * 4);
|
return hash_finish(hash, (p - mask_values) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fold minimask 'mask''s wildcard mask into 'wc's wildcard mask. */
|
/* Fold minimask 'mask''s wildcard mask into 'wc's wildcard mask. */
|
||||||
@@ -305,15 +305,15 @@ miniflow_hash(const struct miniflow *flow, uint32_t basis)
|
|||||||
|
|
||||||
for (map = flow->map; map; map = zero_rightmost_1bit(map)) {
|
for (map = flow->map; map; map = zero_rightmost_1bit(map)) {
|
||||||
if (*p) {
|
if (*p) {
|
||||||
hash = mhash_add(hash, *p);
|
hash = hash_add(hash, *p);
|
||||||
hash_map |= rightmost_1bit(map);
|
hash_map |= rightmost_1bit(map);
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
hash = mhash_add(hash, hash_map);
|
hash = hash_add(hash, hash_map);
|
||||||
hash = mhash_add(hash, hash_map >> 32);
|
hash = hash_add(hash, hash_map >> 32);
|
||||||
|
|
||||||
return mhash_finish(hash, p - values);
|
return hash_finish(hash, p - values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a hash value for 'mask', given 'basis'. */
|
/* Returns a hash value for 'mask', given 'basis'. */
|
||||||
@@ -350,10 +350,10 @@ minimatch_hash_range(const struct minimatch *match, uint8_t start, uint8_t end,
|
|||||||
p = miniflow_get_u32_values(&match->flow) + offset;
|
p = miniflow_get_u32_values(&match->flow) + offset;
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
hash = mhash_add(hash, p[i] & q[i]);
|
hash = hash_add(hash, p[i] & q[i]);
|
||||||
}
|
}
|
||||||
*basis = hash; /* Allow continuation from the unfinished value. */
|
*basis = hash; /* Allow continuation from the unfinished value. */
|
||||||
return mhash_finish(hash, (offset + n) * 4);
|
return hash_finish(hash, (offset + n) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -193,7 +193,7 @@ other_hash(uint32_t hash)
|
|||||||
static uint32_t
|
static uint32_t
|
||||||
rehash(const struct cmap_impl *impl, uint32_t hash)
|
rehash(const struct cmap_impl *impl, uint32_t hash)
|
||||||
{
|
{
|
||||||
return mhash_finish(impl->basis, hash);
|
return hash_finish(impl->basis, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cmap_impl *
|
static struct cmap_impl *
|
||||||
|
24
lib/flow.c
24
lib/flow.c
@@ -909,7 +909,7 @@ miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
|
|||||||
if (flow) {
|
if (flow) {
|
||||||
ovs_be16 dl_type = MINIFLOW_GET_BE16(flow, dl_type);
|
ovs_be16 dl_type = MINIFLOW_GET_BE16(flow, dl_type);
|
||||||
|
|
||||||
hash = mhash_add(hash, MINIFLOW_GET_U8(flow, nw_proto));
|
hash = hash_add(hash, MINIFLOW_GET_U8(flow, nw_proto));
|
||||||
|
|
||||||
/* Separate loops for better optimization. */
|
/* Separate loops for better optimization. */
|
||||||
if (dl_type == htons(ETH_TYPE_IPV6)) {
|
if (dl_type == htons(ETH_TYPE_IPV6)) {
|
||||||
@@ -918,7 +918,7 @@ miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
|
|||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
MINIFLOW_FOR_EACH_IN_MAP(value, flow, map) {
|
MINIFLOW_FOR_EACH_IN_MAP(value, flow, map) {
|
||||||
hash = mhash_add(hash, value);
|
hash = hash_add(hash, value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint64_t map = MINIFLOW_MAP(nw_src) | MINIFLOW_MAP(nw_dst)
|
uint64_t map = MINIFLOW_MAP(nw_src) | MINIFLOW_MAP(nw_dst)
|
||||||
@@ -926,10 +926,10 @@ miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
|
|||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
MINIFLOW_FOR_EACH_IN_MAP(value, flow, map) {
|
MINIFLOW_FOR_EACH_IN_MAP(value, flow, map) {
|
||||||
hash = mhash_add(hash, value);
|
hash = hash_add(hash, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash = mhash_finish(hash, 42); /* Arbitrary number. */
|
hash = hash_finish(hash, 42); /* Arbitrary number. */
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
@@ -950,22 +950,22 @@ flow_hash_5tuple(const struct flow *flow, uint32_t basis)
|
|||||||
if (flow) {
|
if (flow) {
|
||||||
const uint32_t *flow_u32 = (const uint32_t *)flow;
|
const uint32_t *flow_u32 = (const uint32_t *)flow;
|
||||||
|
|
||||||
hash = mhash_add(hash, flow->nw_proto);
|
hash = hash_add(hash, flow->nw_proto);
|
||||||
|
|
||||||
if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
||||||
int ofs = offsetof(struct flow, ipv6_src) / 4;
|
int ofs = offsetof(struct flow, ipv6_src) / 4;
|
||||||
int end = ofs + 2 * sizeof flow->ipv6_src / 4;
|
int end = ofs + 2 * sizeof flow->ipv6_src / 4;
|
||||||
|
|
||||||
while (ofs < end) {
|
while (ofs < end) {
|
||||||
hash = mhash_add(hash, flow_u32[ofs++]);
|
hash = hash_add(hash, flow_u32[ofs++]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hash = mhash_add(hash, (OVS_FORCE uint32_t) flow->nw_src);
|
hash = hash_add(hash, (OVS_FORCE uint32_t) flow->nw_src);
|
||||||
hash = mhash_add(hash, (OVS_FORCE uint32_t) flow->nw_dst);
|
hash = hash_add(hash, (OVS_FORCE uint32_t) flow->nw_dst);
|
||||||
}
|
}
|
||||||
hash = mhash_add(hash, flow_u32[offsetof(struct flow, tp_src) / 4]);
|
hash = hash_add(hash, flow_u32[offsetof(struct flow, tp_src) / 4]);
|
||||||
|
|
||||||
hash = mhash_finish(hash, 42); /* Arbitrary number. */
|
hash = hash_finish(hash, 42); /* Arbitrary number. */
|
||||||
}
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
@@ -1140,9 +1140,9 @@ flow_hash_in_wildcards(const struct flow *flow,
|
|||||||
|
|
||||||
hash = basis;
|
hash = basis;
|
||||||
for (i = 0; i < FLOW_U32S; i++) {
|
for (i = 0; i < FLOW_U32S; i++) {
|
||||||
hash = mhash_add(hash, flow_u32[i] & wc_u32[i]);
|
hash = hash_add(hash, flow_u32[i] & wc_u32[i]);
|
||||||
}
|
}
|
||||||
return mhash_finish(hash, 4 * FLOW_U32S);
|
return hash_finish(hash, 4 * FLOW_U32S);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
|
/* Sets the VLAN VID that 'flow' matches to 'vid', which is interpreted as an
|
||||||
|
12
lib/hash.c
12
lib/hash.c
@@ -22,7 +22,7 @@
|
|||||||
uint32_t
|
uint32_t
|
||||||
hash_3words(uint32_t a, uint32_t b, uint32_t c)
|
hash_3words(uint32_t a, uint32_t b, uint32_t c)
|
||||||
{
|
{
|
||||||
return mhash_finish(mhash_add(mhash_add(mhash_add(a, 0), b), c), 12);
|
return hash_finish(hash_add(hash_add(hash_add(a, 0), b), c), 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the hash of the 'n' bytes at 'p', starting from 'basis'. */
|
/* Returns the hash of the 'n' bytes at 'p', starting from 'basis'. */
|
||||||
@@ -35,7 +35,7 @@ hash_bytes(const void *p_, size_t n, uint32_t basis)
|
|||||||
|
|
||||||
hash = basis;
|
hash = basis;
|
||||||
while (n >= 4) {
|
while (n >= 4) {
|
||||||
hash = mhash_add(hash, get_unaligned_u32(p));
|
hash = hash_add(hash, get_unaligned_u32(p));
|
||||||
n -= 4;
|
n -= 4;
|
||||||
p += 1;
|
p += 1;
|
||||||
}
|
}
|
||||||
@@ -44,10 +44,10 @@ hash_bytes(const void *p_, size_t n, uint32_t basis)
|
|||||||
uint32_t tmp = 0;
|
uint32_t tmp = 0;
|
||||||
|
|
||||||
memcpy(&tmp, p, n);
|
memcpy(&tmp, p, n);
|
||||||
hash = mhash_add__(hash, tmp);
|
hash = hash_add(hash, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mhash_finish(hash, orig_n);
|
return hash_finish(hash, orig_n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the hash of the 'n' 32-bit words at 'p', starting from 'basis'.
|
/* Returns the hash of the 'n' 32-bit words at 'p', starting from 'basis'.
|
||||||
@@ -60,9 +60,9 @@ hash_words(const uint32_t p[], size_t n_words, uint32_t basis)
|
|||||||
|
|
||||||
hash = basis;
|
hash = basis;
|
||||||
for (i = 0; i < n_words; i++) {
|
for (i = 0; i < n_words; i++) {
|
||||||
hash = mhash_add(hash, p[i]);
|
hash = hash_add(hash, p[i]);
|
||||||
}
|
}
|
||||||
return mhash_finish(hash, n_words * 4);
|
return hash_finish(hash, n_words * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
|
14
lib/hash.h
14
lib/hash.h
@@ -72,7 +72,7 @@ static inline uint32_t mhash_add(uint32_t hash, uint32_t data)
|
|||||||
return hash * 5 + 0xe6546b64;
|
return hash * 5 + 0xe6546b64;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t mhash_finish(uint32_t hash, size_t n_bytes)
|
static inline uint32_t mhash_finish(uint32_t hash, uint32_t n_bytes)
|
||||||
{
|
{
|
||||||
hash ^= n_bytes;
|
hash ^= n_bytes;
|
||||||
hash ^= hash >> 16;
|
hash ^= hash >> 16;
|
||||||
@@ -83,6 +83,16 @@ static inline uint32_t mhash_finish(uint32_t hash, size_t n_bytes)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t hash_add(uint32_t hash, uint32_t data)
|
||||||
|
{
|
||||||
|
return mhash_add(hash, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t hash_finish(uint32_t hash, uint32_t final)
|
||||||
|
{
|
||||||
|
return mhash_finish(hash, final);
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t hash_string(const char *s, uint32_t basis)
|
static inline uint32_t hash_string(const char *s, uint32_t basis)
|
||||||
{
|
{
|
||||||
return hash_bytes(s, strlen(s), basis);
|
return hash_bytes(s, strlen(s), basis);
|
||||||
@@ -117,7 +127,7 @@ static inline uint32_t hash_pointer(const void *p, uint32_t basis)
|
|||||||
|
|
||||||
static inline uint32_t hash_2words(uint32_t x, uint32_t y)
|
static inline uint32_t hash_2words(uint32_t x, uint32_t y)
|
||||||
{
|
{
|
||||||
return mhash_finish(mhash_add(mhash_add(x, 0), y), 8);
|
return hash_finish(hash_add(hash_add(x, 0), y), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t hash_uint64(const uint64_t x)
|
static inline uint32_t hash_uint64(const uint64_t x)
|
||||||
|
@@ -458,13 +458,13 @@ netflow_flow_hash(const struct flow *flow)
|
|||||||
{
|
{
|
||||||
uint32_t hash = 0;
|
uint32_t hash = 0;
|
||||||
|
|
||||||
hash = mhash_add(hash, (OVS_FORCE uint32_t) flow->in_port.ofp_port);
|
hash = hash_add(hash, (OVS_FORCE uint32_t) flow->in_port.ofp_port);
|
||||||
hash = mhash_add(hash, ntohl(flow->nw_src));
|
hash = hash_add(hash, ntohl(flow->nw_src));
|
||||||
hash = mhash_add(hash, ntohl(flow->nw_dst));
|
hash = hash_add(hash, ntohl(flow->nw_dst));
|
||||||
hash = mhash_add(hash, flow->nw_tos);
|
hash = hash_add(hash, flow->nw_tos);
|
||||||
hash = mhash_add(hash, flow->nw_proto);
|
hash = hash_add(hash, flow->nw_proto);
|
||||||
hash = mhash_add(hash, ntohs(flow->tp_src));
|
hash = hash_add(hash, ntohs(flow->tp_src));
|
||||||
hash = mhash_add(hash, ntohs(flow->tp_dst));
|
hash = hash_add(hash, ntohs(flow->tp_dst));
|
||||||
|
|
||||||
return mhash_finish(hash, 28);
|
return hash_finish(hash, 28);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user