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 20 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 < 20; 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^12 routes with different first 12 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 = 256;
715 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
716 TEST_LPM_ASSERT(lpm != NULL);
718 for (i = 0; i < 256; i++) {
720 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
721 TEST_LPM_ASSERT(status == 0);
726 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
727 TEST_LPM_ASSERT(status == -ENOSPC);
731 status = rte_lpm6_delete(lpm, ip, depth);
732 TEST_LPM_ASSERT(status == 0);
736 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
737 TEST_LPM_ASSERT(status == 0);
745 * Call add, lookup and delete for a single rule with depth = 24
750 struct rte_lpm6 *lpm = NULL;
751 struct rte_lpm6_config config;
752 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
753 uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0;
756 config.max_rules = MAX_RULES;
757 config.number_tbl8s = NUMBER_TBL8S;
760 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
761 TEST_LPM_ASSERT(lpm != NULL);
763 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
764 TEST_LPM_ASSERT(status == 0);
766 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
767 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
769 status = rte_lpm6_delete(lpm, ip, depth);
770 TEST_LPM_ASSERT(status == 0);
772 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
773 TEST_LPM_ASSERT(status == -ENOENT);
781 * Call add, lookup and delete for a single rule with depth > 24
786 struct rte_lpm6 *lpm = NULL;
787 struct rte_lpm6_config config;
788 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
789 uint8_t depth = 128, next_hop_add = 100, next_hop_return = 0;
792 config.max_rules = MAX_RULES;
793 config.number_tbl8s = NUMBER_TBL8S;
796 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
797 TEST_LPM_ASSERT(lpm != NULL);
799 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
800 TEST_LPM_ASSERT(status == 0);
802 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
803 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
805 status = rte_lpm6_delete(lpm, ip, depth);
806 TEST_LPM_ASSERT(status == 0);
808 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
809 TEST_LPM_ASSERT(status == -ENOENT);
817 * Use rte_lpm6_add to add rules which effect only the second half of the lpm
818 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
819 * depth. Check lookup hit for on every add and check for lookup miss on the
820 * first half of the lpm table after each add. Finally delete all rules going
821 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
822 * delete. The lookup should return the next_hop_add value related to the
823 * previous depth value (i.e. depth -1).
828 struct rte_lpm6 *lpm = NULL;
829 struct rte_lpm6_config config;
830 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
831 255,255,255,255,255,255,255};
832 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
833 uint8_t depth, next_hop_add, next_hop_return;
836 config.max_rules = MAX_RULES;
837 config.number_tbl8s = NUMBER_TBL8S;
840 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
841 TEST_LPM_ASSERT(lpm != NULL);
843 /* Loop with rte_lpm6_add. */
844 for (depth = 1; depth <= 16; depth++) {
845 /* Let the next_hop_add value = depth. Just for change. */
846 next_hop_add = depth;
848 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
849 TEST_LPM_ASSERT(status == 0);
851 /* Check IP in first half of tbl24 which should be empty. */
852 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
853 TEST_LPM_ASSERT(status == -ENOENT);
855 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
856 TEST_LPM_ASSERT((status == 0) &&
857 (next_hop_return == next_hop_add));
860 /* Loop with rte_lpm6_delete. */
861 for (depth = 16; depth >= 1; depth--) {
862 next_hop_add = (uint8_t) (depth - 1);
864 status = rte_lpm6_delete(lpm, ip2, depth);
865 TEST_LPM_ASSERT(status == 0);
867 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
870 TEST_LPM_ASSERT((status == 0) &&
871 (next_hop_return == next_hop_add));
874 TEST_LPM_ASSERT(status == -ENOENT);
877 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
878 TEST_LPM_ASSERT(status == -ENOENT);
887 * - Add & lookup to hit invalid TBL24 entry
888 * - Add & lookup to hit valid TBL24 entry not extended
889 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
890 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
895 struct rte_lpm6 *lpm = NULL;
896 struct rte_lpm6_config config;
897 uint8_t ip[16], ip_1[16], ip_2[16];
898 uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1,
899 next_hop_add_2, next_hop_return;
902 config.max_rules = MAX_RULES;
903 config.number_tbl8s = NUMBER_TBL8S;
906 /* Add & lookup to hit invalid TBL24 entry */
907 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
911 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
912 TEST_LPM_ASSERT(lpm != NULL);
914 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
915 TEST_LPM_ASSERT(status == 0);
917 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
918 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
920 status = rte_lpm6_delete(lpm, ip, depth);
921 TEST_LPM_ASSERT(status == 0);
923 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
924 TEST_LPM_ASSERT(status == -ENOENT);
926 rte_lpm6_delete_all(lpm);
928 /* Add & lookup to hit valid TBL24 entry not extended */
929 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
933 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
934 TEST_LPM_ASSERT(status == 0);
936 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
937 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
942 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
943 TEST_LPM_ASSERT(status == 0);
945 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
946 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
950 status = rte_lpm6_delete(lpm, ip, depth);
951 TEST_LPM_ASSERT(status == 0);
955 status = rte_lpm6_delete(lpm, ip, depth);
956 TEST_LPM_ASSERT(status == 0);
958 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
959 TEST_LPM_ASSERT(status == -ENOENT);
961 rte_lpm6_delete_all(lpm);
963 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
966 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
970 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
971 TEST_LPM_ASSERT(status == 0);
973 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
974 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
976 IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
980 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
981 TEST_LPM_ASSERT(status == 0);
983 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
984 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
986 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
990 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
991 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
993 status = rte_lpm6_delete(lpm, ip, depth);
994 TEST_LPM_ASSERT(status == 0);
996 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
997 TEST_LPM_ASSERT(status == -ENOENT);
999 rte_lpm6_delete_all(lpm);
1001 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
1004 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1006 next_hop_add_1 = 101;
1008 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1010 next_hop_add_2 = 102;
1012 next_hop_return = 0;
1014 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
1015 TEST_LPM_ASSERT(status == 0);
1017 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1018 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1020 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1021 TEST_LPM_ASSERT(status == 0);
1023 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1024 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1026 status = rte_lpm6_delete(lpm, ip_2, depth_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_1));
1032 status = rte_lpm6_delete(lpm, ip_1, depth_1);
1033 TEST_LPM_ASSERT(status == 0);
1035 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1036 TEST_LPM_ASSERT(status == -ENOENT);
1044 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1046 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1047 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1049 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1050 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1051 * - Delete a rule that is not present in the TBL24 & lookup
1052 * - Delete a rule that is not present in the TBL8 & lookup
1057 struct rte_lpm6 *lpm = NULL;
1058 struct rte_lpm6_config config;
1060 uint8_t depth, next_hop_add, next_hop_return;
1063 config.max_rules = MAX_RULES;
1064 config.number_tbl8s = NUMBER_TBL8S;
1067 /* Add rule that covers a TBL24 range previously invalid & lookup
1068 * (& delete & lookup)
1070 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1071 TEST_LPM_ASSERT(lpm != NULL);
1073 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1077 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1078 TEST_LPM_ASSERT(status == 0);
1080 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1081 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1083 status = rte_lpm6_delete(lpm, ip, depth);
1084 TEST_LPM_ASSERT(status == 0);
1086 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1087 TEST_LPM_ASSERT(status == -ENOENT);
1089 rte_lpm6_delete_all(lpm);
1091 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1095 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1096 TEST_LPM_ASSERT(status == 0);
1098 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1099 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1101 status = rte_lpm6_delete(lpm, ip, depth);
1102 TEST_LPM_ASSERT(status == 0);
1104 rte_lpm6_delete_all(lpm);
1107 * Add rule that extends a TBL24 valid entry & lookup for both rules
1108 * (& delete & lookup)
1111 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1115 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1116 TEST_LPM_ASSERT(status == 0);
1118 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1122 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1123 TEST_LPM_ASSERT(status == 0);
1125 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1126 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1128 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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_delete(lpm, ip, depth);
1138 TEST_LPM_ASSERT(status == 0);
1140 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1141 TEST_LPM_ASSERT(status == -ENOENT);
1143 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1146 status = rte_lpm6_delete(lpm, ip, depth);
1147 TEST_LPM_ASSERT(status == 0);
1149 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1150 TEST_LPM_ASSERT(status == -ENOENT);
1152 rte_lpm6_delete_all(lpm);
1155 * Add rule that updates the next hop in TBL24 & lookup
1156 * (& delete & lookup)
1159 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1163 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1164 TEST_LPM_ASSERT(status == 0);
1166 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1167 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1171 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1172 TEST_LPM_ASSERT(status == 0);
1174 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1175 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1177 status = rte_lpm6_delete(lpm, ip, depth);
1178 TEST_LPM_ASSERT(status == 0);
1180 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1181 TEST_LPM_ASSERT(status == -ENOENT);
1183 rte_lpm6_delete_all(lpm);
1186 * Add rule that updates the next hop in TBL8 & lookup
1187 * (& delete & lookup)
1190 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1194 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1195 TEST_LPM_ASSERT(status == 0);
1197 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1198 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1202 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1203 TEST_LPM_ASSERT(status == 0);
1205 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1206 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1208 status = rte_lpm6_delete(lpm, ip, depth);
1209 TEST_LPM_ASSERT(status == 0);
1211 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1212 TEST_LPM_ASSERT(status == -ENOENT);
1214 rte_lpm6_delete_all(lpm);
1216 /* Delete a rule that is not present in the TBL24 & lookup */
1218 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1222 status = rte_lpm6_delete(lpm, ip, depth);
1223 TEST_LPM_ASSERT(status < 0);
1225 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1226 TEST_LPM_ASSERT(status == -ENOENT);
1228 rte_lpm6_delete_all(lpm);
1230 /* Delete a rule that is not present in the TBL8 & lookup */
1232 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1236 status = rte_lpm6_delete(lpm, ip, depth);
1237 TEST_LPM_ASSERT(status < 0);
1239 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1240 TEST_LPM_ASSERT(status == -ENOENT);
1248 * Add two rules, lookup to hit the more specific one, lookup to hit the less
1249 * specific one delete the less specific rule and lookup previous values again;
1250 * add a more specific rule than the existing rule, lookup again
1255 struct rte_lpm6 *lpm = NULL;
1256 struct rte_lpm6_config config;
1258 uint8_t depth, next_hop_add, next_hop_return;
1261 config.max_rules = MAX_RULES;
1262 config.number_tbl8s = NUMBER_TBL8S;
1265 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1266 TEST_LPM_ASSERT(lpm != NULL);
1268 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1272 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1273 TEST_LPM_ASSERT(status == 0);
1275 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1279 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1280 TEST_LPM_ASSERT(status == 0);
1282 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1283 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1285 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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_delete(lpm, ip, depth);
1295 TEST_LPM_ASSERT(status == 0);
1297 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1298 TEST_LPM_ASSERT(status == -ENOENT);
1300 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1303 status = rte_lpm6_delete(lpm, ip, depth);
1304 TEST_LPM_ASSERT(status == 0);
1306 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1307 TEST_LPM_ASSERT(status == -ENOENT);
1315 * Adds 3 rules and look them up through the lookup_bulk function.
1316 * Includes in the lookup a fourth IP address that won't match
1317 * and checks that the result is as expected.
1322 struct rte_lpm6 *lpm = NULL;
1323 struct rte_lpm6_config config;
1324 uint8_t ip_batch[4][16];
1325 uint8_t depth, next_hop_add;
1326 int16_t next_hop_return[4];
1329 config.max_rules = MAX_RULES;
1330 config.number_tbl8s = NUMBER_TBL8S;
1333 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1334 TEST_LPM_ASSERT(lpm != NULL);
1336 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1340 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1341 TEST_LPM_ASSERT(status == 0);
1343 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1347 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1348 TEST_LPM_ASSERT(status == 0);
1350 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1354 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1355 TEST_LPM_ASSERT(status == 0);
1357 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1359 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1360 next_hop_return, 4);
1361 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1362 && next_hop_return[1] == 101 && next_hop_return[2] == 102
1363 && next_hop_return[3] == -1);
1371 * Adds 5 rules and look them up.
1372 * Use the delete_bulk function to delete two of them. Lookup again.
1373 * Use the delete_bulk function to delete one more. Lookup again.
1374 * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1375 * Use the delete_bulk function to delete the remaining one. Lookup again.
1380 struct rte_lpm6 *lpm = NULL;
1381 struct rte_lpm6_config config;
1382 uint8_t ip_batch[5][16];
1383 uint8_t depth[5], next_hop_add;
1384 int16_t next_hop_return[5];
1387 config.max_rules = MAX_RULES;
1388 config.number_tbl8s = NUMBER_TBL8S;
1391 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1392 TEST_LPM_ASSERT(lpm != NULL);
1394 /* Adds 5 rules and look them up */
1396 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1400 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1401 TEST_LPM_ASSERT(status == 0);
1403 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1407 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1408 TEST_LPM_ASSERT(status == 0);
1410 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1414 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1415 TEST_LPM_ASSERT(status == 0);
1417 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1421 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1422 TEST_LPM_ASSERT(status == 0);
1424 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1428 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
1429 TEST_LPM_ASSERT(status == 0);
1431 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1432 next_hop_return, 5);
1433 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
1434 && next_hop_return[1] == 102 && next_hop_return[2] == 103
1435 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1437 /* Use the delete_bulk function to delete two of them. Lookup again */
1439 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1440 TEST_LPM_ASSERT(status == 0);
1442 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1443 next_hop_return, 5);
1444 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1445 && next_hop_return[1] == -1 && next_hop_return[2] == 103
1446 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1448 /* Use the delete_bulk function to delete one more. Lookup again */
1450 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1451 TEST_LPM_ASSERT(status == 0);
1453 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1454 next_hop_return, 5);
1455 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1456 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1457 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1459 /* Use the delete_bulk function to delete two, one invalid. Lookup again */
1461 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1462 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1463 TEST_LPM_ASSERT(status == 0);
1465 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1466 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1467 next_hop_return, 5);
1468 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1469 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1470 && next_hop_return[3] == -1 && next_hop_return[4] == 105);
1472 /* Use the delete_bulk function to delete the remaining one. Lookup again */
1474 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1475 TEST_LPM_ASSERT(status == 0);
1477 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1478 next_hop_return, 5);
1479 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1480 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1481 && next_hop_return[3] == -1 && next_hop_return[4] == -1);
1489 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1490 * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
1496 struct rte_lpm6 *lpm = NULL;
1497 struct rte_lpm6_config config;
1500 uint8_t depth, next_hop_add, next_hop_return;
1503 config.max_rules = MAX_RULES;
1504 config.number_tbl8s = NUMBER_TBL8S;
1507 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1508 TEST_LPM_ASSERT(lpm != NULL);
1510 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1514 for (i = 0; i < 30; i++) {
1515 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1516 TEST_LPM_ASSERT(status == 0);
1518 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1519 TEST_LPM_ASSERT((status == 0) &&
1520 (next_hop_return == next_hop_add));
1522 status = rte_lpm6_delete(lpm, ip, depth);
1523 TEST_LPM_ASSERT(status == 0);
1525 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1526 TEST_LPM_ASSERT(status == -ENOENT);
1535 * Sequence of operations for find existing lpm table
1538 * - find existing table: hit
1539 * - find non-existing table: miss
1544 struct rte_lpm6 *lpm = NULL, *result = NULL;
1545 struct rte_lpm6_config config;
1547 config.max_rules = 256 * 32;
1548 config.number_tbl8s = NUMBER_TBL8S;
1552 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1553 TEST_LPM_ASSERT(lpm != NULL);
1555 /* Try to find existing lpm */
1556 result = rte_lpm6_find_existing("lpm_find_existing");
1557 TEST_LPM_ASSERT(result == lpm);
1559 /* Try to find non-existing lpm */
1560 result = rte_lpm6_find_existing("lpm_find_non_existing");
1561 TEST_LPM_ASSERT(result == NULL);
1564 rte_lpm6_delete_all(lpm);
1571 * Add a set of random routes with random depths.
1572 * Lookup different IP addresses that match the routes previously added.
1573 * Checks that the next hop is the expected one.
1574 * The routes, IP addresses and expected result for every case have been
1575 * precalculated by using a python script and stored in a .h file.
1580 struct rte_lpm6 *lpm = NULL;
1581 struct rte_lpm6_config config;
1584 uint8_t depth, next_hop_add, next_hop_return, next_hop_expected;
1587 config.max_rules = MAX_RULES;
1588 config.number_tbl8s = NUMBER_TBL8S;
1591 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1592 TEST_LPM_ASSERT(lpm != NULL);
1594 for (i = 0; i < 1000; i++) {
1595 memcpy(ip, large_route_table[i].ip, 16);
1596 depth = large_route_table[i].depth;
1597 next_hop_add = large_route_table[i].next_hop;
1598 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1599 TEST_LPM_ASSERT(status == 0);
1602 for (i = 0; i < 100000; i++) {
1603 memcpy(ip, large_ips_table[i].ip, 16);
1604 next_hop_expected = large_ips_table[i].next_hop;
1606 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1607 TEST_LPM_ASSERT((status == 0) &&
1608 (next_hop_return == next_hop_expected));
1617 * Test for overwriting of tbl8:
1618 * - add rule /32 and lookup
1619 * - add new rule /24 and lookup
1620 * - add third rule /25 and lookup
1621 * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1626 struct rte_lpm6 *lpm = NULL;
1627 struct rte_lpm6_config config;
1628 uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1629 uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1630 uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1631 uint8_t d_ip_10_32 = 32;
1632 uint8_t d_ip_10_24 = 24;
1633 uint8_t d_ip_20_25 = 25;
1634 uint8_t next_hop_ip_10_32 = 100;
1635 uint8_t next_hop_ip_10_24 = 105;
1636 uint8_t next_hop_ip_20_25 = 111;
1637 uint8_t next_hop_return = 0;
1640 config.max_rules = MAX_RULES;
1641 config.number_tbl8s = NUMBER_TBL8S;
1644 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1645 TEST_LPM_ASSERT(lpm != NULL);
1647 if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
1648 next_hop_ip_10_32)) < 0)
1651 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1652 uint8_t test_hop_10_32 = next_hop_return;
1653 TEST_LPM_ASSERT(status == 0);
1654 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1656 if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
1657 next_hop_ip_10_24)) < 0)
1660 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1661 uint8_t test_hop_10_24 = next_hop_return;
1662 TEST_LPM_ASSERT(status == 0);
1663 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1665 if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
1666 next_hop_ip_20_25)) < 0)
1669 status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
1670 uint8_t test_hop_20_25 = next_hop_return;
1671 TEST_LPM_ASSERT(status == 0);
1672 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1674 if (test_hop_10_32 == test_hop_10_24) {
1675 printf("Next hop return equal\n");
1679 if (test_hop_10_24 == test_hop_20_25){
1680 printf("Next hop return equal\n");
1684 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1685 TEST_LPM_ASSERT(status == 0);
1686 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1688 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1689 TEST_LPM_ASSERT(status == 0);
1690 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1698 * Add a rule that reaches the end of the tree.
1699 * Add a rule that is more generic than the first one.
1700 * Check every possible combination that produces a match for the second rule.
1701 * This tests tbl expansion.
1706 struct rte_lpm6 *lpm = NULL;
1707 struct rte_lpm6_config config;
1708 uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
1709 uint8_t depth = 128, next_hop_add = 100, next_hop_return;
1713 config.max_rules = MAX_RULES;
1714 config.number_tbl8s = NUMBER_TBL8S;
1717 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1718 TEST_LPM_ASSERT(lpm != NULL);
1722 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1723 TEST_LPM_ASSERT(status == 0);
1727 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1728 TEST_LPM_ASSERT(status == 0);
1730 for (i = 0; i < 256; i++) {
1731 ip[14] = (uint8_t)i;
1732 for (j = 0; j < 256; j++) {
1733 ip[15] = (uint8_t)j;
1734 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1735 if (i == 0 && j == 0)
1736 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1738 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1748 * Do all unit tests.
1754 int status = -1, global_status = 0;
1756 for (i = 0; i < NUM_LPM6_TESTS; i++) {
1757 printf("# test %02d\n", i);
1758 status = tests6[i]();
1761 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1762 global_status = status;
1766 return global_status;
1769 static struct test_command lpm6_cmd = {
1770 .command = "lpm6_autotest",
1771 .callback = test_lpm6,
1773 REGISTER_TEST_COMMAND(lpm6_cmd);