1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
6 #include <rte_byteorder.h>
7 #include <rte_table_lpm_ipv6.h>
9 #include <rte_cycles.h>
10 #include "test_table_tables.h"
11 #include "test_table.h"
13 table_test table_tests[] = {
20 test_table_hash_cuckoo,
23 #define PREPARE_PACKET(mbuf, value) do { \
24 uint32_t *k32, *signature; \
26 mbuf = rte_pktmbuf_alloc(pool); \
27 signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, \
28 APP_METADATA_OFFSET(0)); \
29 key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, \
30 APP_METADATA_OFFSET(32)); \
31 if (mbuf->priv_size + mbuf->buf_len >= 64) \
33 k32 = (uint32_t *) key; \
35 *signature = pipeline_test_hash(key, NULL, 0, 0); \
38 unsigned n_table_tests = RTE_DIM(table_tests);
40 /* Function prototypes */
42 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size);
44 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size);
46 struct rte_bucket_4_8 {
50 struct rte_bucket_4_8 *next;
57 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
58 uint64_t shuffles = 0xfffffffdfffbfff9ULL;
60 uint64_t shuffles = 0x0003000200010000ULL;
63 static int test_lru_update(void)
65 struct rte_bucket_4_8 b;
66 struct rte_bucket_4_8 *bucket;
73 printf("---------------------------\n");
74 printf("Testing lru_update macro...\n");
75 printf("---------------------------\n");
78 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
79 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
81 bucket->lru_list = 0x0000000100020003ULL;
84 for (j = 0; j < iterations; j++)
85 for (i = 0; i < 9; i++) {
86 uint32_t idx = i >> 1;
87 lru_update(bucket, idx);
88 pos = lru_pos(bucket);
90 printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
92 __func__, i, bucket->lru_list, i>>1, pos);
95 if (bucket->lru_list != shuffles) {
96 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
98 __func__, i, bucket->lru_list, shuffles);
101 printf("%s: output checksum of results =%d\n",
105 printf("%s: ERROR output checksum of results =%d expected %d\n",
106 __func__, poss, 126);
113 uint64_t sc_start = rte_rdtsc();
114 iterations = 100000000;
116 for (j = 0; j < iterations; j++) {
117 for (i = 0; i < 4; i++) {
118 lru_update(bucket, i);
119 pos |= bucket->lru_list;
122 uint64_t sc_end = rte_rdtsc();
124 printf("%s: output checksum of results =%llu\n",
125 __func__, (long long unsigned int)pos);
126 printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
127 __func__, sc_start, sc_end);
128 printf("\nlru_update: %lu cycles per loop iteration.\n\n",
129 (long unsigned int)((sc_end-sc_start)/(iterations*4)));
136 test_table_stub(void)
139 uint64_t expected_mask = 0, result_mask;
140 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
142 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
145 table = rte_table_stub_ops.f_create(NULL, 0, 1);
150 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
152 PREPARE_PACKET(mbufs[i], 0xadadadad);
154 PREPARE_PACKET(mbufs[i], 0xadadadab);
157 rte_table_stub_ops.f_lookup(table, mbufs, -1,
158 &result_mask, (void **)entries);
159 if (result_mask != expected_mask)
163 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
164 rte_pktmbuf_free(mbufs[i]);
170 test_table_array(void)
173 uint64_t result_mask;
174 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
176 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
181 /* Initialize params and create tables */
182 struct rte_table_array_params array_params = {
184 .offset = APP_METADATA_OFFSET(1)
187 table = rte_table_array_ops.f_create(NULL, 0, 1);
191 array_params.n_entries = 0;
193 table = rte_table_array_ops.f_create(&array_params, 0, 1);
197 array_params.n_entries = 7;
199 table = rte_table_array_ops.f_create(&array_params, 0, 1);
203 array_params.n_entries = 1 << 24;
204 array_params.offset = APP_METADATA_OFFSET(1);
206 table = rte_table_array_ops.f_create(&array_params, 0, 1);
210 array_params.offset = APP_METADATA_OFFSET(32);
212 table = rte_table_array_ops.f_create(&array_params, 0, 1);
217 status = rte_table_array_ops.f_free(table);
221 status = rte_table_array_ops.f_free(NULL);
226 struct rte_table_array_key array_key_1 = {
229 struct rte_table_array_key array_key_2 = {
235 table = rte_table_array_ops.f_create(&array_params, 0, 1);
239 status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
240 &key_found, &entry_ptr);
244 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
245 &key_found, &entry_ptr);
249 status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
250 &entry1, &key_found, &entry_ptr);
255 status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
256 &entry2, &key_found, &entry_ptr);
260 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
262 PREPARE_PACKET(mbufs[i], 10);
264 PREPARE_PACKET(mbufs[i], 20);
266 rte_table_array_ops.f_lookup(table, mbufs, -1,
267 &result_mask, (void **)entries);
269 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
270 if (i % 2 == 0 && *entries[i] != 'A')
273 if (i % 2 == 1 && *entries[i] != 'B')
277 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
278 rte_pktmbuf_free(mbufs[i]);
280 status = rte_table_array_ops.f_free(table);
289 uint64_t expected_mask = 0, result_mask;
290 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
292 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
296 uint32_t entry_size = 1;
298 /* Initialize params and create tables */
299 struct rte_table_lpm_params lpm_params = {
302 .number_tbl8s = 1 << 8,
304 .entry_unique_size = entry_size,
305 .offset = APP_METADATA_OFFSET(1)
308 table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
312 lpm_params.name = NULL;
314 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
318 lpm_params.name = "LPM";
319 lpm_params.n_rules = 0;
321 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
325 lpm_params.n_rules = 1 << 24;
326 lpm_params.offset = APP_METADATA_OFFSET(32);
327 lpm_params.entry_unique_size = 0;
329 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
333 lpm_params.entry_unique_size = entry_size + 1;
335 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
339 lpm_params.entry_unique_size = entry_size;
341 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
346 status = rte_table_lpm_ops.f_free(table);
350 status = rte_table_lpm_ops.f_free(NULL);
355 struct rte_table_lpm_key lpm_key;
356 lpm_key.ip = 0xadadadad;
358 table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
362 status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
367 status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
372 status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
378 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
384 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
390 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
396 status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
400 status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
405 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
410 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
415 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
419 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
425 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
430 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
432 expected_mask |= (uint64_t)1 << i;
433 PREPARE_PACKET(mbufs[i], 0xadadadad);
435 PREPARE_PACKET(mbufs[i], 0xadadadab);
437 rte_table_lpm_ops.f_lookup(table, mbufs, -1,
438 &result_mask, (void **)entries);
439 if (result_mask != expected_mask)
443 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
444 rte_pktmbuf_free(mbufs[i]);
446 status = rte_table_lpm_ops.f_free(table);
452 test_table_lpm_ipv6(void)
455 uint64_t expected_mask = 0, result_mask;
456 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
458 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
462 uint32_t entry_size = 1;
464 /* Initialize params and create tables */
465 struct rte_table_lpm_ipv6_params lpm_params = {
468 .number_tbl8s = 1 << 18,
469 .entry_unique_size = entry_size,
470 .offset = APP_METADATA_OFFSET(32)
473 table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
477 lpm_params.name = NULL;
479 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
483 lpm_params.name = "LPM";
484 lpm_params.n_rules = 0;
486 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
490 lpm_params.n_rules = 1 << 24;
491 lpm_params.number_tbl8s = 0;
492 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
496 lpm_params.number_tbl8s = 1 << 18;
497 lpm_params.entry_unique_size = 0;
498 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
502 lpm_params.entry_unique_size = entry_size + 1;
503 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
507 lpm_params.entry_unique_size = entry_size;
508 lpm_params.offset = APP_METADATA_OFFSET(32);
510 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
515 status = rte_table_lpm_ipv6_ops.f_free(table);
519 status = rte_table_lpm_ipv6_ops.f_free(NULL);
524 struct rte_table_lpm_ipv6_key lpm_key;
526 lpm_key.ip[0] = 0xad;
527 lpm_key.ip[1] = 0xad;
528 lpm_key.ip[2] = 0xad;
529 lpm_key.ip[3] = 0xad;
531 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
535 status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
536 &key_found, &entry_ptr);
540 status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
545 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
551 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
552 &key_found, &entry_ptr);
557 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
558 &key_found, &entry_ptr);
563 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
564 &key_found, &entry_ptr);
569 status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
574 status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
579 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
585 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
591 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
596 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
603 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
604 &key_found, &entry_ptr);
608 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
610 expected_mask |= (uint64_t)1 << i;
611 PREPARE_PACKET(mbufs[i], 0xadadadad);
613 PREPARE_PACKET(mbufs[i], 0xadadadab);
615 rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
616 &result_mask, (void **)entries);
617 if (result_mask != expected_mask)
621 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
622 rte_pktmbuf_free(mbufs[i]);
624 status = rte_table_lpm_ipv6_ops.f_free(table);
630 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
633 uint64_t expected_mask = 0, result_mask;
634 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
636 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
641 /* Initialize params and create tables */
642 struct rte_table_hash_params hash_params = {
644 .key_size = key_size,
645 .key_offset = APP_METADATA_OFFSET(32),
648 .n_buckets = 1 << 10,
649 .f_hash = pipeline_test_hash,
653 hash_params.n_keys = 0;
655 table = ops->f_create(&hash_params, 0, 1);
659 hash_params.n_keys = 1 << 10;
660 hash_params.f_hash = NULL;
662 table = ops->f_create(&hash_params, 0, 1);
666 hash_params.f_hash = pipeline_test_hash;
668 table = ops->f_create(&hash_params, 0, 1);
673 status = ops->f_free(table);
677 status = ops->f_free(NULL);
683 uint32_t *k32 = (uint32_t *) &key;
686 k32[0] = rte_be_to_cpu_32(0xadadadad);
688 table = ops->f_create(&hash_params, 0, 1);
693 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
698 status = ops->f_delete(table, &key, &key_found, NULL);
702 status = ops->f_delete(table, &key, &key_found, NULL);
708 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
712 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
714 expected_mask |= (uint64_t)1 << i;
715 PREPARE_PACKET(mbufs[i], 0xadadadad);
717 PREPARE_PACKET(mbufs[i], 0xadadadab);
719 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
720 if (result_mask != expected_mask)
724 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
725 rte_pktmbuf_free(mbufs[i]);
727 status = ops->f_free(table);
733 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
736 uint64_t expected_mask = 0, result_mask;
737 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
739 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
744 /* Initialize params and create tables */
745 struct rte_table_hash_params hash_params = {
747 .key_size = key_size,
748 .key_offset = APP_METADATA_OFFSET(32),
751 .n_buckets = 1 << 10,
752 .f_hash = pipeline_test_hash,
756 hash_params.n_keys = 0;
758 table = ops->f_create(&hash_params, 0, 1);
762 hash_params.n_keys = 1 << 10;
763 hash_params.key_offset = APP_METADATA_OFFSET(1);
765 table = ops->f_create(&hash_params, 0, 1);
769 hash_params.key_offset = APP_METADATA_OFFSET(32);
770 hash_params.f_hash = NULL;
772 table = ops->f_create(&hash_params, 0, 1);
776 hash_params.f_hash = pipeline_test_hash;
778 table = ops->f_create(&hash_params, 0, 1);
783 status = ops->f_free(table);
787 status = ops->f_free(NULL);
793 uint32_t *k32 = (uint32_t *) &key;
796 k32[0] = rte_be_to_cpu_32(0xadadadad);
798 table = ops->f_create(&hash_params, 0, 1);
803 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
808 status = ops->f_delete(table, &key, &key_found, NULL);
812 status = ops->f_delete(table, &key, &key_found, NULL);
818 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
822 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
824 expected_mask |= (uint64_t)1 << i;
825 PREPARE_PACKET(mbufs[i], 0xadadadad);
827 PREPARE_PACKET(mbufs[i], 0xadadadab);
829 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
830 if (result_mask != expected_mask)
834 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
835 rte_pktmbuf_free(mbufs[i]);
837 status = ops->f_free(table);
843 test_table_hash_lru(void)
847 status = test_table_hash_lru_generic(
848 &rte_table_hash_key8_lru_ops,
853 status = test_table_hash_lru_generic(
854 &rte_table_hash_key16_lru_ops,
859 status = test_table_hash_lru_generic(
860 &rte_table_hash_key32_lru_ops,
865 status = test_lru_update();
873 test_table_hash_ext(void)
877 status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8);
881 status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16);
885 status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32);
894 test_table_hash_cuckoo(void)
897 uint64_t expected_mask = 0, result_mask;
898 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
900 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
904 uint32_t entry_size = 1;
906 /* Initialize params and create tables */
907 struct rte_table_hash_cuckoo_params cuckoo_params = {
910 .key_offset = APP_METADATA_OFFSET(32),
913 .n_buckets = 1 << 16,
914 .f_hash = pipeline_test_hash_cuckoo,
918 table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size);
922 cuckoo_params.key_size = 0;
924 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
929 cuckoo_params.key_size = 32;
930 cuckoo_params.n_keys = 0;
932 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
937 cuckoo_params.n_keys = 1 << 24;
938 cuckoo_params.f_hash = NULL;
940 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
945 cuckoo_params.f_hash = pipeline_test_hash_cuckoo;
946 cuckoo_params.name = NULL;
948 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
953 cuckoo_params.name = "CUCKOO";
955 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
961 status = rte_table_hash_cuckoo_ops.f_free(table);
965 status = rte_table_hash_cuckoo_ops.f_free(NULL);
970 uint8_t key_cuckoo[32];
971 uint32_t *kcuckoo = (uint32_t *) &key_cuckoo;
973 memset(key_cuckoo, 0, 32);
974 kcuckoo[0] = rte_be_to_cpu_32(0xadadadad);
976 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1);
981 status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo,
982 &entry, &key_found, &entry_ptr);
986 status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry,
987 &key_found, &entry_ptr);
991 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
992 NULL, &key_found, &entry_ptr);
996 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
997 &entry, &key_found, &entry_ptr);
1001 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1002 &entry, &key_found, &entry_ptr);
1007 status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo,
1012 status = rte_table_hash_cuckoo_ops.f_delete(table, NULL,
1017 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1022 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1024 if (status != -ENOENT)
1029 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1035 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1037 expected_mask |= (uint64_t)1 << i;
1038 PREPARE_PACKET(mbufs[i], 0xadadadad);
1040 PREPARE_PACKET(mbufs[i], 0xadadadab);
1042 rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1,
1043 &result_mask, (void **)entries);
1044 if (result_mask != expected_mask)
1047 /* Free resources */
1048 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1049 rte_pktmbuf_free(mbufs[i]);
1051 status = rte_table_hash_cuckoo_ops.f_free(table);