1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
12 #include <rte_memory.h>
13 #ifdef RTE_EXEC_ENV_WINDOWS
17 printf("lpm6 not supported on Windows, skipping test\n");
25 #include "test_lpm6_data.h"
27 #define TEST_LPM_ASSERT(cond) do { \
29 printf("Error at line %d: \n", __LINE__); \
34 typedef int32_t (* rte_lpm6_test)(void);
36 static int32_t test0(void);
37 static int32_t test1(void);
38 static int32_t test2(void);
39 static int32_t test3(void);
40 static int32_t test4(void);
41 static int32_t test5(void);
42 static int32_t test6(void);
43 static int32_t test7(void);
44 static int32_t test8(void);
45 static int32_t test9(void);
46 static int32_t test10(void);
47 static int32_t test11(void);
48 static int32_t test12(void);
49 static int32_t test13(void);
50 static int32_t test14(void);
51 static int32_t test15(void);
52 static int32_t test16(void);
53 static int32_t test17(void);
54 static int32_t test18(void);
55 static int32_t test19(void);
56 static int32_t test20(void);
57 static int32_t test21(void);
58 static int32_t test22(void);
59 static int32_t test23(void);
60 static int32_t test24(void);
61 static int32_t test25(void);
62 static int32_t test26(void);
63 static int32_t test27(void);
64 static int32_t test28(void);
66 rte_lpm6_test tests6[] = {
100 #define MAX_RULES 1000000
101 #define NUMBER_TBL8S (1 << 16)
102 #define MAX_NUM_TBL8S (1 << 21)
106 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
107 uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
108 uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
130 * Check that rte_lpm6_create fails gracefully for incorrect user input
136 struct rte_lpm6 *lpm = NULL;
137 struct rte_lpm6_config config;
139 config.max_rules = MAX_RULES;
140 config.number_tbl8s = NUMBER_TBL8S;
143 /* rte_lpm6_create: lpm name == NULL */
144 lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
145 TEST_LPM_ASSERT(lpm == NULL);
147 /* rte_lpm6_create: max_rules = 0 */
148 /* Note: __func__ inserts the function name, in this case "test0". */
149 config.max_rules = 0;
150 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
151 TEST_LPM_ASSERT(lpm == NULL);
153 /* socket_id < -1 is invalid */
154 config.max_rules = MAX_RULES;
155 lpm = rte_lpm6_create(__func__, -2, &config);
156 TEST_LPM_ASSERT(lpm == NULL);
158 /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
159 config.number_tbl8s = MAX_NUM_TBL8S + 1;
160 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
161 TEST_LPM_ASSERT(lpm == NULL);
163 /* rte_lpm6_create: config = NULL */
164 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
165 TEST_LPM_ASSERT(lpm == NULL);
171 * Creates two different LPM tables. Tries to create a third one with the same
172 * name as the first one and expects the create function to return the same
178 struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
179 struct rte_lpm6_config config;
181 config.max_rules = MAX_RULES;
182 config.number_tbl8s = NUMBER_TBL8S;
185 /* rte_lpm6_create: lpm name == LPM1 */
186 lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
187 TEST_LPM_ASSERT(lpm1 != NULL);
189 /* rte_lpm6_create: lpm name == LPM2 */
190 lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
191 TEST_LPM_ASSERT(lpm2 != NULL);
193 /* rte_lpm6_create: lpm name == LPM2 */
194 lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
195 TEST_LPM_ASSERT(lpm3 == NULL);
204 * Create lpm table then delete lpm table 20 times
205 * Use a slightly different rules size each time
210 struct rte_lpm6 *lpm = NULL;
211 struct rte_lpm6_config config;
214 config.number_tbl8s = NUMBER_TBL8S;
217 /* rte_lpm6_free: Free NULL */
218 for (i = 0; i < 20; i++) {
219 config.max_rules = MAX_RULES - i;
220 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
221 TEST_LPM_ASSERT(lpm != NULL);
226 /* Can not test free so return success */
231 * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
232 * therefore it is impossible to check for failure but this test is added to
233 * increase function coverage metrics and to validate that freeing null does
239 struct rte_lpm6 *lpm = NULL;
240 struct rte_lpm6_config config;
242 config.max_rules = MAX_RULES;
243 config.number_tbl8s = NUMBER_TBL8S;
246 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
247 TEST_LPM_ASSERT(lpm != NULL);
255 * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
260 struct rte_lpm6 *lpm = NULL;
261 struct rte_lpm6_config config;
263 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
264 uint8_t depth = 24, next_hop = 100;
267 config.max_rules = MAX_RULES;
268 config.number_tbl8s = NUMBER_TBL8S;
271 /* rte_lpm6_add: lpm == NULL */
272 status = rte_lpm6_add(NULL, ip, depth, next_hop);
273 TEST_LPM_ASSERT(status < 0);
275 /*Create valid lpm to use in rest of test. */
276 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
277 TEST_LPM_ASSERT(lpm != NULL);
279 /* rte_lpm6_add: depth < 1 */
280 status = rte_lpm6_add(lpm, ip, 0, next_hop);
281 TEST_LPM_ASSERT(status < 0);
283 /* rte_lpm6_add: depth > MAX_DEPTH */
284 status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
285 TEST_LPM_ASSERT(status < 0);
293 * Check that rte_lpm6_delete fails gracefully for incorrect user input
299 struct rte_lpm6 *lpm = NULL;
300 struct rte_lpm6_config config;
301 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
305 config.max_rules = MAX_RULES;
306 config.number_tbl8s = NUMBER_TBL8S;
309 /* rte_lpm_delete: lpm == NULL */
310 status = rte_lpm6_delete(NULL, ip, depth);
311 TEST_LPM_ASSERT(status < 0);
313 /*Create valid lpm to use in rest of test. */
314 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
315 TEST_LPM_ASSERT(lpm != NULL);
317 /* rte_lpm_delete: depth < 1 */
318 status = rte_lpm6_delete(lpm, ip, 0);
319 TEST_LPM_ASSERT(status < 0);
321 /* rte_lpm_delete: depth > MAX_DEPTH */
322 status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
323 TEST_LPM_ASSERT(status < 0);
331 * Check that rte_lpm6_lookup fails gracefully for incorrect user input
337 struct rte_lpm6 *lpm = NULL;
338 struct rte_lpm6_config config;
339 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
340 uint32_t next_hop_return = 0;
343 config.max_rules = MAX_RULES;
344 config.number_tbl8s = NUMBER_TBL8S;
347 /* rte_lpm6_lookup: lpm == NULL */
348 status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
349 TEST_LPM_ASSERT(status < 0);
351 /*Create valid lpm to use in rest of test. */
352 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
353 TEST_LPM_ASSERT(lpm != NULL);
355 /* rte_lpm6_lookup: ip = NULL */
356 status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
357 TEST_LPM_ASSERT(status < 0);
359 /* rte_lpm6_lookup: next_hop = NULL */
360 status = rte_lpm6_lookup(lpm, ip, NULL);
361 TEST_LPM_ASSERT(status < 0);
369 * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
375 struct rte_lpm6 *lpm = NULL;
376 struct rte_lpm6_config config;
378 int32_t next_hop_return[10];
381 config.max_rules = MAX_RULES;
382 config.number_tbl8s = NUMBER_TBL8S;
385 /* rte_lpm6_lookup: lpm == NULL */
386 status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
387 TEST_LPM_ASSERT(status < 0);
389 /*Create valid lpm to use in rest of test. */
390 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
391 TEST_LPM_ASSERT(lpm != NULL);
393 /* rte_lpm6_lookup: ip = NULL */
394 status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
395 TEST_LPM_ASSERT(status < 0);
397 /* rte_lpm6_lookup: next_hop = NULL */
398 status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
399 TEST_LPM_ASSERT(status < 0);
407 * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
413 struct rte_lpm6 *lpm = NULL;
414 struct rte_lpm6_config config;
419 config.max_rules = MAX_RULES;
420 config.number_tbl8s = NUMBER_TBL8S;
423 /* rte_lpm6_delete: lpm == NULL */
424 status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
425 TEST_LPM_ASSERT(status < 0);
427 /*Create valid lpm to use in rest of test. */
428 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
429 TEST_LPM_ASSERT(lpm != NULL);
431 /* rte_lpm6_delete: ip = NULL */
432 status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
433 TEST_LPM_ASSERT(status < 0);
435 /* rte_lpm6_delete: next_hop = NULL */
436 status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
437 TEST_LPM_ASSERT(status < 0);
445 * Call add, lookup and delete for a single rule with depth < 24.
446 * Check all the combinations for the first three bytes that result in a hit.
447 * Delete the rule and check that the same test returns a miss.
452 struct rte_lpm6 *lpm = NULL;
453 struct rte_lpm6_config config;
454 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
456 uint32_t next_hop_add = 100, next_hop_return = 0;
460 config.max_rules = MAX_RULES;
461 config.number_tbl8s = NUMBER_TBL8S;
464 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
465 TEST_LPM_ASSERT(lpm != NULL);
467 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
468 TEST_LPM_ASSERT(status == 0);
470 for (i = 0; i < UINT8_MAX; i++) {
472 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
473 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
476 status = rte_lpm6_delete(lpm, ip, depth);
477 TEST_LPM_ASSERT(status == 0);
479 for (i = 0; i < UINT8_MAX; i++) {
481 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
482 TEST_LPM_ASSERT(status == -ENOENT);
491 * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
492 * another one and expects success.
497 struct rte_lpm6 *lpm = NULL;
498 struct rte_lpm6_config config;
499 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
501 uint32_t next_hop_add = 100;
505 config.max_rules = 127;
506 config.number_tbl8s = NUMBER_TBL8S;
509 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
510 TEST_LPM_ASSERT(lpm != NULL);
512 for (i = 1; i < 128; i++) {
514 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
515 TEST_LPM_ASSERT(status == 0);
519 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
520 TEST_LPM_ASSERT(status == -ENOSPC);
523 status = rte_lpm6_delete(lpm, ip, depth);
524 TEST_LPM_ASSERT(status == 0);
527 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
528 TEST_LPM_ASSERT(status == 0);
536 * Creates an LPM table with a small number of tbl8s and exhaust them in the
537 * middle of the process of creating a rule.
542 struct rte_lpm6 *lpm = NULL;
543 struct rte_lpm6_config config;
544 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
546 uint32_t next_hop_add = 100;
549 config.max_rules = MAX_RULES;
550 config.number_tbl8s = 16;
553 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
554 TEST_LPM_ASSERT(lpm != NULL);
557 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
558 TEST_LPM_ASSERT(status == 0);
562 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
563 TEST_LPM_ASSERT(status == 0);
565 status = rte_lpm6_delete(lpm, ip, depth);
566 TEST_LPM_ASSERT(status == 0);
569 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
570 TEST_LPM_ASSERT(status == 0);
572 status = rte_lpm6_delete(lpm, ip, depth);
573 TEST_LPM_ASSERT(status == 0);
576 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
577 TEST_LPM_ASSERT(status == 0);
579 status = rte_lpm6_delete(lpm, ip, depth);
580 TEST_LPM_ASSERT(status == 0);
583 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
584 TEST_LPM_ASSERT(status == -ENOSPC);
587 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
588 TEST_LPM_ASSERT(status == 0);
596 * Creates an LPM table with a small number of tbl8s and exhaust them in the
597 * middle of the process of adding a rule when there is already an existing rule
598 * in that position and needs to be extended.
603 struct rte_lpm6 *lpm = NULL;
604 struct rte_lpm6_config config;
605 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
607 uint32_t next_hop_add = 100;
610 config.max_rules = MAX_RULES;
611 config.number_tbl8s = 16;
614 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
615 TEST_LPM_ASSERT(lpm != NULL);
618 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
619 TEST_LPM_ASSERT(status == 0);
623 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
624 TEST_LPM_ASSERT(status == 0);
627 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
628 TEST_LPM_ASSERT(status == -ENOSPC);
636 * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
637 * Delete one of the rules and tries to add the third one again.
642 struct rte_lpm6 *lpm = NULL;
643 struct rte_lpm6_config config;
644 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
646 uint32_t next_hop_add = 100;
649 config.max_rules = 2;
650 config.number_tbl8s = NUMBER_TBL8S;
653 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
654 TEST_LPM_ASSERT(lpm != NULL);
657 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
658 TEST_LPM_ASSERT(status == 0);
661 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
662 TEST_LPM_ASSERT(status == 0);
665 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
666 TEST_LPM_ASSERT(status == -ENOSPC);
669 status = rte_lpm6_delete(lpm, ip, depth);
670 TEST_LPM_ASSERT(status == 0);
673 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
674 TEST_LPM_ASSERT(status == 0);
682 * Add 2^12 routes with different first 12 bits and depth 25.
683 * Add one more route with the same depth and check that results in a failure.
684 * After that delete the last rule and create the one that was attempted to be
685 * created. This checks tbl8 exhaustion.
690 struct rte_lpm6 *lpm = NULL;
691 struct rte_lpm6_config config;
692 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
694 uint32_t next_hop_add = 100;
698 config.max_rules = MAX_RULES;
699 config.number_tbl8s = 256;
702 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
703 TEST_LPM_ASSERT(lpm != NULL);
705 for (i = 0; i < 256; i++) {
707 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
708 TEST_LPM_ASSERT(status == 0);
713 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
714 TEST_LPM_ASSERT(status == -ENOSPC);
718 status = rte_lpm6_delete(lpm, ip, depth);
719 TEST_LPM_ASSERT(status == 0);
723 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
724 TEST_LPM_ASSERT(status == 0);
732 * Call add, lookup and delete for a single rule with depth = 24
737 struct rte_lpm6 *lpm = NULL;
738 struct rte_lpm6_config config;
739 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
741 uint32_t next_hop_add = 100, next_hop_return = 0;
744 config.max_rules = MAX_RULES;
745 config.number_tbl8s = NUMBER_TBL8S;
748 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
749 TEST_LPM_ASSERT(lpm != NULL);
751 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
752 TEST_LPM_ASSERT(status == 0);
754 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
755 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
757 status = rte_lpm6_delete(lpm, ip, depth);
758 TEST_LPM_ASSERT(status == 0);
760 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
761 TEST_LPM_ASSERT(status == -ENOENT);
769 * Call add, lookup and delete for a single rule with depth > 24
774 struct rte_lpm6 *lpm = NULL;
775 struct rte_lpm6_config config;
776 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
778 uint32_t next_hop_add = 100, next_hop_return = 0;
781 config.max_rules = MAX_RULES;
782 config.number_tbl8s = NUMBER_TBL8S;
785 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
786 TEST_LPM_ASSERT(lpm != NULL);
788 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
789 TEST_LPM_ASSERT(status == 0);
791 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
792 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
794 status = rte_lpm6_delete(lpm, ip, depth);
795 TEST_LPM_ASSERT(status == 0);
797 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
798 TEST_LPM_ASSERT(status == -ENOENT);
806 * Use rte_lpm6_add to add rules which effect only the second half of the lpm
807 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
808 * depth. Check lookup hit for on every add and check for lookup miss on the
809 * first half of the lpm table after each add. Finally delete all rules going
810 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
811 * delete. The lookup should return the next_hop_add value related to the
812 * previous depth value (i.e. depth -1).
817 struct rte_lpm6 *lpm = NULL;
818 struct rte_lpm6_config config;
819 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
820 255,255,255,255,255,255,255};
821 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
823 uint32_t next_hop_add, next_hop_return;
826 config.max_rules = MAX_RULES;
827 config.number_tbl8s = NUMBER_TBL8S;
830 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
831 TEST_LPM_ASSERT(lpm != NULL);
833 /* Loop with rte_lpm6_add. */
834 for (depth = 1; depth <= 16; depth++) {
835 /* Let the next_hop_add value = depth. Just for change. */
836 next_hop_add = depth;
838 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
839 TEST_LPM_ASSERT(status == 0);
841 /* Check IP in first half of tbl24 which should be empty. */
842 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
843 TEST_LPM_ASSERT(status == -ENOENT);
845 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
846 TEST_LPM_ASSERT((status == 0) &&
847 (next_hop_return == next_hop_add));
850 /* Loop with rte_lpm6_delete. */
851 for (depth = 16; depth >= 1; depth--) {
852 next_hop_add = (depth - 1);
854 status = rte_lpm6_delete(lpm, ip2, depth);
855 TEST_LPM_ASSERT(status == 0);
857 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
860 TEST_LPM_ASSERT((status == 0) &&
861 (next_hop_return == next_hop_add));
864 TEST_LPM_ASSERT(status == -ENOENT);
867 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
868 TEST_LPM_ASSERT(status == -ENOENT);
877 * - Add & lookup to hit invalid TBL24 entry
878 * - Add & lookup to hit valid TBL24 entry not extended
879 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
880 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
885 struct rte_lpm6 *lpm = NULL;
886 struct rte_lpm6_config config;
887 uint8_t ip[16], ip_1[16], ip_2[16];
888 uint8_t depth, depth_1, depth_2;
889 uint32_t next_hop_add, next_hop_add_1,
890 next_hop_add_2, next_hop_return;
893 config.max_rules = MAX_RULES;
894 config.number_tbl8s = NUMBER_TBL8S;
897 /* Add & lookup to hit invalid TBL24 entry */
898 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
902 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
903 TEST_LPM_ASSERT(lpm != NULL);
905 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
906 TEST_LPM_ASSERT(status == 0);
908 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
909 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
911 status = rte_lpm6_delete(lpm, ip, depth);
912 TEST_LPM_ASSERT(status == 0);
914 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
915 TEST_LPM_ASSERT(status == -ENOENT);
917 rte_lpm6_delete_all(lpm);
919 /* Add & lookup to hit valid TBL24 entry not extended */
920 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
924 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
925 TEST_LPM_ASSERT(status == 0);
927 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
928 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
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));
941 status = rte_lpm6_delete(lpm, ip, depth);
942 TEST_LPM_ASSERT(status == 0);
946 status = rte_lpm6_delete(lpm, ip, depth);
947 TEST_LPM_ASSERT(status == 0);
949 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
950 TEST_LPM_ASSERT(status == -ENOENT);
952 rte_lpm6_delete_all(lpm);
954 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
957 IPv6(ip, 128, 0, 0, 0, 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, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
971 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
972 TEST_LPM_ASSERT(status == 0);
974 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
975 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
977 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
981 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
982 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
984 status = rte_lpm6_delete(lpm, ip, depth);
985 TEST_LPM_ASSERT(status == 0);
987 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
988 TEST_LPM_ASSERT(status == -ENOENT);
990 rte_lpm6_delete_all(lpm);
992 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
995 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
997 next_hop_add_1 = 101;
999 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1001 next_hop_add_2 = 102;
1003 next_hop_return = 0;
1005 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
1006 TEST_LPM_ASSERT(status == 0);
1008 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1009 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1011 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1012 TEST_LPM_ASSERT(status == 0);
1014 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1015 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1017 status = rte_lpm6_delete(lpm, ip_2, depth_2);
1018 TEST_LPM_ASSERT(status == 0);
1020 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1021 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1023 status = rte_lpm6_delete(lpm, ip_1, depth_1);
1024 TEST_LPM_ASSERT(status == 0);
1026 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1027 TEST_LPM_ASSERT(status == -ENOENT);
1035 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1037 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1038 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1040 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1041 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1042 * - Delete a rule that is not present in the TBL24 & lookup
1043 * - Delete a rule that is not present in the TBL8 & lookup
1048 struct rte_lpm6 *lpm = NULL;
1049 struct rte_lpm6_config config;
1052 uint32_t next_hop_add, next_hop_return;
1055 config.max_rules = MAX_RULES;
1056 config.number_tbl8s = NUMBER_TBL8S;
1059 /* Add rule that covers a TBL24 range previously invalid & lookup
1060 * (& delete & lookup)
1062 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1063 TEST_LPM_ASSERT(lpm != NULL);
1065 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1069 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1070 TEST_LPM_ASSERT(status == 0);
1072 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1073 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1075 status = rte_lpm6_delete(lpm, ip, depth);
1076 TEST_LPM_ASSERT(status == 0);
1078 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1079 TEST_LPM_ASSERT(status == -ENOENT);
1081 rte_lpm6_delete_all(lpm);
1083 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1087 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1088 TEST_LPM_ASSERT(status == 0);
1090 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1091 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1093 status = rte_lpm6_delete(lpm, ip, depth);
1094 TEST_LPM_ASSERT(status == 0);
1096 rte_lpm6_delete_all(lpm);
1099 * Add rule that extends a TBL24 valid entry & lookup for both rules
1100 * (& delete & lookup)
1103 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1107 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1108 TEST_LPM_ASSERT(status == 0);
1110 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1114 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1115 TEST_LPM_ASSERT(status == 0);
1117 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1118 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1120 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1123 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1124 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1126 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1129 status = rte_lpm6_delete(lpm, ip, depth);
1130 TEST_LPM_ASSERT(status == 0);
1132 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1133 TEST_LPM_ASSERT(status == -ENOENT);
1135 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1138 status = rte_lpm6_delete(lpm, ip, depth);
1139 TEST_LPM_ASSERT(status == 0);
1141 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1142 TEST_LPM_ASSERT(status == -ENOENT);
1144 rte_lpm6_delete_all(lpm);
1147 * Add rule that updates the next hop in TBL24 & lookup
1148 * (& delete & lookup)
1151 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1155 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1156 TEST_LPM_ASSERT(status == 0);
1158 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1159 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
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));
1169 status = rte_lpm6_delete(lpm, ip, depth);
1170 TEST_LPM_ASSERT(status == 0);
1172 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1173 TEST_LPM_ASSERT(status == -ENOENT);
1175 rte_lpm6_delete_all(lpm);
1178 * Add rule that updates the next hop in TBL8 & lookup
1179 * (& delete & lookup)
1182 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1186 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1187 TEST_LPM_ASSERT(status == 0);
1189 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1190 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
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));
1200 status = rte_lpm6_delete(lpm, ip, depth);
1201 TEST_LPM_ASSERT(status == 0);
1203 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1204 TEST_LPM_ASSERT(status == -ENOENT);
1206 rte_lpm6_delete_all(lpm);
1208 /* Delete a rule that is not present in the TBL24 & lookup */
1210 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1214 status = rte_lpm6_delete(lpm, ip, depth);
1215 TEST_LPM_ASSERT(status < 0);
1217 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1218 TEST_LPM_ASSERT(status == -ENOENT);
1220 rte_lpm6_delete_all(lpm);
1222 /* Delete a rule that is not present in the TBL8 & lookup */
1224 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1228 status = rte_lpm6_delete(lpm, ip, depth);
1229 TEST_LPM_ASSERT(status < 0);
1231 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1232 TEST_LPM_ASSERT(status == -ENOENT);
1240 * Add two rules, lookup to hit the more specific one, lookup to hit the less
1241 * specific one delete the less specific rule and lookup previous values again;
1242 * add a more specific rule than the existing rule, lookup again
1247 struct rte_lpm6 *lpm = NULL;
1248 struct rte_lpm6_config config;
1251 uint32_t next_hop_add, next_hop_return;
1254 config.max_rules = MAX_RULES;
1255 config.number_tbl8s = NUMBER_TBL8S;
1258 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1259 TEST_LPM_ASSERT(lpm != NULL);
1261 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1265 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1266 TEST_LPM_ASSERT(status == 0);
1268 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1272 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1273 TEST_LPM_ASSERT(status == 0);
1275 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1276 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1278 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1281 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1282 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1284 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1287 status = rte_lpm6_delete(lpm, ip, depth);
1288 TEST_LPM_ASSERT(status == 0);
1290 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1291 TEST_LPM_ASSERT(status == -ENOENT);
1293 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1296 status = rte_lpm6_delete(lpm, ip, depth);
1297 TEST_LPM_ASSERT(status == 0);
1299 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1300 TEST_LPM_ASSERT(status == -ENOENT);
1308 * Adds 3 rules and look them up through the lookup_bulk function.
1309 * Includes in the lookup a fourth IP address that won't match
1310 * and checks that the result is as expected.
1315 struct rte_lpm6 *lpm = NULL;
1316 struct rte_lpm6_config config;
1317 uint8_t ip_batch[4][16];
1319 uint32_t next_hop_add;
1320 int32_t next_hop_return[4];
1323 config.max_rules = MAX_RULES;
1324 config.number_tbl8s = NUMBER_TBL8S;
1327 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1328 TEST_LPM_ASSERT(lpm != NULL);
1330 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1334 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1335 TEST_LPM_ASSERT(status == 0);
1337 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1341 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1342 TEST_LPM_ASSERT(status == 0);
1344 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1348 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1349 TEST_LPM_ASSERT(status == 0);
1351 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1353 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1354 next_hop_return, 4);
1355 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1356 && next_hop_return[1] == 101 && next_hop_return[2] == 102
1357 && next_hop_return[3] == -1);
1365 * Adds 5 rules and look them up.
1366 * Use the delete_bulk function to delete two of them. Lookup again.
1367 * Use the delete_bulk function to delete one more. Lookup again.
1368 * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1369 * Use the delete_bulk function to delete the remaining one. Lookup again.
1374 struct rte_lpm6 *lpm = NULL;
1375 struct rte_lpm6_config config;
1376 uint8_t ip_batch[5][16];
1378 uint32_t next_hop_add;
1379 int32_t next_hop_return[5];
1382 config.max_rules = MAX_RULES;
1383 config.number_tbl8s = NUMBER_TBL8S;
1386 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1387 TEST_LPM_ASSERT(lpm != NULL);
1389 /* Adds 5 rules and look them up */
1391 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1395 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1396 TEST_LPM_ASSERT(status == 0);
1398 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1402 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1403 TEST_LPM_ASSERT(status == 0);
1405 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1409 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1410 TEST_LPM_ASSERT(status == 0);
1412 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1416 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1417 TEST_LPM_ASSERT(status == 0);
1419 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1423 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
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] == 101
1429 && next_hop_return[1] == 102 && next_hop_return[2] == 103
1430 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1432 /* Use the delete_bulk function to delete two of them. Lookup again */
1434 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
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] == 103
1441 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1443 /* Use the delete_bulk function to delete one more. Lookup again */
1445 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1446 TEST_LPM_ASSERT(status == 0);
1448 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1449 next_hop_return, 5);
1450 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1451 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1452 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1454 /* Use the delete_bulk function to delete two, one invalid. Lookup again */
1456 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1457 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1458 TEST_LPM_ASSERT(status == 0);
1460 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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] == 105);
1467 /* Use the delete_bulk function to delete the remaining one. Lookup again */
1469 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1470 TEST_LPM_ASSERT(status == 0);
1472 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1473 next_hop_return, 5);
1474 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1475 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1476 && next_hop_return[3] == -1 && next_hop_return[4] == -1);
1484 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1485 * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
1491 struct rte_lpm6 *lpm = NULL;
1492 struct rte_lpm6_config config;
1496 uint32_t next_hop_add, next_hop_return;
1499 config.max_rules = MAX_RULES;
1500 config.number_tbl8s = NUMBER_TBL8S;
1503 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1504 TEST_LPM_ASSERT(lpm != NULL);
1506 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1510 for (i = 0; i < 30; i++) {
1511 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1512 TEST_LPM_ASSERT(status == 0);
1514 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1515 TEST_LPM_ASSERT((status == 0) &&
1516 (next_hop_return == next_hop_add));
1518 status = rte_lpm6_delete(lpm, ip, depth);
1519 TEST_LPM_ASSERT(status == 0);
1521 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1522 TEST_LPM_ASSERT(status == -ENOENT);
1531 * Sequence of operations for find existing lpm table
1534 * - find existing table: hit
1535 * - find non-existing table: miss
1540 struct rte_lpm6 *lpm = NULL, *result = NULL;
1541 struct rte_lpm6_config config;
1543 config.max_rules = 256 * 32;
1544 config.number_tbl8s = NUMBER_TBL8S;
1548 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1549 TEST_LPM_ASSERT(lpm != NULL);
1551 /* Try to find existing lpm */
1552 result = rte_lpm6_find_existing("lpm_find_existing");
1553 TEST_LPM_ASSERT(result == lpm);
1555 /* Try to find non-existing lpm */
1556 result = rte_lpm6_find_existing("lpm_find_non_existing");
1557 TEST_LPM_ASSERT(result == NULL);
1560 rte_lpm6_delete_all(lpm);
1567 * Add a set of random routes with random depths.
1568 * Lookup different IP addresses that match the routes previously added.
1569 * Checks that the next hop is the expected one.
1570 * The routes, IP addresses and expected result for every case have been
1571 * precalculated by using a python script and stored in a .h file.
1576 struct rte_lpm6 *lpm = NULL;
1577 struct rte_lpm6_config config;
1581 uint32_t next_hop_add, next_hop_return, next_hop_expected;
1584 config.max_rules = MAX_RULES;
1585 config.number_tbl8s = NUMBER_TBL8S;
1588 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1589 TEST_LPM_ASSERT(lpm != NULL);
1591 for (i = 0; i < 1000; i++) {
1592 memcpy(ip, large_route_table[i].ip, 16);
1593 depth = large_route_table[i].depth;
1594 next_hop_add = large_route_table[i].next_hop;
1595 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1596 TEST_LPM_ASSERT(status == 0);
1599 /* generate large IPS table and expected next_hops */
1600 generate_large_ips_table(1);
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 uint32_t next_hop_ip_10_32 = 100;
1635 uint32_t next_hop_ip_10_24 = 105;
1636 uint32_t next_hop_ip_20_25 = 111;
1637 uint32_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 uint32_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 uint32_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 uint32_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;
1710 uint32_t next_hop_add = 100, next_hop_return;
1714 config.max_rules = MAX_RULES;
1715 config.number_tbl8s = NUMBER_TBL8S;
1718 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1719 TEST_LPM_ASSERT(lpm != NULL);
1723 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1724 TEST_LPM_ASSERT(status == 0);
1728 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1729 TEST_LPM_ASSERT(status == 0);
1731 for (i = 0; i < 256; i++) {
1732 ip[14] = (uint8_t)i;
1733 for (j = 0; j < 256; j++) {
1734 ip[15] = (uint8_t)j;
1735 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1736 if (i == 0 && j == 0)
1737 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1739 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1749 * Call add, lookup and delete for a single rule with maximum 21bit next_hop
1751 * Check that next_hop returned from lookup is equal to provisioned value.
1752 * Delete the rule and check that the same test returns a miss.
1757 struct rte_lpm6 *lpm = NULL;
1758 struct rte_lpm6_config config;
1759 uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1761 uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
1764 config.max_rules = MAX_RULES;
1765 config.number_tbl8s = NUMBER_TBL8S;
1768 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1769 TEST_LPM_ASSERT(lpm != NULL);
1771 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1772 TEST_LPM_ASSERT(status == 0);
1774 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1775 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1777 status = rte_lpm6_delete(lpm, ip, depth);
1778 TEST_LPM_ASSERT(status == 0);
1785 * Do all unit tests.
1791 int status = -1, global_status = 0;
1793 for (i = 0; i < RTE_DIM(tests6); i++) {
1794 printf("# test %02d\n", i);
1795 status = tests6[i]();
1798 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1799 global_status = status;
1803 return global_status;
1806 #endif /* !RTE_EXEC_ENV_WINDOWS */
1808 REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6);