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[] = {
88 #define NUM_LPM6_TESTS (sizeof(tests6)/sizeof(tests6[0]))
90 #define MAX_RULES 1000000
91 #define NUMBER_TBL8S (1 << 16)
92 #define MAX_NUM_TBL8S (1 << 21)
96 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
97 uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
98 uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
120 * Check that rte_lpm6_create fails gracefully for incorrect user input
126 struct rte_lpm6 *lpm = NULL;
127 struct rte_lpm6_config config;
129 config.max_rules = MAX_RULES;
130 config.number_tbl8s = NUMBER_TBL8S;
133 /* rte_lpm6_create: lpm name == NULL */
134 lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
135 TEST_LPM_ASSERT(lpm == NULL);
137 /* rte_lpm6_create: max_rules = 0 */
138 /* Note: __func__ inserts the function name, in this case "test0". */
139 config.max_rules = 0;
140 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
141 TEST_LPM_ASSERT(lpm == NULL);
143 /* socket_id < -1 is invalid */
144 config.max_rules = MAX_RULES;
145 lpm = rte_lpm6_create(__func__, -2, &config);
146 TEST_LPM_ASSERT(lpm == NULL);
148 /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
149 config.number_tbl8s = MAX_NUM_TBL8S + 1;
150 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
151 TEST_LPM_ASSERT(lpm == NULL);
153 /* rte_lpm6_create: config = NULL */
154 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
155 TEST_LPM_ASSERT(lpm == NULL);
161 * Creates two different LPM tables. Tries to create a third one with the same
162 * name as the first one and expects the create function to return the same
168 struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
169 struct rte_lpm6_config config;
171 config.max_rules = MAX_RULES;
172 config.number_tbl8s = NUMBER_TBL8S;
175 /* rte_lpm6_create: lpm name == LPM1 */
176 lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
177 TEST_LPM_ASSERT(lpm1 != NULL);
179 /* rte_lpm6_create: lpm name == LPM2 */
180 lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
181 TEST_LPM_ASSERT(lpm2 != NULL);
183 /* rte_lpm6_create: lpm name == LPM2 */
184 lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
185 TEST_LPM_ASSERT(lpm3 == NULL);
194 * Create lpm table then delete lpm table 20 times
195 * Use a slightly different rules size each time
200 struct rte_lpm6 *lpm = NULL;
201 struct rte_lpm6_config config;
204 config.number_tbl8s = NUMBER_TBL8S;
207 /* rte_lpm6_free: Free NULL */
208 for (i = 0; i < 20; i++) {
209 config.max_rules = MAX_RULES - i;
210 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
211 TEST_LPM_ASSERT(lpm != NULL);
216 /* Can not test free so return success */
221 * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
222 * therefore it is impossible to check for failure but this test is added to
223 * increase function coverage metrics and to validate that freeing null does
229 struct rte_lpm6 *lpm = NULL;
230 struct rte_lpm6_config config;
232 config.max_rules = MAX_RULES;
233 config.number_tbl8s = NUMBER_TBL8S;
236 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
237 TEST_LPM_ASSERT(lpm != NULL);
245 * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
250 struct rte_lpm6 *lpm = NULL;
251 struct rte_lpm6_config config;
253 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
254 uint8_t depth = 24, next_hop = 100;
257 config.max_rules = MAX_RULES;
258 config.number_tbl8s = NUMBER_TBL8S;
261 /* rte_lpm6_add: lpm == NULL */
262 status = rte_lpm6_add(NULL, ip, depth, next_hop);
263 TEST_LPM_ASSERT(status < 0);
265 /*Create vaild lpm to use in rest of test. */
266 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
267 TEST_LPM_ASSERT(lpm != NULL);
269 /* rte_lpm6_add: depth < 1 */
270 status = rte_lpm6_add(lpm, ip, 0, next_hop);
271 TEST_LPM_ASSERT(status < 0);
273 /* rte_lpm6_add: depth > MAX_DEPTH */
274 status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
275 TEST_LPM_ASSERT(status < 0);
283 * Check that rte_lpm6_delete fails gracefully for incorrect user input
289 struct rte_lpm6 *lpm = NULL;
290 struct rte_lpm6_config config;
291 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
295 config.max_rules = MAX_RULES;
296 config.number_tbl8s = NUMBER_TBL8S;
299 /* rte_lpm_delete: lpm == NULL */
300 status = rte_lpm6_delete(NULL, ip, depth);
301 TEST_LPM_ASSERT(status < 0);
303 /*Create vaild lpm to use in rest of test. */
304 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
305 TEST_LPM_ASSERT(lpm != NULL);
307 /* rte_lpm_delete: depth < 1 */
308 status = rte_lpm6_delete(lpm, ip, 0);
309 TEST_LPM_ASSERT(status < 0);
311 /* rte_lpm_delete: depth > MAX_DEPTH */
312 status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
313 TEST_LPM_ASSERT(status < 0);
321 * Check that rte_lpm6_lookup fails gracefully for incorrect user input
327 struct rte_lpm6 *lpm = NULL;
328 struct rte_lpm6_config config;
329 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
330 uint32_t next_hop_return = 0;
333 config.max_rules = MAX_RULES;
334 config.number_tbl8s = NUMBER_TBL8S;
337 /* rte_lpm6_lookup: lpm == NULL */
338 status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
339 TEST_LPM_ASSERT(status < 0);
341 /*Create vaild lpm to use in rest of test. */
342 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
343 TEST_LPM_ASSERT(lpm != NULL);
345 /* rte_lpm6_lookup: ip = NULL */
346 status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
347 TEST_LPM_ASSERT(status < 0);
349 /* rte_lpm6_lookup: next_hop = NULL */
350 status = rte_lpm6_lookup(lpm, ip, NULL);
351 TEST_LPM_ASSERT(status < 0);
359 * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
365 struct rte_lpm6 *lpm = NULL;
366 struct rte_lpm6_config config;
368 int32_t next_hop_return[10];
371 config.max_rules = MAX_RULES;
372 config.number_tbl8s = NUMBER_TBL8S;
375 /* rte_lpm6_lookup: lpm == NULL */
376 status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
377 TEST_LPM_ASSERT(status < 0);
379 /*Create vaild lpm to use in rest of test. */
380 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
381 TEST_LPM_ASSERT(lpm != NULL);
383 /* rte_lpm6_lookup: ip = NULL */
384 status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
385 TEST_LPM_ASSERT(status < 0);
387 /* rte_lpm6_lookup: next_hop = NULL */
388 status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
389 TEST_LPM_ASSERT(status < 0);
397 * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
403 struct rte_lpm6 *lpm = NULL;
404 struct rte_lpm6_config config;
409 config.max_rules = MAX_RULES;
410 config.number_tbl8s = NUMBER_TBL8S;
413 /* rte_lpm6_delete: lpm == NULL */
414 status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
415 TEST_LPM_ASSERT(status < 0);
417 /*Create vaild lpm to use in rest of test. */
418 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
419 TEST_LPM_ASSERT(lpm != NULL);
421 /* rte_lpm6_delete: ip = NULL */
422 status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
423 TEST_LPM_ASSERT(status < 0);
425 /* rte_lpm6_delete: next_hop = NULL */
426 status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
427 TEST_LPM_ASSERT(status < 0);
435 * Call add, lookup and delete for a single rule with depth < 24.
436 * Check all the combinations for the first three bytes that result in a hit.
437 * Delete the rule and check that the same test returs a miss.
442 struct rte_lpm6 *lpm = NULL;
443 struct rte_lpm6_config config;
444 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
446 uint32_t next_hop_add = 100, next_hop_return = 0;
450 config.max_rules = MAX_RULES;
451 config.number_tbl8s = NUMBER_TBL8S;
454 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
455 TEST_LPM_ASSERT(lpm != NULL);
457 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
458 TEST_LPM_ASSERT(status == 0);
460 for (i = 0; i < UINT8_MAX; i++) {
462 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
463 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
466 status = rte_lpm6_delete(lpm, ip, depth);
467 TEST_LPM_ASSERT(status == 0);
469 for (i = 0; i < UINT8_MAX; i++) {
471 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
472 TEST_LPM_ASSERT(status == -ENOENT);
481 * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
482 * another one and expects success.
487 struct rte_lpm6 *lpm = NULL;
488 struct rte_lpm6_config config;
489 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
491 uint32_t next_hop_add = 100;
495 config.max_rules = 127;
496 config.number_tbl8s = NUMBER_TBL8S;
499 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
500 TEST_LPM_ASSERT(lpm != NULL);
502 for (i = 1; i < 128; i++) {
504 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
505 TEST_LPM_ASSERT(status == 0);
509 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
510 TEST_LPM_ASSERT(status == -ENOSPC);
513 status = rte_lpm6_delete(lpm, ip, depth);
514 TEST_LPM_ASSERT(status == 0);
517 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
518 TEST_LPM_ASSERT(status == 0);
526 * Creates an LPM table with a small number of tbl8s and exhaust them in the
527 * middle of the process of creating a rule.
532 struct rte_lpm6 *lpm = NULL;
533 struct rte_lpm6_config config;
534 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
536 uint32_t next_hop_add = 100;
539 config.max_rules = MAX_RULES;
540 config.number_tbl8s = 16;
543 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
544 TEST_LPM_ASSERT(lpm != NULL);
547 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
548 TEST_LPM_ASSERT(status == 0);
552 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
553 TEST_LPM_ASSERT(status == 0);
555 status = rte_lpm6_delete(lpm, ip, depth);
556 TEST_LPM_ASSERT(status == 0);
559 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
560 TEST_LPM_ASSERT(status == 0);
562 status = rte_lpm6_delete(lpm, ip, depth);
563 TEST_LPM_ASSERT(status == 0);
566 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
567 TEST_LPM_ASSERT(status == 0);
569 status = rte_lpm6_delete(lpm, ip, depth);
570 TEST_LPM_ASSERT(status == 0);
573 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
574 TEST_LPM_ASSERT(status == -ENOSPC);
577 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
578 TEST_LPM_ASSERT(status == 0);
586 * Creates an LPM table with a small number of tbl8s and exhaust them in the
587 * middle of the process of adding a rule when there is already an existing rule
588 * in that position and needs to be extended.
593 struct rte_lpm6 *lpm = NULL;
594 struct rte_lpm6_config config;
595 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
597 uint32_t next_hop_add = 100;
600 config.max_rules = MAX_RULES;
601 config.number_tbl8s = 16;
604 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
605 TEST_LPM_ASSERT(lpm != NULL);
608 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
609 TEST_LPM_ASSERT(status == 0);
613 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
614 TEST_LPM_ASSERT(status == 0);
617 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
618 TEST_LPM_ASSERT(status == -ENOSPC);
626 * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
627 * Delete one of the rules and tries to add the third one again.
632 struct rte_lpm6 *lpm = NULL;
633 struct rte_lpm6_config config;
634 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
636 uint32_t next_hop_add = 100;
639 config.max_rules = 2;
640 config.number_tbl8s = NUMBER_TBL8S;
643 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
644 TEST_LPM_ASSERT(lpm != NULL);
647 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
648 TEST_LPM_ASSERT(status == 0);
651 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
652 TEST_LPM_ASSERT(status == 0);
655 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
656 TEST_LPM_ASSERT(status == -ENOSPC);
659 status = rte_lpm6_delete(lpm, ip, depth);
660 TEST_LPM_ASSERT(status == 0);
663 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
664 TEST_LPM_ASSERT(status == 0);
672 * Add 2^12 routes with different first 12 bits and depth 25.
673 * Add one more route with the same depth and check that results in a failure.
674 * After that delete the last rule and create the one that was attempted to be
675 * created. This checks tbl8 exhaustion.
680 struct rte_lpm6 *lpm = NULL;
681 struct rte_lpm6_config config;
682 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
684 uint32_t next_hop_add = 100;
688 config.max_rules = MAX_RULES;
689 config.number_tbl8s = 256;
692 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
693 TEST_LPM_ASSERT(lpm != NULL);
695 for (i = 0; i < 256; i++) {
697 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
698 TEST_LPM_ASSERT(status == 0);
703 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
704 TEST_LPM_ASSERT(status == -ENOSPC);
708 status = rte_lpm6_delete(lpm, ip, depth);
709 TEST_LPM_ASSERT(status == 0);
713 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
714 TEST_LPM_ASSERT(status == 0);
722 * Call add, lookup and delete for a single rule with depth = 24
727 struct rte_lpm6 *lpm = NULL;
728 struct rte_lpm6_config config;
729 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
731 uint32_t next_hop_add = 100, next_hop_return = 0;
734 config.max_rules = MAX_RULES;
735 config.number_tbl8s = NUMBER_TBL8S;
738 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
739 TEST_LPM_ASSERT(lpm != NULL);
741 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
742 TEST_LPM_ASSERT(status == 0);
744 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
745 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
747 status = rte_lpm6_delete(lpm, ip, depth);
748 TEST_LPM_ASSERT(status == 0);
750 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
751 TEST_LPM_ASSERT(status == -ENOENT);
759 * Call add, lookup and delete for a single rule with depth > 24
764 struct rte_lpm6 *lpm = NULL;
765 struct rte_lpm6_config config;
766 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
768 uint32_t next_hop_add = 100, next_hop_return = 0;
771 config.max_rules = MAX_RULES;
772 config.number_tbl8s = NUMBER_TBL8S;
775 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
776 TEST_LPM_ASSERT(lpm != NULL);
778 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
779 TEST_LPM_ASSERT(status == 0);
781 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
782 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
784 status = rte_lpm6_delete(lpm, ip, depth);
785 TEST_LPM_ASSERT(status == 0);
787 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
788 TEST_LPM_ASSERT(status == -ENOENT);
796 * Use rte_lpm6_add to add rules which effect only the second half of the lpm
797 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
798 * depth. Check lookup hit for on every add and check for lookup miss on the
799 * first half of the lpm table after each add. Finally delete all rules going
800 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
801 * delete. The lookup should return the next_hop_add value related to the
802 * previous depth value (i.e. depth -1).
807 struct rte_lpm6 *lpm = NULL;
808 struct rte_lpm6_config config;
809 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
810 255,255,255,255,255,255,255};
811 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
813 uint32_t next_hop_add, next_hop_return;
816 config.max_rules = MAX_RULES;
817 config.number_tbl8s = NUMBER_TBL8S;
820 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
821 TEST_LPM_ASSERT(lpm != NULL);
823 /* Loop with rte_lpm6_add. */
824 for (depth = 1; depth <= 16; depth++) {
825 /* Let the next_hop_add value = depth. Just for change. */
826 next_hop_add = depth;
828 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
829 TEST_LPM_ASSERT(status == 0);
831 /* Check IP in first half of tbl24 which should be empty. */
832 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
833 TEST_LPM_ASSERT(status == -ENOENT);
835 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
836 TEST_LPM_ASSERT((status == 0) &&
837 (next_hop_return == next_hop_add));
840 /* Loop with rte_lpm6_delete. */
841 for (depth = 16; depth >= 1; depth--) {
842 next_hop_add = (depth - 1);
844 status = rte_lpm6_delete(lpm, ip2, depth);
845 TEST_LPM_ASSERT(status == 0);
847 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
850 TEST_LPM_ASSERT((status == 0) &&
851 (next_hop_return == next_hop_add));
854 TEST_LPM_ASSERT(status == -ENOENT);
857 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
858 TEST_LPM_ASSERT(status == -ENOENT);
867 * - Add & lookup to hit invalid TBL24 entry
868 * - Add & lookup to hit valid TBL24 entry not extended
869 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
870 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
875 struct rte_lpm6 *lpm = NULL;
876 struct rte_lpm6_config config;
877 uint8_t ip[16], ip_1[16], ip_2[16];
878 uint8_t depth, depth_1, depth_2;
879 uint32_t next_hop_add, next_hop_add_1,
880 next_hop_add_2, next_hop_return;
883 config.max_rules = MAX_RULES;
884 config.number_tbl8s = NUMBER_TBL8S;
887 /* Add & lookup to hit invalid TBL24 entry */
888 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
892 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
893 TEST_LPM_ASSERT(lpm != NULL);
895 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
896 TEST_LPM_ASSERT(status == 0);
898 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
899 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
901 status = rte_lpm6_delete(lpm, ip, depth);
902 TEST_LPM_ASSERT(status == 0);
904 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
905 TEST_LPM_ASSERT(status == -ENOENT);
907 rte_lpm6_delete_all(lpm);
909 /* Add & lookup to hit valid TBL24 entry not extended */
910 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
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));
923 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
924 TEST_LPM_ASSERT(status == 0);
926 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
927 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
931 status = rte_lpm6_delete(lpm, ip, depth);
932 TEST_LPM_ASSERT(status == 0);
936 status = rte_lpm6_delete(lpm, ip, depth);
937 TEST_LPM_ASSERT(status == 0);
939 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
940 TEST_LPM_ASSERT(status == -ENOENT);
942 rte_lpm6_delete_all(lpm);
944 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
947 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
951 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
952 TEST_LPM_ASSERT(status == 0);
954 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
955 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
957 IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
961 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
962 TEST_LPM_ASSERT(status == 0);
964 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
965 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
967 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
971 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
972 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
974 status = rte_lpm6_delete(lpm, ip, depth);
975 TEST_LPM_ASSERT(status == 0);
977 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
978 TEST_LPM_ASSERT(status == -ENOENT);
980 rte_lpm6_delete_all(lpm);
982 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
985 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
987 next_hop_add_1 = 101;
989 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
991 next_hop_add_2 = 102;
995 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
996 TEST_LPM_ASSERT(status == 0);
998 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
999 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1001 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1002 TEST_LPM_ASSERT(status == 0);
1004 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1005 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1007 status = rte_lpm6_delete(lpm, ip_2, depth_2);
1008 TEST_LPM_ASSERT(status == 0);
1010 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1011 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1013 status = rte_lpm6_delete(lpm, ip_1, depth_1);
1014 TEST_LPM_ASSERT(status == 0);
1016 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1017 TEST_LPM_ASSERT(status == -ENOENT);
1025 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1027 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1028 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1030 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1031 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1032 * - Delete a rule that is not present in the TBL24 & lookup
1033 * - Delete a rule that is not present in the TBL8 & lookup
1038 struct rte_lpm6 *lpm = NULL;
1039 struct rte_lpm6_config config;
1042 uint32_t next_hop_add, next_hop_return;
1045 config.max_rules = MAX_RULES;
1046 config.number_tbl8s = NUMBER_TBL8S;
1049 /* Add rule that covers a TBL24 range previously invalid & lookup
1050 * (& delete & lookup)
1052 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1053 TEST_LPM_ASSERT(lpm != NULL);
1055 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1059 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1060 TEST_LPM_ASSERT(status == 0);
1062 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1063 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1065 status = rte_lpm6_delete(lpm, ip, depth);
1066 TEST_LPM_ASSERT(status == 0);
1068 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1069 TEST_LPM_ASSERT(status == -ENOENT);
1071 rte_lpm6_delete_all(lpm);
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 rte_lpm6_delete_all(lpm);
1089 * Add rule that extends a TBL24 valid entry & lookup for both rules
1090 * (& delete & lookup)
1093 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1097 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1098 TEST_LPM_ASSERT(status == 0);
1100 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1104 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1105 TEST_LPM_ASSERT(status == 0);
1107 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1108 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1110 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1113 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1114 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1116 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1119 status = rte_lpm6_delete(lpm, ip, depth);
1120 TEST_LPM_ASSERT(status == 0);
1122 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1123 TEST_LPM_ASSERT(status == -ENOENT);
1125 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1128 status = rte_lpm6_delete(lpm, ip, depth);
1129 TEST_LPM_ASSERT(status == 0);
1131 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1132 TEST_LPM_ASSERT(status == -ENOENT);
1134 rte_lpm6_delete_all(lpm);
1137 * Add rule that updates the next hop in TBL24 & lookup
1138 * (& delete & lookup)
1141 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1145 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1146 TEST_LPM_ASSERT(status == 0);
1148 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1149 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1153 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1154 TEST_LPM_ASSERT(status == 0);
1156 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1157 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1159 status = rte_lpm6_delete(lpm, ip, depth);
1160 TEST_LPM_ASSERT(status == 0);
1162 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1163 TEST_LPM_ASSERT(status == -ENOENT);
1165 rte_lpm6_delete_all(lpm);
1168 * Add rule that updates the next hop in TBL8 & lookup
1169 * (& delete & lookup)
1172 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1176 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1177 TEST_LPM_ASSERT(status == 0);
1179 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1180 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1184 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1185 TEST_LPM_ASSERT(status == 0);
1187 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1188 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1190 status = rte_lpm6_delete(lpm, ip, depth);
1191 TEST_LPM_ASSERT(status == 0);
1193 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1194 TEST_LPM_ASSERT(status == -ENOENT);
1196 rte_lpm6_delete_all(lpm);
1198 /* Delete a rule that is not present in the TBL24 & lookup */
1200 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1204 status = rte_lpm6_delete(lpm, ip, depth);
1205 TEST_LPM_ASSERT(status < 0);
1207 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1208 TEST_LPM_ASSERT(status == -ENOENT);
1210 rte_lpm6_delete_all(lpm);
1212 /* Delete a rule that is not present in the TBL8 & lookup */
1214 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1218 status = rte_lpm6_delete(lpm, ip, depth);
1219 TEST_LPM_ASSERT(status < 0);
1221 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1222 TEST_LPM_ASSERT(status == -ENOENT);
1230 * Add two rules, lookup to hit the more specific one, lookup to hit the less
1231 * specific one delete the less specific rule and lookup previous values again;
1232 * add a more specific rule than the existing rule, lookup again
1237 struct rte_lpm6 *lpm = NULL;
1238 struct rte_lpm6_config config;
1241 uint32_t next_hop_add, next_hop_return;
1244 config.max_rules = MAX_RULES;
1245 config.number_tbl8s = NUMBER_TBL8S;
1248 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1249 TEST_LPM_ASSERT(lpm != NULL);
1251 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1255 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1256 TEST_LPM_ASSERT(status == 0);
1258 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1262 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1263 TEST_LPM_ASSERT(status == 0);
1265 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1266 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1268 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1271 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1272 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1274 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1277 status = rte_lpm6_delete(lpm, ip, depth);
1278 TEST_LPM_ASSERT(status == 0);
1280 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1281 TEST_LPM_ASSERT(status == -ENOENT);
1283 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1286 status = rte_lpm6_delete(lpm, ip, depth);
1287 TEST_LPM_ASSERT(status == 0);
1289 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1290 TEST_LPM_ASSERT(status == -ENOENT);
1298 * Adds 3 rules and look them up through the lookup_bulk function.
1299 * Includes in the lookup a fourth IP address that won't match
1300 * and checks that the result is as expected.
1305 struct rte_lpm6 *lpm = NULL;
1306 struct rte_lpm6_config config;
1307 uint8_t ip_batch[4][16];
1309 uint32_t next_hop_add;
1310 int32_t next_hop_return[4];
1313 config.max_rules = MAX_RULES;
1314 config.number_tbl8s = NUMBER_TBL8S;
1317 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1318 TEST_LPM_ASSERT(lpm != NULL);
1320 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1324 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1325 TEST_LPM_ASSERT(status == 0);
1327 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1331 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1332 TEST_LPM_ASSERT(status == 0);
1334 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1338 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1339 TEST_LPM_ASSERT(status == 0);
1341 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1343 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1344 next_hop_return, 4);
1345 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1346 && next_hop_return[1] == 101 && next_hop_return[2] == 102
1347 && next_hop_return[3] == -1);
1355 * Adds 5 rules and look them up.
1356 * Use the delete_bulk function to delete two of them. Lookup again.
1357 * Use the delete_bulk function to delete one more. Lookup again.
1358 * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1359 * Use the delete_bulk function to delete the remaining one. Lookup again.
1364 struct rte_lpm6 *lpm = NULL;
1365 struct rte_lpm6_config config;
1366 uint8_t ip_batch[5][16];
1368 uint32_t next_hop_add;
1369 int32_t next_hop_return[5];
1372 config.max_rules = MAX_RULES;
1373 config.number_tbl8s = NUMBER_TBL8S;
1376 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1377 TEST_LPM_ASSERT(lpm != NULL);
1379 /* Adds 5 rules and look them up */
1381 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1385 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1386 TEST_LPM_ASSERT(status == 0);
1388 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1392 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1393 TEST_LPM_ASSERT(status == 0);
1395 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1399 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1400 TEST_LPM_ASSERT(status == 0);
1402 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1406 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1407 TEST_LPM_ASSERT(status == 0);
1409 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1413 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
1414 TEST_LPM_ASSERT(status == 0);
1416 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1417 next_hop_return, 5);
1418 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
1419 && next_hop_return[1] == 102 && next_hop_return[2] == 103
1420 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1422 /* Use the delete_bulk function to delete two of them. Lookup again */
1424 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1425 TEST_LPM_ASSERT(status == 0);
1427 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1428 next_hop_return, 5);
1429 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1430 && next_hop_return[1] == -1 && next_hop_return[2] == 103
1431 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1433 /* Use the delete_bulk function to delete one more. Lookup again */
1435 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1436 TEST_LPM_ASSERT(status == 0);
1438 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1439 next_hop_return, 5);
1440 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1441 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1442 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1444 /* Use the delete_bulk function to delete two, one invalid. Lookup again */
1446 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1447 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1448 TEST_LPM_ASSERT(status == 0);
1450 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1451 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1452 next_hop_return, 5);
1453 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1454 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1455 && next_hop_return[3] == -1 && next_hop_return[4] == 105);
1457 /* Use the delete_bulk function to delete the remaining one. Lookup again */
1459 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1460 TEST_LPM_ASSERT(status == 0);
1462 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1463 next_hop_return, 5);
1464 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1465 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1466 && next_hop_return[3] == -1 && next_hop_return[4] == -1);
1474 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1475 * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
1481 struct rte_lpm6 *lpm = NULL;
1482 struct rte_lpm6_config config;
1486 uint32_t next_hop_add, next_hop_return;
1489 config.max_rules = MAX_RULES;
1490 config.number_tbl8s = NUMBER_TBL8S;
1493 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1494 TEST_LPM_ASSERT(lpm != NULL);
1496 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1500 for (i = 0; i < 30; i++) {
1501 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1502 TEST_LPM_ASSERT(status == 0);
1504 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1505 TEST_LPM_ASSERT((status == 0) &&
1506 (next_hop_return == next_hop_add));
1508 status = rte_lpm6_delete(lpm, ip, depth);
1509 TEST_LPM_ASSERT(status == 0);
1511 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1512 TEST_LPM_ASSERT(status == -ENOENT);
1521 * Sequence of operations for find existing lpm table
1524 * - find existing table: hit
1525 * - find non-existing table: miss
1530 struct rte_lpm6 *lpm = NULL, *result = NULL;
1531 struct rte_lpm6_config config;
1533 config.max_rules = 256 * 32;
1534 config.number_tbl8s = NUMBER_TBL8S;
1538 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1539 TEST_LPM_ASSERT(lpm != NULL);
1541 /* Try to find existing lpm */
1542 result = rte_lpm6_find_existing("lpm_find_existing");
1543 TEST_LPM_ASSERT(result == lpm);
1545 /* Try to find non-existing lpm */
1546 result = rte_lpm6_find_existing("lpm_find_non_existing");
1547 TEST_LPM_ASSERT(result == NULL);
1550 rte_lpm6_delete_all(lpm);
1557 * Add a set of random routes with random depths.
1558 * Lookup different IP addresses that match the routes previously added.
1559 * Checks that the next hop is the expected one.
1560 * The routes, IP addresses and expected result for every case have been
1561 * precalculated by using a python script and stored in a .h file.
1566 struct rte_lpm6 *lpm = NULL;
1567 struct rte_lpm6_config config;
1571 uint32_t next_hop_add, next_hop_return, next_hop_expected;
1574 config.max_rules = MAX_RULES;
1575 config.number_tbl8s = NUMBER_TBL8S;
1578 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1579 TEST_LPM_ASSERT(lpm != NULL);
1581 for (i = 0; i < 1000; i++) {
1582 memcpy(ip, large_route_table[i].ip, 16);
1583 depth = large_route_table[i].depth;
1584 next_hop_add = large_route_table[i].next_hop;
1585 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1586 TEST_LPM_ASSERT(status == 0);
1589 /* generate large IPS table and expected next_hops */
1590 generate_large_ips_table(1);
1592 for (i = 0; i < 100000; i++) {
1593 memcpy(ip, large_ips_table[i].ip, 16);
1594 next_hop_expected = large_ips_table[i].next_hop;
1596 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1597 TEST_LPM_ASSERT((status == 0) &&
1598 (next_hop_return == next_hop_expected));
1607 * Test for overwriting of tbl8:
1608 * - add rule /32 and lookup
1609 * - add new rule /24 and lookup
1610 * - add third rule /25 and lookup
1611 * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1616 struct rte_lpm6 *lpm = NULL;
1617 struct rte_lpm6_config config;
1618 uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1619 uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1620 uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1621 uint8_t d_ip_10_32 = 32;
1622 uint8_t d_ip_10_24 = 24;
1623 uint8_t d_ip_20_25 = 25;
1624 uint32_t next_hop_ip_10_32 = 100;
1625 uint32_t next_hop_ip_10_24 = 105;
1626 uint32_t next_hop_ip_20_25 = 111;
1627 uint32_t next_hop_return = 0;
1630 config.max_rules = MAX_RULES;
1631 config.number_tbl8s = NUMBER_TBL8S;
1634 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1635 TEST_LPM_ASSERT(lpm != NULL);
1637 if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
1638 next_hop_ip_10_32)) < 0)
1641 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1642 uint32_t test_hop_10_32 = next_hop_return;
1643 TEST_LPM_ASSERT(status == 0);
1644 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1646 if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
1647 next_hop_ip_10_24)) < 0)
1650 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1651 uint32_t test_hop_10_24 = next_hop_return;
1652 TEST_LPM_ASSERT(status == 0);
1653 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1655 if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
1656 next_hop_ip_20_25)) < 0)
1659 status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
1660 uint32_t test_hop_20_25 = next_hop_return;
1661 TEST_LPM_ASSERT(status == 0);
1662 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1664 if (test_hop_10_32 == test_hop_10_24) {
1665 printf("Next hop return equal\n");
1669 if (test_hop_10_24 == test_hop_20_25){
1670 printf("Next hop return equal\n");
1674 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1675 TEST_LPM_ASSERT(status == 0);
1676 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1678 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1679 TEST_LPM_ASSERT(status == 0);
1680 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1688 * Add a rule that reaches the end of the tree.
1689 * Add a rule that is more generic than the first one.
1690 * Check every possible combination that produces a match for the second rule.
1691 * This tests tbl expansion.
1696 struct rte_lpm6 *lpm = NULL;
1697 struct rte_lpm6_config config;
1698 uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
1699 uint8_t depth = 128;
1700 uint32_t next_hop_add = 100, next_hop_return;
1704 config.max_rules = MAX_RULES;
1705 config.number_tbl8s = NUMBER_TBL8S;
1708 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1709 TEST_LPM_ASSERT(lpm != NULL);
1713 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1714 TEST_LPM_ASSERT(status == 0);
1718 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1719 TEST_LPM_ASSERT(status == 0);
1721 for (i = 0; i < 256; i++) {
1722 ip[14] = (uint8_t)i;
1723 for (j = 0; j < 256; j++) {
1724 ip[15] = (uint8_t)j;
1725 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1726 if (i == 0 && j == 0)
1727 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1729 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1739 * Call add, lookup and delete for a single rule with maximum 21bit next_hop
1741 * Check that next_hop returned from lookup is equal to provisioned value.
1742 * Delete the rule and check that the same test returs a miss.
1747 struct rte_lpm6 *lpm = NULL;
1748 struct rte_lpm6_config config;
1749 uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1751 uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
1754 config.max_rules = MAX_RULES;
1755 config.number_tbl8s = NUMBER_TBL8S;
1758 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1759 TEST_LPM_ASSERT(lpm != NULL);
1761 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1762 TEST_LPM_ASSERT(status == 0);
1764 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1765 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1767 status = rte_lpm6_delete(lpm, ip, depth);
1768 TEST_LPM_ASSERT(status == 0);
1775 * Do all unit tests.
1781 int status = -1, global_status = 0;
1783 for (i = 0; i < NUM_LPM6_TESTS; i++) {
1784 printf("# test %02d\n", i);
1785 status = tests6[i]();
1788 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1789 global_status = status;
1793 return global_status;
1796 REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6);