1
2
3
4
5#include <stdio.h>
6#include <stdint.h>
7#include <string.h>
8#include <stdlib.h>
9#include <stdarg.h>
10#include <errno.h>
11#include <sys/queue.h>
12
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>
18#include <rte_eal.h>
19#include <rte_ip.h>
20#include <rte_string_fns.h>
21
22#include "test.h"
23
24#include <rte_hash.h>
25#include <rte_fbk_hash.h>
26#include <rte_jhash.h>
27#include <rte_hash_crc.h>
28
29
30
31
32
33
34
35
36static rte_hash_function hashtest_funcs[] = {rte_jhash, rte_hash_crc};
37static uint32_t hashtest_initvals[] = {0};
38static 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)
42
43
44
45
46
47#define RETURN_IF_ERROR(cond, str, ...) do { \
48 if (cond) { \
49 printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
50 if (handle) rte_hash_free(handle); \
51 return -1; \
52 } \
53} while(0)
54
55#define RETURN_IF_ERROR_FBK(cond, str, ...) do { \
56 if (cond) { \
57 printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
58 if (handle) rte_fbk_hash_free(handle); \
59 return -1; \
60 } \
61} while(0)
62
63#define RETURN_IF_ERROR_RCU_QSBR(cond, str, ...) do { \
64 if (cond) { \
65 printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
66 if (rcu_cfg.mode == RTE_HASH_QSBR_MODE_SYNC) { \
67 writer_done = 1; \
68 \
69 rte_eal_mp_wait_lcore(); \
70 } \
71 rte_hash_free(g_handle); \
72 rte_free(g_qsv); \
73 return -1; \
74 } \
75} while (0)
76
77
78
79
80
81
82struct flow_key {
83 uint32_t ip_src;
84 uint32_t ip_dst;
85 uint16_t port_src;
86 uint16_t port_dst;
87 uint32_t proto;
88} __rte_packed;
89
90
91
92
93
94static uint32_t pseudo_hash(__rte_unused const void *keys,
95 __rte_unused uint32_t key_len,
96 __rte_unused uint32_t init_val)
97{
98 return 3;
99}
100
101RTE_LOG_REGISTER(hash_logtype_test, test.hash, INFO);
102
103
104
105
106static void print_key_info(const char *msg, const struct flow_key *key,
107 int32_t pos)
108{
109 const uint8_t *p = (const uint8_t *)key;
110 unsigned int i;
111
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);
116}
117
118
119static struct flow_key keys[5] = { {
120 .ip_src = RTE_IPV4(0x03, 0x02, 0x01, 0x00),
121 .ip_dst = RTE_IPV4(0x07, 0x06, 0x05, 0x04),
122 .port_src = 0x0908,
123 .port_dst = 0x0b0a,
124 .proto = 0x0c,
125}, {
126 .ip_src = RTE_IPV4(0x13, 0x12, 0x11, 0x10),
127 .ip_dst = RTE_IPV4(0x17, 0x16, 0x15, 0x14),
128 .port_src = 0x1918,
129 .port_dst = 0x1b1a,
130 .proto = 0x1c,
131}, {
132 .ip_src = RTE_IPV4(0x23, 0x22, 0x21, 0x20),
133 .ip_dst = RTE_IPV4(0x27, 0x26, 0x25, 0x24),
134 .port_src = 0x2928,
135 .port_dst = 0x2b2a,
136 .proto = 0x2c,
137}, {
138 .ip_src = RTE_IPV4(0x33, 0x32, 0x31, 0x30),
139 .ip_dst = RTE_IPV4(0x37, 0x36, 0x35, 0x34),
140 .port_src = 0x3938,
141 .port_dst = 0x3b3a,
142 .proto = 0x3c,
143}, {
144 .ip_src = RTE_IPV4(0x43, 0x42, 0x41, 0x40),
145 .ip_dst = RTE_IPV4(0x47, 0x46, 0x45, 0x44),
146 .port_src = 0x4948,
147 .port_dst = 0x4b4a,
148 .proto = 0x4c,
149} };
150
151
152static struct rte_hash_parameters ut_params = {
153 .entries = 64,
154 .key_len = sizeof(struct flow_key),
155 .hash_func = rte_jhash,
156 .hash_func_init_val = 0,
157 .socket_id = 0,
158};
159
160#define CRC32_ITERATIONS (1U << 10)
161#define CRC32_DWORDS (1U << 6)
162
163
164
165static int
166test_crc32_hash_alg_equiv(void)
167{
168 uint32_t hash_val;
169 uint32_t init_val;
170 uint64_t data64[CRC32_DWORDS];
171 unsigned i, j;
172 size_t data_len;
173
174 printf("\n# CRC32 implementations equivalence test\n");
175 for (i = 0; i < CRC32_ITERATIONS; i++) {
176
177 data_len = (size_t) ((rte_rand() % sizeof(data64)) + 1);
178 init_val = (uint32_t) rte_rand();
179
180
181 for (j = 0; j < CRC32_DWORDS; j++)
182 data64[j] = rte_rand();
183
184
185 rte_hash_crc_set_alg(CRC32_SW);
186 hash_val = rte_hash_crc(data64, data_len, init_val);
187
188
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");
192 break;
193 }
194
195
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");
199 break;
200 }
201
202
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");
206 break;
207 }
208 }
209
210
211 rte_hash_crc_set_alg(CRC32_SSE42_x64);
212
213 if (i == CRC32_ITERATIONS)
214 return 0;
215
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' : ' ');
220
221 return -1;
222}
223
224
225
226
227static void run_hash_func_test(rte_hash_function f, uint32_t init_val,
228 uint32_t key_len)
229{
230 static uint8_t key[MAX_KEYSIZE];
231 unsigned i;
232
233
234 for (i = 0; i < key_len; i++)
235 key[i] = (uint8_t) rte_rand();
236
237
238 if (!f)
239 return;
240
241 f(key, key_len, init_val);
242}
243
244
245
246
247static void run_hash_func_tests(void)
248{
249 unsigned i, j, k;
250
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]);
257 }
258 }
259 }
260}
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276static int test_add_delete(void)
277{
278 struct rte_hash *handle;
279
280 int pos0, expectedPos0;
281
282 ut_params.name = "test1";
283 handle = rte_hash_create(&ut_params);
284 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
285
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);
289 expectedPos0 = pos0;
290
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);
295
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);
300
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);
305
306 rte_hash_free(handle);
307
308
309 hash_sig_t hash_value;
310 int pos1, expectedPos1, delPos1;
311
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;
316
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);
321 expectedPos1 = pos1;
322
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);
327
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);
332 delPos1 = pos1;
333
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);
338
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);
343
344 rte_hash_free(handle);
345
346 return 0;
347}
348
349
350
351
352
353
354
355
356
357
358
359
360static int test_add_update_delete(void)
361{
362 struct rte_hash *handle;
363 int pos0, expectedPos0;
364
365 ut_params.name = "test2";
366 handle = rte_hash_create(&ut_params);
367 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
368
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);
373
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);
377 expectedPos0 = pos0;
378
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);
383
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);
388
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);
393
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);
398
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);
403
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);
408
409 rte_hash_free(handle);
410 return 0;
411}
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426static int test_add_update_delete_free(void)
427{
428 struct rte_hash *handle;
429 int pos0, expectedPos0, delPos0, result;
430
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;
436
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);
441
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);
445 expectedPos0 = pos0;
446
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);
451
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);
456
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);
461
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);
466
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);
471
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);
476
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);
481
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);
486
487 rte_hash_free(handle);
488 return 0;
489}
490
491
492
493
494
495
496
497
498
499
500
501static int test_add_delete_free_lf(void)
502{
503
504#define LCORE_CACHE_SIZE 64
505 struct rte_hash *handle;
506 hash_sig_t hash_value;
507 int pos, expectedPos, delPos;
508 uint8_t extra_flag;
509 uint32_t i, ip_src;
510
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;
516
517
518
519
520
521
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);
527 expectedPos = pos;
528
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);
533 delPos = pos;
534
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);
539 }
540
541 rte_hash_free(handle);
542
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;
549
550 ip_src = keys[0].ip_src;
551
552
553
554
555
556 for (i = 0; i < ut_params.entries + (RTE_MAX_LCORE - 1) *
557 (LCORE_CACHE_SIZE - 1) + 1; i++) {
558 keys[0].ip_src++;
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);
563 expectedPos = pos;
564
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);
569 delPos = pos;
570
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);
575 }
576 keys[0].ip_src = ip_src;
577
578 rte_hash_free(handle);
579
580 return 0;
581}
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602static int test_hash_get_key_with_position(void)
603{
604 struct rte_hash *handle = NULL;
605 int pos, expectedPos, delPos, result;
606 void *key;
607
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");
611
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);
615 expectedPos = pos;
616
617 result = rte_hash_get_key_with_position(handle, pos, &key);
618 RETURN_IF_ERROR(result != 0, "error retrieving a key");
619
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);
624
625 result = rte_hash_get_key_with_position(handle, pos, &key);
626 RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
627
628 rte_hash_free(handle);
629
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;
635
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);
639 expectedPos = pos;
640
641 result = rte_hash_get_key_with_position(handle, pos, &key);
642 RETURN_IF_ERROR(result != 0, "error retrieving a key");
643
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);
648
649 result = rte_hash_get_key_with_position(handle, delPos, &key);
650 RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
651
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);
656
657 result = rte_hash_get_key_with_position(handle, delPos, &key);
658 RETURN_IF_ERROR(result != -ENOENT, "non valid key retrieved");
659
660 rte_hash_free(handle);
661 return 0;
662}
663
664
665
666
667
668
669
670
671
672static int test_hash_find_existing(void)
673{
674 struct rte_hash *handle = NULL, *result = NULL;
675
676
677 ut_params.name = "hash_find_existing";
678 handle = rte_hash_create(&ut_params);
679 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
680
681
682 result = rte_hash_find_existing("hash_find_existing");
683 RETURN_IF_ERROR(result != handle, "could not find existing hash table");
684
685
686 result = rte_hash_find_existing("hash_find_non_existing");
687 RETURN_IF_ERROR(!(result == NULL), "found table that shouldn't exist");
688
689
690 rte_hash_free(handle);
691
692 return 0;
693}
694
695
696
697
698
699
700
701
702
703
704static int test_five_keys(void)
705{
706 struct rte_hash *handle;
707 const void *key_array[5] = {0};
708 int pos[5];
709 int expected_pos[5];
710 unsigned i;
711 int ret;
712
713 ut_params.name = "test3";
714 handle = rte_hash_create(&ut_params);
715 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
716
717
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];
724 }
725
726
727 for(i = 0; i < 5; i++)
728 key_array[i] = &keys[i];
729
730 ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
731 if(ret == 0)
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]);
736 }
737
738
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]);
744 }
745
746
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]);
752 }
753
754
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]);
760 }
761
762
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]);
768 }
769
770
771 ret = rte_hash_lookup_bulk(handle, &key_array[0], 5, (int32_t *)pos);
772 if (ret == 0)
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]);
777 }
778
779 rte_hash_free(handle);
780
781 return 0;
782}
783
784
785
786
787
788
789
790
791
792
793
794static int test_full_bucket(void)
795{
796 struct rte_hash_parameters params_pseudo_hash = {
797 .name = "test4",
798 .entries = 64,
799 .key_len = sizeof(struct flow_key),
800 .hash_func = pseudo_hash,
801 .hash_func_init_val = 0,
802 .socket_id = 0,
803 };
804 struct rte_hash *handle;
805 int pos[5];
806 int expected_pos[5];
807 unsigned i;
808
809 handle = rte_hash_create(¶ms_pseudo_hash);
810 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
811
812
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];
819 }
820
821
822
823
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];
829
830
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]);
836 }
837
838
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]);
844 }
845
846
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]);
852 }
853
854
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]);
864
865
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]);
870
871
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]);
877 }
878
879
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]);
885 }
886
887 rte_hash_free(handle);
888
889
890 rte_hash_free(0);
891 return 0;
892}
893
894
895
896
897static int test_extendable_bucket(void)
898{
899 struct rte_hash_parameters params_pseudo_hash = {
900 .name = "test5",
901 .entries = 64,
902 .key_len = sizeof(struct flow_key),
903 .hash_func = pseudo_hash,
904 .hash_func_init_val = 0,
905 .socket_id = 0,
906 .extra_flag = RTE_HASH_EXTRA_FLAGS_EXT_TABLE
907 };
908 struct rte_hash *handle;
909 int pos[64];
910 int expected_pos[64];
911 unsigned int i;
912 struct flow_key rand_keys[64];
913
914 for (i = 0; i < 64; i++) {
915 rand_keys[i].port_dst = i;
916 rand_keys[i].port_src = i+1;
917 }
918
919 handle = rte_hash_create(¶ms_pseudo_hash);
920 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
921
922
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];
929 }
930
931
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]);
937 }
938
939
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]);
945 }
946
947
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]);
953 }
954
955
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]);
965
966
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]);
971
972
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]);
978 }
979
980
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]);
986 }
987
988
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];
995 }
996
997 rte_hash_free(handle);
998
999
1000 rte_hash_free(0);
1001 return 0;
1002}
1003
1004
1005static int
1006fbk_hash_unit_test(void)
1007{
1008 struct rte_fbk_hash_params params = {
1009 .name = "fbk_hash_test",
1010 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1011 .entries_per_bucket = 4,
1012 .socket_id = 0,
1013 };
1014
1015 struct rte_fbk_hash_params invalid_params_1 = {
1016 .name = "invalid_1",
1017 .entries = LOCAL_FBK_HASH_ENTRIES_MAX + 1,
1018 .entries_per_bucket = 4,
1019 .socket_id = 0,
1020 };
1021
1022 struct rte_fbk_hash_params invalid_params_2 = {
1023 .name = "invalid_2",
1024 .entries = 4,
1025 .entries_per_bucket = 3,
1026 .socket_id = 0,
1027 };
1028
1029 struct rte_fbk_hash_params invalid_params_3 = {
1030 .name = "invalid_3",
1031 .entries = 0,
1032 .entries_per_bucket = 4,
1033 .socket_id = 0,
1034 };
1035
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,
1040 .socket_id = 0,
1041 };
1042
1043 struct rte_fbk_hash_params invalid_params_5 = {
1044 .name = "invalid_5",
1045 .entries = 4,
1046 .entries_per_bucket = 8,
1047 .socket_id = 0,
1048 };
1049
1050 struct rte_fbk_hash_params invalid_params_6 = {
1051 .name = "invalid_6",
1052 .entries = RTE_FBK_HASH_ENTRIES_MAX * 2,
1053 .entries_per_bucket = 4,
1054 .socket_id = 0,
1055 };
1056
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,
1061 .socket_id = 0,
1062 };
1063
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,
1069 };
1070
1071
1072
1073
1074
1075
1076 struct rte_fbk_hash_params invalid_params_same_name_1 = {
1077 .name = "same_name",
1078 .entries = 4,
1079 .entries_per_bucket = 2,
1080 .socket_id = 0,
1081 };
1082
1083
1084 struct rte_fbk_hash_params invalid_params_same_name_2 = {
1085 .name = "same_name",
1086 .entries = RTE_FBK_HASH_ENTRIES_MAX,
1087 .entries_per_bucket = 4,
1088 .socket_id = 0,
1089 };
1090
1091
1092
1093
1094
1095 struct rte_fbk_hash_params different_name = {
1096 .name = "different_name",
1097 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1098 .entries_per_bucket = 4,
1099 .socket_id = 0,
1100 };
1101
1102 struct rte_fbk_hash_params params_jhash = {
1103 .name = "valid",
1104 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1105 .entries_per_bucket = 4,
1106 .socket_id = 0,
1107 .hash_func = rte_jhash_1word,
1108 .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
1109 };
1110
1111 struct rte_fbk_hash_params params_nohash = {
1112 .name = "valid nohash",
1113 .entries = LOCAL_FBK_HASH_ENTRIES_MAX,
1114 .entries_per_bucket = 4,
1115 .socket_id = 0,
1116 .hash_func = NULL,
1117 .init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT,
1118 };
1119
1120 struct rte_fbk_hash_table *handle, *tmp;
1121 uint32_t keys[5] =
1122 {0xc6e18639, 0xe67c201c, 0xd4c8cffd, 0x44728691, 0xd5430fa9};
1123 uint16_t vals[5] = {28108, 5699, 38490, 2166, 61571};
1124 int status;
1125 unsigned i;
1126 double used_entries;
1127
1128
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");
1133
1134 handle = rte_fbk_hash_create(&invalid_params_2);
1135 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1136
1137 handle = rte_fbk_hash_create(&invalid_params_3);
1138 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1139
1140 handle = rte_fbk_hash_create(&invalid_params_4);
1141 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1142
1143 handle = rte_fbk_hash_create(&invalid_params_5);
1144 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1145
1146 handle = rte_fbk_hash_create(&invalid_params_6);
1147 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1148
1149 handle = rte_fbk_hash_create(&invalid_params_7);
1150 RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
1151
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");
1156 }
1157
1158 handle = rte_fbk_hash_create(&invalid_params_same_name_1);
1159 RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded");
1160
1161 tmp = rte_fbk_hash_create(&invalid_params_same_name_2);
1162 if (tmp != NULL)
1163 rte_fbk_hash_free(tmp);
1164 RETURN_IF_ERROR_FBK(tmp != NULL, "fbk hash creation should have failed");
1165
1166
1167
1168
1169
1170 tmp = rte_fbk_hash_create(&different_name);
1171 RETURN_IF_ERROR_FBK(tmp == NULL, "fbk hash creation should have succeeded");
1172
1173
1174 rte_fbk_hash_free(handle);
1175 rte_fbk_hash_free(tmp);
1176
1177
1178 handle = rte_fbk_hash_create(¶ms_jhash);
1179 RETURN_IF_ERROR_FBK(handle == NULL, "fbk jhash hash creation failed");
1180
1181
1182 rte_fbk_hash_free(handle);
1183
1184
1185 handle = rte_fbk_hash_create(¶ms_nohash);
1186 RETURN_IF_ERROR_FBK(handle == NULL, "fbk nohash hash creation failed");
1187
1188
1189 rte_fbk_hash_free(handle);
1190
1191
1192 handle = rte_fbk_hash_create(¶ms);
1193 RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed");
1194
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");
1198
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");
1202 }
1203
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
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");
1212 }
1213
1214
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");
1218 }
1219
1220
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");
1225 }
1226
1227
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");
1231 }
1232
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
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");
1241 }
1242
1243
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");
1247 }
1248
1249
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");
1254 }
1255
1256
1257 rte_fbk_hash_clear_all(handle);
1258
1259
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");
1264 }
1265
1266
1267
1268
1269 for (i = 0; i < RTE_FBK_HASH_ENTRIES_MAX + 1; i++)
1270 rte_fbk_hash_add_key(handle, i, (uint16_t) i);
1271
1272
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");
1276
1277
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");
1281
1282
1283 status = rte_fbk_hash_delete_key(handle, 1);
1284 RETURN_IF_ERROR_FBK(status != 0,
1285 "fbk hash delete failed");
1286
1287
1288 rte_fbk_hash_clear_all(handle);
1289
1290
1291 rte_fbk_hash_free(handle);
1292
1293
1294 rte_fbk_hash_free(0);
1295
1296 return 0;
1297}
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307static int test_fbk_hash_find_existing(void)
1308{
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,
1313 .socket_id = 0,
1314 };
1315 struct rte_fbk_hash_table *handle = NULL, *result = NULL;
1316
1317
1318 handle = rte_fbk_hash_create(¶ms);
1319 RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation failed");
1320
1321
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");
1324
1325
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");
1328
1329
1330 rte_fbk_hash_free(handle);
1331
1332 return 0;
1333}
1334
1335#define BUCKET_ENTRIES 4
1336
1337
1338
1339static int test_hash_creation_with_bad_parameters(void)
1340{
1341 struct rte_hash *handle, *tmp;
1342 struct rte_hash_parameters params;
1343
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");
1348 return -1;
1349 }
1350
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");
1358 return -1;
1359 }
1360
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");
1368 return -1;
1369 }
1370
1371 memcpy(¶ms, &ut_params, sizeof(params));
1372 params.name = "creation_with_bad_parameters_3";
1373 params.key_len = 0;
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");
1378 return -1;
1379 }
1380
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");
1388 return -1;
1389 }
1390
1391
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");
1397 return -1;
1398 }
1399 tmp = rte_hash_create(¶ms);
1400 if (tmp != NULL) {
1401 printf("Creation of hash table with same name should fail\n");
1402 rte_hash_free(handle);
1403 rte_hash_free(tmp);
1404 return -1;
1405 }
1406 rte_hash_free(handle);
1407
1408 printf("# Test successful. No more errors expected\n");
1409
1410 return 0;
1411}
1412
1413
1414
1415
1416
1417static int
1418test_hash_creation_with_good_parameters(void)
1419{
1420 struct rte_hash *handle;
1421 struct rte_hash_parameters params;
1422
1423
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");
1430 return -1;
1431 }
1432
1433 rte_hash_free(handle);
1434
1435 return 0;
1436}
1437
1438#define ITERATIONS 3
1439
1440
1441
1442
1443static int test_average_table_utilization(uint32_t ext_table)
1444{
1445 struct rte_hash *handle;
1446 uint8_t simple_key[MAX_KEYSIZE];
1447 unsigned i, j;
1448 unsigned added_keys, average_keys_added = 0;
1449 int ret;
1450 unsigned int cnt;
1451
1452 printf("\n# Running test to determine average utilization"
1453 "\n before adding elements begins to fail\n");
1454 if (ext_table)
1455 printf("ext table is enabled\n");
1456 else
1457 printf("ext table is disabled\n");
1458
1459 printf("Measuring performance, please wait");
1460 fflush(stdout);
1461 ut_params.entries = 1 << 16;
1462 ut_params.name = "test_average_utilization";
1463 ut_params.hash_func = rte_jhash;
1464 if (ext_table)
1465 ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1466 else
1467 ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1468
1469 handle = rte_hash_create(&ut_params);
1470
1471 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
1472
1473 for (j = 0; j < ITERATIONS; j++) {
1474 ret = 0;
1475
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);
1480 if (ret < 0)
1481 break;
1482 }
1483
1484 if (ret != -ENOSPC) {
1485 printf("Unexpected error when adding keys\n");
1486 rte_hash_free(handle);
1487 return -1;
1488 }
1489
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);
1495 return -1;
1496 }
1497 if (ext_table) {
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);
1502 return -1;
1503 }
1504 }
1505
1506 average_keys_added += added_keys;
1507
1508
1509 rte_hash_reset(handle);
1510
1511
1512 printf(".");
1513 fflush(stdout);
1514 }
1515
1516 average_keys_added /= ITERATIONS;
1517
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);
1522
1523 return 0;
1524}
1525
1526#define NUM_ENTRIES 256
1527static int test_hash_iteration(uint32_t ext_table)
1528{
1529 struct rte_hash *handle;
1530 unsigned i;
1531 uint8_t keys[NUM_ENTRIES][MAX_KEYSIZE];
1532 const void *next_key;
1533 void *next_data;
1534 void *data[NUM_ENTRIES];
1535 unsigned added_keys;
1536 uint32_t iter = 0;
1537 int ret = 0;
1538
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;
1543 if (ext_table)
1544 ut_params.extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1545 else
1546 ut_params.extra_flag &= ~RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1547
1548 handle = rte_hash_create(&ut_params);
1549 RETURN_IF_ERROR(handle == NULL, "hash creation failed");
1550
1551
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]);
1557 if (ret < 0) {
1558 if (ext_table) {
1559 printf("Insertion failed for ext table\n");
1560 goto err;
1561 }
1562 break;
1563 }
1564 }
1565
1566
1567 while (rte_hash_iterate(handle, &next_key, &next_data, &iter) >= 0) {
1568
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");
1574 goto err;
1575 }
1576 added_keys--;
1577 break;
1578 }
1579 }
1580 if (i == NUM_ENTRIES) {
1581 printf("Key found in the hash table was not added\n");
1582 goto err;
1583 }
1584 }
1585
1586
1587 if (added_keys != 0) {
1588 printf("There were still %u keys to iterate\n", added_keys);
1589 goto err;
1590 }
1591
1592 rte_hash_free(handle);
1593 return 0;
1594
1595err:
1596 rte_hash_free(handle);
1597 return -1;
1598}
1599
1600static uint8_t key[16] = {0x00, 0x01, 0x02, 0x03,
1601 0x04, 0x05, 0x06, 0x07,
1602 0x08, 0x09, 0x0a, 0x0b,
1603 0x0c, 0x0d, 0x0e, 0x0f};
1604static struct rte_hash_parameters hash_params_ex = {
1605 .name = NULL,
1606 .entries = 64,
1607 .key_len = 0,
1608 .hash_func = NULL,
1609 .hash_func_init_val = 0,
1610 .socket_id = 0,
1611};
1612
1613
1614
1615
1616
1617
1618static inline uint32_t
1619test_jhash_32b(const void *k, uint32_t length, uint32_t initval)
1620{
1621 return rte_jhash_32b(k, length >> 2, initval);
1622}
1623
1624
1625
1626
1627static int
1628test_hash_add_delete_jhash2(void)
1629{
1630 int ret = -1;
1631 struct rte_hash *handle;
1632 int32_t pos1, pos2;
1633
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;
1637
1638 handle = rte_hash_create(&hash_params_ex);
1639 if (handle == NULL) {
1640 printf("test_hash_add_delete_jhash2 fail to create hash\n");
1641 goto fail_jhash2;
1642 }
1643 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1644 if (pos1 < 0) {
1645 printf("test_hash_add_delete_jhash2 fail to add hash key\n");
1646 goto fail_jhash2;
1647 }
1648
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");
1652 goto fail_jhash2;
1653 }
1654 ret = 0;
1655
1656fail_jhash2:
1657 if (handle != NULL)
1658 rte_hash_free(handle);
1659
1660 return ret;
1661}
1662
1663
1664
1665
1666static int
1667test_hash_add_delete_2_jhash2(void)
1668{
1669 int ret = -1;
1670 struct rte_hash *handle;
1671 int32_t pos1, pos2;
1672
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;
1676
1677 handle = rte_hash_create(&hash_params_ex);
1678 if (handle == NULL)
1679 goto fail_2_jhash2;
1680
1681 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1682 if (pos1 < 0)
1683 goto fail_2_jhash2;
1684
1685 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1686 if (pos2 < 0 || pos1 != pos2)
1687 goto fail_2_jhash2;
1688
1689 ret = 0;
1690
1691fail_2_jhash2:
1692 if (handle != NULL)
1693 rte_hash_free(handle);
1694
1695 return ret;
1696}
1697
1698static uint32_t
1699test_hash_jhash_1word(const void *key, uint32_t length, uint32_t initval)
1700{
1701 const uint32_t *k = key;
1702
1703 RTE_SET_USED(length);
1704
1705 return rte_jhash_1word(k[0], initval);
1706}
1707
1708static uint32_t
1709test_hash_jhash_2word(const void *key, uint32_t length, uint32_t initval)
1710{
1711 const uint32_t *k = key;
1712
1713 RTE_SET_USED(length);
1714
1715 return rte_jhash_2words(k[0], k[1], initval);
1716}
1717
1718static uint32_t
1719test_hash_jhash_3word(const void *key, uint32_t length, uint32_t initval)
1720{
1721 const uint32_t *k = key;
1722
1723 RTE_SET_USED(length);
1724
1725 return rte_jhash_3words(k[0], k[1], k[2], initval);
1726}
1727
1728
1729
1730
1731static int
1732test_hash_add_delete_jhash_1word(void)
1733{
1734 int ret = -1;
1735 struct rte_hash *handle;
1736 int32_t pos1, pos2;
1737
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;
1741
1742 handle = rte_hash_create(&hash_params_ex);
1743 if (handle == NULL)
1744 goto fail_jhash_1word;
1745
1746 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1747 if (pos1 < 0)
1748 goto fail_jhash_1word;
1749
1750 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1751 if (pos2 < 0 || pos1 != pos2)
1752 goto fail_jhash_1word;
1753
1754 ret = 0;
1755
1756fail_jhash_1word:
1757 if (handle != NULL)
1758 rte_hash_free(handle);
1759
1760 return ret;
1761}
1762
1763
1764
1765
1766static int
1767test_hash_add_delete_jhash_2word(void)
1768{
1769 int ret = -1;
1770 struct rte_hash *handle;
1771 int32_t pos1, pos2;
1772
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;
1776
1777 handle = rte_hash_create(&hash_params_ex);
1778 if (handle == NULL)
1779 goto fail_jhash_2word;
1780
1781 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1782 if (pos1 < 0)
1783 goto fail_jhash_2word;
1784
1785 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1786 if (pos2 < 0 || pos1 != pos2)
1787 goto fail_jhash_2word;
1788
1789 ret = 0;
1790
1791fail_jhash_2word:
1792 if (handle != NULL)
1793 rte_hash_free(handle);
1794
1795 return ret;
1796}
1797
1798
1799
1800
1801static int
1802test_hash_add_delete_jhash_3word(void)
1803{
1804 int ret = -1;
1805 struct rte_hash *handle;
1806 int32_t pos1, pos2;
1807
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;
1811
1812 handle = rte_hash_create(&hash_params_ex);
1813 if (handle == NULL)
1814 goto fail_jhash_3word;
1815
1816 pos1 = rte_hash_add_key(handle, (void *)&key[0]);
1817 if (pos1 < 0)
1818 goto fail_jhash_3word;
1819
1820 pos2 = rte_hash_del_key(handle, (void *)&key[0]);
1821 if (pos2 < 0 || pos1 != pos2)
1822 goto fail_jhash_3word;
1823
1824 ret = 0;
1825
1826fail_jhash_3word:
1827 if (handle != NULL)
1828 rte_hash_free(handle);
1829
1830 return ret;
1831}
1832
1833static struct rte_hash *g_handle;
1834static struct rte_rcu_qsbr *g_qsv;
1835static volatile uint8_t writer_done;
1836struct flow_key g_rand_keys[9];
1837
1838
1839
1840
1841
1842
1843
1844static int
1845test_hash_rcu_qsbr_add(void)
1846{
1847 size_t sz;
1848 struct rte_rcu_qsbr *qsv2 = NULL;
1849 int32_t status;
1850 struct rte_hash_rcu_config rcu_cfg = {0};
1851 struct rte_hash_parameters params;
1852
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");
1860
1861
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");
1867
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");
1871
1872 rcu_cfg.v = g_qsv;
1873
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");
1877
1878 rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;
1879
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");
1883
1884
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");
1889
1890 rcu_cfg.v = qsv2;
1891 rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;
1892 status = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);
1893 rte_free(qsv2);
1894 RETURN_IF_ERROR_RCU_QSBR(status == 0,
1895 "Attach RCU QSBR to hash table succeeded where failure"
1896 " is expected");
1897
1898 rte_hash_free(g_handle);
1899 rte_free(g_qsv);
1900
1901 return 0;
1902}
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920static int
1921test_hash_rcu_qsbr_dq_mode(uint8_t ext_bkt)
1922{
1923 uint32_t total_entries = (ext_bkt == 0) ? 8 : 9;
1924
1925 uint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
1926
1927 if (ext_bkt)
1928 hash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
1929
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,
1936 .socket_id = 0,
1937 .extra_flag = hash_extra_flag,
1938 };
1939 int pos[total_entries];
1940 int expected_pos[total_entries];
1941 unsigned int i;
1942 size_t sz;
1943 int32_t status;
1944 struct rte_hash_rcu_config rcu_cfg = {0};
1945
1946 g_qsv = NULL;
1947 g_handle = NULL;
1948
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;
1952 }
1953
1954 if (ext_bkt)
1955 printf("\n# Running RCU QSBR DQ mode functional test with"
1956 " ext bkt\n");
1957 else
1958 printf("\n# Running RCU QSBR DQ mode functional test\n");
1959
1960 g_handle = rte_hash_create(¶ms_pseudo_hash);
1961 RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed");
1962
1963
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");
1969
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");
1973
1974 rcu_cfg.v = g_qsv;
1975 rcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;
1976
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");
1980
1981
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,
1987 pos[i]);
1988 expected_pos[i] = pos[i];
1989 }
1990
1991
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);
1996
1997
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,
2002 pos[0]);
2003
2004
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,
2009 pos[0]);
2010
2011
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]);
2016
2017
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]);
2022
2023
2024 rte_rcu_qsbr_quiescent(g_qsv, 0);
2025
2026
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];
2032
2033 rte_rcu_qsbr_thread_offline(g_qsv, 0);
2034 (void)rte_rcu_qsbr_thread_unregister(g_qsv, 0);
2035
2036
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,
2041 pos[0]);
2042
2043 rte_hash_free(g_handle);
2044 rte_free(g_qsv);
2045 return 0;
2046
2047}
2048
2049
2050
2051
2052#define QSBR_REPORTING_INTERVAL 1024
2053#define WRITER_ITERATIONS 512
2054
2055
2056
2057
2058static int
2059test_hash_rcu_qsbr_reader(void *arg)
2060{
2061 int i;
2062
2063 RTE_SET_USED(arg);
2064
2065 (void)rte_rcu_qsbr_thread_register(g_qsv, 0);
2066 rte_rcu_qsbr_thread_online(g_qsv, 0);
2067
2068 do {
2069 for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
2070 rte_hash_lookup(g_handle, &g_rand_keys[0]);
2071
2072
2073 rte_rcu_qsbr_quiescent(g_qsv, 0);
2074 } while (!writer_done);
2075
2076 rte_rcu_qsbr_thread_offline(g_qsv, 0);
2077 (void)rte_rcu_qsbr_thread_unregister(g_qsv, 0);
2078
2079 return 0;
2080}
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090static int
2091test_hash_rcu_qsbr_sync_mode(uint8_t ext_bkt)
2092{
2093 uint32_t total_entries = (ext_bkt == 0) ? 8 : 9;
2094
2095 uint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;
2096
2097 if (ext_bkt)
2098 hash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;
2099
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,
2106 .socket_id = 0,
2107 .extra_flag = hash_extra_flag,
2108 };
2109 int pos[total_entries];
2110 int expected_pos[total_entries];
2111 unsigned int i;
2112 size_t sz;
2113 int32_t status;
2114 struct rte_hash_rcu_config rcu_cfg = {0};
2115
2116 g_qsv = NULL;
2117 g_handle = NULL;
2118
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;
2122 }
2123
2124 if (ext_bkt)
2125 printf("\n# Running RCU QSBR sync mode functional test with"
2126 " ext bkt\n");
2127 else
2128 printf("\n# Running RCU QSBR sync mode functional test\n");
2129
2130 g_handle = rte_hash_create(¶ms_pseudo_hash);
2131 RETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, "Hash creation failed");
2132
2133
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");
2139
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");
2143
2144 rcu_cfg.v = g_qsv;
2145 rcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;
2146
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");
2150
2151
2152 rte_eal_remote_launch(test_hash_rcu_qsbr_reader, NULL,
2153 rte_get_next_lcore(-1, 1, 0));
2154
2155
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];
2162 }
2163 writer_done = 0;
2164
2165
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)"
2172 , 0, pos[0]);
2173
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,
2178 pos[0]);
2179 }
2180
2181 writer_done = 1;
2182
2183 rte_eal_mp_wait_lcore();
2184
2185 rte_hash_free(g_handle);
2186 rte_free(g_qsv);
2187
2188 return 0;
2189
2190}
2191
2192
2193
2194
2195static int
2196test_hash(void)
2197{
2198 RTE_BUILD_BUG_ON(sizeof(struct flow_key) % sizeof(uint32_t) != 0);
2199
2200 if (test_add_delete() < 0)
2201 return -1;
2202 if (test_hash_add_delete_jhash2() < 0)
2203 return -1;
2204 if (test_hash_add_delete_2_jhash2() < 0)
2205 return -1;
2206 if (test_hash_add_delete_jhash_1word() < 0)
2207 return -1;
2208 if (test_hash_add_delete_jhash_2word() < 0)
2209 return -1;
2210 if (test_hash_add_delete_jhash_3word() < 0)
2211 return -1;
2212 if (test_hash_get_key_with_position() < 0)
2213 return -1;
2214 if (test_hash_find_existing() < 0)
2215 return -1;
2216 if (test_add_update_delete() < 0)
2217 return -1;
2218 if (test_add_update_delete_free() < 0)
2219 return -1;
2220 if (test_add_delete_free_lf() < 0)
2221 return -1;
2222 if (test_five_keys() < 0)
2223 return -1;
2224 if (test_full_bucket() < 0)
2225 return -1;
2226 if (test_extendable_bucket() < 0)
2227 return -1;
2228
2229 if (test_fbk_hash_find_existing() < 0)
2230 return -1;
2231 if (fbk_hash_unit_test() < 0)
2232 return -1;
2233 if (test_hash_creation_with_bad_parameters() < 0)
2234 return -1;
2235 if (test_hash_creation_with_good_parameters() < 0)
2236 return -1;
2237
2238
2239 if (test_average_table_utilization(0) < 0)
2240 return -1;
2241 if (test_hash_iteration(0) < 0)
2242 return -1;
2243
2244
2245 if (test_average_table_utilization(1) < 0)
2246 return -1;
2247 if (test_hash_iteration(1) < 0)
2248 return -1;
2249
2250 run_hash_func_tests();
2251
2252 if (test_crc32_hash_alg_equiv() < 0)
2253 return -1;
2254
2255 if (test_hash_rcu_qsbr_add() < 0)
2256 return -1;
2257
2258 if (test_hash_rcu_qsbr_dq_mode(0) < 0)
2259 return -1;
2260
2261 if (test_hash_rcu_qsbr_dq_mode(1) < 0)
2262 return -1;
2263
2264 if (test_hash_rcu_qsbr_sync_mode(0) < 0)
2265 return -1;
2266
2267 if (test_hash_rcu_qsbr_sync_mode(1) < 0)
2268 return -1;
2269
2270 return 0;
2271}
2272
2273REGISTER_TEST_COMMAND(hash_autotest, test_hash);
2274