4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <rte_memory.h>
43 #include "test_lpm6_data.h"
45 #define TEST_LPM_ASSERT(cond) do { \
47 printf("Error at line %d: \n", __LINE__); \
52 typedef int32_t (* rte_lpm6_test)(void);
54 static int32_t test0(void);
55 static int32_t test1(void);
56 static int32_t test2(void);
57 static int32_t test3(void);
58 static int32_t test4(void);
59 static int32_t test5(void);
60 static int32_t test6(void);
61 static int32_t test7(void);
62 static int32_t test8(void);
63 static int32_t test9(void);
64 static int32_t test10(void);
65 static int32_t test11(void);
66 static int32_t test12(void);
67 static int32_t test13(void);
68 static int32_t test14(void);
69 static int32_t test15(void);
70 static int32_t test16(void);
71 static int32_t test17(void);
72 static int32_t test18(void);
73 static int32_t test19(void);
74 static int32_t test20(void);
75 static int32_t test21(void);
76 static int32_t test22(void);
77 static int32_t test23(void);
78 static int32_t test24(void);
79 static int32_t test25(void);
80 static int32_t test26(void);
81 static int32_t test27(void);
82 static int32_t test28(void);
84 rte_lpm6_test tests6[] = {
117 #define NUM_LPM6_TESTS (sizeof(tests6)/sizeof(tests6[0]))
118 #define MAX_DEPTH 128
119 #define MAX_RULES 1000000
120 #define NUMBER_TBL8S (1 << 16)
121 #define MAX_NUM_TBL8S (1 << 21)
125 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
126 uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
127 uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
149 * Check that rte_lpm6_create fails gracefully for incorrect user input
155 struct rte_lpm6 *lpm = NULL;
156 struct rte_lpm6_config config;
158 config.max_rules = MAX_RULES;
159 config.number_tbl8s = NUMBER_TBL8S;
162 /* rte_lpm6_create: lpm name == NULL */
163 lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
164 TEST_LPM_ASSERT(lpm == NULL);
166 /* rte_lpm6_create: max_rules = 0 */
167 /* Note: __func__ inserts the function name, in this case "test0". */
168 config.max_rules = 0;
169 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
170 TEST_LPM_ASSERT(lpm == NULL);
172 /* socket_id < -1 is invalid */
173 config.max_rules = MAX_RULES;
174 lpm = rte_lpm6_create(__func__, -2, &config);
175 TEST_LPM_ASSERT(lpm == NULL);
177 /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
178 config.number_tbl8s = MAX_NUM_TBL8S + 1;
179 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
180 TEST_LPM_ASSERT(lpm == NULL);
182 /* rte_lpm6_create: config = NULL */
183 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
184 TEST_LPM_ASSERT(lpm == NULL);
190 * Creates two different LPM tables. Tries to create a third one with the same
191 * name as the first one and expects the create function to return the same
197 struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
198 struct rte_lpm6_config config;
200 config.max_rules = MAX_RULES;
201 config.number_tbl8s = NUMBER_TBL8S;
204 /* rte_lpm6_create: lpm name == LPM1 */
205 lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
206 TEST_LPM_ASSERT(lpm1 != NULL);
208 /* rte_lpm6_create: lpm name == LPM2 */
209 lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
210 TEST_LPM_ASSERT(lpm2 != NULL);
212 /* rte_lpm6_create: lpm name == LPM2 */
213 lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
214 TEST_LPM_ASSERT(lpm3 == NULL);
223 * Create lpm table then delete lpm table 20 times
224 * Use a slightly different rules size each time
229 struct rte_lpm6 *lpm = NULL;
230 struct rte_lpm6_config config;
233 config.number_tbl8s = NUMBER_TBL8S;
236 /* rte_lpm6_free: Free NULL */
237 for (i = 0; i < 20; i++) {
238 config.max_rules = MAX_RULES - i;
239 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
240 TEST_LPM_ASSERT(lpm != NULL);
245 /* Can not test free so return success */
250 * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
251 * therefore it is impossible to check for failure but this test is added to
252 * increase function coverage metrics and to validate that freeing null does
258 struct rte_lpm6 *lpm = NULL;
259 struct rte_lpm6_config config;
261 config.max_rules = MAX_RULES;
262 config.number_tbl8s = NUMBER_TBL8S;
265 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
266 TEST_LPM_ASSERT(lpm != NULL);
274 * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
279 struct rte_lpm6 *lpm = NULL;
280 struct rte_lpm6_config config;
282 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
283 uint8_t depth = 24, next_hop = 100;
286 config.max_rules = MAX_RULES;
287 config.number_tbl8s = NUMBER_TBL8S;
290 /* rte_lpm6_add: lpm == NULL */
291 status = rte_lpm6_add(NULL, ip, depth, next_hop);
292 TEST_LPM_ASSERT(status < 0);
294 /*Create vaild lpm to use in rest of test. */
295 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
296 TEST_LPM_ASSERT(lpm != NULL);
298 /* rte_lpm6_add: depth < 1 */
299 status = rte_lpm6_add(lpm, ip, 0, next_hop);
300 TEST_LPM_ASSERT(status < 0);
302 /* rte_lpm6_add: depth > MAX_DEPTH */
303 status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
304 TEST_LPM_ASSERT(status < 0);
312 * Check that rte_lpm6_delete fails gracefully for incorrect user input
318 struct rte_lpm6 *lpm = NULL;
319 struct rte_lpm6_config config;
320 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
324 config.max_rules = MAX_RULES;
325 config.number_tbl8s = NUMBER_TBL8S;
328 /* rte_lpm_delete: lpm == NULL */
329 status = rte_lpm6_delete(NULL, ip, depth);
330 TEST_LPM_ASSERT(status < 0);
332 /*Create vaild lpm to use in rest of test. */
333 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
334 TEST_LPM_ASSERT(lpm != NULL);
336 /* rte_lpm_delete: depth < 1 */
337 status = rte_lpm6_delete(lpm, ip, 0);
338 TEST_LPM_ASSERT(status < 0);
340 /* rte_lpm_delete: depth > MAX_DEPTH */
341 status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
342 TEST_LPM_ASSERT(status < 0);
350 * Check that rte_lpm6_lookup fails gracefully for incorrect user input
356 struct rte_lpm6 *lpm = NULL;
357 struct rte_lpm6_config config;
358 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
359 uint32_t next_hop_return = 0;
362 config.max_rules = MAX_RULES;
363 config.number_tbl8s = NUMBER_TBL8S;
366 /* rte_lpm6_lookup: lpm == NULL */
367 status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
368 TEST_LPM_ASSERT(status < 0);
370 /*Create vaild lpm to use in rest of test. */
371 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
372 TEST_LPM_ASSERT(lpm != NULL);
374 /* rte_lpm6_lookup: ip = NULL */
375 status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
376 TEST_LPM_ASSERT(status < 0);
378 /* rte_lpm6_lookup: next_hop = NULL */
379 status = rte_lpm6_lookup(lpm, ip, NULL);
380 TEST_LPM_ASSERT(status < 0);
388 * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
394 struct rte_lpm6 *lpm = NULL;
395 struct rte_lpm6_config config;
397 int32_t next_hop_return[10];
400 config.max_rules = MAX_RULES;
401 config.number_tbl8s = NUMBER_TBL8S;
404 /* rte_lpm6_lookup: lpm == NULL */
405 status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
406 TEST_LPM_ASSERT(status < 0);
408 /*Create vaild lpm to use in rest of test. */
409 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
410 TEST_LPM_ASSERT(lpm != NULL);
412 /* rte_lpm6_lookup: ip = NULL */
413 status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
414 TEST_LPM_ASSERT(status < 0);
416 /* rte_lpm6_lookup: next_hop = NULL */
417 status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
418 TEST_LPM_ASSERT(status < 0);
426 * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
432 struct rte_lpm6 *lpm = NULL;
433 struct rte_lpm6_config config;
438 config.max_rules = MAX_RULES;
439 config.number_tbl8s = NUMBER_TBL8S;
442 /* rte_lpm6_delete: lpm == NULL */
443 status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
444 TEST_LPM_ASSERT(status < 0);
446 /*Create vaild lpm to use in rest of test. */
447 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
448 TEST_LPM_ASSERT(lpm != NULL);
450 /* rte_lpm6_delete: ip = NULL */
451 status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
452 TEST_LPM_ASSERT(status < 0);
454 /* rte_lpm6_delete: next_hop = NULL */
455 status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
456 TEST_LPM_ASSERT(status < 0);
464 * Call add, lookup and delete for a single rule with depth < 24.
465 * Check all the combinations for the first three bytes that result in a hit.
466 * Delete the rule and check that the same test returs a miss.
471 struct rte_lpm6 *lpm = NULL;
472 struct rte_lpm6_config config;
473 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
475 uint32_t next_hop_add = 100, next_hop_return = 0;
479 config.max_rules = MAX_RULES;
480 config.number_tbl8s = NUMBER_TBL8S;
483 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
484 TEST_LPM_ASSERT(lpm != NULL);
486 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
487 TEST_LPM_ASSERT(status == 0);
489 for (i = 0; i < UINT8_MAX; i++) {
491 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
492 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
495 status = rte_lpm6_delete(lpm, ip, depth);
496 TEST_LPM_ASSERT(status == 0);
498 for (i = 0; i < UINT8_MAX; i++) {
500 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
501 TEST_LPM_ASSERT(status == -ENOENT);
510 * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
511 * another one and expects success.
516 struct rte_lpm6 *lpm = NULL;
517 struct rte_lpm6_config config;
518 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
520 uint32_t next_hop_add = 100;
524 config.max_rules = 127;
525 config.number_tbl8s = NUMBER_TBL8S;
528 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
529 TEST_LPM_ASSERT(lpm != NULL);
531 for (i = 1; i < 128; i++) {
533 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
534 TEST_LPM_ASSERT(status == 0);
538 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
539 TEST_LPM_ASSERT(status == -ENOSPC);
542 status = rte_lpm6_delete(lpm, ip, depth);
543 TEST_LPM_ASSERT(status == 0);
546 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
547 TEST_LPM_ASSERT(status == 0);
555 * Creates an LPM table with a small number of tbl8s and exhaust them in the
556 * middle of the process of creating a rule.
561 struct rte_lpm6 *lpm = NULL;
562 struct rte_lpm6_config config;
563 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
565 uint32_t next_hop_add = 100;
568 config.max_rules = MAX_RULES;
569 config.number_tbl8s = 16;
572 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
573 TEST_LPM_ASSERT(lpm != NULL);
576 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
577 TEST_LPM_ASSERT(status == 0);
581 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
582 TEST_LPM_ASSERT(status == 0);
584 status = rte_lpm6_delete(lpm, ip, depth);
585 TEST_LPM_ASSERT(status == 0);
588 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
589 TEST_LPM_ASSERT(status == 0);
591 status = rte_lpm6_delete(lpm, ip, depth);
592 TEST_LPM_ASSERT(status == 0);
595 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
596 TEST_LPM_ASSERT(status == 0);
598 status = rte_lpm6_delete(lpm, ip, depth);
599 TEST_LPM_ASSERT(status == 0);
602 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
603 TEST_LPM_ASSERT(status == -ENOSPC);
606 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
607 TEST_LPM_ASSERT(status == 0);
615 * Creates an LPM table with a small number of tbl8s and exhaust them in the
616 * middle of the process of adding a rule when there is already an existing rule
617 * in that position and needs to be extended.
622 struct rte_lpm6 *lpm = NULL;
623 struct rte_lpm6_config config;
624 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
626 uint32_t next_hop_add = 100;
629 config.max_rules = MAX_RULES;
630 config.number_tbl8s = 16;
633 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
634 TEST_LPM_ASSERT(lpm != NULL);
637 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
638 TEST_LPM_ASSERT(status == 0);
642 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
643 TEST_LPM_ASSERT(status == 0);
646 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
647 TEST_LPM_ASSERT(status == -ENOSPC);
655 * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
656 * Delete one of the rules and tries to add the third one again.
661 struct rte_lpm6 *lpm = NULL;
662 struct rte_lpm6_config config;
663 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
665 uint32_t next_hop_add = 100;
668 config.max_rules = 2;
669 config.number_tbl8s = NUMBER_TBL8S;
672 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
673 TEST_LPM_ASSERT(lpm != NULL);
676 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
677 TEST_LPM_ASSERT(status == 0);
680 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
681 TEST_LPM_ASSERT(status == 0);
684 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
685 TEST_LPM_ASSERT(status == -ENOSPC);
688 status = rte_lpm6_delete(lpm, ip, depth);
689 TEST_LPM_ASSERT(status == 0);
692 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
693 TEST_LPM_ASSERT(status == 0);
701 * Add 2^12 routes with different first 12 bits and depth 25.
702 * Add one more route with the same depth and check that results in a failure.
703 * After that delete the last rule and create the one that was attempted to be
704 * created. This checks tbl8 exhaustion.
709 struct rte_lpm6 *lpm = NULL;
710 struct rte_lpm6_config config;
711 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
713 uint32_t next_hop_add = 100;
717 config.max_rules = MAX_RULES;
718 config.number_tbl8s = 256;
721 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
722 TEST_LPM_ASSERT(lpm != NULL);
724 for (i = 0; i < 256; i++) {
726 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
727 TEST_LPM_ASSERT(status == 0);
732 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
733 TEST_LPM_ASSERT(status == -ENOSPC);
737 status = rte_lpm6_delete(lpm, ip, depth);
738 TEST_LPM_ASSERT(status == 0);
742 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
743 TEST_LPM_ASSERT(status == 0);
751 * Call add, lookup and delete for a single rule with depth = 24
756 struct rte_lpm6 *lpm = NULL;
757 struct rte_lpm6_config config;
758 uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
760 uint32_t next_hop_add = 100, next_hop_return = 0;
763 config.max_rules = MAX_RULES;
764 config.number_tbl8s = NUMBER_TBL8S;
767 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
768 TEST_LPM_ASSERT(lpm != NULL);
770 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
771 TEST_LPM_ASSERT(status == 0);
773 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
774 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
776 status = rte_lpm6_delete(lpm, ip, depth);
777 TEST_LPM_ASSERT(status == 0);
779 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
780 TEST_LPM_ASSERT(status == -ENOENT);
788 * Call add, lookup and delete for a single rule with depth > 24
793 struct rte_lpm6 *lpm = NULL;
794 struct rte_lpm6_config config;
795 uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
797 uint32_t next_hop_add = 100, next_hop_return = 0;
800 config.max_rules = MAX_RULES;
801 config.number_tbl8s = NUMBER_TBL8S;
804 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
805 TEST_LPM_ASSERT(lpm != NULL);
807 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
808 TEST_LPM_ASSERT(status == 0);
810 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
811 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
813 status = rte_lpm6_delete(lpm, ip, depth);
814 TEST_LPM_ASSERT(status == 0);
816 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
817 TEST_LPM_ASSERT(status == -ENOENT);
825 * Use rte_lpm6_add to add rules which effect only the second half of the lpm
826 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
827 * depth. Check lookup hit for on every add and check for lookup miss on the
828 * first half of the lpm table after each add. Finally delete all rules going
829 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
830 * delete. The lookup should return the next_hop_add value related to the
831 * previous depth value (i.e. depth -1).
836 struct rte_lpm6 *lpm = NULL;
837 struct rte_lpm6_config config;
838 uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
839 255,255,255,255,255,255,255};
840 uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
842 uint32_t next_hop_add, next_hop_return;
845 config.max_rules = MAX_RULES;
846 config.number_tbl8s = NUMBER_TBL8S;
849 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
850 TEST_LPM_ASSERT(lpm != NULL);
852 /* Loop with rte_lpm6_add. */
853 for (depth = 1; depth <= 16; depth++) {
854 /* Let the next_hop_add value = depth. Just for change. */
855 next_hop_add = depth;
857 status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
858 TEST_LPM_ASSERT(status == 0);
860 /* Check IP in first half of tbl24 which should be empty. */
861 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
862 TEST_LPM_ASSERT(status == -ENOENT);
864 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
865 TEST_LPM_ASSERT((status == 0) &&
866 (next_hop_return == next_hop_add));
869 /* Loop with rte_lpm6_delete. */
870 for (depth = 16; depth >= 1; depth--) {
871 next_hop_add = (depth - 1);
873 status = rte_lpm6_delete(lpm, ip2, depth);
874 TEST_LPM_ASSERT(status == 0);
876 status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
879 TEST_LPM_ASSERT((status == 0) &&
880 (next_hop_return == next_hop_add));
883 TEST_LPM_ASSERT(status == -ENOENT);
886 status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
887 TEST_LPM_ASSERT(status == -ENOENT);
896 * - Add & lookup to hit invalid TBL24 entry
897 * - Add & lookup to hit valid TBL24 entry not extended
898 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
899 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
904 struct rte_lpm6 *lpm = NULL;
905 struct rte_lpm6_config config;
906 uint8_t ip[16], ip_1[16], ip_2[16];
907 uint8_t depth, depth_1, depth_2;
908 uint32_t next_hop_add, next_hop_add_1,
909 next_hop_add_2, next_hop_return;
912 config.max_rules = MAX_RULES;
913 config.number_tbl8s = NUMBER_TBL8S;
916 /* Add & lookup to hit invalid TBL24 entry */
917 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
921 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
922 TEST_LPM_ASSERT(lpm != NULL);
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));
930 status = rte_lpm6_delete(lpm, ip, depth);
931 TEST_LPM_ASSERT(status == 0);
933 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
934 TEST_LPM_ASSERT(status == -ENOENT);
936 rte_lpm6_delete_all(lpm);
938 /* Add & lookup to hit valid TBL24 entry not extended */
939 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
943 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
944 TEST_LPM_ASSERT(status == 0);
946 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
947 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
952 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
953 TEST_LPM_ASSERT(status == 0);
955 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
956 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
960 status = rte_lpm6_delete(lpm, ip, depth);
961 TEST_LPM_ASSERT(status == 0);
965 status = rte_lpm6_delete(lpm, ip, depth);
966 TEST_LPM_ASSERT(status == 0);
968 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
969 TEST_LPM_ASSERT(status == -ENOENT);
971 rte_lpm6_delete_all(lpm);
973 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
976 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
980 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
981 TEST_LPM_ASSERT(status == 0);
983 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
984 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
986 IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
990 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
991 TEST_LPM_ASSERT(status == 0);
993 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
994 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
996 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1000 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1001 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1003 status = rte_lpm6_delete(lpm, ip, depth);
1004 TEST_LPM_ASSERT(status == 0);
1006 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1007 TEST_LPM_ASSERT(status == -ENOENT);
1009 rte_lpm6_delete_all(lpm);
1011 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
1014 IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1016 next_hop_add_1 = 101;
1018 IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1020 next_hop_add_2 = 102;
1022 next_hop_return = 0;
1024 status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
1025 TEST_LPM_ASSERT(status == 0);
1027 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1028 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1030 status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1031 TEST_LPM_ASSERT(status == 0);
1033 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1034 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1036 status = rte_lpm6_delete(lpm, ip_2, depth_2);
1037 TEST_LPM_ASSERT(status == 0);
1039 status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1040 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1042 status = rte_lpm6_delete(lpm, ip_1, depth_1);
1043 TEST_LPM_ASSERT(status == 0);
1045 status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1046 TEST_LPM_ASSERT(status == -ENOENT);
1054 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1056 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1057 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1059 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1060 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1061 * - Delete a rule that is not present in the TBL24 & lookup
1062 * - Delete a rule that is not present in the TBL8 & lookup
1067 struct rte_lpm6 *lpm = NULL;
1068 struct rte_lpm6_config config;
1071 uint32_t next_hop_add, next_hop_return;
1074 config.max_rules = MAX_RULES;
1075 config.number_tbl8s = NUMBER_TBL8S;
1078 /* Add rule that covers a TBL24 range previously invalid & lookup
1079 * (& delete & lookup)
1081 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1082 TEST_LPM_ASSERT(lpm != NULL);
1084 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1088 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1089 TEST_LPM_ASSERT(status == 0);
1091 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1092 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1094 status = rte_lpm6_delete(lpm, ip, depth);
1095 TEST_LPM_ASSERT(status == 0);
1097 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1098 TEST_LPM_ASSERT(status == -ENOENT);
1100 rte_lpm6_delete_all(lpm);
1102 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1106 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1107 TEST_LPM_ASSERT(status == 0);
1109 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1110 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1112 status = rte_lpm6_delete(lpm, ip, depth);
1113 TEST_LPM_ASSERT(status == 0);
1115 rte_lpm6_delete_all(lpm);
1118 * Add rule that extends a TBL24 valid entry & lookup for both rules
1119 * (& delete & lookup)
1122 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1126 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1127 TEST_LPM_ASSERT(status == 0);
1129 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1133 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1134 TEST_LPM_ASSERT(status == 0);
1136 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1137 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1139 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1142 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1143 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1145 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1148 status = rte_lpm6_delete(lpm, ip, depth);
1149 TEST_LPM_ASSERT(status == 0);
1151 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1152 TEST_LPM_ASSERT(status == -ENOENT);
1154 IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1157 status = rte_lpm6_delete(lpm, ip, depth);
1158 TEST_LPM_ASSERT(status == 0);
1160 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1161 TEST_LPM_ASSERT(status == -ENOENT);
1163 rte_lpm6_delete_all(lpm);
1166 * Add rule that updates the next hop in TBL24 & lookup
1167 * (& delete & lookup)
1170 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1174 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1175 TEST_LPM_ASSERT(status == 0);
1177 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1178 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1182 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1183 TEST_LPM_ASSERT(status == 0);
1185 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1186 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1188 status = rte_lpm6_delete(lpm, ip, depth);
1189 TEST_LPM_ASSERT(status == 0);
1191 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1192 TEST_LPM_ASSERT(status == -ENOENT);
1194 rte_lpm6_delete_all(lpm);
1197 * Add rule that updates the next hop in TBL8 & lookup
1198 * (& delete & lookup)
1201 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1205 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1206 TEST_LPM_ASSERT(status == 0);
1208 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1209 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1213 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1214 TEST_LPM_ASSERT(status == 0);
1216 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1217 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1219 status = rte_lpm6_delete(lpm, ip, depth);
1220 TEST_LPM_ASSERT(status == 0);
1222 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1223 TEST_LPM_ASSERT(status == -ENOENT);
1225 rte_lpm6_delete_all(lpm);
1227 /* Delete a rule that is not present in the TBL24 & lookup */
1229 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1233 status = rte_lpm6_delete(lpm, ip, depth);
1234 TEST_LPM_ASSERT(status < 0);
1236 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1237 TEST_LPM_ASSERT(status == -ENOENT);
1239 rte_lpm6_delete_all(lpm);
1241 /* Delete a rule that is not present in the TBL8 & lookup */
1243 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1247 status = rte_lpm6_delete(lpm, ip, depth);
1248 TEST_LPM_ASSERT(status < 0);
1250 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1251 TEST_LPM_ASSERT(status == -ENOENT);
1259 * Add two rules, lookup to hit the more specific one, lookup to hit the less
1260 * specific one delete the less specific rule and lookup previous values again;
1261 * add a more specific rule than the existing rule, lookup again
1266 struct rte_lpm6 *lpm = NULL;
1267 struct rte_lpm6_config config;
1270 uint32_t next_hop_add, next_hop_return;
1273 config.max_rules = MAX_RULES;
1274 config.number_tbl8s = NUMBER_TBL8S;
1277 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1278 TEST_LPM_ASSERT(lpm != NULL);
1280 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1284 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1285 TEST_LPM_ASSERT(status == 0);
1287 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1291 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1292 TEST_LPM_ASSERT(status == 0);
1294 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1295 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1297 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1300 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1301 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1303 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1306 status = rte_lpm6_delete(lpm, ip, depth);
1307 TEST_LPM_ASSERT(status == 0);
1309 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1310 TEST_LPM_ASSERT(status == -ENOENT);
1312 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1315 status = rte_lpm6_delete(lpm, ip, depth);
1316 TEST_LPM_ASSERT(status == 0);
1318 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1319 TEST_LPM_ASSERT(status == -ENOENT);
1327 * Adds 3 rules and look them up through the lookup_bulk function.
1328 * Includes in the lookup a fourth IP address that won't match
1329 * and checks that the result is as expected.
1334 struct rte_lpm6 *lpm = NULL;
1335 struct rte_lpm6_config config;
1336 uint8_t ip_batch[4][16];
1338 uint32_t next_hop_add;
1339 int32_t next_hop_return[4];
1342 config.max_rules = MAX_RULES;
1343 config.number_tbl8s = NUMBER_TBL8S;
1346 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1347 TEST_LPM_ASSERT(lpm != NULL);
1349 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1353 status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1354 TEST_LPM_ASSERT(status == 0);
1356 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1360 status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1361 TEST_LPM_ASSERT(status == 0);
1363 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1367 status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1368 TEST_LPM_ASSERT(status == 0);
1370 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1372 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1373 next_hop_return, 4);
1374 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1375 && next_hop_return[1] == 101 && next_hop_return[2] == 102
1376 && next_hop_return[3] == -1);
1384 * Adds 5 rules and look them up.
1385 * Use the delete_bulk function to delete two of them. Lookup again.
1386 * Use the delete_bulk function to delete one more. Lookup again.
1387 * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1388 * Use the delete_bulk function to delete the remaining one. Lookup again.
1393 struct rte_lpm6 *lpm = NULL;
1394 struct rte_lpm6_config config;
1395 uint8_t ip_batch[5][16];
1397 uint32_t next_hop_add;
1398 int32_t next_hop_return[5];
1401 config.max_rules = MAX_RULES;
1402 config.number_tbl8s = NUMBER_TBL8S;
1405 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1406 TEST_LPM_ASSERT(lpm != NULL);
1408 /* Adds 5 rules and look them up */
1410 IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1414 status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1415 TEST_LPM_ASSERT(status == 0);
1417 IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1421 status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1422 TEST_LPM_ASSERT(status == 0);
1424 IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1428 status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1429 TEST_LPM_ASSERT(status == 0);
1431 IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1435 status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1436 TEST_LPM_ASSERT(status == 0);
1438 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1442 status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
1443 TEST_LPM_ASSERT(status == 0);
1445 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1446 next_hop_return, 5);
1447 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
1448 && next_hop_return[1] == 102 && next_hop_return[2] == 103
1449 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1451 /* Use the delete_bulk function to delete two of them. Lookup again */
1453 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1454 TEST_LPM_ASSERT(status == 0);
1456 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1457 next_hop_return, 5);
1458 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1459 && next_hop_return[1] == -1 && next_hop_return[2] == 103
1460 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1462 /* Use the delete_bulk function to delete one more. Lookup again */
1464 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1465 TEST_LPM_ASSERT(status == 0);
1467 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1468 next_hop_return, 5);
1469 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1470 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1471 && next_hop_return[3] == 104 && next_hop_return[4] == 105);
1473 /* Use the delete_bulk function to delete two, one invalid. Lookup again */
1475 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1476 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1477 TEST_LPM_ASSERT(status == 0);
1479 IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1480 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1481 next_hop_return, 5);
1482 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1483 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1484 && next_hop_return[3] == -1 && next_hop_return[4] == 105);
1486 /* Use the delete_bulk function to delete the remaining one. Lookup again */
1488 status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1489 TEST_LPM_ASSERT(status == 0);
1491 status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1492 next_hop_return, 5);
1493 TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1494 && next_hop_return[1] == -1 && next_hop_return[2] == -1
1495 && next_hop_return[3] == -1 && next_hop_return[4] == -1);
1503 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1504 * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
1510 struct rte_lpm6 *lpm = NULL;
1511 struct rte_lpm6_config config;
1515 uint32_t next_hop_add, next_hop_return;
1518 config.max_rules = MAX_RULES;
1519 config.number_tbl8s = NUMBER_TBL8S;
1522 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1523 TEST_LPM_ASSERT(lpm != NULL);
1525 IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1529 for (i = 0; i < 30; i++) {
1530 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1531 TEST_LPM_ASSERT(status == 0);
1533 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1534 TEST_LPM_ASSERT((status == 0) &&
1535 (next_hop_return == next_hop_add));
1537 status = rte_lpm6_delete(lpm, ip, depth);
1538 TEST_LPM_ASSERT(status == 0);
1540 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1541 TEST_LPM_ASSERT(status == -ENOENT);
1550 * Sequence of operations for find existing lpm table
1553 * - find existing table: hit
1554 * - find non-existing table: miss
1559 struct rte_lpm6 *lpm = NULL, *result = NULL;
1560 struct rte_lpm6_config config;
1562 config.max_rules = 256 * 32;
1563 config.number_tbl8s = NUMBER_TBL8S;
1567 lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1568 TEST_LPM_ASSERT(lpm != NULL);
1570 /* Try to find existing lpm */
1571 result = rte_lpm6_find_existing("lpm_find_existing");
1572 TEST_LPM_ASSERT(result == lpm);
1574 /* Try to find non-existing lpm */
1575 result = rte_lpm6_find_existing("lpm_find_non_existing");
1576 TEST_LPM_ASSERT(result == NULL);
1579 rte_lpm6_delete_all(lpm);
1586 * Add a set of random routes with random depths.
1587 * Lookup different IP addresses that match the routes previously added.
1588 * Checks that the next hop is the expected one.
1589 * The routes, IP addresses and expected result for every case have been
1590 * precalculated by using a python script and stored in a .h file.
1595 struct rte_lpm6 *lpm = NULL;
1596 struct rte_lpm6_config config;
1600 uint32_t next_hop_add, next_hop_return, next_hop_expected;
1603 config.max_rules = MAX_RULES;
1604 config.number_tbl8s = NUMBER_TBL8S;
1607 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1608 TEST_LPM_ASSERT(lpm != NULL);
1610 for (i = 0; i < 1000; i++) {
1611 memcpy(ip, large_route_table[i].ip, 16);
1612 depth = large_route_table[i].depth;
1613 next_hop_add = large_route_table[i].next_hop;
1614 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1615 TEST_LPM_ASSERT(status == 0);
1618 /* generate large IPS table and expected next_hops */
1619 generate_large_ips_table(1);
1621 for (i = 0; i < 100000; i++) {
1622 memcpy(ip, large_ips_table[i].ip, 16);
1623 next_hop_expected = large_ips_table[i].next_hop;
1625 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1626 TEST_LPM_ASSERT((status == 0) &&
1627 (next_hop_return == next_hop_expected));
1636 * Test for overwriting of tbl8:
1637 * - add rule /32 and lookup
1638 * - add new rule /24 and lookup
1639 * - add third rule /25 and lookup
1640 * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1645 struct rte_lpm6 *lpm = NULL;
1646 struct rte_lpm6_config config;
1647 uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1648 uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1649 uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1650 uint8_t d_ip_10_32 = 32;
1651 uint8_t d_ip_10_24 = 24;
1652 uint8_t d_ip_20_25 = 25;
1653 uint32_t next_hop_ip_10_32 = 100;
1654 uint32_t next_hop_ip_10_24 = 105;
1655 uint32_t next_hop_ip_20_25 = 111;
1656 uint32_t next_hop_return = 0;
1659 config.max_rules = MAX_RULES;
1660 config.number_tbl8s = NUMBER_TBL8S;
1663 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1664 TEST_LPM_ASSERT(lpm != NULL);
1666 if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
1667 next_hop_ip_10_32)) < 0)
1670 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1671 uint32_t test_hop_10_32 = next_hop_return;
1672 TEST_LPM_ASSERT(status == 0);
1673 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1675 if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
1676 next_hop_ip_10_24)) < 0)
1679 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1680 uint32_t test_hop_10_24 = next_hop_return;
1681 TEST_LPM_ASSERT(status == 0);
1682 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1684 if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
1685 next_hop_ip_20_25)) < 0)
1688 status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
1689 uint32_t test_hop_20_25 = next_hop_return;
1690 TEST_LPM_ASSERT(status == 0);
1691 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1693 if (test_hop_10_32 == test_hop_10_24) {
1694 printf("Next hop return equal\n");
1698 if (test_hop_10_24 == test_hop_20_25){
1699 printf("Next hop return equal\n");
1703 status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1704 TEST_LPM_ASSERT(status == 0);
1705 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1707 status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1708 TEST_LPM_ASSERT(status == 0);
1709 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1717 * Add a rule that reaches the end of the tree.
1718 * Add a rule that is more generic than the first one.
1719 * Check every possible combination that produces a match for the second rule.
1720 * This tests tbl expansion.
1725 struct rte_lpm6 *lpm = NULL;
1726 struct rte_lpm6_config config;
1727 uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
1728 uint8_t depth = 128;
1729 uint32_t next_hop_add = 100, next_hop_return;
1733 config.max_rules = MAX_RULES;
1734 config.number_tbl8s = NUMBER_TBL8S;
1737 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1738 TEST_LPM_ASSERT(lpm != NULL);
1742 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1743 TEST_LPM_ASSERT(status == 0);
1747 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1748 TEST_LPM_ASSERT(status == 0);
1750 for (i = 0; i < 256; i++) {
1751 ip[14] = (uint8_t)i;
1752 for (j = 0; j < 256; j++) {
1753 ip[15] = (uint8_t)j;
1754 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1755 if (i == 0 && j == 0)
1756 TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1758 TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1768 * Call add, lookup and delete for a single rule with maximum 21bit next_hop
1770 * Check that next_hop returned from lookup is equal to provisioned value.
1771 * Delete the rule and check that the same test returs a miss.
1776 struct rte_lpm6 *lpm = NULL;
1777 struct rte_lpm6_config config;
1778 uint8_t ip[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1780 uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
1783 config.max_rules = MAX_RULES;
1784 config.number_tbl8s = NUMBER_TBL8S;
1787 lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1788 TEST_LPM_ASSERT(lpm != NULL);
1790 status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1791 TEST_LPM_ASSERT(status == 0);
1793 status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1794 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1796 status = rte_lpm6_delete(lpm, ip, depth);
1797 TEST_LPM_ASSERT(status == 0);
1804 * Do all unit tests.
1810 int status = -1, global_status = 0;
1812 for (i = 0; i < NUM_LPM6_TESTS; i++) {
1813 printf("# test %02d\n", i);
1814 status = tests6[i]();
1817 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1818 global_status = status;
1822 return global_status;
1825 REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6);