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)); \
32 k32 = (uint32_t *) key; \
34 *signature = pipeline_test_hash(key, NULL, 0, 0); \
37 unsigned n_table_tests = RTE_DIM(table_tests);
39 /* Function prototypes */
41 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size);
43 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size);
45 struct rte_bucket_4_8 {
49 struct rte_bucket_4_8 *next;
56 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
57 uint64_t shuffles = 0xfffffffdfffbfff9ULL;
59 uint64_t shuffles = 0x0003000200010000ULL;
62 static int test_lru_update(void)
64 struct rte_bucket_4_8 b;
65 struct rte_bucket_4_8 *bucket;
72 printf("---------------------------\n");
73 printf("Testing lru_update macro...\n");
74 printf("---------------------------\n");
77 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
78 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
80 bucket->lru_list = 0x0000000100020003ULL;
83 for (j = 0; j < iterations; j++)
84 for (i = 0; i < 9; i++) {
85 uint32_t idx = i >> 1;
86 lru_update(bucket, idx);
87 pos = lru_pos(bucket);
89 printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
91 __func__, i, bucket->lru_list, i>>1, pos);
94 if (bucket->lru_list != shuffles) {
95 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
97 __func__, i, bucket->lru_list, shuffles);
100 printf("%s: output checksum of results =%d\n",
104 printf("%s: ERROR output checksum of results =%d expected %d\n",
105 __func__, poss, 126);
112 uint64_t sc_start = rte_rdtsc();
113 iterations = 100000000;
115 for (j = 0; j < iterations; j++) {
116 for (i = 0; i < 4; i++) {
117 lru_update(bucket, i);
118 pos |= bucket->lru_list;
121 uint64_t sc_end = rte_rdtsc();
123 printf("%s: output checksum of results =%llu\n",
124 __func__, (long long unsigned int)pos);
125 printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
126 __func__, sc_start, sc_end);
127 printf("\nlru_update: %lu cycles per loop iteration.\n\n",
128 (long unsigned int)((sc_end-sc_start)/(iterations*4)));
135 test_table_stub(void)
138 uint64_t expected_mask = 0, result_mask;
139 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
141 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
144 table = rte_table_stub_ops.f_create(NULL, 0, 1);
149 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
151 PREPARE_PACKET(mbufs[i], 0xadadadad);
153 PREPARE_PACKET(mbufs[i], 0xadadadab);
156 rte_table_stub_ops.f_lookup(table, mbufs, -1,
157 &result_mask, (void **)entries);
158 if (result_mask != expected_mask)
162 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
163 rte_pktmbuf_free(mbufs[i]);
169 test_table_array(void)
172 uint64_t result_mask;
173 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
175 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
180 /* Initialize params and create tables */
181 struct rte_table_array_params array_params = {
183 .offset = APP_METADATA_OFFSET(1)
186 table = rte_table_array_ops.f_create(NULL, 0, 1);
190 array_params.n_entries = 0;
192 table = rte_table_array_ops.f_create(&array_params, 0, 1);
196 array_params.n_entries = 7;
198 table = rte_table_array_ops.f_create(&array_params, 0, 1);
202 array_params.n_entries = 1 << 24;
203 array_params.offset = APP_METADATA_OFFSET(1);
205 table = rte_table_array_ops.f_create(&array_params, 0, 1);
209 array_params.offset = APP_METADATA_OFFSET(32);
211 table = rte_table_array_ops.f_create(&array_params, 0, 1);
216 status = rte_table_array_ops.f_free(table);
220 status = rte_table_array_ops.f_free(NULL);
225 struct rte_table_array_key array_key_1 = {
228 struct rte_table_array_key array_key_2 = {
234 table = rte_table_array_ops.f_create(&array_params, 0, 1);
238 status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
239 &key_found, &entry_ptr);
243 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
244 &key_found, &entry_ptr);
248 status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
249 &entry1, &key_found, &entry_ptr);
254 status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
255 &entry2, &key_found, &entry_ptr);
259 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
261 PREPARE_PACKET(mbufs[i], 10);
263 PREPARE_PACKET(mbufs[i], 20);
265 rte_table_array_ops.f_lookup(table, mbufs, -1,
266 &result_mask, (void **)entries);
268 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
269 if (i % 2 == 0 && *entries[i] != 'A')
272 if (i % 2 == 1 && *entries[i] != 'B')
276 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
277 rte_pktmbuf_free(mbufs[i]);
279 status = rte_table_array_ops.f_free(table);
288 uint64_t expected_mask = 0, result_mask;
289 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
291 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
295 uint32_t entry_size = 1;
297 /* Initialize params and create tables */
298 struct rte_table_lpm_params lpm_params = {
301 .number_tbl8s = 1 << 8,
303 .entry_unique_size = entry_size,
304 .offset = APP_METADATA_OFFSET(1)
307 table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
311 lpm_params.name = NULL;
313 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
317 lpm_params.name = "LPM";
318 lpm_params.n_rules = 0;
320 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
324 lpm_params.n_rules = 1 << 24;
325 lpm_params.offset = APP_METADATA_OFFSET(32);
326 lpm_params.entry_unique_size = 0;
328 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
332 lpm_params.entry_unique_size = entry_size + 1;
334 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
338 lpm_params.entry_unique_size = entry_size;
340 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
345 status = rte_table_lpm_ops.f_free(table);
349 status = rte_table_lpm_ops.f_free(NULL);
354 struct rte_table_lpm_key lpm_key;
355 lpm_key.ip = 0xadadadad;
357 table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
361 status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
366 status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
371 status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
377 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
383 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
389 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
395 status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
399 status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
404 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
409 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
414 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
418 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
424 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
429 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
431 expected_mask |= (uint64_t)1 << i;
432 PREPARE_PACKET(mbufs[i], 0xadadadad);
434 PREPARE_PACKET(mbufs[i], 0xadadadab);
436 rte_table_lpm_ops.f_lookup(table, mbufs, -1,
437 &result_mask, (void **)entries);
438 if (result_mask != expected_mask)
442 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
443 rte_pktmbuf_free(mbufs[i]);
445 status = rte_table_lpm_ops.f_free(table);
451 test_table_lpm_ipv6(void)
454 uint64_t expected_mask = 0, result_mask;
455 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
457 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
461 uint32_t entry_size = 1;
463 /* Initialize params and create tables */
464 struct rte_table_lpm_ipv6_params lpm_params = {
467 .number_tbl8s = 1 << 18,
468 .entry_unique_size = entry_size,
469 .offset = APP_METADATA_OFFSET(32)
472 table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
476 lpm_params.name = NULL;
478 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
482 lpm_params.name = "LPM";
483 lpm_params.n_rules = 0;
485 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
489 lpm_params.n_rules = 1 << 24;
490 lpm_params.number_tbl8s = 0;
491 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
495 lpm_params.number_tbl8s = 1 << 18;
496 lpm_params.entry_unique_size = 0;
497 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
501 lpm_params.entry_unique_size = entry_size + 1;
502 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
506 lpm_params.entry_unique_size = entry_size;
507 lpm_params.offset = APP_METADATA_OFFSET(32);
509 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
514 status = rte_table_lpm_ipv6_ops.f_free(table);
518 status = rte_table_lpm_ipv6_ops.f_free(NULL);
523 struct rte_table_lpm_ipv6_key lpm_key;
525 lpm_key.ip[0] = 0xad;
526 lpm_key.ip[1] = 0xad;
527 lpm_key.ip[2] = 0xad;
528 lpm_key.ip[3] = 0xad;
530 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
534 status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
535 &key_found, &entry_ptr);
539 status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
544 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
550 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
551 &key_found, &entry_ptr);
556 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
557 &key_found, &entry_ptr);
562 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
563 &key_found, &entry_ptr);
568 status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
573 status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
578 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
584 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
590 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
595 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
602 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
603 &key_found, &entry_ptr);
607 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
609 expected_mask |= (uint64_t)1 << i;
610 PREPARE_PACKET(mbufs[i], 0xadadadad);
612 PREPARE_PACKET(mbufs[i], 0xadadadab);
614 rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
615 &result_mask, (void **)entries);
616 if (result_mask != expected_mask)
620 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
621 rte_pktmbuf_free(mbufs[i]);
623 status = rte_table_lpm_ipv6_ops.f_free(table);
629 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
632 uint64_t expected_mask = 0, result_mask;
633 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
635 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
640 /* Initialize params and create tables */
641 struct rte_table_hash_params hash_params = {
643 .key_size = key_size,
644 .key_offset = APP_METADATA_OFFSET(32),
647 .n_buckets = 1 << 10,
648 .f_hash = pipeline_test_hash,
652 hash_params.n_keys = 0;
654 table = ops->f_create(&hash_params, 0, 1);
658 hash_params.n_keys = 1 << 10;
659 hash_params.f_hash = NULL;
661 table = ops->f_create(&hash_params, 0, 1);
665 hash_params.f_hash = pipeline_test_hash;
667 table = ops->f_create(&hash_params, 0, 1);
672 status = ops->f_free(table);
676 status = ops->f_free(NULL);
682 uint32_t *k32 = (uint32_t *) &key;
685 k32[0] = rte_be_to_cpu_32(0xadadadad);
687 table = ops->f_create(&hash_params, 0, 1);
692 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
697 status = ops->f_delete(table, &key, &key_found, NULL);
701 status = ops->f_delete(table, &key, &key_found, NULL);
707 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
711 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
713 expected_mask |= (uint64_t)1 << i;
714 PREPARE_PACKET(mbufs[i], 0xadadadad);
716 PREPARE_PACKET(mbufs[i], 0xadadadab);
718 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
719 if (result_mask != expected_mask)
723 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
724 rte_pktmbuf_free(mbufs[i]);
726 status = ops->f_free(table);
732 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
735 uint64_t expected_mask = 0, result_mask;
736 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
738 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
743 /* Initialize params and create tables */
744 struct rte_table_hash_params hash_params = {
746 .key_size = key_size,
747 .key_offset = APP_METADATA_OFFSET(32),
750 .n_buckets = 1 << 10,
751 .f_hash = pipeline_test_hash,
755 hash_params.n_keys = 0;
757 table = ops->f_create(&hash_params, 0, 1);
761 hash_params.n_keys = 1 << 10;
762 hash_params.key_offset = APP_METADATA_OFFSET(1);
764 table = ops->f_create(&hash_params, 0, 1);
768 hash_params.key_offset = APP_METADATA_OFFSET(32);
769 hash_params.f_hash = NULL;
771 table = ops->f_create(&hash_params, 0, 1);
775 hash_params.f_hash = pipeline_test_hash;
777 table = ops->f_create(&hash_params, 0, 1);
782 status = ops->f_free(table);
786 status = ops->f_free(NULL);
792 uint32_t *k32 = (uint32_t *) &key;
795 k32[0] = rte_be_to_cpu_32(0xadadadad);
797 table = ops->f_create(&hash_params, 0, 1);
802 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
807 status = ops->f_delete(table, &key, &key_found, NULL);
811 status = ops->f_delete(table, &key, &key_found, NULL);
817 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
821 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
823 expected_mask |= (uint64_t)1 << i;
824 PREPARE_PACKET(mbufs[i], 0xadadadad);
826 PREPARE_PACKET(mbufs[i], 0xadadadab);
828 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
829 if (result_mask != expected_mask)
833 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
834 rte_pktmbuf_free(mbufs[i]);
836 status = ops->f_free(table);
842 test_table_hash_lru(void)
846 status = test_table_hash_lru_generic(
847 &rte_table_hash_key8_lru_ops,
852 status = test_table_hash_lru_generic(
853 &rte_table_hash_key16_lru_ops,
858 status = test_table_hash_lru_generic(
859 &rte_table_hash_key32_lru_ops,
864 status = test_lru_update();
872 test_table_hash_ext(void)
876 status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8);
880 status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16);
884 status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32);
893 test_table_hash_cuckoo(void)
896 uint64_t expected_mask = 0, result_mask;
897 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
899 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
903 uint32_t entry_size = 1;
905 /* Initialize params and create tables */
906 struct rte_table_hash_cuckoo_params cuckoo_params = {
909 .key_offset = APP_METADATA_OFFSET(32),
912 .n_buckets = 1 << 16,
913 .f_hash = pipeline_test_hash_cuckoo,
917 table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size);
921 cuckoo_params.key_size = 0;
923 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
928 cuckoo_params.key_size = 32;
929 cuckoo_params.n_keys = 0;
931 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
936 cuckoo_params.n_keys = 1 << 24;
937 cuckoo_params.f_hash = NULL;
939 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
944 cuckoo_params.f_hash = pipeline_test_hash_cuckoo;
945 cuckoo_params.name = NULL;
947 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
952 cuckoo_params.name = "CUCKOO";
954 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
960 status = rte_table_hash_cuckoo_ops.f_free(table);
964 status = rte_table_hash_cuckoo_ops.f_free(NULL);
969 uint8_t key_cuckoo[32];
970 uint32_t *kcuckoo = (uint32_t *) &key_cuckoo;
972 memset(key_cuckoo, 0, 32);
973 kcuckoo[0] = rte_be_to_cpu_32(0xadadadad);
975 table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1);
980 status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo,
981 &entry, &key_found, &entry_ptr);
985 status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry,
986 &key_found, &entry_ptr);
990 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
991 NULL, &key_found, &entry_ptr);
995 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
996 &entry, &key_found, &entry_ptr);
1000 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1001 &entry, &key_found, &entry_ptr);
1006 status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo,
1011 status = rte_table_hash_cuckoo_ops.f_delete(table, NULL,
1016 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1021 status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1023 if (status != -ENOENT)
1028 status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1034 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1036 expected_mask |= (uint64_t)1 << i;
1037 PREPARE_PACKET(mbufs[i], 0xadadadad);
1039 PREPARE_PACKET(mbufs[i], 0xadadadab);
1041 rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1,
1042 &result_mask, (void **)entries);
1043 if (result_mask != expected_mask)
1046 /* Free resources */
1047 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1048 rte_pktmbuf_free(mbufs[i]);
1050 status = rte_table_hash_cuckoo_ops.f_free(table);