1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
10 #include <rte_memory.h>
14 #include "test_lpm6_data.h"
16 #define TEST_LPM_ASSERT(cond) do { \
18 printf("Error at line %d: \n", __LINE__); \
23 typedef int32_t (* rte_lpm6_test)(void);
25 static int32_t test0(void);
26 static int32_t test1(void);
27 static int32_t test2(void);
28 static int32_t test3(void);
29 static int32_t test4(void);
30 static int32_t test5(void);
31 static int32_t test6(void);
32 static int32_t test7(void);
33 static int32_t test8(void);
34 static int32_t test9(void);
35 static int32_t test10(void);
36 static int32_t test11(void);
37 static int32_t test12(void);
38 static int32_t test13(void);
39 static int32_t test14(void);
40 static int32_t test15(void);
41 static int32_t test16(void);
42 static int32_t test17(void);
43 static int32_t test18(void);
44 static int32_t test19(void);
45 static int32_t test20(void);
46 static int32_t test21(void);
47 static int32_t test22(void);
48 static int32_t test23(void);
49 static int32_t test24(void);
50 static int32_t test25(void);
51 static int32_t test26(void);
52 static int32_t test27(void);
53 static int32_t test28(void);
55 rte_lpm6_test tests6[] = {
89 #define MAX_RULES 1000000
90 #define NUMBER_TBL8S (1 << 16)
91 #define MAX_NUM_TBL8S (1 << 21)
95 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
96 uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
97 uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
119 * Check that rte_lpm6_create fails gracefully for incorrect user input
125 struct rte_lpm6 *lpm = NULL;
126 struct rte_lpm6_config config;
128 config.max_rules = MAX_RULES;
129 config.number_tbl8s = NUMBER_TBL8S;
132 /* rte_lpm6_create: lpm name == NULL */
133 lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
134 TEST_LPM_ASSERT(lpm == NULL);
136 /* rte_lpm6_create: max_rules = 0 */
137 /* Note: __func__ inserts the function name, in this case "test0". */
138 config.max_rules = 0;
139 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
140 TEST_LPM_ASSERT(lpm == NULL);
142 /* socket_id < -1 is invalid */
143 config.max_rules = MAX_RULES;
144 lpm = rte_lpm6_create(__func__, -2, &config);
145 TEST_LPM_ASSERT(lpm == NULL);
147 /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
148 config.number_tbl8s = MAX_NUM_TBL8S + 1;
149 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
150 TEST_LPM_ASSERT(lpm == NULL);
152 /* rte_lpm6_create: config = NULL */
153 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
154 TEST_LPM_ASSERT(lpm == NULL);
160 * Creates two different LPM tables. Tries to create a third one with the same
161 * name as the first one and expects the create function to return the same
167 struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
168 struct rte_lpm6_config config;
170 config.max_rules = MAX_RULES;
171 config.number_tbl8s = NUMBER_TBL8S;
174 /* rte_lpm6_create: lpm name == LPM1 */
175 lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
176 TEST_LPM_ASSERT(lpm1 != NULL);
178 /* rte_lpm6_create: lpm name == LPM2 */
179 lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
180 TEST_LPM_ASSERT(lpm2 != NULL);
182 /* rte_lpm6_create: lpm name == LPM2 */
183 lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
184 TEST_LPM_ASSERT(lpm3 == NULL);
193 * Create lpm table then delete lpm table 20 times
194 * Use a slightly different rules size each time
199 struct rte_lpm6 *lpm = NULL;
200 struct rte_lpm6_config config;
203 config.number_tbl8s = NUMBER_TBL8S;
206 /* rte_lpm6_free: Free NULL */
207 for (i = 0; i < 20; i++) {
208 config.max_rules = MAX_RULES - i;
209 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
210 TEST_LPM_ASSERT(lpm != NULL);
215 /* Can not test free so return success */
220 * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
221 * therefore it is impossible to check for failure but this test is added to
222 * increase function coverage metrics and to validate that freeing null does
228 struct rte_lpm6 *lpm = NULL;
229 struct rte_lpm6_config config;
231 config.max_rules = MAX_RULES;
232 config.number_tbl8s = NUMBER_TBL8S;
235 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
236 TEST_LPM_ASSERT(lpm != NULL);
244 * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
249 struct rte_lpm6 *lpm = NULL;
250 struct rte_lpm6_config config;
252 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
253 uint8_t depth = 24, next_hop = 100;
256 config.max_rules = MAX_RULES;
257 config.number_tbl8s = NUMBER_TBL8S;
260 /* rte_lpm6_add: lpm == NULL */
261 status = rte_lpm6_add(NULL, ip, depth, next_hop);
262 TEST_LPM_ASSERT(status < 0);
264 /*Create vaild lpm to use in rest of test. */
265 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
266 TEST_LPM_ASSERT(lpm != NULL);
268 /* rte_lpm6_add: depth < 1 */
269 status = rte_lpm6_add(lpm, ip, 0, next_hop);
270 TEST_LPM_ASSERT(status < 0);
272 /* rte_lpm6_add: depth > MAX_DEPTH */
273 status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
274 TEST_LPM_ASSERT(status < 0);
282 * Check that rte_lpm6_delete fails gracefully for incorrect user input
288 struct rte_lpm6 *lpm = NULL;
289 struct rte_lpm6_config config;
290 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
294 config.max_rules = MAX_RULES;
295 config.number_tbl8s = NUMBER_TBL8S;
298 /* rte_lpm_delete: lpm == NULL */
299 status = rte_lpm6_delete(NULL, ip, depth);
300 TEST_LPM_ASSERT(status < 0);
302 /*Create vaild lpm to use in rest of test. */
303 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
304 TEST_LPM_ASSERT(lpm != NULL);
306 /* rte_lpm_delete: depth < 1 */
307 status = rte_lpm6_delete(lpm, ip, 0);
308 TEST_LPM_ASSERT(status < 0);
310 /* rte_lpm_delete: depth > MAX_DEPTH */
311 status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
312 TEST_LPM_ASSERT(status < 0);
320 * Check that rte_lpm6_lookup fails gracefully for incorrect user input
326 struct rte_lpm6 *lpm = NULL;
327 struct rte_lpm6_config config;
328 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
329 uint32_t next_hop_return = 0;
332 config.max_rules = MAX_RULES;
333 config.number_tbl8s = NUMBER_TBL8S;
336 /* rte_lpm6_lookup: lpm == NULL */
337 status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
338 TEST_LPM_ASSERT(status < 0);
340 /*Create vaild lpm to use in rest of test. */
341 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
342 TEST_LPM_ASSERT(lpm != NULL);
344 /* rte_lpm6_lookup: ip = NULL */
345 status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
346 TEST_LPM_ASSERT(status < 0);
348 /* rte_lpm6_lookup: next_hop = NULL */
349 status = rte_lpm6_lookup(lpm, ip, NULL);
350 TEST_LPM_ASSERT(status < 0);
358 * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
364 struct rte_lpm6 *lpm = NULL;
365 struct rte_lpm6_config config;
367 int32_t next_hop_return[10];
370 config.max_rules = MAX_RULES;
371 config.number_tbl8s = NUMBER_TBL8S;
374 /* rte_lpm6_lookup: lpm == NULL */
375 status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
376 TEST_LPM_ASSERT(status < 0);
378 /*Create vaild lpm to use in rest of test. */
379 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
380 TEST_LPM_ASSERT(lpm != NULL);
382 /* rte_lpm6_lookup: ip = NULL */
383 status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
384 TEST_LPM_ASSERT(status < 0);
386 /* rte_lpm6_lookup: next_hop = NULL */
387 status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
388 TEST_LPM_ASSERT(status < 0);
396 * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
402 struct rte_lpm6 *lpm = NULL;
403 struct rte_lpm6_config config;
408 config.max_rules = MAX_RULES;
409 config.number_tbl8s = NUMBER_TBL8S;
412 /* rte_lpm6_delete: lpm == NULL */
413 status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
414 TEST_LPM_ASSERT(status < 0);
416 /*Create vaild lpm to use in rest of test. */
417 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
418 TEST_LPM_ASSERT(lpm != NULL);
420 /* rte_lpm6_delete: ip = NULL */
421 status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
422 TEST_LPM_ASSERT(status < 0);
424 /* rte_lpm6_delete: next_hop = NULL */
425 status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
426 TEST_LPM_ASSERT(status < 0);
434 * Call add, lookup and delete for a single rule with depth < 24.
435 * Check all the combinations for the first three bytes that result in a hit.
436 * Delete the rule and check that the same test returs a miss.
441 struct rte_lpm6 *lpm = NULL;
442 struct rte_lpm6_config config;
443 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
445 uint32_t next_hop_add = 100, next_hop_return = 0;
449 config.max_rules = MAX_RULES;
450 config.number_tbl8s = NUMBER_TBL8S;
453 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
454 TEST_LPM_ASSERT(lpm != NULL);
456 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
457 TEST_LPM_ASSERT(status == 0);
459 for (i = 0; i < UINT8_MAX; i++) {
461 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
462 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
465 status = rte_lpm6_delete(lpm, ip, depth);
466 TEST_LPM_ASSERT(status == 0);
468 for (i = 0; i < UINT8_MAX; i++) {
470 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
471 TEST_LPM_ASSERT(status == -ENOENT);
480 * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
481 * another one and expects success.
486 struct rte_lpm6 *lpm = NULL;
487 struct rte_lpm6_config config;
488 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
490 uint32_t next_hop_add = 100;
494 config.max_rules = 127;
495 config.number_tbl8s = NUMBER_TBL8S;
498 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
499 TEST_LPM_ASSERT(lpm != NULL);
501 for (i = 1; i < 128; i++) {
503 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
504 TEST_LPM_ASSERT(status == 0);
508 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
509 TEST_LPM_ASSERT(status == -ENOSPC);
512 status = rte_lpm6_delete(lpm, ip, depth);
513 TEST_LPM_ASSERT(status == 0);
516 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
517 TEST_LPM_ASSERT(status == 0);
525 * Creates an LPM table with a small number of tbl8s and exhaust them in the
526 * middle of the process of creating a rule.
531 struct rte_lpm6 *lpm = NULL;
532 struct rte_lpm6_config config;
533 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
535 uint32_t next_hop_add = 100;
538 config.max_rules = MAX_RULES;
539 config.number_tbl8s = 16;
542 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
543 TEST_LPM_ASSERT(lpm != NULL);
546 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
547 TEST_LPM_ASSERT(status == 0);
551 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
552 TEST_LPM_ASSERT(status == 0);
554 status = rte_lpm6_delete(lpm, ip, depth);
555 TEST_LPM_ASSERT(status == 0);
558 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
559 TEST_LPM_ASSERT(status == 0);
561 status = rte_lpm6_delete(lpm, ip, depth);
562 TEST_LPM_ASSERT(status == 0);
565 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
566 TEST_LPM_ASSERT(status == 0);
568 status = rte_lpm6_delete(lpm, ip, depth);
569 TEST_LPM_ASSERT(status == 0);
572 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
573 TEST_LPM_ASSERT(status == -ENOSPC);
576 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
577 TEST_LPM_ASSERT(status == 0);
585 * Creates an LPM table with a small number of tbl8s and exhaust them in the
586 * middle of the process of adding a rule when there is already an existing rule
587 * in that position and needs to be extended.
592 struct rte_lpm6 *lpm = NULL;
593 struct rte_lpm6_config config;
594 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
596 uint32_t next_hop_add = 100;
599 config.max_rules = MAX_RULES;
600 config.number_tbl8s = 16;
603 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
604 TEST_LPM_ASSERT(lpm != NULL);
607 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
608 TEST_LPM_ASSERT(status == 0);
612 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
613 TEST_LPM_ASSERT(status == 0);
616 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
617 TEST_LPM_ASSERT(status == -ENOSPC);
625 * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
626 * Delete one of the rules and tries to add the third one again.
631 struct rte_lpm6 *lpm = NULL;
632 struct rte_lpm6_config config;
633 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
635 uint32_t next_hop_add = 100;
638 config.max_rules = 2;
639 config.number_tbl8s = NUMBER_TBL8S;
642 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
643 TEST_LPM_ASSERT(lpm != NULL);
646 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
647 TEST_LPM_ASSERT(status == 0);
650 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
651 TEST_LPM_ASSERT(status == 0);
654 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
655 TEST_LPM_ASSERT(status == -ENOSPC);
658 status = rte_lpm6_delete(lpm, ip, depth);
659 TEST_LPM_ASSERT(status == 0);
662 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
663 TEST_LPM_ASSERT(status == 0);
671 * Add 2^12 routes with different first 12 bits and depth 25.
672 * Add one more route with the same depth and check that results in a failure.
673 * After that delete the last rule and create the one that was attempted to be
674 * created. This checks tbl8 exhaustion.
679 struct rte_lpm6 *lpm = NULL;
680 struct rte_lpm6_config config;
681 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
683 uint32_t next_hop_add = 100;
687 config.max_rules = MAX_RULES;
688 config.number_tbl8s = 256;
691 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
692 TEST_LPM_ASSERT(lpm != NULL);
694 for (i = 0; i < 256; i++) {
696 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
697 TEST_LPM_ASSERT(status == 0);
702 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
703 TEST_LPM_ASSERT(status == -ENOSPC);
707 status = rte_lpm6_delete(lpm, ip, depth);
708 TEST_LPM_ASSERT(status == 0);
712 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
713 TEST_LPM_ASSERT(status == 0);
721 * Call add, lookup and delete for a single rule with depth = 24
726 struct rte_lpm6 *lpm = NULL;
727 struct rte_lpm6_config config;
728 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
730 uint32_t next_hop_add = 100, next_hop_return = 0;
733 config.max_rules = MAX_RULES;
734 config.number_tbl8s = NUMBER_TBL8S;
737 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
738 TEST_LPM_ASSERT(lpm != NULL);
740 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
741 TEST_LPM_ASSERT(status == 0);
743 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
744 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
746 status = rte_lpm6_delete(lpm, ip, depth);
747 TEST_LPM_ASSERT(status == 0);
749 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
750 TEST_LPM_ASSERT(status == -ENOENT);
758 * Call add, lookup and delete for a single rule with depth > 24
763 struct rte_lpm6 *lpm = NULL;
764 struct rte_lpm6_config config;
765 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
767 uint32_t next_hop_add = 100, next_hop_return = 0;
770 config.max_rules = MAX_RULES;
771 config.number_tbl8s = NUMBER_TBL8S;
774 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
775 TEST_LPM_ASSERT(lpm != NULL);
777 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
778 TEST_LPM_ASSERT(status == 0);
780 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
781 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
783 status = rte_lpm6_delete(lpm, ip, depth);
784 TEST_LPM_ASSERT(status == 0);
786 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
787 TEST_LPM_ASSERT(status == -ENOENT);
795 * Use rte_lpm6_add to add rules which effect only the second half of the lpm
796 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
797 * depth. Check lookup hit for on every add and check for lookup miss on the
798 * first half of the lpm table after each add. Finally delete all rules going
799 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
800 * delete. The lookup should return the next_hop_add value related to the
801 * previous depth value (i.e. depth -1).
806 struct rte_lpm6 *lpm = NULL;
807 struct rte_lpm6_config config;
808 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
809 255,255,255,255,255,255,255};
810 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
812 uint32_t next_hop_add, next_hop_return;
815 config.max_rules = MAX_RULES;
816 config.number_tbl8s = NUMBER_TBL8S;
819 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
820 TEST_LPM_ASSERT(lpm != NULL);
822 /* Loop with rte_lpm6_add. */
823 for (depth = 1; depth <= 16; depth++) {
824 /* Let the next_hop_add value = depth. Just for change. */
825 next_hop_add = depth;
827 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
828 TEST_LPM_ASSERT(status == 0);
830 /* Check IP in first half of tbl24 which should be empty. */
831 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
832 TEST_LPM_ASSERT(status == -ENOENT);
834 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
835 TEST_LPM_ASSERT((status == 0) &&
836 (next_hop_return == next_hop_add));
839 /* Loop with rte_lpm6_delete. */
840 for (depth = 16; depth >= 1; depth--) {
841 next_hop_add = (depth - 1);
843 status = rte_lpm6_delete(lpm, ip2, depth);
844 TEST_LPM_ASSERT(status == 0);
846 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
849 TEST_LPM_ASSERT((status == 0) &&
850 (next_hop_return == next_hop_add));
853 TEST_LPM_ASSERT(status == -ENOENT);
856 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
857 TEST_LPM_ASSERT(status == -ENOENT);
866 * - Add & lookup to hit invalid TBL24 entry
867 * - Add & lookup to hit valid TBL24 entry not extended
868 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
869 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
874 struct rte_lpm6 *lpm = NULL;
875 struct rte_lpm6_config config;
876 uint8_t ip[16], ip_1[16], ip_2[16];
877 uint8_t depth, depth_1, depth_2;
878 uint32_t next_hop_add, next_hop_add_1,
879 next_hop_add_2, next_hop_return;
882 config.max_rules = MAX_RULES;
883 config.number_tbl8s = NUMBER_TBL8S;
886 /* Add & lookup to hit invalid TBL24 entry */
887 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
891 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
892 TEST_LPM_ASSERT(lpm != NULL);
894 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
895 TEST_LPM_ASSERT(status == 0);
897 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
898 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
900 status = rte_lpm6_delete(lpm, ip, depth);
901 TEST_LPM_ASSERT(status == 0);
903 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
904 TEST_LPM_ASSERT(status == -ENOENT);
906 rte_lpm6_delete_all(lpm);
908 /* Add & lookup to hit valid TBL24 entry not extended */
909 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
913 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
914 TEST_LPM_ASSERT(status == 0);
916 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
917 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
922 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
923 TEST_LPM_ASSERT(status == 0);
925 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
926 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
930 status = rte_lpm6_delete(lpm, ip, depth);
931 TEST_LPM_ASSERT(status == 0);
935 status = rte_lpm6_delete(lpm, ip, depth);
936 TEST_LPM_ASSERT(status == 0);
938 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
939 TEST_LPM_ASSERT(status == -ENOENT);
941 rte_lpm6_delete_all(lpm);
943 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
946 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
950 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
951 TEST_LPM_ASSERT(status == 0);
953 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
954 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
956 IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
960 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
961 TEST_LPM_ASSERT(status == 0);
963 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
964 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
966 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
970 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
971 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
973 status = rte_lpm6_delete(lpm, ip, depth);
974 TEST_LPM_ASSERT(status == 0);
976 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
977 TEST_LPM_ASSERT(status == -ENOENT);
979 rte_lpm6_delete_all(lpm);
981 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
984 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
986 next_hop_add_1 = 101;
988 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
990 next_hop_add_2 = 102;
994 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
995 TEST_LPM_ASSERT(status == 0);
997 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
998 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1000 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1001 TEST_LPM_ASSERT(status == 0);
1003 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1004 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1006 status = rte_lpm6_delete(lpm, ip_2, depth_2);
1007 TEST_LPM_ASSERT(status == 0);
1009 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1010 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1012 status = rte_lpm6_delete(lpm, ip_1, depth_1);
1013 TEST_LPM_ASSERT(status == 0);
1015 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1016 TEST_LPM_ASSERT(status == -ENOENT);
1024 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1026 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1027 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1029 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1030 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1031 * - Delete a rule that is not present in the TBL24 & lookup
1032 * - Delete a rule that is not present in the TBL8 & lookup
1037 struct rte_lpm6 *lpm = NULL;
1038 struct rte_lpm6_config config;
1041 uint32_t next_hop_add, next_hop_return;
1044 config.max_rules = MAX_RULES;
1045 config.number_tbl8s = NUMBER_TBL8S;
1048 /* Add rule that covers a TBL24 range previously invalid & lookup
1049 * (& delete & lookup)
1051 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1052 TEST_LPM_ASSERT(lpm != NULL);
1054 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1058 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1059 TEST_LPM_ASSERT(status == 0);
1061 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1062 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1064 status = rte_lpm6_delete(lpm, ip, depth);
1065 TEST_LPM_ASSERT(status == 0);
1067 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1068 TEST_LPM_ASSERT(status == -ENOENT);
1070 rte_lpm6_delete_all(lpm);
1072 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1076 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1077 TEST_LPM_ASSERT(status == 0);
1079 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1080 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1082 status = rte_lpm6_delete(lpm, ip, depth);
1083 TEST_LPM_ASSERT(status == 0);
1085 rte_lpm6_delete_all(lpm);
1088 * Add rule that extends a TBL24 valid entry & lookup for both rules
1089 * (& delete & lookup)
1092 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1096 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1097 TEST_LPM_ASSERT(status == 0);
1099 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1103 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1104 TEST_LPM_ASSERT(status == 0);
1106 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1107 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1109 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1112 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1113 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1115 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1118 status = rte_lpm6_delete(lpm, ip, depth);
1119 TEST_LPM_ASSERT(status == 0);
1121 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1122 TEST_LPM_ASSERT(status == -ENOENT);
1124 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1127 status = rte_lpm6_delete(lpm, ip, depth);
1128 TEST_LPM_ASSERT(status == 0);
1130 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1131 TEST_LPM_ASSERT(status == -ENOENT);
1133 rte_lpm6_delete_all(lpm);
1136 * Add rule that updates the next hop in TBL24 & lookup
1137 * (& delete & lookup)
1140 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1144 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1145 TEST_LPM_ASSERT(status == 0);
1147 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1148 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1152 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1153 TEST_LPM_ASSERT(status == 0);
1155 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1156 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1158 status = rte_lpm6_delete(lpm, ip, depth);
1159 TEST_LPM_ASSERT(status == 0);
1161 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1162 TEST_LPM_ASSERT(status == -ENOENT);
1164 rte_lpm6_delete_all(lpm);
1167 * Add rule that updates the next hop in TBL8 & lookup
1168 * (& delete & lookup)
1171 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1175 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1176 TEST_LPM_ASSERT(status == 0);
1178 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1179 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1183 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1184 TEST_LPM_ASSERT(status == 0);
1186 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1187 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1189 status = rte_lpm6_delete(lpm, ip, depth);
1190 TEST_LPM_ASSERT(status == 0);
1192 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1193 TEST_LPM_ASSERT(status == -ENOENT);
1195 rte_lpm6_delete_all(lpm);
1197 /* Delete a rule that is not present in the TBL24 & lookup */
1199 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1203 status = rte_lpm6_delete(lpm, ip, depth);
1204 TEST_LPM_ASSERT(status < 0);
1206 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1207 TEST_LPM_ASSERT(status == -ENOENT);
1209 rte_lpm6_delete_all(lpm);
1211 /* Delete a rule that is not present in the TBL8 & lookup */
1213 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1217 status = rte_lpm6_delete(lpm, ip, depth);
1218 TEST_LPM_ASSERT(status < 0);
1220 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1221 TEST_LPM_ASSERT(status == -ENOENT);
1229 * Add two rules, lookup to hit the more specific one, lookup to hit the less
1230 * specific one delete the less specific rule and lookup previous values again;
1231 * add a more specific rule than the existing rule, lookup again
1236 struct rte_lpm6 *lpm = NULL;
1237 struct rte_lpm6_config config;
1240 uint32_t next_hop_add, next_hop_return;
1243 config.max_rules = MAX_RULES;
1244 config.number_tbl8s = NUMBER_TBL8S;
1247 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1248 TEST_LPM_ASSERT(lpm != NULL);
1250 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1254 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1255 TEST_LPM_ASSERT(status == 0);
1257 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1261 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1262 TEST_LPM_ASSERT(status == 0);
1264 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1265 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1267 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1270 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1271 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1273 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1276 status = rte_lpm6_delete(lpm, ip, depth);
1277 TEST_LPM_ASSERT(status == 0);
1279 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1280 TEST_LPM_ASSERT(status == -ENOENT);
1282 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1285 status = rte_lpm6_delete(lpm, ip, depth);
1286 TEST_LPM_ASSERT(status == 0);
1288 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1289 TEST_LPM_ASSERT(status == -ENOENT);
1297 * Adds 3 rules and look them up through the lookup_bulk function.
1298 * Includes in the lookup a fourth IP address that won't match
1299 * and checks that the result is as expected.
1304 struct rte_lpm6 *lpm = NULL;
1305 struct rte_lpm6_config config;
1306 uint8_t ip_batch[4][16];
1308 uint32_t next_hop_add;
1309 int32_t next_hop_return[4];
1312 config.max_rules = MAX_RULES;
1313 config.number_tbl8s = NUMBER_TBL8S;
1316 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1317 TEST_LPM_ASSERT(lpm != NULL);
1319 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1323 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1324 TEST_LPM_ASSERT(status == 0);
1326 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1330 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1331 TEST_LPM_ASSERT(status == 0);
1333 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1337 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1338 TEST_LPM_ASSERT(status == 0);
1340 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1342 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1343 next_hop_return, 4);
1344 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1345 && next_hop_return[1] == 101 && next_hop_return[2] == 102
1346 && next_hop_return[3] == -1);
1354 * Adds 5 rules and look them up.
1355 * Use the delete_bulk function to delete two of them. Lookup again.
1356 * Use the delete_bulk function to delete one more. Lookup again.
1357 * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1358 * Use the delete_bulk function to delete the remaining one. Lookup again.
1363 struct rte_lpm6 *lpm = NULL;
1364 struct rte_lpm6_config config;
1365 uint8_t ip_batch[5][16];
1367 uint32_t next_hop_add;
1368 int32_t next_hop_return[5];
1371 config.max_rules = MAX_RULES;
1372 config.number_tbl8s = NUMBER_TBL8S;
1375 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1376 TEST_LPM_ASSERT(lpm != NULL);
1378 /* Adds 5 rules and look them up */
1380 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1384 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1385 TEST_LPM_ASSERT(status == 0);
1387 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1391 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1392 TEST_LPM_ASSERT(status == 0);
1394 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1398 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1399 TEST_LPM_ASSERT(status == 0);
1401 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1405 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1406 TEST_LPM_ASSERT(status == 0);
1408 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1412 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
1413 TEST_LPM_ASSERT(status == 0);
1415 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1416 next_hop_return, 5);
1417 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
1418 && next_hop_return[1] == 102 && next_hop_return[2] == 103
1419 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1421 /* Use the delete_bulk function to delete two of them. Lookup again */
1423 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1424 TEST_LPM_ASSERT(status == 0);
1426 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1427 next_hop_return, 5);
1428 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1429 && next_hop_return[1] == -1 && next_hop_return[2] == 103
1430 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1432 /* Use the delete_bulk function to delete one more. Lookup again */
1434 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
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] == -1
1440 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1441 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1443 /* Use the delete_bulk function to delete two, one invalid. Lookup again */
1445 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1446 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1447 TEST_LPM_ASSERT(status == 0);
1449 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1450 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1451 next_hop_return, 5);
1452 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1453 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1454 && next_hop_return[3] == -1 && next_hop_return[4] == 105);
1456 /* Use the delete_bulk function to delete the remaining one. Lookup again */
1458 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1459 TEST_LPM_ASSERT(status == 0);
1461 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1462 next_hop_return, 5);
1463 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1464 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1465 && next_hop_return[3] == -1 && next_hop_return[4] == -1);
1473 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1474 * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
1480 struct rte_lpm6 *lpm = NULL;
1481 struct rte_lpm6_config config;
1485 uint32_t next_hop_add, next_hop_return;
1488 config.max_rules = MAX_RULES;
1489 config.number_tbl8s = NUMBER_TBL8S;
1492 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1493 TEST_LPM_ASSERT(lpm != NULL);
1495 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1499 for (i = 0; i < 30; i++) {
1500 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1501 TEST_LPM_ASSERT(status == 0);
1503 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1504 TEST_LPM_ASSERT((status == 0) &&
1505 (next_hop_return == next_hop_add));
1507 status = rte_lpm6_delete(lpm, ip, depth);
1508 TEST_LPM_ASSERT(status == 0);
1510 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1511 TEST_LPM_ASSERT(status == -ENOENT);
1520 * Sequence of operations for find existing lpm table
1523 * - find existing table: hit
1524 * - find non-existing table: miss
1529 struct rte_lpm6 *lpm = NULL, *result = NULL;
1530 struct rte_lpm6_config config;
1532 config.max_rules = 256 * 32;
1533 config.number_tbl8s = NUMBER_TBL8S;
1537 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1538 TEST_LPM_ASSERT(lpm != NULL);
1540 /* Try to find existing lpm */
1541 result = rte_lpm6_find_existing("lpm_find_existing");
1542 TEST_LPM_ASSERT(result == lpm);
1544 /* Try to find non-existing lpm */
1545 result = rte_lpm6_find_existing("lpm_find_non_existing");
1546 TEST_LPM_ASSERT(result == NULL);
1549 rte_lpm6_delete_all(lpm);
1556 * Add a set of random routes with random depths.
1557 * Lookup different IP addresses that match the routes previously added.
1558 * Checks that the next hop is the expected one.
1559 * The routes, IP addresses and expected result for every case have been
1560 * precalculated by using a python script and stored in a .h file.
1565 struct rte_lpm6 *lpm = NULL;
1566 struct rte_lpm6_config config;
1570 uint32_t next_hop_add, next_hop_return, next_hop_expected;
1573 config.max_rules = MAX_RULES;
1574 config.number_tbl8s = NUMBER_TBL8S;
1577 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1578 TEST_LPM_ASSERT(lpm != NULL);
1580 for (i = 0; i < 1000; i++) {
1581 memcpy(ip, large_route_table[i].ip, 16);
1582 depth = large_route_table[i].depth;
1583 next_hop_add = large_route_table[i].next_hop;
1584 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1585 TEST_LPM_ASSERT(status == 0);
1588 /* generate large IPS table and expected next_hops */
1589 generate_large_ips_table(1);
1591 for (i = 0; i < 100000; i++) {
1592 memcpy(ip, large_ips_table[i].ip, 16);
1593 next_hop_expected = large_ips_table[i].next_hop;
1595 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1596 TEST_LPM_ASSERT((status == 0) &&
1597 (next_hop_return == next_hop_expected));
1606 * Test for overwriting of tbl8:
1607 * - add rule /32 and lookup
1608 * - add new rule /24 and lookup
1609 * - add third rule /25 and lookup
1610 * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1615 struct rte_lpm6 *lpm = NULL;
1616 struct rte_lpm6_config config;
1617 uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1618 uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1619 uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1620 uint8_t d_ip_10_32 = 32;
1621 uint8_t d_ip_10_24 = 24;
1622 uint8_t d_ip_20_25 = 25;
1623 uint32_t next_hop_ip_10_32 = 100;
1624 uint32_t next_hop_ip_10_24 = 105;
1625 uint32_t next_hop_ip_20_25 = 111;
1626 uint32_t next_hop_return = 0;
1629 config.max_rules = MAX_RULES;
1630 config.number_tbl8s = NUMBER_TBL8S;
1633 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1634 TEST_LPM_ASSERT(lpm != NULL);
1636 if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
1637 next_hop_ip_10_32)) < 0)
1640 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1641 uint32_t test_hop_10_32 = next_hop_return;
1642 TEST_LPM_ASSERT(status == 0);
1643 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1645 if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
1646 next_hop_ip_10_24)) < 0)
1649 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1650 uint32_t test_hop_10_24 = next_hop_return;
1651 TEST_LPM_ASSERT(status == 0);
1652 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1654 if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
1655 next_hop_ip_20_25)) < 0)
1658 status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
1659 uint32_t test_hop_20_25 = next_hop_return;
1660 TEST_LPM_ASSERT(status == 0);
1661 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1663 if (test_hop_10_32 == test_hop_10_24) {
1664 printf("Next hop return equal\n");
1668 if (test_hop_10_24 == test_hop_20_25){
1669 printf("Next hop return equal\n");
1673 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1674 TEST_LPM_ASSERT(status == 0);
1675 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1677 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1678 TEST_LPM_ASSERT(status == 0);
1679 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1687 * Add a rule that reaches the end of the tree.
1688 * Add a rule that is more generic than the first one.
1689 * Check every possible combination that produces a match for the second rule.
1690 * This tests tbl expansion.
1695 struct rte_lpm6 *lpm = NULL;
1696 struct rte_lpm6_config config;
1697 uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
1698 uint8_t depth = 128;
1699 uint32_t next_hop_add = 100, next_hop_return;
1703 config.max_rules = MAX_RULES;
1704 config.number_tbl8s = NUMBER_TBL8S;
1707 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1708 TEST_LPM_ASSERT(lpm != NULL);
1712 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1713 TEST_LPM_ASSERT(status == 0);
1717 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1718 TEST_LPM_ASSERT(status == 0);
1720 for (i = 0; i < 256; i++) {
1721 ip[14] = (uint8_t)i;
1722 for (j = 0; j < 256; j++) {
1723 ip[15] = (uint8_t)j;
1724 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1725 if (i == 0 && j == 0)
1726 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1728 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1738 * Call add, lookup and delete for a single rule with maximum 21bit next_hop
1740 * Check that next_hop returned from lookup is equal to provisioned value.
1741 * Delete the rule and check that the same test returs a miss.
1746 struct rte_lpm6 *lpm = NULL;
1747 struct rte_lpm6_config config;
1748 uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1750 uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
1753 config.max_rules = MAX_RULES;
1754 config.number_tbl8s = NUMBER_TBL8S;
1757 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1758 TEST_LPM_ASSERT(lpm != NULL);
1760 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1761 TEST_LPM_ASSERT(status == 0);
1763 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1764 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1766 status = rte_lpm6_delete(lpm, ip, depth);
1767 TEST_LPM_ASSERT(status == 0);
1774 * Do all unit tests.
1780 int status = -1, global_status = 0;
1782 for (i = 0; i < RTE_DIM(tests6); i++) {
1783 printf("# test %02d\n", i);
1784 status = tests6[i]();
1787 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1788 global_status = status;
1792 return global_status;
1795 REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6);