static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc};
static uint32_t hashtest_initvals[] = {0};
static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21, 31, 32, 33, 63, 64};
+#define MAX_KEYSIZE 64
/******************************************************************************/
#define LOCAL_FBK_HASH_ENTRIES_MAX (1 << 15)
.socket_id = 0,
};
-#define CRC32_ITERATIONS (1U << 20)
+#define CRC32_ITERATIONS (1U << 10)
#define CRC32_DWORDS (1U << 6)
/*
* Test if all CRC32 implementations yield the same hash value
printf("Failed checking CRC32_SW against CRC32_SSE42_x64\n");
break;
}
+
+ /* Check against 8-byte-operand ARM64 CRC32 if available */
+ rte_hash_crc_set_alg(CRC32_ARM64);
+ if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
+ printf("Failed checking CRC32_SW against CRC32_ARM64\n");
+ break;
+ }
}
/* Resetting to best available algorithm */
static void run_hash_func_test(rte_hash_function f, uint32_t init_val,
uint32_t key_len)
{
- static uint8_t key[RTE_HASH_KEY_LENGTH_MAX];
+ static uint8_t key[MAX_KEYSIZE];
unsigned i;
return 0;
}
+/*
+ * Sequence of operations for retrieving a key with its position
+ *
+ * - create table
+ * - add key
+ * - get the key with its position: hit
+ * - delete key
+ * - try to get the deleted key: miss
+ *
+ */
+static int test_hash_get_key_with_position(void)
+{
+ struct rte_hash *handle = NULL;
+ int pos, expectedPos, result;
+ void *key;
+
+ ut_params.name = "hash_get_key_w_pos";
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ pos = rte_hash_add_key(handle, &keys[0]);
+ print_key_info("Add", &keys[0], pos);
+ RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos);
+ expectedPos = pos;
+
+ result = rte_hash_get_key_with_position(handle, pos, &key);
+ RETURN_IF_ERROR(result != 0, "error retrieving a key");
+
+ pos = rte_hash_del_key(handle, &keys[0]);
+ print_key_info("Del", &keys[0], pos);
+ RETURN_IF_ERROR(pos != expectedPos,
+ "failed to delete key (pos0=%d)", pos);
+
+ result = rte_hash_get_key_with_position(handle, pos, &key);
+ RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
+
+ rte_hash_free(handle);
+ return 0;
+}
+
/*
* Sequence of operations for find existing hash table
*
for(i = 0; i < 5; i++)
key_array[i] = &keys[i];
- ret = rte_hash_lookup_multi(handle, &key_array[0], 5, (int32_t *)pos);
+ ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
if(ret == 0)
for(i = 0; i < 5; i++) {
print_key_info("Lkp", key_array[i], pos[i]);
}
/* Lookup multi */
- ret = rte_hash_lookup_multi(handle, &key_array[0], 5, (int32_t *)pos);
+ ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
if (ret == 0)
for (i = 0; i < 5; i++) {
print_key_info("Lkp", key_array[i], pos[i]);
*/
struct rte_fbk_hash_params different_name = {
.name = "different_name", /* different name */
- .entries = RTE_FBK_HASH_ENTRIES_MAX,
+ .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
.entries_per_bucket = 4,
.socket_id = 0,
};
RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded");
tmp = rte_fbk_hash_create(&invalid_params_same_name_2);
- RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded");
- if (tmp != handle) {
- printf("ERROR line %d: hashes should have been the same\n", __LINE__);
- rte_fbk_hash_free(handle);
- rte_fbk_hash_free(tmp);
- return -1;
- }
+ if (tmp != NULL)
+ rte_fbk_hash_free(tmp);
+ RETURN_IF_ERROR_FBK(tmp != NULL, "fbk hash creation should have failed");
- /* we are not freeing tmp or handle here because we need a hash list
+ /* we are not freeing handle here because we need a hash list
* to be not empty for the next test */
/* create a hash in non-empty list - good for coverage */
*/
static int test_hash_creation_with_bad_parameters(void)
{
- struct rte_hash *handle;
+ struct rte_hash *handle, *tmp;
struct rte_hash_parameters params;
handle = rte_hash_create(NULL);
return -1;
}
+ /* test with same name should fail */
+ memcpy(¶ms, &ut_params, sizeof(params));
+ params.name = "same_name";
+ handle = rte_hash_create(¶ms);
+ if (handle == NULL) {
+ printf("Cannot create first hash table with 'same_name'\n");
+ return -1;
+ }
+ tmp = rte_hash_create(¶ms);
+ if (tmp != NULL) {
+ printf("Creation of hash table with same name should fail\n");
+ rte_hash_free(handle);
+ rte_hash_free(tmp);
+ return -1;
+ }
rte_hash_free(handle);
+
printf("# Test successful. No more errors expected\n");
return 0;
static int
test_hash_creation_with_good_parameters(void)
{
- struct rte_hash *handle, *tmp;
+ struct rte_hash *handle;
struct rte_hash_parameters params;
/* create with null hash function - should choose DEFAULT_HASH_FUNC */
memcpy(¶ms, &ut_params, sizeof(params));
- params.name = "same_name";
+ params.name = "name";
params.hash_func = NULL;
handle = rte_hash_create(¶ms);
if (handle == NULL) {
return -1;
}
- /* this test is trying to create a hash with the same name as previous one.
- * this should return a pointer to the hash we previously created.
- * the previous hash isn't freed exactly for the purpose of it being in
- * the hash list.
- */
- memcpy(¶ms, &ut_params, sizeof(params));
- params.name = "same_name";
- tmp = rte_hash_create(¶ms);
-
- /* check if the returned handle is actually equal to the previous hash */
- if (handle != tmp) {
- rte_hash_free(handle);
- rte_hash_free(tmp);
- printf("Creating hash with existing name was successful\n");
- return -1;
- }
-
- /* try creating hash when there already are hashes in the list.
- * the previous hash is not freed to have a non-empty hash list.
- * the other hash that's in the list is still pointed to by "handle" var.
- */
- memcpy(¶ms, &ut_params, sizeof(params));
- params.name = "different_name";
- tmp = rte_hash_create(¶ms);
- if (tmp == NULL) {
- rte_hash_free(handle);
- printf("Creating hash with valid parameters failed\n");
- return -1;
- }
-
- rte_hash_free(tmp);
rte_hash_free(handle);
return 0;
}
-#define ITERATIONS 50
+#define ITERATIONS 3
/*
* Test to see the average table utilization (entries added/max entries)
* before hitting a random entry that cannot be added
static int test_average_table_utilization(void)
{
struct rte_hash *handle;
- uint8_t simple_key[RTE_HASH_KEY_LENGTH_MAX];
+ uint8_t simple_key[MAX_KEYSIZE];
unsigned i, j;
unsigned added_keys, average_keys_added = 0;
int ret;
"\n before adding elements begins to fail\n");
printf("Measuring performance, please wait");
fflush(stdout);
- ut_params.entries = 1 << 20;
+ ut_params.entries = 1 << 16;
ut_params.name = "test_average_utilization";
ut_params.hash_func = rte_jhash;
handle = rte_hash_create(&ut_params);
average_keys_added += added_keys;
/* Reset the table */
- rte_hash_free(handle);
- handle = rte_hash_create(&ut_params);
- RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+ rte_hash_reset(handle);
/* Print a dot to show progress on operations */
printf(".");
return 0;
}
+#define NUM_ENTRIES 256
+static int test_hash_iteration(void)
+{
+ struct rte_hash *handle;
+ unsigned i;
+ uint8_t keys[NUM_ENTRIES][MAX_KEYSIZE];
+ const void *next_key;
+ void *next_data;
+ void *data[NUM_ENTRIES];
+ unsigned added_keys;
+ uint32_t iter = 0;
+ int ret = 0;
+
+ ut_params.entries = NUM_ENTRIES;
+ ut_params.name = "test_hash_iteration";
+ ut_params.hash_func = rte_jhash;
+ ut_params.key_len = 16;
+ handle = rte_hash_create(&ut_params);
+ RETURN_IF_ERROR(handle == NULL, "hash creation failed");
+
+ /* Add random entries until key cannot be added */
+ for (added_keys = 0; added_keys < NUM_ENTRIES; added_keys++) {
+ data[added_keys] = (void *) ((uintptr_t) rte_rand());
+ for (i = 0; i < ut_params.key_len; i++)
+ keys[added_keys][i] = rte_rand() % 255;
+ ret = rte_hash_add_key_data(handle, keys[added_keys], data[added_keys]);
+ if (ret < 0)
+ break;
+ }
+
+ /* Iterate through the hash table */
+ while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {
+ /* Search for the key in the list of keys added */
+ for (i = 0; i < NUM_ENTRIES; i++) {
+ if (memcmp(next_key, keys[i], ut_params.key_len) == 0) {
+ if (next_data != data[i]) {
+ printf("Data found in the hash table is"
+ "not the data added with the key\n");
+ goto err;
+ }
+ added_keys--;
+ break;
+ }
+ }
+ if (i == NUM_ENTRIES) {
+ printf("Key found in the hash table was not added\n");
+ goto err;
+ }
+ }
+
+ /* Check if all keys have been iterated */
+ if (added_keys != 0) {
+ printf("There were still %u keys to iterate\n", added_keys);
+ goto err;
+ }
+
+ rte_hash_free(handle);
+ return 0;
+
+err:
+ rte_hash_free(handle);
+ return -1;
+}
+
static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b,
return -1;
if (test_hash_add_delete_jhash_3word() < 0)
return -1;
+ if (test_hash_get_key_with_position() < 0)
+ return -1;
if (test_hash_find_existing() < 0)
return -1;
if (test_add_update_delete() < 0)
return -1;
if (test_average_table_utilization() < 0)
return -1;
+ if (test_hash_iteration() < 0)
+ return -1;
run_hash_func_tests();
return 0;
}
-static struct test_command hash_cmd = {
- .command = "hash_autotest",
- .callback = test_hash,
-};
-REGISTER_TEST_COMMAND(hash_cmd);
+REGISTER_TEST_COMMAND(hash_autotest, test_hash);