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.
39 #include <rte_memory.h>
43 #include "test_lpm6_routes.h"
45 #define TEST_LPM_ASSERT(cond) do { \
47 printf("Error at line %d: \n", __LINE__); \
52 typedef int32_t (* rte_lpm6_test)(void);
54 static int32_t test0(void);
55 static int32_t test1(void);
56 static int32_t test2(void);
57 static int32_t test3(void);
58 static int32_t test4(void);
59 static int32_t test5(void);
60 static int32_t test6(void);
61 static int32_t test7(void);
62 static int32_t test8(void);
63 static int32_t test9(void);
64 static int32_t test10(void);
65 static int32_t test11(void);
66 static int32_t test12(void);
67 static int32_t test13(void);
68 static int32_t test14(void);
69 static int32_t test15(void);
70 static int32_t test16(void);
71 static int32_t test17(void);
72 static int32_t test18(void);
73 static int32_t test19(void);
74 static int32_t test20(void);
75 static int32_t test21(void);
76 static int32_t test22(void);
77 static int32_t test23(void);
78 static int32_t test24(void);
79 static int32_t test25(void);
80 static int32_t test26(void);
81 static int32_t test27(void);
83 rte_lpm6_test tests6[] = {
115 #define NUM_LPM6_TESTS (sizeof(tests6)/sizeof(tests6[0]))
116 #define RTE_LPM6_TBL24_NUM_ENTRIES (1 << 24)
117 #define RTE_LPM6_LOOKUP_SUCCESS 0x04000000
118 #define MAX_DEPTH 128
119 #define MAX_RULES 1000000
120 #define NUMBER_TBL8S (1 << 16)
121 #define MAX_NUM_TBL8S (1 << 21)
125 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
126 uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
127 uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
149 * Check that rte_lpm6_create fails gracefully for incorrect user input
155 struct rte_lpm6 *lpm = NULL;
156 struct rte_lpm6_config config;
158 config.max_rules = MAX_RULES;
159 config.number_tbl8s = NUMBER_TBL8S;
162 /* rte_lpm6_create: lpm name == NULL */
163 lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
164 TEST_LPM_ASSERT(lpm == NULL);
166 /* rte_lpm6_create: max_rules = 0 */
167 /* Note: __func__ inserts the function name, in this case "test0". */
168 config.max_rules = 0;
169 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
170 TEST_LPM_ASSERT(lpm == NULL);
172 /* socket_id < -1 is invalid */
173 config.max_rules = MAX_RULES;
174 lpm = rte_lpm6_create(__func__, -2, &config);
175 TEST_LPM_ASSERT(lpm == NULL);
177 /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
178 config.number_tbl8s = MAX_NUM_TBL8S + 1;
179 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
180 TEST_LPM_ASSERT(lpm == NULL);
182 /* rte_lpm6_create: config = NULL */
183 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
184 TEST_LPM_ASSERT(lpm == NULL);
190 * Creates two different LPM tables. Tries to create a third one with the same
191 * name as the first one and expects the create function to return the same
197 struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
198 struct rte_lpm6_config config;
200 config.max_rules = MAX_RULES;
201 config.number_tbl8s = NUMBER_TBL8S;
204 /* rte_lpm6_create: lpm name == LPM1 */
205 lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
206 TEST_LPM_ASSERT(lpm1 != NULL);
208 /* rte_lpm6_create: lpm name == LPM2 */
209 lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
210 TEST_LPM_ASSERT(lpm2 != NULL);
212 /* rte_lpm6_create: lpm name == LPM2 */
213 lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
214 TEST_LPM_ASSERT(lpm3 == NULL);
223 * Create lpm table then delete lpm table 100 times
224 * Use a slightly different rules size each time
229 struct rte_lpm6 *lpm = NULL;
230 struct rte_lpm6_config config;
233 config.number_tbl8s = NUMBER_TBL8S;
236 /* rte_lpm6_free: Free NULL */
237 for (i = 0; i < 100; i++) {
238 config.max_rules = MAX_RULES - i;
239 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
240 TEST_LPM_ASSERT(lpm != NULL);
245 /* Can not test free so return success */
250 * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
251 * therefore it is impossible to check for failure but this test is added to
252 * increase function coverage metrics and to validate that freeing null does
258 struct rte_lpm6 *lpm = NULL;
259 struct rte_lpm6_config config;
261 config.max_rules = MAX_RULES;
262 config.number_tbl8s = NUMBER_TBL8S;
265 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
266 TEST_LPM_ASSERT(lpm != NULL);
274 * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
279 struct rte_lpm6 *lpm = NULL;
280 struct rte_lpm6_config config;
282 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
283 uint8_t depth = 24, next_hop = 100;
286 config.max_rules = MAX_RULES;
287 config.number_tbl8s = NUMBER_TBL8S;
290 /* rte_lpm6_add: lpm == NULL */
291 status = rte_lpm6_add(NULL, ip, depth, next_hop);
292 TEST_LPM_ASSERT(status < 0);
294 /*Create vaild lpm to use in rest of test. */
295 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
296 TEST_LPM_ASSERT(lpm != NULL);
298 /* rte_lpm6_add: depth < 1 */
299 status = rte_lpm6_add(lpm, ip, 0, next_hop);
300 TEST_LPM_ASSERT(status < 0);
302 /* rte_lpm6_add: depth > MAX_DEPTH */
303 status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
304 TEST_LPM_ASSERT(status < 0);
312 * Check that rte_lpm6_delete fails gracefully for incorrect user input
318 struct rte_lpm6 *lpm = NULL;
319 struct rte_lpm6_config config;
320 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
324 config.max_rules = MAX_RULES;
325 config.number_tbl8s = NUMBER_TBL8S;
328 /* rte_lpm_delete: lpm == NULL */
329 status = rte_lpm6_delete(NULL, ip, depth);
330 TEST_LPM_ASSERT(status < 0);
332 /*Create vaild lpm to use in rest of test. */
333 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
334 TEST_LPM_ASSERT(lpm != NULL);
336 /* rte_lpm_delete: depth < 1 */
337 status = rte_lpm6_delete(lpm, ip, 0);
338 TEST_LPM_ASSERT(status < 0);
340 /* rte_lpm_delete: depth > MAX_DEPTH */
341 status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
342 TEST_LPM_ASSERT(status < 0);
350 * Check that rte_lpm6_lookup fails gracefully for incorrect user input
356 struct rte_lpm6 *lpm = NULL;
357 struct rte_lpm6_config config;
358 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
359 uint8_t next_hop_return = 0;
362 config.max_rules = MAX_RULES;
363 config.number_tbl8s = NUMBER_TBL8S;
366 /* rte_lpm6_lookup: lpm == NULL */
367 status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
368 TEST_LPM_ASSERT(status < 0);
370 /*Create vaild lpm to use in rest of test. */
371 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
372 TEST_LPM_ASSERT(lpm != NULL);
374 /* rte_lpm6_lookup: ip = NULL */
375 status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
376 TEST_LPM_ASSERT(status < 0);
378 /* rte_lpm6_lookup: next_hop = NULL */
379 status = rte_lpm6_lookup(lpm, ip, NULL);
380 TEST_LPM_ASSERT(status < 0);
388 * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
394 struct rte_lpm6 *lpm = NULL;
395 struct rte_lpm6_config config;
397 int16_t next_hop_return[10];
400 config.max_rules = MAX_RULES;
401 config.number_tbl8s = NUMBER_TBL8S;
404 /* rte_lpm6_lookup: lpm == NULL */
405 status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
406 TEST_LPM_ASSERT(status < 0);
408 /*Create vaild lpm to use in rest of test. */
409 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
410 TEST_LPM_ASSERT(lpm != NULL);
412 /* rte_lpm6_lookup: ip = NULL */
413 status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
414 TEST_LPM_ASSERT(status < 0);
416 /* rte_lpm6_lookup: next_hop = NULL */
417 status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
418 TEST_LPM_ASSERT(status < 0);
426 * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
432 struct rte_lpm6 *lpm = NULL;
433 struct rte_lpm6_config config;
438 config.max_rules = MAX_RULES;
439 config.number_tbl8s = NUMBER_TBL8S;
442 /* rte_lpm6_delete: lpm == NULL */
443 status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
444 TEST_LPM_ASSERT(status < 0);
446 /*Create vaild lpm to use in rest of test. */
447 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
448 TEST_LPM_ASSERT(lpm != NULL);
450 /* rte_lpm6_delete: ip = NULL */
451 status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
452 TEST_LPM_ASSERT(status < 0);
454 /* rte_lpm6_delete: next_hop = NULL */
455 status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
456 TEST_LPM_ASSERT(status < 0);
464 * Call add, lookup and delete for a single rule with depth < 24.
465 * Check all the combinations for the first three bytes that result in a hit.
466 * Delete the rule and check that the same test returs a miss.
471 struct rte_lpm6 *lpm = NULL;
472 struct rte_lpm6_config config;
473 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
474 uint8_t depth = 16, next_hop_add = 100, next_hop_return = 0;
478 config.max_rules = MAX_RULES;
479 config.number_tbl8s = NUMBER_TBL8S;
482 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
483 TEST_LPM_ASSERT(lpm != NULL);
485 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
486 TEST_LPM_ASSERT(status == 0);
488 for (i = 0; i < UINT8_MAX; i++) {
490 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
491 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
494 status = rte_lpm6_delete(lpm, ip, depth);
495 TEST_LPM_ASSERT(status == 0);
497 for (i = 0; i < UINT8_MAX; i++) {
499 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
500 TEST_LPM_ASSERT(status == -ENOENT);
509 * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
510 * another one and expects success.
515 struct rte_lpm6 *lpm = NULL;
516 struct rte_lpm6_config config;
517 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
518 uint8_t depth, next_hop_add = 100;
522 config.max_rules = 127;
523 config.number_tbl8s = NUMBER_TBL8S;
526 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
527 TEST_LPM_ASSERT(lpm != NULL);
529 for (i = 1; i < 128; i++) {
531 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
532 TEST_LPM_ASSERT(status == 0);
536 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
537 TEST_LPM_ASSERT(status == -ENOSPC);
540 status = rte_lpm6_delete(lpm, ip, depth);
541 TEST_LPM_ASSERT(status == 0);
544 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
545 TEST_LPM_ASSERT(status == 0);
553 * Creates an LPM table with a small number of tbl8s and exhaust them in the
554 * middle of the process of creating a rule.
559 struct rte_lpm6 *lpm = NULL;
560 struct rte_lpm6_config config;
561 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
562 uint8_t depth, next_hop_add = 100;
565 config.max_rules = MAX_RULES;
566 config.number_tbl8s = 16;
569 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
570 TEST_LPM_ASSERT(lpm != NULL);
573 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
574 TEST_LPM_ASSERT(status == 0);
578 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
579 TEST_LPM_ASSERT(status == 0);
581 status = rte_lpm6_delete(lpm, ip, depth);
582 TEST_LPM_ASSERT(status == 0);
585 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
586 TEST_LPM_ASSERT(status == 0);
588 status = rte_lpm6_delete(lpm, ip, depth);
589 TEST_LPM_ASSERT(status == 0);
592 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
593 TEST_LPM_ASSERT(status == 0);
595 status = rte_lpm6_delete(lpm, ip, depth);
596 TEST_LPM_ASSERT(status == 0);
599 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
600 TEST_LPM_ASSERT(status == -ENOSPC);
603 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
604 TEST_LPM_ASSERT(status == 0);
612 * Creates an LPM table with a small number of tbl8s and exhaust them in the
613 * middle of the process of adding a rule when there is already an existing rule
614 * in that position and needs to be extended.
619 struct rte_lpm6 *lpm = NULL;
620 struct rte_lpm6_config config;
621 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
622 uint8_t depth, next_hop_add = 100;
625 config.max_rules = MAX_RULES;
626 config.number_tbl8s = 16;
629 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
630 TEST_LPM_ASSERT(lpm != NULL);
633 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
634 TEST_LPM_ASSERT(status == 0);
638 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
639 TEST_LPM_ASSERT(status == 0);
642 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
643 TEST_LPM_ASSERT(status == -ENOSPC);
651 * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
652 * Delete one of the rules and tries to add the third one again.
657 struct rte_lpm6 *lpm = NULL;
658 struct rte_lpm6_config config;
659 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
660 uint8_t depth, next_hop_add = 100;
663 config.max_rules = 2;
664 config.number_tbl8s = NUMBER_TBL8S;
667 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
668 TEST_LPM_ASSERT(lpm != NULL);
671 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
672 TEST_LPM_ASSERT(status == 0);
675 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
676 TEST_LPM_ASSERT(status == 0);
679 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
680 TEST_LPM_ASSERT(status == -ENOSPC);
683 status = rte_lpm6_delete(lpm, ip, depth);
684 TEST_LPM_ASSERT(status == 0);
687 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
688 TEST_LPM_ASSERT(status == 0);
696 * Add 2^16 routes with different first 16 bits and depth 25.
697 * Add one more route with the same depth and check that results in a failure.
698 * After that delete the last rule and create the one that was attempted to be
699 * created. This checks tbl8 exhaustion.
704 struct rte_lpm6 *lpm = NULL;
705 struct rte_lpm6_config config;
706 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
707 uint8_t depth = 25, next_hop_add = 100;
711 config.max_rules = MAX_RULES;
712 config.number_tbl8s = NUMBER_TBL8S;
715 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
716 TEST_LPM_ASSERT(lpm != NULL);
718 for (i = 0; i < 256; i++) {
720 for (j = 0; j < 256; j++) {
722 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
723 TEST_LPM_ASSERT(status == 0);
730 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
731 TEST_LPM_ASSERT(status == -ENOSPC);
736 status = rte_lpm6_delete(lpm, ip, depth);
737 TEST_LPM_ASSERT(status == 0);
742 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
743 TEST_LPM_ASSERT(status == 0);
751 * Call add, lookup and delete for a single rule with depth = 24
756 struct rte_lpm6 *lpm = NULL;
757 struct rte_lpm6_config config;
758 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
759 uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0;
762 config.max_rules = MAX_RULES;
763 config.number_tbl8s = NUMBER_TBL8S;
766 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
767 TEST_LPM_ASSERT(lpm != NULL);
769 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
770 TEST_LPM_ASSERT(status == 0);
772 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
773 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
775 status = rte_lpm6_delete(lpm, ip, depth);
776 TEST_LPM_ASSERT(status == 0);
778 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
779 TEST_LPM_ASSERT(status == -ENOENT);
787 * Call add, lookup and delete for a single rule with depth > 24
792 struct rte_lpm6 *lpm = NULL;
793 struct rte_lpm6_config config;
794 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
795 uint8_t depth = 128, next_hop_add = 100, next_hop_return = 0;
798 config.max_rules = MAX_RULES;
799 config.number_tbl8s = NUMBER_TBL8S;
802 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
803 TEST_LPM_ASSERT(lpm != NULL);
805 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
806 TEST_LPM_ASSERT(status == 0);
808 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
809 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
811 status = rte_lpm6_delete(lpm, ip, depth);
812 TEST_LPM_ASSERT(status == 0);
814 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
815 TEST_LPM_ASSERT(status == -ENOENT);
823 * Use rte_lpm6_add to add rules which effect only the second half of the lpm
824 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
825 * depth. Check lookup hit for on every add and check for lookup miss on the
826 * first half of the lpm table after each add. Finally delete all rules going
827 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
828 * delete. The lookup should return the next_hop_add value related to the
829 * previous depth value (i.e. depth -1).
834 struct rte_lpm6 *lpm = NULL;
835 struct rte_lpm6_config config;
836 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
837 255,255,255,255,255,255,255};
838 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
839 uint8_t depth, next_hop_add, next_hop_return;
842 config.max_rules = MAX_RULES;
843 config.number_tbl8s = NUMBER_TBL8S;
846 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
847 TEST_LPM_ASSERT(lpm != NULL);
849 /* Loop with rte_lpm6_add. */
850 for (depth = 1; depth <= 128; depth++) {
851 /* Let the next_hop_add value = depth. Just for change. */
852 next_hop_add = depth;
854 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
855 TEST_LPM_ASSERT(status == 0);
857 /* Check IP in first half of tbl24 which should be empty. */
858 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
859 TEST_LPM_ASSERT(status == -ENOENT);
861 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
862 TEST_LPM_ASSERT((status == 0) &&
863 (next_hop_return == next_hop_add));
866 /* Loop with rte_lpm6_delete. */
867 for (depth = 128; depth >= 1; depth--) {
868 next_hop_add = (uint8_t) (depth - 1);
870 status = rte_lpm6_delete(lpm, ip2, depth);
871 TEST_LPM_ASSERT(status == 0);
873 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
876 TEST_LPM_ASSERT((status == 0) &&
877 (next_hop_return == next_hop_add));
880 TEST_LPM_ASSERT(status == -ENOENT);
883 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
884 TEST_LPM_ASSERT(status == -ENOENT);
893 * - Add & lookup to hit invalid TBL24 entry
894 * - Add & lookup to hit valid TBL24 entry not extended
895 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
896 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
901 struct rte_lpm6 *lpm = NULL;
902 struct rte_lpm6_config config;
903 uint8_t ip[16], ip_1[16], ip_2[16];
904 uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1,
905 next_hop_add_2, next_hop_return;
908 config.max_rules = MAX_RULES;
909 config.number_tbl8s = NUMBER_TBL8S;
912 /* Add & lookup to hit invalid TBL24 entry */
913 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
917 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
918 TEST_LPM_ASSERT(lpm != NULL);
920 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
921 TEST_LPM_ASSERT(status == 0);
923 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
924 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
926 status = rte_lpm6_delete(lpm, ip, depth);
927 TEST_LPM_ASSERT(status == 0);
929 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
930 TEST_LPM_ASSERT(status == -ENOENT);
932 rte_lpm6_delete_all(lpm);
934 /* Add & lookup to hit valid TBL24 entry not extended */
935 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
939 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
940 TEST_LPM_ASSERT(status == 0);
942 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
943 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
948 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
949 TEST_LPM_ASSERT(status == 0);
951 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
952 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
956 status = rte_lpm6_delete(lpm, ip, depth);
957 TEST_LPM_ASSERT(status == 0);
961 status = rte_lpm6_delete(lpm, ip, depth);
962 TEST_LPM_ASSERT(status == 0);
964 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
965 TEST_LPM_ASSERT(status == -ENOENT);
967 rte_lpm6_delete_all(lpm);
969 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
972 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
976 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
977 TEST_LPM_ASSERT(status == 0);
979 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
980 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
982 IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
986 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
987 TEST_LPM_ASSERT(status == 0);
989 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
990 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
992 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
996 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
997 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
999 status = rte_lpm6_delete(lpm, ip, depth);
1000 TEST_LPM_ASSERT(status == 0);
1002 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1003 TEST_LPM_ASSERT(status == -ENOENT);
1005 rte_lpm6_delete_all(lpm);
1007 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
1010 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1012 next_hop_add_1 = 101;
1014 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1016 next_hop_add_2 = 102;
1018 next_hop_return = 0;
1020 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
1021 TEST_LPM_ASSERT(status == 0);
1023 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1024 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1026 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1027 TEST_LPM_ASSERT(status == 0);
1029 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1030 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1032 status = rte_lpm6_delete(lpm, ip_2, depth_2);
1033 TEST_LPM_ASSERT(status == 0);
1035 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1036 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1038 status = rte_lpm6_delete(lpm, ip_1, depth_1);
1039 TEST_LPM_ASSERT(status == 0);
1041 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1042 TEST_LPM_ASSERT(status == -ENOENT);
1050 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1052 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1053 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1055 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1056 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1057 * - Delete a rule that is not present in the TBL24 & lookup
1058 * - Delete a rule that is not present in the TBL8 & lookup
1063 struct rte_lpm6 *lpm = NULL;
1064 struct rte_lpm6_config config;
1066 uint8_t depth, next_hop_add, next_hop_return;
1069 config.max_rules = MAX_RULES;
1070 config.number_tbl8s = NUMBER_TBL8S;
1073 /* Add rule that covers a TBL24 range previously invalid & lookup
1074 * (& delete & lookup)
1076 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1077 TEST_LPM_ASSERT(lpm != NULL);
1079 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1083 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1084 TEST_LPM_ASSERT(status == 0);
1086 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1087 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1089 status = rte_lpm6_delete(lpm, ip, depth);
1090 TEST_LPM_ASSERT(status == 0);
1092 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1093 TEST_LPM_ASSERT(status == -ENOENT);
1095 rte_lpm6_delete_all(lpm);
1097 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1101 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1102 TEST_LPM_ASSERT(status == 0);
1104 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1105 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1107 status = rte_lpm6_delete(lpm, ip, depth);
1108 TEST_LPM_ASSERT(status == 0);
1110 rte_lpm6_delete_all(lpm);
1113 * Add rule that extends a TBL24 valid entry & lookup for both rules
1114 * (& delete & lookup)
1117 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1121 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1122 TEST_LPM_ASSERT(status == 0);
1124 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1128 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1129 TEST_LPM_ASSERT(status == 0);
1131 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1132 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1134 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1137 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1138 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1140 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1143 status = rte_lpm6_delete(lpm, ip, depth);
1144 TEST_LPM_ASSERT(status == 0);
1146 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1147 TEST_LPM_ASSERT(status == -ENOENT);
1149 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1152 status = rte_lpm6_delete(lpm, ip, depth);
1153 TEST_LPM_ASSERT(status == 0);
1155 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1156 TEST_LPM_ASSERT(status == -ENOENT);
1158 rte_lpm6_delete_all(lpm);
1161 * Add rule that updates the next hop in TBL24 & lookup
1162 * (& delete & lookup)
1165 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1169 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1170 TEST_LPM_ASSERT(status == 0);
1172 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1173 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1177 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1178 TEST_LPM_ASSERT(status == 0);
1180 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1181 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1183 status = rte_lpm6_delete(lpm, ip, depth);
1184 TEST_LPM_ASSERT(status == 0);
1186 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1187 TEST_LPM_ASSERT(status == -ENOENT);
1189 rte_lpm6_delete_all(lpm);
1192 * Add rule that updates the next hop in TBL8 & lookup
1193 * (& delete & lookup)
1196 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1200 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1201 TEST_LPM_ASSERT(status == 0);
1203 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1204 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1208 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1209 TEST_LPM_ASSERT(status == 0);
1211 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1212 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1214 status = rte_lpm6_delete(lpm, ip, depth);
1215 TEST_LPM_ASSERT(status == 0);
1217 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1218 TEST_LPM_ASSERT(status == -ENOENT);
1220 rte_lpm6_delete_all(lpm);
1222 /* Delete a rule that is not present in the TBL24 & lookup */
1224 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1228 status = rte_lpm6_delete(lpm, ip, depth);
1229 TEST_LPM_ASSERT(status < 0);
1231 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1232 TEST_LPM_ASSERT(status == -ENOENT);
1234 rte_lpm6_delete_all(lpm);
1236 /* Delete a rule that is not present in the TBL8 & lookup */
1238 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1242 status = rte_lpm6_delete(lpm, ip, depth);
1243 TEST_LPM_ASSERT(status < 0);
1245 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1246 TEST_LPM_ASSERT(status == -ENOENT);
1254 * Add two rules, lookup to hit the more specific one, lookup to hit the less
1255 * specific one delete the less specific rule and lookup previous values again;
1256 * add a more specific rule than the existing rule, lookup again
1261 struct rte_lpm6 *lpm = NULL;
1262 struct rte_lpm6_config config;
1264 uint8_t depth, next_hop_add, next_hop_return;
1267 config.max_rules = MAX_RULES;
1268 config.number_tbl8s = NUMBER_TBL8S;
1271 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1272 TEST_LPM_ASSERT(lpm != NULL);
1274 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1278 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1279 TEST_LPM_ASSERT(status == 0);
1281 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1285 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1286 TEST_LPM_ASSERT(status == 0);
1288 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1289 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1291 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1294 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1295 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1297 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1300 status = rte_lpm6_delete(lpm, ip, depth);
1301 TEST_LPM_ASSERT(status == 0);
1303 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1304 TEST_LPM_ASSERT(status == -ENOENT);
1306 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1309 status = rte_lpm6_delete(lpm, ip, depth);
1310 TEST_LPM_ASSERT(status == 0);
1312 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1313 TEST_LPM_ASSERT(status == -ENOENT);
1321 * Adds 3 rules and look them up through the lookup_bulk function.
1322 * Includes in the lookup a fourth IP address that won't match
1323 * and checks that the result is as expected.
1328 struct rte_lpm6 *lpm = NULL;
1329 struct rte_lpm6_config config;
1330 uint8_t ip_batch[4][16];
1331 uint8_t depth, next_hop_add;
1332 int16_t next_hop_return[4];
1335 config.max_rules = MAX_RULES;
1336 config.number_tbl8s = NUMBER_TBL8S;
1339 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1340 TEST_LPM_ASSERT(lpm != NULL);
1342 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1346 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1347 TEST_LPM_ASSERT(status == 0);
1349 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1353 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1354 TEST_LPM_ASSERT(status == 0);
1356 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1360 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1361 TEST_LPM_ASSERT(status == 0);
1363 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1365 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1366 next_hop_return, 4);
1367 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1368 && next_hop_return[1] == 101 && next_hop_return[2] == 102
1369 && next_hop_return[3] == -1);
1377 * Adds 5 rules and look them up.
1378 * Use the delete_bulk function to delete two of them. Lookup again.
1379 * Use the delete_bulk function to delete one more. Lookup again.
1380 * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1381 * Use the delete_bulk function to delete the remaining one. Lookup again.
1386 struct rte_lpm6 *lpm = NULL;
1387 struct rte_lpm6_config config;
1388 uint8_t ip_batch[5][16];
1389 uint8_t depth[5], next_hop_add;
1390 int16_t next_hop_return[5];
1393 config.max_rules = MAX_RULES;
1394 config.number_tbl8s = NUMBER_TBL8S;
1397 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1398 TEST_LPM_ASSERT(lpm != NULL);
1400 /* Adds 5 rules and look them up */
1402 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1406 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1407 TEST_LPM_ASSERT(status == 0);
1409 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1413 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1414 TEST_LPM_ASSERT(status == 0);
1416 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1420 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1421 TEST_LPM_ASSERT(status == 0);
1423 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1427 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1428 TEST_LPM_ASSERT(status == 0);
1430 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1434 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
1435 TEST_LPM_ASSERT(status == 0);
1437 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1438 next_hop_return, 5);
1439 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
1440 && next_hop_return[1] == 102 && next_hop_return[2] == 103
1441 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1443 /* Use the delete_bulk function to delete two of them. Lookup again */
1445 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1446 TEST_LPM_ASSERT(status == 0);
1448 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1449 next_hop_return, 5);
1450 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1451 && next_hop_return[1] == -1 && next_hop_return[2] == 103
1452 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1454 /* Use the delete_bulk function to delete one more. Lookup again */
1456 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1457 TEST_LPM_ASSERT(status == 0);
1459 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1460 next_hop_return, 5);
1461 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1462 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1463 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1465 /* Use the delete_bulk function to delete two, one invalid. Lookup again */
1467 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1468 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1469 TEST_LPM_ASSERT(status == 0);
1471 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1472 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1473 next_hop_return, 5);
1474 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1475 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1476 && next_hop_return[3] == -1 && next_hop_return[4] == 105);
1478 /* Use the delete_bulk function to delete the remaining one. Lookup again */
1480 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1481 TEST_LPM_ASSERT(status == 0);
1483 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1484 next_hop_return, 5);
1485 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1486 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1487 && next_hop_return[3] == -1 && next_hop_return[4] == -1);
1495 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1496 * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
1502 struct rte_lpm6 *lpm = NULL;
1503 struct rte_lpm6_config config;
1506 uint8_t depth, next_hop_add, next_hop_return;
1509 config.max_rules = MAX_RULES;
1510 config.number_tbl8s = NUMBER_TBL8S;
1513 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1514 TEST_LPM_ASSERT(lpm != NULL);
1516 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1520 for (i = 0; i < 1000; i++) {
1521 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1522 TEST_LPM_ASSERT(status == 0);
1524 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1525 TEST_LPM_ASSERT((status == 0) &&
1526 (next_hop_return == next_hop_add));
1528 status = rte_lpm6_delete(lpm, ip, depth);
1529 TEST_LPM_ASSERT(status == 0);
1531 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1532 TEST_LPM_ASSERT(status == -ENOENT);
1541 * Sequence of operations for find existing lpm table
1544 * - find existing table: hit
1545 * - find non-existing table: miss
1550 struct rte_lpm6 *lpm = NULL, *result = NULL;
1551 struct rte_lpm6_config config;
1553 config.max_rules = 256 * 32;
1554 config.number_tbl8s = NUMBER_TBL8S;
1558 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1559 TEST_LPM_ASSERT(lpm != NULL);
1561 /* Try to find existing lpm */
1562 result = rte_lpm6_find_existing("lpm_find_existing");
1563 TEST_LPM_ASSERT(result == lpm);
1565 /* Try to find non-existing lpm */
1566 result = rte_lpm6_find_existing("lpm_find_non_existing");
1567 TEST_LPM_ASSERT(result == NULL);
1570 rte_lpm6_delete_all(lpm);
1577 * Add a set of random routes with random depths.
1578 * Lookup different IP addresses that match the routes previously added.
1579 * Checks that the next hop is the expected one.
1580 * The routes, IP addresses and expected result for every case have been
1581 * precalculated by using a python script and stored in a .h file.
1586 struct rte_lpm6 *lpm = NULL;
1587 struct rte_lpm6_config config;
1590 uint8_t depth, next_hop_add, next_hop_return, next_hop_expected;
1593 config.max_rules = MAX_RULES;
1594 config.number_tbl8s = NUMBER_TBL8S;
1597 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1598 TEST_LPM_ASSERT(lpm != NULL);
1600 for (i = 0; i < 1000; i++) {
1601 memcpy(ip, large_route_table[i].ip, 16);
1602 depth = large_route_table[i].depth;
1603 next_hop_add = large_route_table[i].next_hop;
1604 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1605 TEST_LPM_ASSERT(status == 0);
1608 for (i = 0; i < 100000; i++) {
1609 memcpy(ip, large_ips_table[i].ip, 16);
1610 next_hop_expected = large_ips_table[i].next_hop;
1612 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1613 TEST_LPM_ASSERT((status == 0) &&
1614 (next_hop_return == next_hop_expected));
1623 * Test for overwriting of tbl8:
1624 * - add rule /32 and lookup
1625 * - add new rule /24 and lookup
1626 * - add third rule /25 and lookup
1627 * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1632 struct rte_lpm6 *lpm = NULL;
1633 struct rte_lpm6_config config;
1634 uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1635 uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1636 uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1637 uint8_t d_ip_10_32 = 32;
1638 uint8_t d_ip_10_24 = 24;
1639 uint8_t d_ip_20_25 = 25;
1640 uint8_t next_hop_ip_10_32 = 100;
1641 uint8_t next_hop_ip_10_24 = 105;
1642 uint8_t next_hop_ip_20_25 = 111;
1643 uint8_t next_hop_return = 0;
1646 config.max_rules = MAX_RULES;
1647 config.number_tbl8s = NUMBER_TBL8S;
1650 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1651 TEST_LPM_ASSERT(lpm != NULL);
1653 if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
1654 next_hop_ip_10_32)) < 0)
1657 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1658 uint8_t test_hop_10_32 = next_hop_return;
1659 TEST_LPM_ASSERT(status == 0);
1660 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1662 if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
1663 next_hop_ip_10_24)) < 0)
1666 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1667 uint8_t test_hop_10_24 = next_hop_return;
1668 TEST_LPM_ASSERT(status == 0);
1669 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1671 if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
1672 next_hop_ip_20_25)) < 0)
1675 status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
1676 uint8_t test_hop_20_25 = next_hop_return;
1677 TEST_LPM_ASSERT(status == 0);
1678 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1680 if (test_hop_10_32 == test_hop_10_24) {
1681 printf("Next hop return equal\n");
1685 if (test_hop_10_24 == test_hop_20_25){
1686 printf("Next hop return equal\n");
1690 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1691 TEST_LPM_ASSERT(status == 0);
1692 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1694 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1695 TEST_LPM_ASSERT(status == 0);
1696 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1704 * Add a rule that reaches the end of the tree.
1705 * Add a rule that is more generic than the first one.
1706 * Check every possible combination that produces a match for the second rule.
1707 * This tests tbl expansion.
1712 struct rte_lpm6 *lpm = NULL;
1713 struct rte_lpm6_config config;
1714 uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
1715 uint8_t depth = 128, next_hop_add = 100, next_hop_return;
1719 config.max_rules = MAX_RULES;
1720 config.number_tbl8s = NUMBER_TBL8S;
1723 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1724 TEST_LPM_ASSERT(lpm != NULL);
1728 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1729 TEST_LPM_ASSERT(status == 0);
1733 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1734 TEST_LPM_ASSERT(status == 0);
1736 for (i = 0; i < 256; i++) {
1737 ip[14] = (uint8_t)i;
1738 for (j = 0; j < 256; j++) {
1739 ip[15] = (uint8_t)j;
1740 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1741 if (i == 0 && j == 0)
1742 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1744 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1754 * Do all unit tests.
1760 int status = -1, global_status = 0;
1762 for (i = 0; i < NUM_LPM6_TESTS; i++) {
1763 status = tests6[i]();
1766 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1767 global_status = status;
1771 return global_status;
1774 static struct test_command lpm6_cmd = {
1775 .command = "lpm6_autotest",
1776 .callback = test_lpm6,
1778 REGISTER_TEST_COMMAND(lpm6_cmd);