4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #ifdef RTE_LIBRTE_TABLE
37 #include <rte_byteorder.h>
38 #include <rte_table_lpm_ipv6.h>
40 #include <rte_cycles.h>
41 #include "test_table_tables.h"
42 #include "test_table.h"
44 table_test table_tests[] = {
53 #define PREPARE_PACKET(mbuf, value) do { \
54 uint32_t *k32, *signature; \
56 mbuf = rte_pktmbuf_alloc(pool); \
57 signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, 0); \
58 key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, 32); \
60 k32 = (uint32_t *) key; \
62 *signature = pipeline_test_hash(key, 0, 0); \
65 unsigned n_table_tests = RTE_DIM(table_tests);
67 /* Function prototypes */
69 test_table_hash_lru_generic(struct rte_table_ops *ops);
71 test_table_hash_ext_generic(struct rte_table_ops *ops);
73 struct rte_bucket_4_8 {
77 struct rte_bucket_4_8 *next;
84 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
85 uint64_t shuffles = 0xfffffffdfffbfff9ULL;
87 uint64_t shuffles = 0x0003000200010000ULL;
90 static int test_lru_update(void)
92 struct rte_bucket_4_8 b;
93 struct rte_bucket_4_8 *bucket;
100 printf("---------------------------\n");
101 printf("Testing lru_update macro...\n");
102 printf("---------------------------\n");
105 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
106 bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
108 bucket->lru_list = 0x0000000100020003ULL;
111 for (j = 0; j < iterations; j++)
112 for (i = 0; i < 9; i++) {
113 uint32_t idx = i >> 1;
114 lru_update(bucket, idx);
115 pos = lru_pos(bucket);
117 printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
119 __func__, i, bucket->lru_list, i>>1, pos);
122 if (bucket->lru_list != shuffles) {
123 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
125 __func__, i, bucket->lru_list, shuffles);
128 printf("%s: output checksum of results =%d\n",
132 printf("%s: ERROR output checksum of results =%d expected %d\n",
133 __func__, poss, 126);
140 uint64_t sc_start = rte_rdtsc();
141 iterations = 100000000;
143 for (j = 0; j < iterations; j++) {
144 for (i = 0; i < 4; i++) {
145 lru_update(bucket, i);
146 pos |= bucket->lru_list;
149 uint64_t sc_end = rte_rdtsc();
151 printf("%s: output checksum of results =%llu\n",
152 __func__, (long long unsigned int)pos);
153 printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
154 __func__, sc_start, sc_end);
155 printf("\nlru_update: %lu cycles per loop iteration.\n\n",
156 (long unsigned int)((sc_end-sc_start)/(iterations*4)));
163 test_table_stub(void)
166 uint64_t expected_mask = 0, result_mask;
167 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
169 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
172 table = rte_table_stub_ops.f_create(NULL, 0, 1);
177 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
179 PREPARE_PACKET(mbufs[i], 0xadadadad);
181 PREPARE_PACKET(mbufs[i], 0xadadadab);
184 rte_table_stub_ops.f_lookup(table, mbufs, -1,
185 &result_mask, (void **)entries);
186 if (result_mask != expected_mask)
190 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
191 rte_pktmbuf_free(mbufs[i]);
197 test_table_array(void)
200 uint64_t result_mask;
201 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
203 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
209 struct rte_table_array_params array_params;
211 table = rte_table_array_ops.f_create(NULL, 0, 1);
215 array_params.n_entries = 0;
217 table = rte_table_array_ops.f_create(&array_params, 0, 1);
221 array_params.n_entries = 7;
223 table = rte_table_array_ops.f_create(&array_params, 0, 1);
227 array_params.n_entries = 1 << 24;
228 array_params.offset = 1;
230 table = rte_table_array_ops.f_create(&array_params, 0, 1);
234 array_params.offset = 32;
236 table = rte_table_array_ops.f_create(&array_params, 0, 1);
241 status = rte_table_array_ops.f_free(table);
245 status = rte_table_array_ops.f_free(NULL);
250 struct rte_table_array_key array_key_1 = {
253 struct rte_table_array_key array_key_2 = {
259 table = rte_table_array_ops.f_create(&array_params, 0, 1);
263 status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
264 &key_found, &entry_ptr);
268 status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
269 &key_found, &entry_ptr);
273 status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
274 &entry1, &key_found, &entry_ptr);
279 status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
280 &entry2, &key_found, &entry_ptr);
284 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
286 PREPARE_PACKET(mbufs[i], 10);
288 PREPARE_PACKET(mbufs[i], 20);
290 rte_table_array_ops.f_lookup(table, mbufs, -1,
291 &result_mask, (void **)entries);
293 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
294 if (i % 2 == 0 && *entries[i] != 'A')
297 if (i % 2 == 1 && *entries[i] != 'B')
301 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
302 rte_pktmbuf_free(mbufs[i]);
304 status = rte_table_array_ops.f_free(table);
313 uint64_t expected_mask = 0, result_mask;
314 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
316 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
320 uint32_t entry_size = 1;
323 struct rte_table_lpm_params lpm_params;
325 table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
329 lpm_params.n_rules = 0;
331 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
335 lpm_params.n_rules = 1 << 24;
336 lpm_params.offset = 1;
338 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
342 lpm_params.offset = 32;
343 lpm_params.entry_unique_size = 0;
345 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
349 lpm_params.entry_unique_size = entry_size + 1;
351 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
355 lpm_params.entry_unique_size = entry_size;
357 table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
362 status = rte_table_lpm_ops.f_free(table);
366 status = rte_table_lpm_ops.f_free(NULL);
371 struct rte_table_lpm_key lpm_key;
372 lpm_key.ip = 0xadadadad;
374 table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
378 status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
383 status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
388 status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
394 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
400 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
406 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
412 status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
416 status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
421 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
426 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
431 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
435 status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
441 status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
446 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
448 expected_mask |= (uint64_t)1 << i;
449 PREPARE_PACKET(mbufs[i], 0xadadadad);
451 PREPARE_PACKET(mbufs[i], 0xadadadab);
453 rte_table_lpm_ops.f_lookup(table, mbufs, -1,
454 &result_mask, (void **)entries);
455 if (result_mask != expected_mask)
459 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
460 rte_pktmbuf_free(mbufs[i]);
462 status = rte_table_lpm_ops.f_free(table);
468 test_table_lpm_ipv6(void)
471 uint64_t expected_mask = 0, result_mask;
472 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
474 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
478 uint32_t entry_size = 1;
481 struct rte_table_lpm_ipv6_params lpm_params;
483 table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
487 lpm_params.n_rules = 0;
489 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
493 lpm_params.n_rules = 1 << 24;
494 lpm_params.number_tbl8s = 0;
495 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
499 lpm_params.number_tbl8s = 1 << 21;
500 lpm_params.entry_unique_size = 0;
501 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
505 lpm_params.entry_unique_size = entry_size + 1;
506 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
510 lpm_params.entry_unique_size = entry_size;
511 lpm_params.offset = 32;
513 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
518 status = rte_table_lpm_ipv6_ops.f_free(table);
522 status = rte_table_lpm_ipv6_ops.f_free(NULL);
527 struct rte_table_lpm_ipv6_key lpm_key;
529 lpm_key.ip[0] = 0xad;
530 lpm_key.ip[1] = 0xad;
531 lpm_key.ip[2] = 0xad;
532 lpm_key.ip[3] = 0xad;
534 table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
538 status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
539 &key_found, &entry_ptr);
543 status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
548 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
554 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
555 &key_found, &entry_ptr);
560 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
561 &key_found, &entry_ptr);
566 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
567 &key_found, &entry_ptr);
572 status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
577 status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
582 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
588 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
594 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
599 status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
606 status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
607 &key_found, &entry_ptr);
611 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
613 expected_mask |= (uint64_t)1 << i;
614 PREPARE_PACKET(mbufs[i], 0xadadadad);
616 PREPARE_PACKET(mbufs[i], 0xadadadab);
618 rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
619 &result_mask, (void **)entries);
620 if (result_mask != expected_mask)
624 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
625 rte_pktmbuf_free(mbufs[i]);
627 status = rte_table_lpm_ipv6_ops.f_free(table);
633 test_table_hash_lru_generic(struct rte_table_ops *ops)
636 uint64_t expected_mask = 0, result_mask;
637 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
639 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
645 struct rte_table_hash_key8_lru_params hash_params;
647 hash_params.n_entries = 0;
649 table = ops->f_create(&hash_params, 0, 1);
653 hash_params.n_entries = 1 << 10;
654 hash_params.signature_offset = 1;
656 table = ops->f_create(&hash_params, 0, 1);
660 hash_params.signature_offset = 0;
661 hash_params.key_offset = 1;
663 table = ops->f_create(&hash_params, 0, 1);
667 hash_params.key_offset = 32;
668 hash_params.f_hash = NULL;
670 table = ops->f_create(&hash_params, 0, 1);
674 hash_params.f_hash = pipeline_test_hash;
676 table = ops->f_create(&hash_params, 0, 1);
681 status = ops->f_free(table);
685 status = ops->f_free(NULL);
691 uint32_t *k32 = (uint32_t *) &key;
694 k32[0] = rte_be_to_cpu_32(0xadadadad);
696 table = ops->f_create(&hash_params, 0, 1);
701 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
706 status = ops->f_delete(table, &key, &key_found, NULL);
710 status = ops->f_delete(table, &key, &key_found, NULL);
716 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
720 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
722 expected_mask |= (uint64_t)1 << i;
723 PREPARE_PACKET(mbufs[i], 0xadadadad);
725 PREPARE_PACKET(mbufs[i], 0xadadadab);
727 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
728 if (result_mask != expected_mask)
732 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
733 rte_pktmbuf_free(mbufs[i]);
735 status = ops->f_free(table);
741 test_table_hash_ext_generic(struct rte_table_ops *ops)
744 uint64_t expected_mask = 0, result_mask;
745 struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
747 char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
753 struct rte_table_hash_key8_ext_params hash_params;
755 hash_params.n_entries = 0;
757 table = ops->f_create(&hash_params, 0, 1);
761 hash_params.n_entries = 1 << 10;
762 hash_params.n_entries_ext = 0;
763 table = ops->f_create(&hash_params, 0, 1);
767 hash_params.n_entries_ext = 1 << 4;
768 hash_params.signature_offset = 1;
769 table = ops->f_create(&hash_params, 0, 1);
773 hash_params.signature_offset = 0;
774 hash_params.key_offset = 1;
776 table = ops->f_create(&hash_params, 0, 1);
780 hash_params.key_offset = 32;
781 hash_params.f_hash = NULL;
783 table = ops->f_create(&hash_params, 0, 1);
787 hash_params.f_hash = pipeline_test_hash;
789 table = ops->f_create(&hash_params, 0, 1);
794 status = ops->f_free(table);
798 status = ops->f_free(NULL);
804 uint32_t *k32 = (uint32_t *) &key;
807 k32[0] = rte_be_to_cpu_32(0xadadadad);
809 table = ops->f_create(&hash_params, 0, 1);
814 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
819 status = ops->f_delete(table, &key, &key_found, NULL);
823 status = ops->f_delete(table, &key, &key_found, NULL);
829 status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
833 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
835 expected_mask |= (uint64_t)1 << i;
836 PREPARE_PACKET(mbufs[i], 0xadadadad);
838 PREPARE_PACKET(mbufs[i], 0xadadadab);
840 ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
841 if (result_mask != expected_mask)
845 for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
846 rte_pktmbuf_free(mbufs[i]);
848 status = ops->f_free(table);
854 test_table_hash_lru(void)
858 status = test_table_hash_lru_generic(&rte_table_hash_key8_lru_ops);
862 status = test_table_hash_lru_generic(
863 &rte_table_hash_key8_lru_dosig_ops);
867 status = test_table_hash_lru_generic(&rte_table_hash_key16_lru_ops);
871 status = test_table_hash_lru_generic(&rte_table_hash_key32_lru_ops);
875 status = test_lru_update();
883 test_table_hash_ext(void)
887 status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops);
891 status = test_table_hash_ext_generic(
892 &rte_table_hash_key8_ext_dosig_ops);
896 status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops);
900 status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops);