[dpdk-dev] [PATCH v2 08/11] hash: add new functionality to store data in hash table
Stephen Hemminger
stephen at networkplumber.org
Fri Jun 26 18:49:55 CEST 2015
We did same thing with a slightly different method.
Subject: rte_hash: split key and bucket size
It is useful to store more data in the has bucket than just the key size.
For example, storing an addresss and additional data.
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
--- a/lib/librte_hash/rte_hash.h
+++ b/lib/librte_hash/rte_hash.h
@@ -78,7 +78,8 @@ struct rte_hash_parameters {
const char *name; /**< Name of the hash. */
uint32_t entries; /**< Total hash table entries. */
uint32_t bucket_entries; /**< Bucket entries. */
- uint32_t key_len; /**< Length of hash key. */
+ uint16_t key_len; /**< Length of hash key. */
+ uint16_t cmp_len; /**< Length of hash key compare (bytes). */
rte_hash_function hash_func; /**< Function used to calculate hash. */
uint32_t hash_func_init_val; /**< Init value used by hash_func. */
int socket_id; /**< NUMA Socket ID for memory. */
@@ -89,7 +90,8 @@ struct rte_hash {
char name[RTE_HASH_NAMESIZE]; /**< Name of the hash. */
uint32_t entries; /**< Total table entries. */
uint32_t bucket_entries; /**< Bucket entries. */
- uint32_t key_len; /**< Length of hash key. */
+ uint16_t key_len; /**< Length of hash key. */
+ uint16_t cmp_len; /**< Length of hash key compare (bytes) */
rte_hash_function hash_func; /**< Function used to calculate hash. */
uint32_t hash_func_init_val; /**< Init value used by hash_func. */
uint32_t num_buckets; /**< Number of buckets in table. */
@@ -240,7 +242,7 @@ rte_hash_del_key_with_hash(const struct
* value that was returned when the key was added.
*/
int32_t
-rte_hash_lookup(const struct rte_hash *h, const void *key);
+rte_hash_lookup(const struct rte_hash *h, void *key);
/**
* Find a key in the hash table. This operation is multi-thread safe.
@@ -260,7 +262,7 @@ rte_hash_lookup(const struct rte_hash *h
*/
int32_t
rte_hash_lookup_with_hash(const struct rte_hash *h,
- const void *key, hash_sig_t sig);
+ void *key, hash_sig_t sig);
/**
@@ -277,7 +279,7 @@ static inline hash_sig_t
rte_hash_hash(const struct rte_hash *h, const void *key)
{
/* calc hash result by key */
- return h->hash_func(key, h->key_len, h->hash_func_init_val);
+ return h->hash_func(key, h->cmp_len, h->hash_func_init_val);
}
#define rte_hash_lookup_multi rte_hash_lookup_bulk
--- a/lib/librte_hash/rte_hash.c
+++ b/lib/librte_hash/rte_hash.c
@@ -185,7 +185,8 @@ rte_hash_create(const struct rte_hash_pa
!rte_is_power_of_2(params->entries) ||
!rte_is_power_of_2(params->bucket_entries) ||
(params->key_len == 0) ||
- (params->key_len > RTE_HASH_KEY_LENGTH_MAX)) {
+ (params->key_len > RTE_HASH_KEY_LENGTH_MAX)||
+ (params->cmp_len > params->key_len)) {
rte_errno = EINVAL;
RTE_LOG(ERR, HASH, "rte_hash_create has invalid parameters\n");
return NULL;
@@ -238,6 +239,7 @@ rte_hash_create(const struct rte_hash_pa
h->entries = params->entries;
h->bucket_entries = params->bucket_entries;
h->key_len = params->key_len;
+ h->cmp_len = params->cmp_len ? params->cmp_len : h->key_len;
h->hash_func_init_val = params->hash_func_init_val;
h->num_buckets = num_buckets;
h->bucket_bitmask = h->num_buckets - 1;
@@ -310,7 +312,7 @@ __rte_hash_add_key_with_hash(const struc
for (i = 0; i < h->bucket_entries; i++) {
if ((sig == sig_bucket[i]) &&
likely(memcmp(key, get_key_from_bucket(h, key_bucket, i),
- h->key_len) == 0)) {
+ h->cmp_len) == 0)) {
return bucket_index * h->bucket_entries + i;
}
}
@@ -360,7 +362,7 @@ __rte_hash_del_key_with_hash(const struc
for (i = 0; i < h->bucket_entries; i++) {
if ((sig == sig_bucket[i]) &&
likely(memcmp(key, get_key_from_bucket(h, key_bucket, i),
- h->key_len) == 0)) {
+ h->cmp_len) == 0)) {
sig_bucket[i] = NULL_SIGNATURE;
return bucket_index * h->bucket_entries + i;
}
@@ -386,7 +388,7 @@ rte_hash_del_key(const struct rte_hash *
static inline int32_t
__rte_hash_lookup_with_hash(const struct rte_hash *h,
- const void *key, hash_sig_t sig)
+ void *key, hash_sig_t sig)
{
hash_sig_t *sig_bucket;
uint8_t *key_bucket;
@@ -402,7 +404,9 @@ __rte_hash_lookup_with_hash(const struct
for (i = 0; i < h->bucket_entries; i++) {
if ((sig == sig_bucket[i]) &&
likely(memcmp(key, get_key_from_bucket(h, key_bucket, i),
- h->key_len) == 0)) {
+ h->cmp_len) == 0)) {
+ rte_memcpy(key, get_key_from_bucket(h, key_bucket, i),
+ h->key_len);
return bucket_index * h->bucket_entries + i;
}
}
@@ -412,14 +416,14 @@ __rte_hash_lookup_with_hash(const struct
int32_t
rte_hash_lookup_with_hash(const struct rte_hash *h,
- const void *key, hash_sig_t sig)
+ void *key, hash_sig_t sig)
{
RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
return __rte_hash_lookup_with_hash(h, key, sig);
}
int32_t
-rte_hash_lookup(const struct rte_hash *h, const void *key)
+rte_hash_lookup(const struct rte_hash *h, void *key)
{
RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key));
@@ -438,7 +442,7 @@ rte_hash_lookup_bulk(const struct rte_ha
/* Get the hash signature and bucket index */
for (i = 0; i < num_keys; i++) {
- sigs[i] = h->hash_func(keys[i], h->key_len,
+ sigs[i] = h->hash_func(keys[i], h->cmp_len,
h->hash_func_init_val) | h->sig_msb;
bucket_index = sigs[i] & h->bucket_bitmask;
@@ -459,7 +463,7 @@ rte_hash_lookup_bulk(const struct rte_ha
if ((sigs[i] == sig_bucket[j]) &&
likely(memcmp(keys[i],
get_key_from_bucket(h, key_bucket, j),
- h->key_len) == 0)) {
+ h->cmp_len) == 0)) {
positions[i] = bucket_index *
h->bucket_entries + j;
break;
More information about the dev
mailing list