diff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c index ee8dc0356e..f7b86c8c95 100644 --- a/lib/librte_hash/rte_cuckoo_hash.c +++ b/lib/librte_hash/rte_cuckoo_hash.c @@ -369,6 +369,30 @@ rte_hash_secondary_hash(const hash_sig_t primary_hash) return primary_hash ^ ((tag + 1) * alt_bits_xor); } +int32_t +rte_hash_count(const struct rte_hash *h) +{ + uint32_t tot_ring_cnt, cached_cnt = 0; + uint32_t i, ret; + + if (h == NULL) + return -EINVAL; + + if (h->multi_writer_support) { + tot_ring_cnt = h->entries + (RTE_MAX_LCORE - 1) * + (LCORE_CACHE_SIZE - 1); + for (i = 0; i < RTE_MAX_LCORE; i++) + cached_cnt += h->local_free_slots[i].len; + + ret = tot_ring_cnt - rte_ring_count(h->free_slots) - + cached_cnt; + } else { + tot_ring_cnt = h->entries; + ret = tot_ring_cnt - rte_ring_count(h->free_slots); + } + return ret; +} + /* Read write locks implemented using rte_rwlock */ static inline void __hash_rw_writer_lock(const struct rte_hash *h) diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h index ecb49e4ff5..1f1a276df7 100644 --- a/lib/librte_hash/rte_hash.h +++ b/lib/librte_hash/rte_hash.h @@ -126,6 +126,17 @@ rte_hash_free(struct rte_hash *h); void rte_hash_reset(struct rte_hash *h); +/** + * Return the number of keys in the hash table + * @param h + * Hash table to query from + * @return + * - -EINVAL if parameters are invalid + * - A value indicating how many keys were inserted in the table. + */ +int32_t +rte_hash_count(const struct rte_hash *h); + /** * Add a key-value pair to an existing hash table. * This operation is not multi-thread safe diff --git a/lib/librte_hash/rte_hash_version.map b/lib/librte_hash/rte_hash_version.map index 52a2576f92..e216ac8e2d 100644 --- a/lib/librte_hash/rte_hash_version.map +++ b/lib/librte_hash/rte_hash_version.map @@ -45,3 +45,11 @@ DPDK_16.07 { rte_hash_get_key_with_position; } DPDK_2.2; + + +DPDK_18.08 { + global: + + rte_hash_count; + +} DPDK_16.07; diff --git a/test/test/test_hash.c b/test/test/test_hash.c index edf41f5a7f..b3db9fd105 100644 --- a/test/test/test_hash.c +++ b/test/test/test_hash.c @@ -1103,6 +1103,7 @@ static int test_average_table_utilization(void) unsigned i, j; unsigned added_keys, average_keys_added = 0; int ret; + unsigned int cnt; printf("\n# Running test to determine average utilization" "\n before adding elements begins to fail\n"); @@ -1121,13 +1122,24 @@ static int test_average_table_utilization(void) for (i = 0; i < ut_params.key_len; i++) simple_key[i] = rte_rand() % 255; ret = rte_hash_add_key(handle, simple_key); + if (ret < 0) + break; } + if (ret != -ENOSPC) { printf("Unexpected error when adding keys\n"); rte_hash_free(handle); return -1; } + cnt = rte_hash_count(handle); + if (cnt != added_keys) { + printf("rte_hash_count returned wrong value %u, %u," + "%u\n", j, added_keys, cnt); + rte_hash_free(handle); + return -1; + } + average_keys_added += added_keys; /* Reset the table */ diff --git a/test/test/test_hash_multiwriter.c b/test/test/test_hash_multiwriter.c index ef5fce3d29..f182f40525 100644 --- a/test/test/test_hash_multiwriter.c +++ b/test/test/test_hash_multiwriter.c @@ -116,6 +116,7 @@ test_hash_multiwriter(void) uint32_t duplicated_keys = 0; uint32_t lost_keys = 0; + uint32_t count; snprintf(name, 32, "test%u", calledCount++); hash_params.name = name; @@ -163,6 +164,13 @@ test_hash_multiwriter(void) NULL, CALL_MASTER); rte_eal_mp_wait_lcore(); + count = rte_hash_count(handle); + if (count != rounded_nb_total_tsx_insertion) { + printf("rte_hash_count returned wrong value %u, %d\n", + rounded_nb_total_tsx_insertion, count); + goto err3; + } + while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) { /* Search for the key in the list of keys added .*/ i = *(const uint32_t *)next_key;