1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2015 Intel Corporation
11 #include <sys/queue.h>
13 #include <rte_common.h>
14 #include <rte_malloc.h>
15 #include <rte_cycles.h>
16 #include <rte_random.h>
17 #include <rte_memory.h>
20 #include <rte_string_fns.h>
25 #include <rte_fbk_hash.h>
26 #include <rte_jhash.h>
27 #include <rte_hash_crc.h>
29 /*******************************************************************************
30 * Hash function performance test configuration section. Each performance test
31 * will be performed HASHTEST_ITERATIONS times.
33 * The five arrays below control what tests are performed. Every combination
34 * from the array entries is tested.
36 static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc};
37 static uint32_t hashtest_initvals[] = {0};
38 static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21, 31, 32, 33, 63, 64};
39 #define MAX_KEYSIZE 64
40 /******************************************************************************/
41 #define LOCAL_FBK_HASH_ENTRIES_MAX (1 << 15)
44 * Check condition and return an error if true. Assumes that "handle" is the
45 * name of the hash structure pointer to be freed.
47 #define RETURN_IF_ERROR(cond, str, ...) do { \
49 printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
50 if (handle) rte_hash_free(handle); \
55 #define RETURN_IF_ERROR_FBK(cond, str, ...) do { \
57 printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
58 if (handle) rte_fbk_hash_free(handle); \
63 #define RETURN_IF_ERROR_RCU_QSBR(cond, str, ...) do { \
65 printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
66 if (rcu_cfg.mode == RTE_HASH_QSBR_MODE_SYNC) { \
68 /* Wait until reader exited. */ \
69 rte_eal_mp_wait_lcore(); \
71 rte_hash_free(g_handle); \
79 * Should be packed to avoid holes with potentially
80 * undefined content in the middle.
91 * Hash function that always returns the same value, to easily test what
92 * happens when a bucket is full.
94 static uint32_t pseudo_hash(__rte_unused const void *keys,
95 __rte_unused uint32_t key_len,
96 __rte_unused uint32_t init_val)
101 RTE_LOG_REGISTER(hash_logtype_test, test.hash, INFO);
104 * Print out result of unit test hash operation.
106 static void print_key_info(const char *msg, const struct flow_key *key,
109 const uint8_t *p = (const uint8_t *)key;
112 rte_log(RTE_LOG_DEBUG, hash_logtype_test, "%s key:0x", msg);
113 for (i = 0; i < sizeof(struct flow_key); i++)
114 rte_log(RTE_LOG_DEBUG, hash_logtype_test, "%02X", p[i]);
115 rte_log(RTE_LOG_DEBUG, hash_logtype_test, " @ pos %d\n", pos);
118 /* Keys used by unit test functions */
119 static struct flow_key keys[5] = { {
120 .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00),
121 .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04),
126 .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10),
127 .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14),
132 .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20),
133 .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24),
138 .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30),
139 .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34),
144 .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40),
145 .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44),
151 /* Parameters used for hash table in unit test functions. Name set later. */
152 static struct rte_hash_parameters ut_params = {
154 .key_len = sizeof(struct flow_key),
155 .hash_func = rte_jhash,
156 .hash_func_init_val = 0,
160 #define CRC32_ITERATIONS (1U << 10)
161 #define CRC32_DWORDS (1U << 6)
163 * Test if all CRC32 implementations yield the same hash value
166 test_crc32_hash_alg_equiv(void)
170 uint64_t data64[CRC32_DWORDS];
174 printf("\n# CRC32 implementations equivalence test\n");
175 for (i = 0; i < CRC32_ITERATIONS; i++) {
176 /* Randomizing data_len of data set */
177 data_len = (size_t) ((rte_rand() % sizeof(data64)) + 1);
178 init_val = (uint32_t) rte_rand();
180 /* Fill the data set */
181 for (j = 0; j < CRC32_DWORDS; j++)
182 data64[j] = rte_rand();
184 /* Calculate software CRC32 */
185 rte_hash_crc_set_alg(CRC32_SW);
186 hash_val = rte_hash_crc(data64, data_len, init_val);
188 /* Check against 4-byte-operand sse4.2 CRC32 if available */
189 rte_hash_crc_set_alg(CRC32_SSE42);
190 if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
191 printf("Failed checking CRC32_SW against CRC32_SSE42\n");
195 /* Check against 8-byte-operand sse4.2 CRC32 if available */
196 rte_hash_crc_set_alg(CRC32_SSE42_x64);
197 if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
198 printf("Failed checking CRC32_SW against CRC32_SSE42_x64\n");
202 /* Check against 8-byte-operand ARM64 CRC32 if available */
203 rte_hash_crc_set_alg(CRC32_ARM64);
204 if (hash_val != rte_hash_crc(data64, data_len, init_val)) {
205 printf("Failed checking CRC32_SW against CRC32_ARM64\n");
210 /* Resetting to best available algorithm */
211 rte_hash_crc_set_alg(CRC32_SSE42_x64);
213 if (i == CRC32_ITERATIONS)
216 printf("Failed test data (hex, %zu bytes total):\n", data_len);
217 for (j = 0; j < data_len; j++)
218 printf("%02X%c", ((uint8_t *)data64)[j],
219 ((j+1) % 16 == 0 || j == data_len - 1) ? '\n' : ' ');
225 * Test a hash function.
227 static void run_hash_func_test(rte_hash_function f, uint32_t init_val,
230 static uint8_t key[MAX_KEYSIZE];
234 for (i = 0; i < key_len; i++)
235 key[i] = (uint8_t) rte_rand();
237 /* just to be on the safe side */
241 f(key, key_len, init_val);
245 * Test all hash functions.
247 static void run_hash_func_tests(void)
251 for (i = 0; i < RTE_DIM(hashtest_funcs); i++) {
252 for (j = 0; j < RTE_DIM(hashtest_initvals); j++) {
253 for (k = 0; k < RTE_DIM(hashtest_key_lens); k++) {
254 run_hash_func_test(hashtest_funcs[i],
255 hashtest_initvals[j],
256 hashtest_key_lens[k]);
263 * Basic sequence of operations for a single key:
269 * Repeat the test case when 'free on delete' is disabled.
276 static int test_add_delete(void)
278 struct rte_hash *handle;
279 /* test with standard add/lookup/delete functions */
280 int pos0, expectedPos0;
282 ut_params.name = "test1";
283 handle = rte_hash_create(&ut_params);
284 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
286 pos0 = rte_hash_add_key(handle, &keys[0]);
287 print_key_info("Add", &keys[0], pos0);
288 RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0);
291 pos0 = rte_hash_lookup(handle, &keys[0]);
292 print_key_info("Lkp", &keys[0], pos0);
293 RETURN_IF_ERROR(pos0 != expectedPos0,
294 "failed to find key (pos0=%d)", pos0);
296 pos0 = rte_hash_del_key(handle, &keys[0]);
297 print_key_info("Del", &keys[0], pos0);
298 RETURN_IF_ERROR(pos0 != expectedPos0,
299 "failed to delete key (pos0=%d)", pos0);
301 pos0 = rte_hash_lookup(handle, &keys[0]);
302 print_key_info("Lkp", &keys[0], pos0);
303 RETURN_IF_ERROR(pos0 != -ENOENT,
304 "fail: found key after deleting! (pos0=%d)", pos0);
306 rte_hash_free(handle);
308 /* repeat test with precomputed hash functions */
309 hash_sig_t hash_value;
310 int pos1, expectedPos1, delPos1;
312 ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;
313 handle = rte_hash_create(&ut_params);
314 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
315 ut_params.extra_flag = 0;
317 hash_value = rte_hash_hash(handle, &keys[0]);
318 pos1 = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);
319 print_key_info("Add", &keys[0], pos1);
320 RETURN_IF_ERROR(pos1 < 0, "failed to add key (pos1=%d)", pos1);
323 pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value);
324 print_key_info("Lkp", &keys[0], pos1);
325 RETURN_IF_ERROR(pos1 != expectedPos1,
326 "failed to find key (pos1=%d)", pos1);
328 pos1 = rte_hash_del_key_with_hash(handle, &keys[0], hash_value);
329 print_key_info("Del", &keys[0], pos1);
330 RETURN_IF_ERROR(pos1 != expectedPos1,
331 "failed to delete key (pos1=%d)", pos1);
334 pos1 = rte_hash_lookup_with_hash(handle, &keys[0], hash_value);
335 print_key_info("Lkp", &keys[0], pos1);
336 RETURN_IF_ERROR(pos1 != -ENOENT,
337 "fail: found key after deleting! (pos1=%d)", pos1);
339 pos1 = rte_hash_free_key_with_position(handle, delPos1);
340 print_key_info("Free", &keys[0], delPos1);
341 RETURN_IF_ERROR(pos1 != 0,
342 "failed to free key (pos1=%d)", delPos1);
344 rte_hash_free(handle);
350 * Sequence of operations for a single key:
355 * - lookup: hit (updated data)
360 static int test_add_update_delete(void)
362 struct rte_hash *handle;
363 int pos0, expectedPos0;
365 ut_params.name = "test2";
366 handle = rte_hash_create(&ut_params);
367 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
369 pos0 = rte_hash_del_key(handle, &keys[0]);
370 print_key_info("Del", &keys[0], pos0);
371 RETURN_IF_ERROR(pos0 != -ENOENT,
372 "fail: found non-existent key (pos0=%d)", pos0);
374 pos0 = rte_hash_add_key(handle, &keys[0]);
375 print_key_info("Add", &keys[0], pos0);
376 RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0);
379 pos0 = rte_hash_lookup(handle, &keys[0]);
380 print_key_info("Lkp", &keys[0], pos0);
381 RETURN_IF_ERROR(pos0 != expectedPos0,
382 "failed to find key (pos0=%d)", pos0);
384 pos0 = rte_hash_add_key(handle, &keys[0]);
385 print_key_info("Add", &keys[0], pos0);
386 RETURN_IF_ERROR(pos0 != expectedPos0,
387 "failed to re-add key (pos0=%d)", pos0);
389 pos0 = rte_hash_lookup(handle, &keys[0]);
390 print_key_info("Lkp", &keys[0], pos0);
391 RETURN_IF_ERROR(pos0 != expectedPos0,
392 "failed to find key (pos0=%d)", pos0);
394 pos0 = rte_hash_del_key(handle, &keys[0]);
395 print_key_info("Del", &keys[0], pos0);
396 RETURN_IF_ERROR(pos0 != expectedPos0,
397 "failed to delete key (pos0=%d)", pos0);
399 pos0 = rte_hash_del_key(handle, &keys[0]);
400 print_key_info("Del", &keys[0], pos0);
401 RETURN_IF_ERROR(pos0 != -ENOENT,
402 "fail: deleted already deleted key (pos0=%d)", pos0);
404 pos0 = rte_hash_lookup(handle, &keys[0]);
405 print_key_info("Lkp", &keys[0], pos0);
406 RETURN_IF_ERROR(pos0 != -ENOENT,
407 "fail: found key after deleting! (pos0=%d)", pos0);
409 rte_hash_free(handle);
414 * Sequence of operations for a single key with 'disable free on del' set:
419 * - lookup: hit (updated data)
426 static int test_add_update_delete_free(void)
428 struct rte_hash *handle;
429 int pos0, expectedPos0, delPos0, result;
431 ut_params.name = "test2";
432 ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;
433 handle = rte_hash_create(&ut_params);
434 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
435 ut_params.extra_flag = 0;
437 pos0 = rte_hash_del_key(handle, &keys[0]);
438 print_key_info("Del", &keys[0], pos0);
439 RETURN_IF_ERROR(pos0 != -ENOENT,
440 "fail: found non-existent key (pos0=%d)", pos0);
442 pos0 = rte_hash_add_key(handle, &keys[0]);
443 print_key_info("Add", &keys[0], pos0);
444 RETURN_IF_ERROR(pos0 < 0, "failed to add key (pos0=%d)", pos0);
447 pos0 = rte_hash_lookup(handle, &keys[0]);
448 print_key_info("Lkp", &keys[0], pos0);
449 RETURN_IF_ERROR(pos0 != expectedPos0,
450 "failed to find key (pos0=%d)", pos0);
452 pos0 = rte_hash_add_key(handle, &keys[0]);
453 print_key_info("Add", &keys[0], pos0);
454 RETURN_IF_ERROR(pos0 != expectedPos0,
455 "failed to re-add key (pos0=%d)", pos0);
457 pos0 = rte_hash_lookup(handle, &keys[0]);
458 print_key_info("Lkp", &keys[0], pos0);
459 RETURN_IF_ERROR(pos0 != expectedPos0,
460 "failed to find key (pos0=%d)", pos0);
462 delPos0 = rte_hash_del_key(handle, &keys[0]);
463 print_key_info("Del", &keys[0], delPos0);
464 RETURN_IF_ERROR(delPos0 != expectedPos0,
465 "failed to delete key (pos0=%d)", delPos0);
467 pos0 = rte_hash_del_key(handle, &keys[0]);
468 print_key_info("Del", &keys[0], pos0);
469 RETURN_IF_ERROR(pos0 != -ENOENT,
470 "fail: deleted already deleted key (pos0=%d)", pos0);
472 pos0 = rte_hash_lookup(handle, &keys[0]);
473 print_key_info("Lkp", &keys[0], pos0);
474 RETURN_IF_ERROR(pos0 != -ENOENT,
475 "fail: found key after deleting! (pos0=%d)", pos0);
477 result = rte_hash_free_key_with_position(handle, delPos0);
478 print_key_info("Free", &keys[0], delPos0);
479 RETURN_IF_ERROR(result != 0,
480 "failed to free key (pos1=%d)", delPos0);
482 pos0 = rte_hash_lookup(handle, &keys[0]);
483 print_key_info("Lkp", &keys[0], pos0);
484 RETURN_IF_ERROR(pos0 != -ENOENT,
485 "fail: found key after deleting! (pos0=%d)", pos0);
487 rte_hash_free(handle);
492 * Sequence of operations for a single key with 'rw concurrency lock free' set:
496 * Repeat the test case when 'multi writer add' is enabled.
501 static int test_add_delete_free_lf(void)
503 /* Should match the #define LCORE_CACHE_SIZE value in rte_cuckoo_hash.h */
504 #define LCORE_CACHE_SIZE 64
505 struct rte_hash *handle;
506 hash_sig_t hash_value;
507 int pos, expectedPos, delPos;
511 extra_flag = ut_params.extra_flag;
512 ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
513 handle = rte_hash_create(&ut_params);
514 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
515 ut_params.extra_flag = extra_flag;
518 * The number of iterations is at least the same as the number of slots
519 * rte_hash allocates internally. This is to reveal potential issues of
520 * not freeing keys successfully.
522 for (i = 0; i < ut_params.entries + 1; i++) {
523 hash_value = rte_hash_hash(handle, &keys[0]);
524 pos = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);
525 print_key_info("Add", &keys[0], pos);
526 RETURN_IF_ERROR(pos < 0, "failed to add key (pos=%d)", pos);
529 pos = rte_hash_del_key_with_hash(handle, &keys[0], hash_value);
530 print_key_info("Del", &keys[0], pos);
531 RETURN_IF_ERROR(pos != expectedPos,
532 "failed to delete key (pos=%d)", pos);
535 pos = rte_hash_free_key_with_position(handle, delPos);
536 print_key_info("Free", &keys[0], delPos);
537 RETURN_IF_ERROR(pos != 0,
538 "failed to free key (pos=%d)", delPos);
541 rte_hash_free(handle);
543 extra_flag = ut_params.extra_flag;
544 ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |
545 RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
546 handle = rte_hash_create(&ut_params);
547 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
548 ut_params.extra_flag = extra_flag;
550 ip_src = keys[0].ip_src;
552 * The number of iterations is at least the same as the number of slots
553 * rte_hash allocates internally. This is to reveal potential issues of
554 * not freeing keys successfully.
556 for (i = 0; i < ut_params.entries + (RTE_MAX_LCORE - 1) *
557 (LCORE_CACHE_SIZE - 1) + 1; i++) {
559 hash_value = rte_hash_hash(handle, &keys[0]);
560 pos = rte_hash_add_key_with_hash(handle, &keys[0], hash_value);
561 print_key_info("Add", &keys[0], pos);
562 RETURN_IF_ERROR(pos < 0, "failed to add key (pos=%d)", pos);
565 pos = rte_hash_del_key_with_hash(handle, &keys[0], hash_value);
566 print_key_info("Del", &keys[0], pos);
567 RETURN_IF_ERROR(pos != expectedPos,
568 "failed to delete key (pos=%d)", pos);
571 pos = rte_hash_free_key_with_position(handle, delPos);
572 print_key_info("Free", &keys[0], delPos);
573 RETURN_IF_ERROR(pos != 0,
574 "failed to free key (pos=%d)", delPos);
576 keys[0].ip_src = ip_src;
578 rte_hash_free(handle);
584 * Sequence of operations for retrieving a key with its position
588 * - get the key with its position: hit
590 * - try to get the deleted key: miss
592 * Repeat the test case when 'free on delete' is disabled.
595 * - get the key with its position: hit
597 * - try to get the deleted key: hit
599 * - try to get the deleted key: miss
602 static int test_hash_get_key_with_position(void)
604 struct rte_hash *handle = NULL;
605 int pos, expectedPos, delPos, result;
608 ut_params.name = "hash_get_key_w_pos";
609 handle = rte_hash_create(&ut_params);
610 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
612 pos = rte_hash_add_key(handle, &keys[0]);
613 print_key_info("Add", &keys[0], pos);
614 RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos);
617 result = rte_hash_get_key_with_position(handle, pos, &key);
618 RETURN_IF_ERROR(result != 0, "error retrieving a key");
620 pos = rte_hash_del_key(handle, &keys[0]);
621 print_key_info("Del", &keys[0], pos);
622 RETURN_IF_ERROR(pos != expectedPos,
623 "failed to delete key (pos0=%d)", pos);
625 result = rte_hash_get_key_with_position(handle, pos, &key);
626 RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
628 rte_hash_free(handle);
630 ut_params.name = "hash_get_key_w_pos";
631 ut_params.extra_flag = RTE_HASH_EXTRA_FLAGS_NO_FREE_ON_DEL;
632 handle = rte_hash_create(&ut_params);
633 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
634 ut_params.extra_flag = 0;
636 pos = rte_hash_add_key(handle, &keys[0]);
637 print_key_info("Add", &keys[0], pos);
638 RETURN_IF_ERROR(pos < 0, "failed to add key (pos0=%d)", pos);
641 result = rte_hash_get_key_with_position(handle, pos, &key);
642 RETURN_IF_ERROR(result != 0, "error retrieving a key");
644 delPos = rte_hash_del_key(handle, &keys[0]);
645 print_key_info("Del", &keys[0], delPos);
646 RETURN_IF_ERROR(delPos != expectedPos,
647 "failed to delete key (pos0=%d)", delPos);
649 result = rte_hash_get_key_with_position(handle, delPos, &key);
650 RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
652 result = rte_hash_free_key_with_position(handle, delPos);
653 print_key_info("Free", &keys[0], delPos);
654 RETURN_IF_ERROR(result != 0,
655 "failed to free key (pos1=%d)", delPos);
657 result = rte_hash_get_key_with_position(handle, delPos, &key);
658 RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
660 rte_hash_free(handle);
665 * Sequence of operations for find existing hash table
668 * - find existing table: hit
669 * - find non-existing table: miss
672 static int test_hash_find_existing(void)
674 struct rte_hash *handle = NULL, *result = NULL;
676 /* Create hash table. */
677 ut_params.name = "hash_find_existing";
678 handle = rte_hash_create(&ut_params);
679 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
681 /* Try to find existing hash table */
682 result = rte_hash_find_existing("hash_find_existing");
683 RETURN_IF_ERROR(result != handle, "could not find existing hash table");
685 /* Try to find non-existing hash table */
686 result = rte_hash_find_existing("hash_find_non_existing");
687 RETURN_IF_ERROR(!(result == NULL), "found table that shouldn't exist");
690 rte_hash_free(handle);
696 * Sequence of operations for 5 keys
699 * - add keys (update)
700 * - lookup keys: hit (updated data)
701 * - delete keys : hit
702 * - lookup keys: miss
704 static int test_five_keys(void)
706 struct rte_hash *handle;
707 const void *key_array[5] = {0};
713 ut_params.name = "test3";
714 handle = rte_hash_create(&ut_params);
715 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
718 for (i = 0; i < 5; i++) {
719 pos[i] = rte_hash_add_key(handle, &keys[i]);
720 print_key_info("Add", &keys[i], pos[i]);
721 RETURN_IF_ERROR(pos[i] < 0,
722 "failed to add key (pos[%u]=%d)", i, pos[i]);
723 expected_pos[i] = pos[i];
727 for(i = 0; i < 5; i++)
728 key_array[i] = &keys[i];
730 ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
732 for(i = 0; i < 5; i++) {
733 print_key_info("Lkp", key_array[i], pos[i]);
734 RETURN_IF_ERROR(pos[i] != expected_pos[i],
735 "failed to find key (pos[%u]=%d)", i, pos[i]);
739 for (i = 0; i < 5; i++) {
740 pos[i] = rte_hash_add_key(handle, &keys[i]);
741 print_key_info("Add", &keys[i], pos[i]);
742 RETURN_IF_ERROR(pos[i] != expected_pos[i],
743 "failed to add key (pos[%u]=%d)", i, pos[i]);
747 for (i = 0; i < 5; i++) {
748 pos[i] = rte_hash_lookup(handle, &keys[i]);
749 print_key_info("Lkp", &keys[i], pos[i]);
750 RETURN_IF_ERROR(pos[i] != expected_pos[i],
751 "failed to find key (pos[%u]=%d)", i, pos[i]);
755 for (i = 0; i < 5; i++) {
756 pos[i] = rte_hash_del_key(handle, &keys[i]);
757 print_key_info("Del", &keys[i], pos[i]);
758 RETURN_IF_ERROR(pos[i] != expected_pos[i],
759 "failed to delete key (pos[%u]=%d)", i, pos[i]);
763 for (i = 0; i < 5; i++) {
764 pos[i] = rte_hash_lookup(handle, &keys[i]);
765 print_key_info("Lkp", &keys[i], pos[i]);
766 RETURN_IF_ERROR(pos[i] != -ENOENT,
767 "found non-existent key (pos[%u]=%d)", i, pos[i]);
771 ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
773 for (i = 0; i < 5; i++) {
774 print_key_info("Lkp", key_array[i], pos[i]);
775 RETURN_IF_ERROR(pos[i] != -ENOENT,
776 "found not-existent key (pos[%u]=%d)", i, pos[i]);
779 rte_hash_free(handle);
785 * Add keys to the same bucket until bucket full.
786 * - add 5 keys to the same bucket (hash created with 4 keys per bucket):
787 * first 4 successful, 5th successful, pushing existing item in bucket
788 * - lookup the 5 keys: 5 hits
789 * - add the 5 keys again: 5 OK
790 * - lookup the 5 keys: 5 hits (updated data)
791 * - delete the 5 keys: 5 OK
792 * - lookup the 5 keys: 5 misses
794 static int test_full_bucket(void)
796 struct rte_hash_parameters params_pseudo_hash = {
799 .key_len = sizeof(struct flow_key),
800 .hash_func = pseudo_hash,
801 .hash_func_init_val = 0,
804 struct rte_hash *handle;
809 handle = rte_hash_create(¶ms_pseudo_hash);
810 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
813 for (i = 0; i < 4; i++) {
814 pos[i] = rte_hash_add_key(handle, &keys[i]);
815 print_key_info("Add", &keys[i], pos[i]);
816 RETURN_IF_ERROR(pos[i] < 0,
817 "failed to add key (pos[%u]=%d)", i, pos[i]);
818 expected_pos[i] = pos[i];
821 * This should work and will push one of the items
822 * in the bucket because it is full
824 pos[4] = rte_hash_add_key(handle, &keys[4]);
825 print_key_info("Add", &keys[4], pos[4]);
826 RETURN_IF_ERROR(pos[4] < 0,
827 "failed to add key (pos[4]=%d)", pos[4]);
828 expected_pos[4] = pos[4];
831 for (i = 0; i < 5; i++) {
832 pos[i] = rte_hash_lookup(handle, &keys[i]);
833 print_key_info("Lkp", &keys[i], pos[i]);
834 RETURN_IF_ERROR(pos[i] != expected_pos[i],
835 "failed to find key (pos[%u]=%d)", i, pos[i]);
839 for (i = 0; i < 5; i++) {
840 pos[i] = rte_hash_add_key(handle, &keys[i]);
841 print_key_info("Add", &keys[i], pos[i]);
842 RETURN_IF_ERROR(pos[i] != expected_pos[i],
843 "failed to add key (pos[%u]=%d)", i, pos[i]);
847 for (i = 0; i < 5; i++) {
848 pos[i] = rte_hash_lookup(handle, &keys[i]);
849 print_key_info("Lkp", &keys[i], pos[i]);
850 RETURN_IF_ERROR(pos[i] != expected_pos[i],
851 "failed to find key (pos[%u]=%d)", i, pos[i]);
854 /* Delete 1 key, check other keys are still found */
855 pos[1] = rte_hash_del_key(handle, &keys[1]);
856 print_key_info("Del", &keys[1], pos[1]);
857 RETURN_IF_ERROR(pos[1] != expected_pos[1],
858 "failed to delete key (pos[1]=%d)", pos[1]);
859 pos[3] = rte_hash_lookup(handle, &keys[3]);
860 print_key_info("Lkp", &keys[3], pos[3]);
861 RETURN_IF_ERROR(pos[3] != expected_pos[3],
862 "failed lookup after deleting key from same bucket "
863 "(pos[3]=%d)", pos[3]);
865 /* Go back to previous state */
866 pos[1] = rte_hash_add_key(handle, &keys[1]);
867 print_key_info("Add", &keys[1], pos[1]);
868 expected_pos[1] = pos[1];
869 RETURN_IF_ERROR(pos[1] < 0, "failed to add key (pos[1]=%d)", pos[1]);
872 for (i = 0; i < 5; i++) {
873 pos[i] = rte_hash_del_key(handle, &keys[i]);
874 print_key_info("Del", &keys[i], pos[i]);
875 RETURN_IF_ERROR(pos[i] != expected_pos[i],
876 "failed to delete key (pos[%u]=%d)", i, pos[i]);
880 for (i = 0; i < 5; i++) {
881 pos[i] = rte_hash_lookup(handle, &keys[i]);
882 print_key_info("Lkp", &keys[i], pos[i]);
883 RETURN_IF_ERROR(pos[i] != -ENOENT,
884 "fail: found non-existent key (pos[%u]=%d)", i, pos[i]);
887 rte_hash_free(handle);
889 /* Cover the NULL case. */
895 * Similar to the test above (full bucket test), but for extendable buckets.
897 static int test_extendable_bucket(void)
899 struct rte_hash_parameters params_pseudo_hash = {
902 .key_len = sizeof(struct flow_key),
903 .hash_func = pseudo_hash,
904 .hash_func_init_val = 0,
906 .extra_flag = RTE_HASH_EXTRA_FLAGS_EXT_TABLE
908 struct rte_hash *handle;
910 int expected_pos[64];
912 struct flow_key rand_keys[64];
914 for (i = 0; i < 64; i++) {
915 rand_keys[i].port_dst = i;
916 rand_keys[i].port_src = i+1;
919 handle = rte_hash_create(¶ms_pseudo_hash);
920 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
923 for (i = 0; i < 64; i++) {
924 pos[i] = rte_hash_add_key(handle, &rand_keys[i]);
925 print_key_info("Add", &rand_keys[i], pos[i]);
926 RETURN_IF_ERROR(pos[i] < 0,
927 "failed to add key (pos[%u]=%d)", i, pos[i]);
928 expected_pos[i] = pos[i];
932 for (i = 0; i < 64; i++) {
933 pos[i] = rte_hash_lookup(handle, &rand_keys[i]);
934 print_key_info("Lkp", &rand_keys[i], pos[i]);
935 RETURN_IF_ERROR(pos[i] != expected_pos[i],
936 "failed to find key (pos[%u]=%d)", i, pos[i]);
940 for (i = 0; i < 64; i++) {
941 pos[i] = rte_hash_add_key(handle, &rand_keys[i]);
942 print_key_info("Add", &rand_keys[i], pos[i]);
943 RETURN_IF_ERROR(pos[i] != expected_pos[i],
944 "failed to add key (pos[%u]=%d)", i, pos[i]);
948 for (i = 0; i < 64; i++) {
949 pos[i] = rte_hash_lookup(handle, &rand_keys[i]);
950 print_key_info("Lkp", &rand_keys[i], pos[i]);
951 RETURN_IF_ERROR(pos[i] != expected_pos[i],
952 "failed to find key (pos[%u]=%d)", i, pos[i]);
955 /* Delete 1 key, check other keys are still found */
956 pos[35] = rte_hash_del_key(handle, &rand_keys[35]);
957 print_key_info("Del", &rand_keys[35], pos[35]);
958 RETURN_IF_ERROR(pos[35] != expected_pos[35],
959 "failed to delete key (pos[1]=%d)", pos[35]);
960 pos[20] = rte_hash_lookup(handle, &rand_keys[20]);
961 print_key_info("Lkp", &rand_keys[20], pos[20]);
962 RETURN_IF_ERROR(pos[20] != expected_pos[20],
963 "failed lookup after deleting key from same bucket "
964 "(pos[20]=%d)", pos[20]);
966 /* Go back to previous state */
967 pos[35] = rte_hash_add_key(handle, &rand_keys[35]);
968 print_key_info("Add", &rand_keys[35], pos[35]);
969 expected_pos[35] = pos[35];
970 RETURN_IF_ERROR(pos[35] < 0, "failed to add key (pos[1]=%d)", pos[35]);
973 for (i = 0; i < 64; i++) {
974 pos[i] = rte_hash_del_key(handle, &rand_keys[i]);
975 print_key_info("Del", &rand_keys[i], pos[i]);
976 RETURN_IF_ERROR(pos[i] != expected_pos[i],
977 "failed to delete key (pos[%u]=%d)", i, pos[i]);
981 for (i = 0; i < 64; i++) {
982 pos[i] = rte_hash_lookup(handle, &rand_keys[i]);
983 print_key_info("Lkp", &rand_keys[i], pos[i]);
984 RETURN_IF_ERROR(pos[i] != -ENOENT,
985 "fail: found non-existent key (pos[%u]=%d)", i, pos[i]);
989 for (i = 0; i < 64; i++) {
990 pos[i] = rte_hash_add_key(handle, &rand_keys[i]);
991 print_key_info("Add", &rand_keys[i], pos[i]);
992 RETURN_IF_ERROR(pos[i] < 0,
993 "failed to add key (pos[%u]=%d)", i, pos[i]);
994 expected_pos[i] = pos[i];
997 rte_hash_free(handle);
999 /* Cover the NULL case. */
1004 /******************************************************************************/
1006 fbk_hash_unit_test(void)
1008 struct rte_fbk_hash_params params = {
1009 .name = "fbk_hash_test",
1010 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1011 .entries_per_bucket = 4,
1015 struct rte_fbk_hash_params invalid_params_1 = {
1016 .name = "invalid_1",
1017 .entries = LOCAL_FBK_HASH_ENTRIES_MAX + 1, /* Not power of 2 */
1018 .entries_per_bucket = 4,
1022 struct rte_fbk_hash_params invalid_params_2 = {
1023 .name = "invalid_2",
1025 .entries_per_bucket = 3, /* Not power of 2 */
1029 struct rte_fbk_hash_params invalid_params_3 = {
1030 .name = "invalid_3",
1031 .entries = 0, /* Entries is 0 */
1032 .entries_per_bucket = 4,
1036 struct rte_fbk_hash_params invalid_params_4 = {
1037 .name = "invalid_4",
1038 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1039 .entries_per_bucket = 0, /* Entries per bucket is 0 */
1043 struct rte_fbk_hash_params invalid_params_5 = {
1044 .name = "invalid_5",
1046 .entries_per_bucket = 8, /* Entries per bucket > entries */
1050 struct rte_fbk_hash_params invalid_params_6 = {
1051 .name = "invalid_6",
1052 .entries = RTE_FBK_HASH_ENTRIES_MAX * 2, /* Entries > max allowed */
1053 .entries_per_bucket = 4,
1057 struct rte_fbk_hash_params invalid_params_7 = {
1058 .name = "invalid_7",
1059 .entries = RTE_FBK_HASH_ENTRIES_MAX,
1060 .entries_per_bucket = RTE_FBK_HASH_ENTRIES_PER_BUCKET_MAX * 2, /* Entries > max allowed */
1064 struct rte_fbk_hash_params invalid_params_8 = {
1065 .name = "invalid_7",
1066 .entries = RTE_FBK_HASH_ENTRIES_MAX,
1067 .entries_per_bucket = 4,
1068 .socket_id = RTE_MAX_NUMA_NODES + 1, /* invalid socket */
1071 /* try to create two hashes with identical names
1072 * in this case, trying to create a second one will not
1073 * fail but will simply return pointer to the existing
1074 * hash with that name. sort of like a "find hash by name" :-)
1076 struct rte_fbk_hash_params invalid_params_same_name_1 = {
1077 .name = "same_name", /* hash with identical name */
1079 .entries_per_bucket = 2,
1083 /* trying to create this hash should return a pointer to an existing hash */
1084 struct rte_fbk_hash_params invalid_params_same_name_2 = {
1085 .name = "same_name", /* hash with identical name */
1086 .entries = RTE_FBK_HASH_ENTRIES_MAX,
1087 .entries_per_bucket = 4,
1091 /* this is a sanity check for "same name" test
1092 * creating this hash will check if we are actually able to create
1093 * multiple hashes with different names (instead of having just one).
1095 struct rte_fbk_hash_params different_name = {
1096 .name = "different_name", /* different name */
1097 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1098 .entries_per_bucket = 4,
1102 struct rte_fbk_hash_params params_jhash = {
1104 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1105 .entries_per_bucket = 4,
1107 .hash_func = rte_jhash_1word, /* Tests for different hash_func */
1108 .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
1111 struct rte_fbk_hash_params params_nohash = {
1112 .name = "valid nohash",
1113 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1114 .entries_per_bucket = 4,
1116 .hash_func = NULL, /* Tests for null hash_func */
1117 .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
1120 struct rte_fbk_hash_table *handle, *tmp;
1122 {0xc6e18639, 0xe67c201c, 0xd4c8cffd, 0x44728691, 0xd5430fa9};
1123 uint16_t vals[5] = {28108, 5699, 38490, 2166, 61571};
1126 double used_entries;
1128 /* Try creating hashes with invalid parameters */
1129 printf("# Testing hash creation with invalid parameters "
1130 "- expect error msgs\n");
1131 handle = rte_fbk_hash_create(&invalid_params_1);
1132 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1134 handle = rte_fbk_hash_create(&invalid_params_2);
1135 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1137 handle = rte_fbk_hash_create(&invalid_params_3);
1138 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1140 handle = rte_fbk_hash_create(&invalid_params_4);
1141 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1143 handle = rte_fbk_hash_create(&invalid_params_5);
1144 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1146 handle = rte_fbk_hash_create(&invalid_params_6);
1147 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1149 handle = rte_fbk_hash_create(&invalid_params_7);
1150 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1152 if (rte_eal_has_hugepages()) {
1153 handle = rte_fbk_hash_create(&invalid_params_8);
1154 RETURN_IF_ERROR_FBK(handle != NULL,
1155 "fbk hash creation should have failed");
1158 handle = rte_fbk_hash_create(&invalid_params_same_name_1);
1159 RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded");
1161 tmp = rte_fbk_hash_create(&invalid_params_same_name_2);
1163 rte_fbk_hash_free(tmp);
1164 RETURN_IF_ERROR_FBK(tmp != NULL, "fbk hash creation should have failed");
1166 /* we are not freeing handle here because we need a hash list
1167 * to be not empty for the next test */
1169 /* create a hash in non-empty list - good for coverage */
1170 tmp = rte_fbk_hash_create(&different_name);
1171 RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded");
1173 /* free both hashes */
1174 rte_fbk_hash_free(handle);
1175 rte_fbk_hash_free(tmp);
1177 /* Create empty jhash hash. */
1178 handle = rte_fbk_hash_create(¶ms_jhash);
1179 RETURN_IF_ERROR_FBK(handle == NULL, "fbk jhash hash creation failed");
1182 rte_fbk_hash_free(handle);
1184 /* Create empty jhash hash. */
1185 handle = rte_fbk_hash_create(¶ms_nohash);
1186 RETURN_IF_ERROR_FBK(handle == NULL, "fbk nohash hash creation failed");
1189 rte_fbk_hash_free(handle);
1191 /* Create empty hash. */
1192 handle = rte_fbk_hash_create(¶ms);
1193 RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed");
1195 used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX;
1196 RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \
1197 "load factor right after creation is not zero but it should be");
1199 for (i = 0; i < 5; i++) {
1200 status = rte_fbk_hash_add_key(handle, keys[i], vals[i]);
1201 RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed");
1204 used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX;
1205 RETURN_IF_ERROR_FBK((unsigned)used_entries != (unsigned)((((double)5)/LOCAL_FBK_HASH_ENTRIES_MAX)*LOCAL_FBK_HASH_ENTRIES_MAX), \
1206 "load factor now is not as expected");
1207 /* Find value of added keys. */
1208 for (i = 0; i < 5; i++) {
1209 status = rte_fbk_hash_lookup(handle, keys[i]);
1210 RETURN_IF_ERROR_FBK(status != vals[i],
1211 "fbk hash lookup failed");
1214 /* Change value of added keys. */
1215 for (i = 0; i < 5; i++) {
1216 status = rte_fbk_hash_add_key(handle, keys[i], vals[4 - i]);
1217 RETURN_IF_ERROR_FBK(status != 0, "fbk hash update failed");
1220 /* Find new values. */
1221 for (i = 0; i < 5; i++) {
1222 status = rte_fbk_hash_lookup(handle, keys[i]);
1223 RETURN_IF_ERROR_FBK(status != vals[4-i],
1224 "fbk hash lookup failed");
1227 /* Delete keys individually. */
1228 for (i = 0; i < 5; i++) {
1229 status = rte_fbk_hash_delete_key(handle, keys[i]);
1230 RETURN_IF_ERROR_FBK(status != 0, "fbk hash delete failed");
1233 used_entries = rte_fbk_hash_get_load_factor(handle) * LOCAL_FBK_HASH_ENTRIES_MAX;
1234 RETURN_IF_ERROR_FBK((unsigned)used_entries != 0, \
1235 "load factor right after deletion is not zero but it should be");
1236 /* Lookup should now fail. */
1237 for (i = 0; i < 5; i++) {
1238 status = rte_fbk_hash_lookup(handle, keys[i]);
1239 RETURN_IF_ERROR_FBK(status == 0,
1240 "fbk hash lookup should have failed");
1243 /* Add keys again. */
1244 for (i = 0; i < 5; i++) {
1245 status = rte_fbk_hash_add_key(handle, keys[i], vals[i]);
1246 RETURN_IF_ERROR_FBK(status != 0, "fbk hash add failed");
1249 /* Make sure they were added. */
1250 for (i = 0; i < 5; i++) {
1251 status = rte_fbk_hash_lookup(handle, keys[i]);
1252 RETURN_IF_ERROR_FBK(status != vals[i],
1253 "fbk hash lookup failed");
1256 /* Clear all entries. */
1257 rte_fbk_hash_clear_all(handle);
1259 /* Lookup should fail. */
1260 for (i = 0; i < 5; i++) {
1261 status = rte_fbk_hash_lookup(handle, keys[i]);
1262 RETURN_IF_ERROR_FBK(status == 0,
1263 "fbk hash lookup should have failed");
1268 /* fill up the hash_table */
1269 for (i = 0; i < RTE_FBK_HASH_ENTRIES_MAX + 1; i++)
1270 rte_fbk_hash_add_key(handle, i, (uint16_t) i);
1272 /* Find non-existent key in a full hashtable */
1273 status = rte_fbk_hash_lookup(handle, RTE_FBK_HASH_ENTRIES_MAX + 1);
1274 RETURN_IF_ERROR_FBK(status != -ENOENT,
1275 "fbk hash lookup succeeded");
1277 /* Delete non-existent key in a full hashtable */
1278 status = rte_fbk_hash_delete_key(handle, RTE_FBK_HASH_ENTRIES_MAX + 1);
1279 RETURN_IF_ERROR_FBK(status != -ENOENT,
1280 "fbk hash delete succeeded");
1282 /* Delete one key from a full hashtable */
1283 status = rte_fbk_hash_delete_key(handle, 1);
1284 RETURN_IF_ERROR_FBK(status != 0,
1285 "fbk hash delete failed");
1287 /* Clear all entries. */
1288 rte_fbk_hash_clear_all(handle);
1291 rte_fbk_hash_free(handle);
1293 /* Cover the NULL case. */
1294 rte_fbk_hash_free(0);
1300 * Sequence of operations for find existing fbk hash table
1303 * - find existing table: hit
1304 * - find non-existing table: miss
1307 static int test_fbk_hash_find_existing(void)
1309 struct rte_fbk_hash_params params = {
1310 .name = "fbk_hash_find_existing",
1311 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1312 .entries_per_bucket = 4,
1315 struct rte_fbk_hash_table *handle = NULL, *result = NULL;
1317 /* Create hash table. */
1318 handle = rte_fbk_hash_create(¶ms);
1319 RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed");
1321 /* Try to find existing fbk hash table */
1322 result = rte_fbk_hash_find_existing("fbk_hash_find_existing");
1323 RETURN_IF_ERROR_FBK(result != handle, "could not find existing fbk hash table");
1325 /* Try to find non-existing fbk hash table */
1326 result = rte_fbk_hash_find_existing("fbk_hash_find_non_existing");
1327 RETURN_IF_ERROR_FBK(!(result == NULL), "found fbk table that shouldn't exist");
1330 rte_fbk_hash_free(handle);
1335 #define BUCKET_ENTRIES 4
1337 * Do tests for hash creation with bad parameters.
1339 static int test_hash_creation_with_bad_parameters(void)
1341 struct rte_hash *handle, *tmp;
1342 struct rte_hash_parameters params;
1344 handle = rte_hash_create(NULL);
1345 if (handle != NULL) {
1346 rte_hash_free(handle);
1347 printf("Impossible creating hash successfully without any parameter\n");
1351 memcpy(¶ms, &ut_params, sizeof(params));
1352 params.name = "creation_with_bad_parameters_0";
1353 params.entries = RTE_HASH_ENTRIES_MAX + 1;
1354 handle = rte_hash_create(¶ms);
1355 if (handle != NULL) {
1356 rte_hash_free(handle);
1357 printf("Impossible creating hash successfully with entries in parameter exceeded\n");
1361 memcpy(¶ms, &ut_params, sizeof(params));
1362 params.name = "creation_with_bad_parameters_2";
1363 params.entries = BUCKET_ENTRIES - 1;
1364 handle = rte_hash_create(¶ms);
1365 if (handle != NULL) {
1366 rte_hash_free(handle);
1367 printf("Impossible creating hash successfully if entries less than bucket_entries in parameter\n");
1371 memcpy(¶ms, &ut_params, sizeof(params));
1372 params.name = "creation_with_bad_parameters_3";
1374 handle = rte_hash_create(¶ms);
1375 if (handle != NULL) {
1376 rte_hash_free(handle);
1377 printf("Impossible creating hash successfully if key_len in parameter is zero\n");
1381 memcpy(¶ms, &ut_params, sizeof(params));
1382 params.name = "creation_with_bad_parameters_4";
1383 params.socket_id = RTE_MAX_NUMA_NODES + 1;
1384 handle = rte_hash_create(¶ms);
1385 if (handle != NULL) {
1386 rte_hash_free(handle);
1387 printf("Impossible creating hash successfully with invalid socket\n");
1391 /* test with same name should fail */
1392 memcpy(¶ms, &ut_params, sizeof(params));
1393 params.name = "same_name";
1394 handle = rte_hash_create(¶ms);
1395 if (handle == NULL) {
1396 printf("Cannot create first hash table with 'same_name'\n");
1399 tmp = rte_hash_create(¶ms);
1401 printf("Creation of hash table with same name should fail\n");
1402 rte_hash_free(handle);
1406 rte_hash_free(handle);
1408 printf("# Test successful. No more errors expected\n");
1414 * Do tests for hash creation with parameters that look incorrect
1415 * but are actually valid.
1418 test_hash_creation_with_good_parameters(void)
1420 struct rte_hash *handle;
1421 struct rte_hash_parameters params;
1423 /* create with null hash function - should choose DEFAULT_HASH_FUNC */
1424 memcpy(¶ms, &ut_params, sizeof(params));
1425 params.name = "name";
1426 params.hash_func = NULL;
1427 handle = rte_hash_create(¶ms);
1428 if (handle == NULL) {
1429 printf("Creating hash with null hash_func failed\n");
1433 rte_hash_free(handle);
1438 #define ITERATIONS 3
1440 * Test to see the average table utilization (entries added/max entries)
1441 * before hitting a random entry that cannot be added
1443 static int test_average_table_utilization(uint32_t ext_table)
1445 struct rte_hash *handle;
1446 uint8_t simple_key[MAX_KEYSIZE];
1448 unsigned added_keys, average_keys_added = 0;
1452 printf("\n# Running test to determine average utilization"
1453 "\n before adding elements begins to fail\n");
1455 printf("ext table is enabled\n");
1457 printf("ext table is disabled\n");
1459 printf("Measuring performance, please wait");
1461 ut_params.entries = 1 << 16;
1462 ut_params.name = "test_average_utilization";
1463 ut_params.hash_func = rte_jhash;
1465 ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1467 ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1469 handle = rte_hash_create(&ut_params);
1471 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
1473 for (j = 0; j < ITERATIONS; j++) {
1475 /* Add random entries until key cannot be added */
1476 for (added_keys = 0; ret >= 0; added_keys++) {
1477 for (i = 0; i < ut_params.key_len; i++)
1478 simple_key[i] = rte_rand() % 255;
1479 ret = rte_hash_add_key(handle, simple_key);
1484 if (ret != -ENOSPC) {
1485 printf("Unexpected error when adding keys\n");
1486 rte_hash_free(handle);
1490 cnt = rte_hash_count(handle);
1491 if (cnt != added_keys) {
1492 printf("rte_hash_count returned wrong value %u, %u,"
1493 "%u\n", j, added_keys, cnt);
1494 rte_hash_free(handle);
1498 if (cnt != ut_params.entries) {
1499 printf("rte_hash_count returned wrong value "
1500 "%u, %u, %u\n", j, added_keys, cnt);
1501 rte_hash_free(handle);
1506 average_keys_added += added_keys;
1508 /* Reset the table */
1509 rte_hash_reset(handle);
1511 /* Print a dot to show progress on operations */
1516 average_keys_added /= ITERATIONS;
1518 printf("\nAverage table utilization = %.2f%% (%u/%u)\n",
1519 ((double) average_keys_added / ut_params.entries * 100),
1520 average_keys_added, ut_params.entries);
1521 rte_hash_free(handle);
1526 #define NUM_ENTRIES 256
1527 static int test_hash_iteration(uint32_t ext_table)
1529 struct rte_hash *handle;
1531 uint8_t keys[NUM_ENTRIES][MAX_KEYSIZE];
1532 const void *next_key;
1534 void *data[NUM_ENTRIES];
1535 unsigned added_keys;
1539 ut_params.entries = NUM_ENTRIES;
1540 ut_params.name = "test_hash_iteration";
1541 ut_params.hash_func = rte_jhash;
1542 ut_params.key_len = 16;
1544 ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1546 ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1548 handle = rte_hash_create(&ut_params);
1549 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
1551 /* Add random entries until key cannot be added */
1552 for (added_keys = 0; added_keys < NUM_ENTRIES; added_keys++) {
1553 data[added_keys] = (void *) ((uintptr_t) rte_rand());
1554 for (i = 0; i < ut_params.key_len; i++)
1555 keys[added_keys][i] = rte_rand() % 255;
1556 ret = rte_hash_add_key_data(handle, keys[added_keys], data[added_keys]);
1559 printf("Insertion failed for ext table\n");
1566 /* Iterate through the hash table */
1567 while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {
1568 /* Search for the key in the list of keys added */
1569 for (i = 0; i < NUM_ENTRIES; i++) {
1570 if (memcmp(next_key, keys[i], ut_params.key_len) == 0) {
1571 if (next_data != data[i]) {
1572 printf("Data found in the hash table is"
1573 "not the data added with the key\n");
1580 if (i == NUM_ENTRIES) {
1581 printf("Key found in the hash table was not added\n");
1586 /* Check if all keys have been iterated */
1587 if (added_keys != 0) {
1588 printf("There were still %u keys to iterate\n", added_keys);
1592 rte_hash_free(handle);
1596 rte_hash_free(handle);
1600 static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03,
1601 0x04, 0x05, 0x06, 0x07,
1602 0x08, 0x09, 0x0a, 0x0b,
1603 0x0c, 0x0d, 0x0e, 0x0f};
1604 static struct rte_hash_parameters hash_params_ex = {
1609 .hash_func_init_val = 0,
1614 * Wrapper function around rte_jhash_32b.
1615 * It is required because rte_jhash_32b() accepts the length
1616 * as size of 4-byte units.
1618 static inline uint32_t
1619 test_jhash_32b(const void *k, uint32_t length, uint32_t initval)
1621 return rte_jhash_32b(k, length >> 2, initval);
1625 * add/delete key with jhash2
1628 test_hash_add_delete_jhash2(void)
1631 struct rte_hash *handle;
1634 hash_params_ex.name = "hash_test_jhash2";
1635 hash_params_ex.key_len = 4;
1636 hash_params_ex.hash_func = (rte_hash_function)test_jhash_32b;
1638 handle = rte_hash_create(&hash_params_ex);
1639 if (handle == NULL) {
1640 printf("test_hash_add_delete_jhash2 fail to create hash\n");
1643 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1645 printf("test_hash_add_delete_jhash2 fail to add hash key\n");
1649 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1650 if (pos2 < 0 || pos1 != pos2) {
1651 printf("test_hash_add_delete_jhash2 delete different key from being added\n");
1658 rte_hash_free(handle);
1664 * add/delete (2) key with jhash2
1667 test_hash_add_delete_2_jhash2(void)
1670 struct rte_hash *handle;
1673 hash_params_ex.name = "hash_test_2_jhash2";
1674 hash_params_ex.key_len = 8;
1675 hash_params_ex.hash_func = (rte_hash_function)test_jhash_32b;
1677 handle = rte_hash_create(&hash_params_ex);
1681 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1685 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1686 if (pos2 < 0 || pos1 != pos2)
1693 rte_hash_free(handle);
1699 test_hash_jhash_1word(const void *key, uint32_t length, uint32_t initval)
1701 const uint32_t *k = key;
1703 RTE_SET_USED(length);
1705 return rte_jhash_1word(k[0], initval);
1709 test_hash_jhash_2word(const void *key, uint32_t length, uint32_t initval)
1711 const uint32_t *k = key;
1713 RTE_SET_USED(length);
1715 return rte_jhash_2words(k[0], k[1], initval);
1719 test_hash_jhash_3word(const void *key, uint32_t length, uint32_t initval)
1721 const uint32_t *k = key;
1723 RTE_SET_USED(length);
1725 return rte_jhash_3words(k[0], k[1], k[2], initval);
1729 * add/delete key with jhash 1word
1732 test_hash_add_delete_jhash_1word(void)
1735 struct rte_hash *handle;
1738 hash_params_ex.name = "hash_test_jhash_1word";
1739 hash_params_ex.key_len = 4;
1740 hash_params_ex.hash_func = test_hash_jhash_1word;
1742 handle = rte_hash_create(&hash_params_ex);
1744 goto fail_jhash_1word;
1746 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1748 goto fail_jhash_1word;
1750 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1751 if (pos2 < 0 || pos1 != pos2)
1752 goto fail_jhash_1word;
1758 rte_hash_free(handle);
1764 * add/delete key with jhash 2word
1767 test_hash_add_delete_jhash_2word(void)
1770 struct rte_hash *handle;
1773 hash_params_ex.name = "hash_test_jhash_2word";
1774 hash_params_ex.key_len = 8;
1775 hash_params_ex.hash_func = test_hash_jhash_2word;
1777 handle = rte_hash_create(&hash_params_ex);
1779 goto fail_jhash_2word;
1781 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1783 goto fail_jhash_2word;
1785 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1786 if (pos2 < 0 || pos1 != pos2)
1787 goto fail_jhash_2word;
1793 rte_hash_free(handle);
1799 * add/delete key with jhash 3word
1802 test_hash_add_delete_jhash_3word(void)
1805 struct rte_hash *handle;
1808 hash_params_ex.name = "hash_test_jhash_3word";
1809 hash_params_ex.key_len = 12;
1810 hash_params_ex.hash_func = test_hash_jhash_3word;
1812 handle = rte_hash_create(&hash_params_ex);
1814 goto fail_jhash_3word;
1816 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1818 goto fail_jhash_3word;
1820 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1821 if (pos2 < 0 || pos1 != pos2)
1822 goto fail_jhash_3word;
1828 rte_hash_free(handle);
1833 static struct rte_hash *g_handle;
1834 static struct rte_rcu_qsbr *g_qsv;
1835 static volatile uint8_t writer_done;
1836 struct flow_key g_rand_keys[9];
1839 * rte_hash_rcu_qsbr_add positive and negative tests.
1840 * - Add RCU QSBR variable to Hash
1841 * - Add another RCU QSBR variable to Hash
1845 test_hash_rcu_qsbr_add(void)
1848 struct rte_rcu_qsbr *qsv2 = NULL;
1850 struct rte_hash_rcu_config rcu_cfg = {0};
1851 struct rte_hash_parameters params;
1853 printf("\n# Running RCU QSBR add tests\n");
1854 memcpy(¶ms, &ut_params, sizeof(params));
1855 params.name = "test_hash_rcu_qsbr_add";
1856 params.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |
1857 RTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;
1858 g_handle = rte_hash_create(¶ms);
1859 RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed");
1861 /* Create RCU QSBR variable */
1862 sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
1863 g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1864 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1865 RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,
1866 "RCU QSBR variable creation failed");
1868 status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);
1869 RETURN_IF_ERROR_RCU_QSBR(status != 0,
1870 "RCU QSBR variable initialization failed");
1873 /* Invalid QSBR mode */
1874 rcu_cfg.mode = 0xff;
1875 status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
1876 RETURN_IF_ERROR_RCU_QSBR(status == 0, "Invalid QSBR mode test failed");
1878 rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;
1879 /* Attach RCU QSBR to hash table */
1880 status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
1881 RETURN_IF_ERROR_RCU_QSBR(status != 0,
1882 "Attach RCU QSBR to hash table failed");
1884 /* Create and attach another RCU QSBR to hash table */
1885 qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1886 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1887 RETURN_IF_ERROR_RCU_QSBR(qsv2 == NULL,
1888 "RCU QSBR variable creation failed");
1891 rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;
1892 status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
1894 RETURN_IF_ERROR_RCU_QSBR(status == 0,
1895 "Attach RCU QSBR to hash table succeeded where failure"
1898 rte_hash_free(g_handle);
1905 * rte_hash_rcu_qsbr_add DQ mode functional test.
1906 * Reader and writer are in the same thread in this test.
1907 * - Create hash which supports maximum 8 (9 if ext bkt is enabled) entries
1908 * - Add RCU QSBR variable to hash
1909 * - Add 8 hash entries and fill the bucket
1910 * - If ext bkt is enabled, add 1 extra entry that is available in the ext bkt
1911 * - Register a reader thread (not a real thread)
1912 * - Reader lookup existing entry
1913 * - Writer deletes the entry
1914 * - Reader lookup the entry
1915 * - Writer re-add the entry (no available free index)
1916 * - Reader report quiescent state and unregister
1917 * - Writer re-add the entry
1918 * - Reader lookup the entry
1921 test_hash_rcu_qsbr_dq_mode(uint8_t ext_bkt)
1923 uint32_t total_entries = (ext_bkt == 0) ? 8 : 9;
1925 uint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
1928 hash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1930 struct rte_hash_parameters params_pseudo_hash = {
1931 .name = "test_hash_rcu_qsbr_dq_mode",
1932 .entries = total_entries,
1933 .key_len = sizeof(struct flow_key),
1934 .hash_func = pseudo_hash,
1935 .hash_func_init_val = 0,
1937 .extra_flag = hash_extra_flag,
1939 int pos[total_entries];
1940 int expected_pos[total_entries];
1944 struct rte_hash_rcu_config rcu_cfg = {0};
1949 for (i = 0; i < total_entries; i++) {
1950 g_rand_keys[i].port_dst = i;
1951 g_rand_keys[i].port_src = i+1;
1955 printf("\n# Running RCU QSBR DQ mode functional test with"
1958 printf("\n# Running RCU QSBR DQ mode functional test\n");
1960 g_handle = rte_hash_create(¶ms_pseudo_hash);
1961 RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed");
1963 /* Create RCU QSBR variable */
1964 sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
1965 g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1966 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1967 RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,
1968 "RCU QSBR variable creation failed");
1970 status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);
1971 RETURN_IF_ERROR_RCU_QSBR(status != 0,
1972 "RCU QSBR variable initialization failed");
1975 rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;
1976 /* Attach RCU QSBR to hash table */
1977 status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
1978 RETURN_IF_ERROR_RCU_QSBR(status != 0,
1979 "Attach RCU QSBR to hash table failed");
1982 for (i = 0; i < total_entries; i++) {
1983 pos[i] = rte_hash_add_key(g_handle, &g_rand_keys[i]);
1984 print_key_info("Add", &g_rand_keys[i], pos[i]);
1985 RETURN_IF_ERROR_RCU_QSBR(pos[i] < 0,
1986 "failed to add key (pos[%u]=%d)", i,
1988 expected_pos[i] = pos[i];
1991 /* Register pseudo reader */
1992 status = rte_rcu_qsbr_thread_register(g_qsv, 0);
1993 RETURN_IF_ERROR_RCU_QSBR(status != 0,
1994 "RCU QSBR thread registration failed");
1995 rte_rcu_qsbr_thread_online(g_qsv, 0);
1998 pos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]);
1999 print_key_info("Lkp", &g_rand_keys[0], pos[0]);
2000 RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],
2001 "failed to find correct key (pos[%u]=%d)", 0,
2005 pos[0] = rte_hash_del_key(g_handle, &g_rand_keys[0]);
2006 print_key_info("Del", &g_rand_keys[0], pos[0]);
2007 RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],
2008 "failed to del correct key (pos[%u]=%d)", 0,
2012 pos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]);
2013 print_key_info("Lkp", &g_rand_keys[0], pos[0]);
2014 RETURN_IF_ERROR_RCU_QSBR(pos[0] != -ENOENT,
2015 "found deleted key (pos[%u]=%d)", 0, pos[0]);
2018 pos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]);
2019 print_key_info("Add", &g_rand_keys[0], pos[0]);
2020 RETURN_IF_ERROR_RCU_QSBR(pos[0] != -ENOSPC,
2021 "Added key successfully (pos[%u]=%d)", 0, pos[0]);
2023 /* Reader quiescent */
2024 rte_rcu_qsbr_quiescent(g_qsv, 0);
2027 pos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]);
2028 print_key_info("Add", &g_rand_keys[0], pos[0]);
2029 RETURN_IF_ERROR_RCU_QSBR(pos[0] < 0,
2030 "failed to add key (pos[%u]=%d)", 0, pos[0]);
2031 expected_pos[0] = pos[0];
2033 rte_rcu_qsbr_thread_offline(g_qsv, 0);
2034 (void)rte_rcu_qsbr_thread_unregister(g_qsv, 0);
2037 pos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]);
2038 print_key_info("Lkp", &g_rand_keys[0], pos[0]);
2039 RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],
2040 "failed to find correct key (pos[%u]=%d)", 0,
2043 rte_hash_free(g_handle);
2049 /* Report quiescent state interval every 1024 lookups. Larger critical
2050 * sections in reader will result in writer polling multiple times.
2052 #define QSBR_REPORTING_INTERVAL 1024
2053 #define WRITER_ITERATIONS 512
2056 * Reader thread using rte_hash data structure with RCU.
2059 test_hash_rcu_qsbr_reader(void *arg)
2064 /* Register this thread to report quiescent state */
2065 (void)rte_rcu_qsbr_thread_register(g_qsv, 0);
2066 rte_rcu_qsbr_thread_online(g_qsv, 0);
2069 for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
2070 rte_hash_lookup(g_handle, &g_rand_keys[0]);
2072 /* Update quiescent state */
2073 rte_rcu_qsbr_quiescent(g_qsv, 0);
2074 } while (!writer_done);
2076 rte_rcu_qsbr_thread_offline(g_qsv, 0);
2077 (void)rte_rcu_qsbr_thread_unregister(g_qsv, 0);
2083 * rte_hash_rcu_qsbr_add sync mode functional test.
2084 * 1 Reader and 1 writer. They cannot be in the same thread in this test.
2085 * - Create hash which supports maximum 8 (9 if ext bkt is enabled) entries
2086 * - Add RCU QSBR variable to hash
2087 * - Register a reader thread. Reader keeps looking up a specific key.
2088 * - Writer keeps adding and deleting a specific key.
2091 test_hash_rcu_qsbr_sync_mode(uint8_t ext_bkt)
2093 uint32_t total_entries = (ext_bkt == 0) ? 8 : 9;
2095 uint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
2098 hash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
2100 struct rte_hash_parameters params_pseudo_hash = {
2101 .name = "test_hash_rcu_qsbr_sync_mode",
2102 .entries = total_entries,
2103 .key_len = sizeof(struct flow_key),
2104 .hash_func = pseudo_hash,
2105 .hash_func_init_val = 0,
2107 .extra_flag = hash_extra_flag,
2109 int pos[total_entries];
2110 int expected_pos[total_entries];
2114 struct rte_hash_rcu_config rcu_cfg = {0};
2119 for (i = 0; i < total_entries; i++) {
2120 g_rand_keys[i].port_dst = i;
2121 g_rand_keys[i].port_src = i+1;
2125 printf("\n# Running RCU QSBR sync mode functional test with"
2128 printf("\n# Running RCU QSBR sync mode functional test\n");
2130 g_handle = rte_hash_create(¶ms_pseudo_hash);
2131 RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed");
2133 /* Create RCU QSBR variable */
2134 sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
2135 g_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
2136 RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
2137 RETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,
2138 "RCU QSBR variable creation failed");
2140 status = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);
2141 RETURN_IF_ERROR_RCU_QSBR(status != 0,
2142 "RCU QSBR variable initialization failed");
2145 rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;
2146 /* Attach RCU QSBR to hash table */
2147 status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
2148 RETURN_IF_ERROR_RCU_QSBR(status != 0,
2149 "Attach RCU QSBR to hash table failed");
2151 /* Launch reader thread */
2152 rte_eal_remote_launch(test_hash_rcu_qsbr_reader, NULL,
2153 rte_get_next_lcore(-1, 1, 0));
2156 for (i = 0; i < total_entries; i++) {
2157 pos[i] = rte_hash_add_key(g_handle, &g_rand_keys[i]);
2158 print_key_info("Add", &g_rand_keys[i], pos[i]);
2159 RETURN_IF_ERROR_RCU_QSBR(pos[i] < 0,
2160 "failed to add key (pos[%u]=%d)", i, pos[i]);
2161 expected_pos[i] = pos[i];
2166 for (i = 0; i < WRITER_ITERATIONS; i++) {
2167 expected_pos[0] = pos[0];
2168 pos[0] = rte_hash_del_key(g_handle, &g_rand_keys[0]);
2169 print_key_info("Del", &g_rand_keys[0], status);
2170 RETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],
2171 "failed to del correct key (pos[%u]=%d)"
2174 pos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]);
2175 print_key_info("Add", &g_rand_keys[0], pos[0]);
2176 RETURN_IF_ERROR_RCU_QSBR(pos[0] < 0,
2177 "failed to add key (pos[%u]=%d)", 0,
2182 /* Wait until reader exited. */
2183 rte_eal_mp_wait_lcore();
2185 rte_hash_free(g_handle);
2193 * Do all unit and performance tests.
2198 RTE_BUILD_BUG_ON(sizeof(struct flow_key) % sizeof(uint32_t) != 0);
2200 if (test_add_delete() < 0)
2202 if (test_hash_add_delete_jhash2() < 0)
2204 if (test_hash_add_delete_2_jhash2() < 0)
2206 if (test_hash_add_delete_jhash_1word() < 0)
2208 if (test_hash_add_delete_jhash_2word() < 0)
2210 if (test_hash_add_delete_jhash_3word() < 0)
2212 if (test_hash_get_key_with_position() < 0)
2214 if (test_hash_find_existing() < 0)
2216 if (test_add_update_delete() < 0)
2218 if (test_add_update_delete_free() < 0)
2220 if (test_add_delete_free_lf() < 0)
2222 if (test_five_keys() < 0)
2224 if (test_full_bucket() < 0)
2226 if (test_extendable_bucket() < 0)
2229 if (test_fbk_hash_find_existing() < 0)
2231 if (fbk_hash_unit_test() < 0)
2233 if (test_hash_creation_with_bad_parameters() < 0)
2235 if (test_hash_creation_with_good_parameters() < 0)
2238 /* ext table disabled */
2239 if (test_average_table_utilization(0) < 0)
2241 if (test_hash_iteration(0) < 0)
2244 /* ext table enabled */
2245 if (test_average_table_utilization(1) < 0)
2247 if (test_hash_iteration(1) < 0)
2250 run_hash_func_tests();
2252 if (test_crc32_hash_alg_equiv() < 0)
2255 if (test_hash_rcu_qsbr_add() < 0)
2258 if (test_hash_rcu_qsbr_dq_mode(0) < 0)
2261 if (test_hash_rcu_qsbr_dq_mode(1) < 0)
2264 if (test_hash_rcu_qsbr_sync_mode(0) < 0)
2267 if (test_hash_rcu_qsbr_sync_mode(1) < 0)
2273 REGISTER_TEST_COMMAND(hash_autotest, test_hash);