1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
5 #ifndef RTE_EXEC_ENV_WINDOWS
8 #include <rte_byteorder.h>
9 #include <rte_table_lpm_ipv6.h>
11 #include <rte_cycles.h>
12 #include "test_table_tables.h"
13 #include "test_table.h"
15 table_test table_tests[] = {
22 test_table_hash_cuckoo,
25 #define PREPARE_PACKET(mbuf, value) do { \
26 uint32_t *k32, *signature; \
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) \
35 k32 = (uint32_t *) key; \
37 *signature = pipeline_test_hash(key, NULL, 0, 0); \
40 unsigned n_table_tests = RTE_DIM(table_tests);
42 /* Function prototypes */
44 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size);
46 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size);
48 struct rte_bucket_4_8 {
52 struct rte_bucket_4_8 *next;
59 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
60 uint64_t shuffles = 0xfffffffdfffbfff9ULL;
62 uint64_t shuffles = 0x0003000200010000ULL;
65 static int test_lru_update(void)
67 struct rte_bucket_4_8 b;
68 struct rte_bucket_4_8 *bucket;
75 printf("---------------------------\n");
76 printf("Testing lru_update macro...\n");
77 printf("---------------------------\n");
80 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
81 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
83 bucket->lru_list = 0x0000000100020003ULL;
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);
92 printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
94 __func__, i, bucket->lru_list, i>>1, pos);
97 if (bucket->lru_list != shuffles) {
98 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
100 __func__, i, bucket->lru_list, shuffles);
103 printf("%s: output checksum of results =%d\n",
107 printf("%s: ERROR output checksum of results =%d expected %d\n",
108 __func__, poss, 126);
115 uint64_t sc_start = rte_rdtsc();
116 iterations = 100000000;
118 for (j = 0; j < iterations; j++) {
119 for (i = 0; i < 4; i++) {
120 lru_update(bucket, i);
121 pos |= bucket->lru_list;
124 uint64_t sc_end = rte_rdtsc();
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)));
138 test_table_stub(void)
141 uint64_t expected_mask = 0, result_mask;
142 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
144 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
147 table = rte_table_stub_ops.f_create(NULL, 0, 1);
152 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
154 PREPARE_PACKET(mbufs[i], 0xadadadad);
156 PREPARE_PACKET(mbufs[i], 0xadadadab);
159 rte_table_stub_ops.f_lookup(table, mbufs, -1,
160 &result_mask, (void **)entries);
161 if (result_mask != expected_mask)
165 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
166 rte_pktmbuf_free(mbufs[i]);
172 test_table_array(void)
175 uint64_t result_mask;
176 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
178 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
183 /* Initialize params and create tables */
184 struct rte_table_array_params array_params = {
186 .offset = APP_METADATA_OFFSET(1)
189 table = rte_table_array_ops.f_create(NULL, 0, 1);
193 array_params.n_entries = 0;
195 table = rte_table_array_ops.f_create(&array_params, 0, 1);
199 array_params.n_entries = 7;
201 table = rte_table_array_ops.f_create(&array_params, 0, 1);
205 array_params.n_entries = 1 << 24;
206 array_params.offset = APP_METADATA_OFFSET(1);
208 table = rte_table_array_ops.f_create(&array_params, 0, 1);
212 array_params.offset = APP_METADATA_OFFSET(32);
214 table = rte_table_array_ops.f_create(&array_params, 0, 1);
219 status = rte_table_array_ops.f_free(table);
223 status = rte_table_array_ops.f_free(NULL);
228 struct rte_table_array_key array_key_1 = {
231 struct rte_table_array_key array_key_2 = {
237 table = rte_table_array_ops.f_create(&array_params, 0, 1);
241 status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
242 &key_found, &entry_ptr);
246 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
247 &key_found, &entry_ptr);
251 status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
252 &entry1, &key_found, &entry_ptr);
257 status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
258 &entry2, &key_found, &entry_ptr);
262 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
264 PREPARE_PACKET(mbufs[i], 10);
266 PREPARE_PACKET(mbufs[i], 20);
268 rte_table_array_ops.f_lookup(table, mbufs, -1,
269 &result_mask, (void **)entries);
271 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
272 if (i % 2 == 0 && *entries[i] != 'A')
275 if (i % 2 == 1 && *entries[i] != 'B')
279 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
280 rte_pktmbuf_free(mbufs[i]);
282 status = rte_table_array_ops.f_free(table);
291 uint64_t expected_mask = 0, result_mask;
292 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
294 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
298 uint32_t entry_size = sizeof(entry);
300 /* Initialize params and create tables */
301 struct rte_table_lpm_params lpm_params = {
304 .number_tbl8s = 1 << 8,
306 .entry_unique_size = entry_size,
307 .offset = APP_METADATA_OFFSET(1)
310 table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
314 lpm_params.name = NULL;
316 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
320 lpm_params.name = "LPM";
321 lpm_params.n_rules = 0;
323 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
327 lpm_params.n_rules = 1 << 24;
328 lpm_params.offset = APP_METADATA_OFFSET(32);
329 lpm_params.entry_unique_size = 0;
331 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
335 lpm_params.entry_unique_size = entry_size + 1;
337 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
341 lpm_params.entry_unique_size = entry_size;
343 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
348 status = rte_table_lpm_ops.f_free(table);
352 status = rte_table_lpm_ops.f_free(NULL);
357 struct rte_table_lpm_key lpm_key;
358 lpm_key.ip = 0xadadadad;
360 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
364 status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
369 status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
374 status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
380 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
386 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
392 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
398 status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
402 status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
407 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
412 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
417 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
421 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
427 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
432 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
434 expected_mask |= (uint64_t)1 << i;
435 PREPARE_PACKET(mbufs[i], 0xadadadad);
437 PREPARE_PACKET(mbufs[i], 0xadadadab);
439 rte_table_lpm_ops.f_lookup(table, mbufs, -1,
440 &result_mask, (void **)entries);
441 if (result_mask != expected_mask)
445 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
446 rte_pktmbuf_free(mbufs[i]);
448 status = rte_table_lpm_ops.f_free(table);
454 test_table_lpm_ipv6(void)
457 uint64_t expected_mask = 0, result_mask;
458 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
460 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
464 uint32_t entry_size = sizeof(entry);
466 /* Initialize params and create tables */
467 struct rte_table_lpm_ipv6_params lpm_params = {
470 .number_tbl8s = 1 << 18,
471 .entry_unique_size = entry_size,
472 .offset = APP_METADATA_OFFSET(32)
475 table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
479 lpm_params.name = NULL;
481 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
485 lpm_params.name = "LPM";
486 lpm_params.n_rules = 0;
488 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
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);
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);
504 lpm_params.entry_unique_size = entry_size + 1;
505 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
509 lpm_params.entry_unique_size = entry_size;
510 lpm_params.offset = APP_METADATA_OFFSET(32);
512 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
517 status = rte_table_lpm_ipv6_ops.f_free(table);
521 status = rte_table_lpm_ipv6_ops.f_free(NULL);
526 struct rte_table_lpm_ipv6_key lpm_key;
528 lpm_key.ip[0] = 0xad;
529 lpm_key.ip[1] = 0xad;
530 lpm_key.ip[2] = 0xad;
531 lpm_key.ip[3] = 0xad;
533 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
537 status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
538 &key_found, &entry_ptr);
542 status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
547 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
553 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
554 &key_found, &entry_ptr);
559 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
560 &key_found, &entry_ptr);
565 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
566 &key_found, &entry_ptr);
571 status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
576 status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
581 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
587 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
593 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
598 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
605 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
606 &key_found, &entry_ptr);
610 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
612 expected_mask |= (uint64_t)1 << i;
613 PREPARE_PACKET(mbufs[i], 0xadadadad);
615 PREPARE_PACKET(mbufs[i], 0xadadadab);
617 rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
618 &result_mask, (void **)entries);
619 if (result_mask != expected_mask)
623 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
624 rte_pktmbuf_free(mbufs[i]);
626 status = rte_table_lpm_ipv6_ops.f_free(table);
632 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
635 uint64_t expected_mask = 0, result_mask;
636 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
638 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
643 /* Initialize params and create tables */
644 struct rte_table_hash_params hash_params = {
646 .key_size = key_size,
647 .key_offset = APP_METADATA_OFFSET(32),
650 .n_buckets = 1 << 10,
651 .f_hash = pipeline_test_hash,
655 hash_params.n_keys = 0;
657 table = ops->f_create(&hash_params, 0, 1);
661 hash_params.n_keys = 1 << 10;
662 hash_params.f_hash = NULL;
664 table = ops->f_create(&hash_params, 0, 1);
668 hash_params.f_hash = pipeline_test_hash;
670 table = ops->f_create(&hash_params, 0, 1);
675 status = ops->f_free(table);
679 status = ops->f_free(NULL);
685 uint32_t *k32 = (uint32_t *) &key;
688 k32[0] = rte_be_to_cpu_32(0xadadadad);
690 table = ops->f_create(&hash_params, 0, 1);
695 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
700 status = ops->f_delete(table, &key, &key_found, NULL);
704 status = ops->f_delete(table, &key, &key_found, NULL);
710 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
714 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
716 expected_mask |= (uint64_t)1 << i;
717 PREPARE_PACKET(mbufs[i], 0xadadadad);
719 PREPARE_PACKET(mbufs[i], 0xadadadab);
721 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
722 if (result_mask != expected_mask)
726 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
727 rte_pktmbuf_free(mbufs[i]);
729 status = ops->f_free(table);
735 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
738 uint64_t expected_mask = 0, result_mask;
739 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
741 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
746 /* Initialize params and create tables */
747 struct rte_table_hash_params hash_params = {
749 .key_size = key_size,
750 .key_offset = APP_METADATA_OFFSET(32),
753 .n_buckets = 1 << 10,
754 .f_hash = pipeline_test_hash,
758 hash_params.n_keys = 0;
760 table = ops->f_create(&hash_params, 0, 1);
764 hash_params.n_keys = 1 << 10;
765 hash_params.key_offset = APP_METADATA_OFFSET(1);
767 table = ops->f_create(&hash_params, 0, 1);
771 hash_params.key_offset = APP_METADATA_OFFSET(32);
772 hash_params.f_hash = NULL;
774 table = ops->f_create(&hash_params, 0, 1);
778 hash_params.f_hash = pipeline_test_hash;
780 table = ops->f_create(&hash_params, 0, 1);
785 status = ops->f_free(table);
789 status = ops->f_free(NULL);
795 uint32_t *k32 = (uint32_t *) &key;
798 k32[0] = rte_be_to_cpu_32(0xadadadad);
800 table = ops->f_create(&hash_params, 0, 1);
805 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
810 status = ops->f_delete(table, &key, &key_found, NULL);
814 status = ops->f_delete(table, &key, &key_found, NULL);
820 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
824 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
826 expected_mask |= (uint64_t)1 << i;
827 PREPARE_PACKET(mbufs[i], 0xadadadad);
829 PREPARE_PACKET(mbufs[i], 0xadadadab);
831 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
832 if (result_mask != expected_mask)
836 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
837 rte_pktmbuf_free(mbufs[i]);
839 status = ops->f_free(table);
845 test_table_hash_lru(void)
849 status = test_table_hash_lru_generic(
850 &rte_table_hash_key8_lru_ops,
855 status = test_table_hash_lru_generic(
856 &rte_table_hash_key16_lru_ops,
861 status = test_table_hash_lru_generic(
862 &rte_table_hash_key32_lru_ops,
867 status = test_lru_update();
875 test_table_hash_ext(void)
879 status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8);
883 status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16);
887 status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32);
896 test_table_hash_cuckoo(void)
899 uint64_t expected_mask = 0, result_mask;
900 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
902 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
906 uint32_t entry_size = 1;
908 /* Initialize params and create tables */
909 struct rte_table_hash_cuckoo_params cuckoo_params = {
912 .key_offset = APP_METADATA_OFFSET(32),
915 .n_buckets = 1 << 16,
916 .f_hash = pipeline_test_hash_cuckoo,
920 table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size);
924 cuckoo_params.key_size = 0;
926 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
931 cuckoo_params.key_size = 32;
932 cuckoo_params.n_keys = 0;
934 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
939 cuckoo_params.n_keys = 1 << 24;
940 cuckoo_params.f_hash = NULL;
942 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
947 cuckoo_params.f_hash = pipeline_test_hash_cuckoo;
948 cuckoo_params.name = NULL;
950 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
955 cuckoo_params.name = "CUCKOO";
957 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
963 status = rte_table_hash_cuckoo_ops.f_free(table);
967 status = rte_table_hash_cuckoo_ops.f_free(NULL);
972 uint8_t key_cuckoo[32];
973 uint32_t *kcuckoo = (uint32_t *) &key_cuckoo;
975 memset(key_cuckoo, 0, 32);
976 kcuckoo[0] = rte_be_to_cpu_32(0xadadadad);
978 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1);
983 status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo,
984 &entry, &key_found, &entry_ptr);
988 status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry,
989 &key_found, &entry_ptr);
993 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
994 NULL, &key_found, &entry_ptr);
998 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
999 &entry, &key_found, &entry_ptr);
1003 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1004 &entry, &key_found, &entry_ptr);
1009 status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo,
1014 status = rte_table_hash_cuckoo_ops.f_delete(table, NULL,
1019 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1024 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1026 if (status != -ENOENT)
1031 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1037 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1039 expected_mask |= (uint64_t)1 << i;
1040 PREPARE_PACKET(mbufs[i], 0xadadadad);
1042 PREPARE_PACKET(mbufs[i], 0xadadadab);
1044 rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1,
1045 &result_mask, (void **)entries);
1046 if (result_mask != expected_mask)
1049 /* Free resources */
1050 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1051 rte_pktmbuf_free(mbufs[i]);
1053 status = rte_table_hash_cuckoo_ops.f_free(table);
1058 #endif /* !RTE_EXEC_ENV_WINDOWS */