1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
3 */
4
5 #ifndef RTE_EXEC_ENV_WINDOWS
6
7 #include <string.h>
8 #include <rte_byteorder.h>
9 #include <rte_table_lpm_ipv6.h>
10 #include <rte_lru.h>
11 #include <rte_cycles.h>
12 #include "test_table_tables.h"
13 #include "test_table.h"
14
15 table_test table_tests[] = {
16 test_table_stub,
17 test_table_array,
18 test_table_lpm,
19 test_table_lpm_ipv6,
20 test_table_hash_lru,
21 test_table_hash_ext,
22 test_table_hash_cuckoo,
23 };
24
25 #define PREPARE_PACKET(mbuf, value) do { \
26 uint32_t *k32, *signature; \
27 uint8_t *key; \
28 mbuf = rte_pktmbuf_alloc(pool); \
29 signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, \
30 APP_METADATA_OFFSET(0)); \
31 key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, \
32 APP_METADATA_OFFSET(32)); \
33 if (mbuf->priv_size + mbuf->buf_len >= 64) \
34 memset(key, 0, 32); \
35 k32 = (uint32_t *) key; \
36 k32[0] = (value); \
37 *signature = pipeline_test_hash(key, NULL, 0, 0); \
38 } while (0)
39
40 unsigned n_table_tests = RTE_DIM(table_tests);
41
42 /* Function prototypes */
43 static int
44 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size);
45 static int
46 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size);
47
48 struct rte_bucket_4_8 {
49 /* Cache line 0 */
50 uint64_t signature;
51 uint64_t lru_list;
52 struct rte_bucket_4_8 *next;
53 uint64_t next_valid;
54 uint64_t key[4];
55 /* Cache line 1 */
56 uint8_t data[0];
57 };
58
59 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
60 uint64_t shuffles = 0xfffffffdfffbfff9ULL;
61 #else
62 uint64_t shuffles = 0x0003000200010000ULL;
63 #endif
64
test_lru_update(void)65 static int test_lru_update(void)
66 {
67 struct rte_bucket_4_8 b;
68 struct rte_bucket_4_8 *bucket;
69 uint32_t i;
70 uint64_t pos;
71 uint64_t iterations;
72 uint64_t j;
73 int poss;
74
75 printf("---------------------------\n");
76 printf("Testing lru_update macro...\n");
77 printf("---------------------------\n");
78 bucket = &b;
79 iterations = 10;
80 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
81 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
82 #else
83 bucket->lru_list = 0x0000000100020003ULL;
84 #endif
85 poss = 0;
86 for (j = 0; j < iterations; j++)
87 for (i = 0; i < 9; i++) {
88 uint32_t idx = i >> 1;
89 lru_update(bucket, idx);
90 pos = lru_pos(bucket);
91 poss += pos;
92 printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
93 "pos=%"PRIx64"\n",
94 __func__, i, bucket->lru_list, i>>1, pos);
95 }
96
97 if (bucket->lru_list != shuffles) {
98 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
99 PRIx64"\n",
100 __func__, i, bucket->lru_list, shuffles);
101 return -1;
102 }
103 printf("%s: output checksum of results =%d\n",
104 __func__, poss);
105 #if 0
106 if (poss != 126) {
107 printf("%s: ERROR output checksum of results =%d expected %d\n",
108 __func__, poss, 126);
109 return -1;
110 }
111 #endif
112
113 fflush(stdout);
114
115 uint64_t sc_start = rte_rdtsc();
116 iterations = 100000000;
117 poss = 0;
118 for (j = 0; j < iterations; j++) {
119 for (i = 0; i < 4; i++) {
120 lru_update(bucket, i);
121 pos |= bucket->lru_list;
122 }
123 }
124 uint64_t sc_end = rte_rdtsc();
125
126 printf("%s: output checksum of results =%llu\n",
127 __func__, (long long unsigned int)pos);
128 printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
129 __func__, sc_start, sc_end);
130 printf("\nlru_update: %lu cycles per loop iteration.\n\n",
131 (long unsigned int)((sc_end-sc_start)/(iterations*4)));
132
133 return 0;
134 }
135
136 /* Table tests */
137 int
test_table_stub(void)138 test_table_stub(void)
139 {
140 int i;
141 uint64_t expected_mask = 0, result_mask;
142 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
143 void *table;
144 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
145
146 /* Create */
147 table = rte_table_stub_ops.f_create(NULL, 0, 1);
148 if (table == NULL)
149 return -1;
150
151 /* Traffic flow */
152 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
153 if (i % 2 == 0)
154 PREPARE_PACKET(mbufs[i], 0xadadadad);
155 else
156 PREPARE_PACKET(mbufs[i], 0xadadadab);
157
158 expected_mask = 0;
159 rte_table_stub_ops.f_lookup(table, mbufs, -1,
160 &result_mask, (void **)entries);
161 if (result_mask != expected_mask)
162 return -2;
163
164 /* Free resources */
165 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
166 rte_pktmbuf_free(mbufs[i]);
167
168 return 0;
169 }
170
171 int
test_table_array(void)172 test_table_array(void)
173 {
174 int status, i;
175 uint64_t result_mask;
176 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
177 void *table;
178 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
179 char entry1, entry2;
180 void *entry_ptr;
181 int key_found;
182
183 /* Initialize params and create tables */
184 struct rte_table_array_params array_params = {
185 .n_entries = 7,
186 .offset = APP_METADATA_OFFSET(1)
187 };
188
189 table = rte_table_array_ops.f_create(NULL, 0, 1);
190 if (table != NULL)
191 return -1;
192
193 array_params.n_entries = 0;
194
195 table = rte_table_array_ops.f_create(&array_params, 0, 1);
196 if (table != NULL)
197 return -2;
198
199 array_params.n_entries = 7;
200
201 table = rte_table_array_ops.f_create(&array_params, 0, 1);
202 if (table != NULL)
203 return -3;
204
205 array_params.n_entries = 1 << 24;
206 array_params.offset = APP_METADATA_OFFSET(1);
207
208 table = rte_table_array_ops.f_create(&array_params, 0, 1);
209 if (table == NULL)
210 return -4;
211
212 array_params.offset = APP_METADATA_OFFSET(32);
213
214 table = rte_table_array_ops.f_create(&array_params, 0, 1);
215 if (table == NULL)
216 return -5;
217
218 /* Free */
219 status = rte_table_array_ops.f_free(table);
220 if (status < 0)
221 return -6;
222
223 status = rte_table_array_ops.f_free(NULL);
224 if (status == 0)
225 return -7;
226
227 /* Add */
228 struct rte_table_array_key array_key_1 = {
229 .pos = 10,
230 };
231 struct rte_table_array_key array_key_2 = {
232 .pos = 20,
233 };
234 entry1 = 'A';
235 entry2 = 'B';
236
237 table = rte_table_array_ops.f_create(&array_params, 0, 1);
238 if (table == NULL)
239 return -8;
240
241 status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
242 &key_found, &entry_ptr);
243 if (status == 0)
244 return -9;
245
246 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
247 &key_found, &entry_ptr);
248 if (status == 0)
249 return -10;
250
251 status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
252 &entry1, &key_found, &entry_ptr);
253 if (status != 0)
254 return -11;
255
256 /* Traffic flow */
257 status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
258 &entry2, &key_found, &entry_ptr);
259 if (status != 0)
260 return -12;
261
262 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
263 if (i % 2 == 0)
264 PREPARE_PACKET(mbufs[i], 10);
265 else
266 PREPARE_PACKET(mbufs[i], 20);
267
268 rte_table_array_ops.f_lookup(table, mbufs, -1,
269 &result_mask, (void **)entries);
270
271 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
272 if (i % 2 == 0 && *entries[i] != 'A')
273 return -13;
274 else
275 if (i % 2 == 1 && *entries[i] != 'B')
276 return -13;
277
278 /* Free resources */
279 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
280 rte_pktmbuf_free(mbufs[i]);
281
282 status = rte_table_array_ops.f_free(table);
283
284 return 0;
285 }
286
287 int
test_table_lpm(void)288 test_table_lpm(void)
289 {
290 int status, i;
291 uint64_t expected_mask = 0, result_mask;
292 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
293 void *table;
294 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
295 uint64_t entry;
296 void *entry_ptr;
297 int key_found;
298 uint32_t entry_size = sizeof(entry);
299
300 /* Initialize params and create tables */
301 struct rte_table_lpm_params lpm_params = {
302 .name = "LPM",
303 .n_rules = 1 << 24,
304 .number_tbl8s = 1 << 8,
305 .flags = 0,
306 .entry_unique_size = entry_size,
307 .offset = APP_METADATA_OFFSET(1)
308 };
309
310 table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
311 if (table != NULL)
312 return -1;
313
314 lpm_params.name = NULL;
315
316 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
317 if (table != NULL)
318 return -2;
319
320 lpm_params.name = "LPM";
321 lpm_params.n_rules = 0;
322
323 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
324 if (table != NULL)
325 return -3;
326
327 lpm_params.n_rules = 1 << 24;
328 lpm_params.offset = APP_METADATA_OFFSET(32);
329 lpm_params.entry_unique_size = 0;
330
331 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
332 if (table != NULL)
333 return -4;
334
335 lpm_params.entry_unique_size = entry_size + 1;
336
337 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
338 if (table != NULL)
339 return -5;
340
341 lpm_params.entry_unique_size = entry_size;
342
343 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
344 if (table == NULL)
345 return -6;
346
347 /* Free */
348 status = rte_table_lpm_ops.f_free(table);
349 if (status < 0)
350 return -7;
351
352 status = rte_table_lpm_ops.f_free(NULL);
353 if (status == 0)
354 return -8;
355
356 /* Add */
357 struct rte_table_lpm_key lpm_key;
358 lpm_key.ip = 0xadadadad;
359
360 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
361 if (table == NULL)
362 return -9;
363
364 status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
365 &entry_ptr);
366 if (status == 0)
367 return -10;
368
369 status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
370 &entry_ptr);
371 if (status == 0)
372 return -11;
373
374 status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
375 &entry_ptr);
376 if (status == 0)
377 return -12;
378
379 lpm_key.depth = 0;
380 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
381 &entry_ptr);
382 if (status == 0)
383 return -13;
384
385 lpm_key.depth = 33;
386 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
387 &entry_ptr);
388 if (status == 0)
389 return -14;
390
391 lpm_key.depth = 16;
392 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
393 &entry_ptr);
394 if (status != 0)
395 return -15;
396
397 /* Delete */
398 status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
399 if (status == 0)
400 return -16;
401
402 status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
403 if (status == 0)
404 return -17;
405
406 lpm_key.depth = 0;
407 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
408 if (status == 0)
409 return -18;
410
411 lpm_key.depth = 33;
412 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
413 if (status == 0)
414 return -19;
415
416 lpm_key.depth = 16;
417 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
418 if (status != 0)
419 return -20;
420
421 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
422 if (status != 0)
423 return -21;
424
425 /* Traffic flow */
426 entry = 'A';
427 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
428 &entry_ptr);
429 if (status < 0)
430 return -22;
431
432 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
433 if (i % 2 == 0) {
434 expected_mask |= (uint64_t)1 << i;
435 PREPARE_PACKET(mbufs[i], 0xadadadad);
436 } else
437 PREPARE_PACKET(mbufs[i], 0xadadadab);
438
439 rte_table_lpm_ops.f_lookup(table, mbufs, -1,
440 &result_mask, (void **)entries);
441 if (result_mask != expected_mask)
442 return -23;
443
444 /* Free resources */
445 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
446 rte_pktmbuf_free(mbufs[i]);
447
448 status = rte_table_lpm_ops.f_free(table);
449
450 return 0;
451 }
452
453 int
test_table_lpm_ipv6(void)454 test_table_lpm_ipv6(void)
455 {
456 int status, i;
457 uint64_t expected_mask = 0, result_mask;
458 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
459 void *table;
460 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
461 uint64_t entry;
462 void *entry_ptr;
463 int key_found;
464 uint32_t entry_size = sizeof(entry);
465
466 /* Initialize params and create tables */
467 struct rte_table_lpm_ipv6_params lpm_params = {
468 .name = "LPM",
469 .n_rules = 1 << 24,
470 .number_tbl8s = 1 << 18,
471 .entry_unique_size = entry_size,
472 .offset = APP_METADATA_OFFSET(32)
473 };
474
475 table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
476 if (table != NULL)
477 return -1;
478
479 lpm_params.name = NULL;
480
481 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
482 if (table != NULL)
483 return -2;
484
485 lpm_params.name = "LPM";
486 lpm_params.n_rules = 0;
487
488 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
489 if (table != NULL)
490 return -3;
491
492 lpm_params.n_rules = 1 << 24;
493 lpm_params.number_tbl8s = 0;
494 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
495 if (table != NULL)
496 return -4;
497
498 lpm_params.number_tbl8s = 1 << 18;
499 lpm_params.entry_unique_size = 0;
500 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
501 if (table != NULL)
502 return -5;
503
504 lpm_params.entry_unique_size = entry_size + 1;
505 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
506 if (table != NULL)
507 return -6;
508
509 lpm_params.entry_unique_size = entry_size;
510 lpm_params.offset = APP_METADATA_OFFSET(32);
511
512 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
513 if (table == NULL)
514 return -7;
515
516 /* Free */
517 status = rte_table_lpm_ipv6_ops.f_free(table);
518 if (status < 0)
519 return -8;
520
521 status = rte_table_lpm_ipv6_ops.f_free(NULL);
522 if (status == 0)
523 return -9;
524
525 /* Add */
526 struct rte_table_lpm_ipv6_key lpm_key;
527
528 lpm_key.ip[0] = 0xad;
529 lpm_key.ip[1] = 0xad;
530 lpm_key.ip[2] = 0xad;
531 lpm_key.ip[3] = 0xad;
532
533 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
534 if (table == NULL)
535 return -10;
536
537 status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
538 &key_found, &entry_ptr);
539 if (status == 0)
540 return -11;
541
542 status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
543 &entry_ptr);
544 if (status == 0)
545 return -12;
546
547 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
548 &entry_ptr);
549 if (status == 0)
550 return -13;
551
552 lpm_key.depth = 0;
553 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
554 &key_found, &entry_ptr);
555 if (status == 0)
556 return -14;
557
558 lpm_key.depth = 129;
559 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
560 &key_found, &entry_ptr);
561 if (status == 0)
562 return -15;
563
564 lpm_key.depth = 16;
565 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
566 &key_found, &entry_ptr);
567 if (status != 0)
568 return -16;
569
570 /* Delete */
571 status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
572 NULL);
573 if (status == 0)
574 return -17;
575
576 status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
577 if (status == 0)
578 return -18;
579
580 lpm_key.depth = 0;
581 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
582 NULL);
583 if (status == 0)
584 return -19;
585
586 lpm_key.depth = 129;
587 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
588 NULL);
589 if (status == 0)
590 return -20;
591
592 lpm_key.depth = 16;
593 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
594 NULL);
595 if (status != 0)
596 return -21;
597
598 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
599 NULL);
600 if (status != 0)
601 return -22;
602
603 /* Traffic flow */
604 entry = 'A';
605 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
606 &key_found, &entry_ptr);
607 if (status < 0)
608 return -23;
609
610 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
611 if (i % 2 == 0) {
612 expected_mask |= (uint64_t)1 << i;
613 PREPARE_PACKET(mbufs[i], 0xadadadad);
614 } else
615 PREPARE_PACKET(mbufs[i], 0xadadadab);
616
617 rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
618 &result_mask, (void **)entries);
619 if (result_mask != expected_mask)
620 return -24;
621
622 /* Free resources */
623 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
624 rte_pktmbuf_free(mbufs[i]);
625
626 status = rte_table_lpm_ipv6_ops.f_free(table);
627
628 return 0;
629 }
630
631 static int
test_table_hash_lru_generic(struct rte_table_ops * ops,uint32_t key_size)632 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
633 {
634 int status, i;
635 uint64_t expected_mask = 0, result_mask;
636 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
637 void *table;
638 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
639 char entry;
640 void *entry_ptr;
641 int key_found;
642
643 /* Initialize params and create tables */
644 struct rte_table_hash_params hash_params = {
645 .name = "TABLE",
646 .key_size = key_size,
647 .key_offset = APP_METADATA_OFFSET(32),
648 .key_mask = NULL,
649 .n_keys = 1 << 10,
650 .n_buckets = 1 << 10,
651 .f_hash = pipeline_test_hash,
652 .seed = 0,
653 };
654
655 hash_params.n_keys = 0;
656
657 table = ops->f_create(&hash_params, 0, 1);
658 if (table != NULL)
659 return -1;
660
661 hash_params.n_keys = 1 << 10;
662 hash_params.f_hash = NULL;
663
664 table = ops->f_create(&hash_params, 0, 1);
665 if (table != NULL)
666 return -4;
667
668 hash_params.f_hash = pipeline_test_hash;
669
670 table = ops->f_create(&hash_params, 0, 1);
671 if (table == NULL)
672 return -5;
673
674 /* Free */
675 status = ops->f_free(table);
676 if (status < 0)
677 return -6;
678
679 status = ops->f_free(NULL);
680 if (status == 0)
681 return -7;
682
683 /* Add */
684 uint8_t key[32];
685 uint32_t *k32 = (uint32_t *) &key;
686
687 memset(key, 0, 32);
688 k32[0] = rte_be_to_cpu_32(0xadadadad);
689
690 table = ops->f_create(&hash_params, 0, 1);
691 if (table == NULL)
692 return -8;
693
694 entry = 'A';
695 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
696 if (status != 0)
697 return -9;
698
699 /* Delete */
700 status = ops->f_delete(table, &key, &key_found, NULL);
701 if (status != 0)
702 return -10;
703
704 status = ops->f_delete(table, &key, &key_found, NULL);
705 if (status != 0)
706 return -11;
707
708 /* Traffic flow */
709 entry = 'A';
710 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
711 if (status < 0)
712 return -12;
713
714 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
715 if (i % 2 == 0) {
716 expected_mask |= (uint64_t)1 << i;
717 PREPARE_PACKET(mbufs[i], 0xadadadad);
718 } else
719 PREPARE_PACKET(mbufs[i], 0xadadadab);
720
721 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
722 if (result_mask != expected_mask)
723 return -13;
724
725 /* Free resources */
726 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
727 rte_pktmbuf_free(mbufs[i]);
728
729 status = ops->f_free(table);
730
731 return 0;
732 }
733
734 static int
test_table_hash_ext_generic(struct rte_table_ops * ops,uint32_t key_size)735 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
736 {
737 int status, i;
738 uint64_t expected_mask = 0, result_mask;
739 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
740 void *table;
741 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
742 char entry;
743 int key_found;
744 void *entry_ptr;
745
746 /* Initialize params and create tables */
747 struct rte_table_hash_params hash_params = {
748 .name = "TABLE",
749 .key_size = key_size,
750 .key_offset = APP_METADATA_OFFSET(32),
751 .key_mask = NULL,
752 .n_keys = 1 << 10,
753 .n_buckets = 1 << 10,
754 .f_hash = pipeline_test_hash,
755 .seed = 0,
756 };
757
758 hash_params.n_keys = 0;
759
760 table = ops->f_create(&hash_params, 0, 1);
761 if (table != NULL)
762 return -1;
763
764 hash_params.n_keys = 1 << 10;
765 hash_params.key_offset = APP_METADATA_OFFSET(1);
766
767 table = ops->f_create(&hash_params, 0, 1);
768 if (table == NULL)
769 return -3;
770
771 hash_params.key_offset = APP_METADATA_OFFSET(32);
772 hash_params.f_hash = NULL;
773
774 table = ops->f_create(&hash_params, 0, 1);
775 if (table != NULL)
776 return -4;
777
778 hash_params.f_hash = pipeline_test_hash;
779
780 table = ops->f_create(&hash_params, 0, 1);
781 if (table == NULL)
782 return -5;
783
784 /* Free */
785 status = ops->f_free(table);
786 if (status < 0)
787 return -6;
788
789 status = ops->f_free(NULL);
790 if (status == 0)
791 return -7;
792
793 /* Add */
794 uint8_t key[32];
795 uint32_t *k32 = (uint32_t *) &key;
796
797 memset(key, 0, 32);
798 k32[0] = rte_be_to_cpu_32(0xadadadad);
799
800 table = ops->f_create(&hash_params, 0, 1);
801 if (table == NULL)
802 return -8;
803
804 entry = 'A';
805 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
806 if (status != 0)
807 return -9;
808
809 /* Delete */
810 status = ops->f_delete(table, &key, &key_found, NULL);
811 if (status != 0)
812 return -10;
813
814 status = ops->f_delete(table, &key, &key_found, NULL);
815 if (status != 0)
816 return -11;
817
818 /* Traffic flow */
819 entry = 'A';
820 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
821 if (status < 0)
822 return -12;
823
824 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
825 if (i % 2 == 0) {
826 expected_mask |= (uint64_t)1 << i;
827 PREPARE_PACKET(mbufs[i], 0xadadadad);
828 } else
829 PREPARE_PACKET(mbufs[i], 0xadadadab);
830
831 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
832 if (result_mask != expected_mask)
833 return -13;
834
835 /* Free resources */
836 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
837 rte_pktmbuf_free(mbufs[i]);
838
839 status = ops->f_free(table);
840
841 return 0;
842 }
843
844 int
test_table_hash_lru(void)845 test_table_hash_lru(void)
846 {
847 int status;
848
849 status = test_table_hash_lru_generic(
850 &rte_table_hash_key8_lru_ops,
851 8);
852 if (status < 0)
853 return status;
854
855 status = test_table_hash_lru_generic(
856 &rte_table_hash_key16_lru_ops,
857 16);
858 if (status < 0)
859 return status;
860
861 status = test_table_hash_lru_generic(
862 &rte_table_hash_key32_lru_ops,
863 32);
864 if (status < 0)
865 return status;
866
867 status = test_lru_update();
868 if (status < 0)
869 return status;
870
871 return 0;
872 }
873
874 int
test_table_hash_ext(void)875 test_table_hash_ext(void)
876 {
877 int status;
878
879 status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8);
880 if (status < 0)
881 return status;
882
883 status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16);
884 if (status < 0)
885 return status;
886
887 status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32);
888 if (status < 0)
889 return status;
890
891 return 0;
892 }
893
894
895 int
test_table_hash_cuckoo(void)896 test_table_hash_cuckoo(void)
897 {
898 int status, i;
899 uint64_t expected_mask = 0, result_mask;
900 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
901 void *table;
902 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
903 char entry;
904 void *entry_ptr;
905 int key_found;
906 uint32_t entry_size = 1;
907
908 /* Initialize params and create tables */
909 struct rte_table_hash_cuckoo_params cuckoo_params = {
910 .name = "TABLE",
911 .key_size = 32,
912 .key_offset = APP_METADATA_OFFSET(32),
913 .key_mask = NULL,
914 .n_keys = 1 << 16,
915 .n_buckets = 1 << 16,
916 .f_hash = pipeline_test_hash_cuckoo,
917 .seed = 0,
918 };
919
920 table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size);
921 if (table != NULL)
922 return -1;
923
924 cuckoo_params.key_size = 0;
925
926 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
927 0, entry_size);
928 if (table != NULL)
929 return -2;
930
931 cuckoo_params.key_size = 32;
932 cuckoo_params.n_keys = 0;
933
934 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
935 0, entry_size);
936 if (table != NULL)
937 return -3;
938
939 cuckoo_params.n_keys = 1 << 24;
940 cuckoo_params.f_hash = NULL;
941
942 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
943 0, entry_size);
944 if (table != NULL)
945 return -4;
946
947 cuckoo_params.f_hash = pipeline_test_hash_cuckoo;
948 cuckoo_params.name = NULL;
949
950 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
951 0, entry_size);
952 if (table != NULL)
953 return -5;
954
955 cuckoo_params.name = "CUCKOO";
956
957 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
958 0, entry_size);
959 if (table == NULL)
960 return -6;
961
962 /* Free */
963 status = rte_table_hash_cuckoo_ops.f_free(table);
964 if (status < 0)
965 return -7;
966
967 status = rte_table_hash_cuckoo_ops.f_free(NULL);
968 if (status == 0)
969 return -8;
970
971 /* Add */
972 uint8_t key_cuckoo[32];
973 uint32_t *kcuckoo = (uint32_t *) &key_cuckoo;
974
975 memset(key_cuckoo, 0, 32);
976 kcuckoo[0] = rte_be_to_cpu_32(0xadadadad);
977
978 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1);
979 if (table == NULL)
980 return -9;
981
982 entry = 'A';
983 status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo,
984 &entry, &key_found, &entry_ptr);
985 if (status == 0)
986 return -10;
987
988 status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry,
989 &key_found, &entry_ptr);
990 if (status == 0)
991 return -11;
992
993 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
994 NULL, &key_found, &entry_ptr);
995 if (status == 0)
996 return -12;
997
998 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
999 &entry, &key_found, &entry_ptr);
1000 if (status != 0)
1001 return -13;
1002
1003 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1004 &entry, &key_found, &entry_ptr);
1005 if (status != 0)
1006 return -14;
1007
1008 /* Delete */
1009 status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo,
1010 &key_found, NULL);
1011 if (status == 0)
1012 return -15;
1013
1014 status = rte_table_hash_cuckoo_ops.f_delete(table, NULL,
1015 &key_found, NULL);
1016 if (status == 0)
1017 return -16;
1018
1019 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1020 &key_found, NULL);
1021 if (status != 0)
1022 return -17;
1023
1024 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1025 &key_found, NULL);
1026 if (status != -ENOENT)
1027 return -18;
1028
1029 /* Traffic flow */
1030 entry = 'A';
1031 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1032 &entry, &key_found,
1033 &entry_ptr);
1034 if (status < 0)
1035 return -19;
1036
1037 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1038 if (i % 2 == 0) {
1039 expected_mask |= (uint64_t)1 << i;
1040 PREPARE_PACKET(mbufs[i], 0xadadadad);
1041 } else
1042 PREPARE_PACKET(mbufs[i], 0xadadadab);
1043
1044 rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1,
1045 &result_mask, (void **)entries);
1046 if (result_mask != expected_mask)
1047 return -20;
1048
1049 /* Free resources */
1050 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1051 rte_pktmbuf_free(mbufs[i]);
1052
1053 status = rte_table_hash_cuckoo_ops.f_free(table);
1054
1055 return 0;
1056 }
1057
1058 #endif /* !RTE_EXEC_ENV_WINDOWS */
1059