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.
41 #include "test_lpm_routes.h"
42 #include "test_xmmt_ops.h"
44 #define TEST_LPM_ASSERT(cond) do { \
46 printf("Error at line %d: \n", __LINE__); \
51 typedef int32_t (*rte_lpm_test)(void);
53 static int32_t test0(void);
54 static int32_t test1(void);
55 static int32_t test2(void);
56 static int32_t test3(void);
57 static int32_t test4(void);
58 static int32_t test5(void);
59 static int32_t test6(void);
60 static int32_t test7(void);
61 static int32_t test8(void);
62 static int32_t test9(void);
63 static int32_t test10(void);
64 static int32_t test11(void);
65 static int32_t test12(void);
66 static int32_t test13(void);
67 static int32_t test14(void);
68 static int32_t test15(void);
69 static int32_t test16(void);
70 static int32_t test17(void);
72 rte_lpm_test tests[] = {
94 #define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
97 #define NUMBER_TBL8S 256
101 * Check that rte_lpm_create fails gracefully for incorrect user input
107 struct rte_lpm *lpm = NULL;
108 struct rte_lpm_config config;
110 config.max_rules = MAX_RULES;
111 config.number_tbl8s = NUMBER_TBL8S;
114 /* rte_lpm_create: lpm name == NULL */
115 lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
116 TEST_LPM_ASSERT(lpm == NULL);
118 /* rte_lpm_create: max_rules = 0 */
119 /* Note: __func__ inserts the function name, in this case "test0". */
120 config.max_rules = 0;
121 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
122 TEST_LPM_ASSERT(lpm == NULL);
124 /* socket_id < -1 is invalid */
125 config.max_rules = MAX_RULES;
126 lpm = rte_lpm_create(__func__, -2, &config);
127 TEST_LPM_ASSERT(lpm == NULL);
133 * Create lpm table then delete lpm table 100 times
134 * Use a slightly different rules size each time
139 struct rte_lpm *lpm = NULL;
140 struct rte_lpm_config config;
142 config.number_tbl8s = NUMBER_TBL8S;
146 /* rte_lpm_free: Free NULL */
147 for (i = 0; i < 100; i++) {
148 config.max_rules = MAX_RULES - i;
149 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
150 TEST_LPM_ASSERT(lpm != NULL);
155 /* Can not test free so return success */
160 * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
161 * therefore it is impossible to check for failure but this test is added to
162 * increase function coverage metrics and to validate that freeing null does
168 struct rte_lpm *lpm = NULL;
169 struct rte_lpm_config config;
171 config.max_rules = MAX_RULES;
172 config.number_tbl8s = NUMBER_TBL8S;
175 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
176 TEST_LPM_ASSERT(lpm != NULL);
184 * Check that rte_lpm_add fails gracefully for incorrect user input arguments
189 struct rte_lpm *lpm = NULL;
190 struct rte_lpm_config config;
192 config.max_rules = MAX_RULES;
193 config.number_tbl8s = NUMBER_TBL8S;
195 uint32_t ip = IPv4(0, 0, 0, 0), next_hop = 100;
199 /* rte_lpm_add: lpm == NULL */
200 status = rte_lpm_add(NULL, ip, depth, next_hop);
201 TEST_LPM_ASSERT(status < 0);
203 /*Create vaild lpm to use in rest of test. */
204 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
205 TEST_LPM_ASSERT(lpm != NULL);
207 /* rte_lpm_add: depth < 1 */
208 status = rte_lpm_add(lpm, ip, 0, next_hop);
209 TEST_LPM_ASSERT(status < 0);
211 /* rte_lpm_add: depth > MAX_DEPTH */
212 status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
213 TEST_LPM_ASSERT(status < 0);
221 * Check that rte_lpm_delete fails gracefully for incorrect user input
227 struct rte_lpm *lpm = NULL;
228 struct rte_lpm_config config;
230 config.max_rules = MAX_RULES;
231 config.number_tbl8s = NUMBER_TBL8S;
233 uint32_t ip = IPv4(0, 0, 0, 0);
237 /* rte_lpm_delete: lpm == NULL */
238 status = rte_lpm_delete(NULL, ip, depth);
239 TEST_LPM_ASSERT(status < 0);
241 /*Create vaild lpm to use in rest of test. */
242 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
243 TEST_LPM_ASSERT(lpm != NULL);
245 /* rte_lpm_delete: depth < 1 */
246 status = rte_lpm_delete(lpm, ip, 0);
247 TEST_LPM_ASSERT(status < 0);
249 /* rte_lpm_delete: depth > MAX_DEPTH */
250 status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
251 TEST_LPM_ASSERT(status < 0);
259 * Check that rte_lpm_lookup fails gracefully for incorrect user input
265 #if defined(RTE_LIBRTE_LPM_DEBUG)
266 struct rte_lpm *lpm = NULL;
267 struct rte_lpm_config config;
269 config.max_rules = MAX_RULES;
270 config.number_tbl8s = NUMBER_TBL8S;
272 uint32_t ip = IPv4(0, 0, 0, 0), next_hop_return = 0;
275 /* rte_lpm_lookup: lpm == NULL */
276 status = rte_lpm_lookup(NULL, ip, &next_hop_return);
277 TEST_LPM_ASSERT(status < 0);
279 /*Create vaild lpm to use in rest of test. */
280 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
281 TEST_LPM_ASSERT(lpm != NULL);
283 /* rte_lpm_lookup: depth < 1 */
284 status = rte_lpm_lookup(lpm, ip, NULL);
285 TEST_LPM_ASSERT(status < 0);
295 * Call add, lookup and delete for a single rule with depth <= 24
300 struct rte_lpm *lpm = NULL;
301 struct rte_lpm_config config;
303 config.max_rules = MAX_RULES;
304 config.number_tbl8s = NUMBER_TBL8S;
306 uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
310 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
311 TEST_LPM_ASSERT(lpm != NULL);
313 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
314 TEST_LPM_ASSERT(status == 0);
316 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
317 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
319 status = rte_lpm_delete(lpm, ip, depth);
320 TEST_LPM_ASSERT(status == 0);
322 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
323 TEST_LPM_ASSERT(status == -ENOENT);
331 * Call add, lookup and delete for a single rule with depth > 24
339 struct rte_lpm *lpm = NULL;
340 struct rte_lpm_config config;
342 config.max_rules = MAX_RULES;
343 config.number_tbl8s = NUMBER_TBL8S;
345 uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
349 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
350 TEST_LPM_ASSERT(lpm != NULL);
352 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
353 TEST_LPM_ASSERT(status == 0);
355 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
356 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
358 ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
359 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
360 TEST_LPM_ASSERT(hop[0] == next_hop_add);
361 TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
362 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
363 TEST_LPM_ASSERT(hop[3] == next_hop_add);
365 status = rte_lpm_delete(lpm, ip, depth);
366 TEST_LPM_ASSERT(status == 0);
368 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
369 TEST_LPM_ASSERT(status == -ENOENT);
377 * Use rte_lpm_add to add rules which effect only the second half of the lpm
378 * table. Use all possible depths ranging from 1..32. Set the next hop = to the
379 * depth. Check lookup hit for on every add and check for lookup miss on the
380 * first half of the lpm table after each add. Finally delete all rules going
381 * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
382 * delete. The lookup should return the next_hop_add value related to the
383 * previous depth value (i.e. depth -1).
390 struct rte_lpm *lpm = NULL;
391 struct rte_lpm_config config;
393 config.max_rules = MAX_RULES;
394 config.number_tbl8s = NUMBER_TBL8S;
396 uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
397 uint32_t next_hop_add, next_hop_return;
401 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
402 TEST_LPM_ASSERT(lpm != NULL);
404 /* Loop with rte_lpm_add. */
405 for (depth = 1; depth <= 32; depth++) {
406 /* Let the next_hop_add value = depth. Just for change. */
407 next_hop_add = depth;
409 status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
410 TEST_LPM_ASSERT(status == 0);
412 /* Check IP in first half of tbl24 which should be empty. */
413 status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
414 TEST_LPM_ASSERT(status == -ENOENT);
416 status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
417 TEST_LPM_ASSERT((status == 0) &&
418 (next_hop_return == next_hop_add));
420 ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
421 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
422 TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
423 TEST_LPM_ASSERT(hop[1] == next_hop_add);
424 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
425 TEST_LPM_ASSERT(hop[3] == next_hop_add);
428 /* Loop with rte_lpm_delete. */
429 for (depth = 32; depth >= 1; depth--) {
430 next_hop_add = (uint8_t) (depth - 1);
432 status = rte_lpm_delete(lpm, ip2, depth);
433 TEST_LPM_ASSERT(status == 0);
435 status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
438 TEST_LPM_ASSERT((status == 0) &&
439 (next_hop_return == next_hop_add));
441 TEST_LPM_ASSERT(status == -ENOENT);
444 status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
445 TEST_LPM_ASSERT(status == -ENOENT);
447 ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
448 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
450 TEST_LPM_ASSERT(hop[0] == next_hop_add);
451 TEST_LPM_ASSERT(hop[1] == next_hop_add);
453 TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
454 TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
456 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
457 TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
466 * - Add & lookup to hit invalid TBL24 entry
467 * - Add & lookup to hit valid TBL24 entry not extended
468 * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
469 * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
475 struct rte_lpm *lpm = NULL;
476 struct rte_lpm_config config;
478 config.max_rules = MAX_RULES;
479 config.number_tbl8s = NUMBER_TBL8S;
481 uint32_t ip, ip_1, ip_2;
482 uint8_t depth, depth_1, depth_2;
483 uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
486 /* Add & lookup to hit invalid TBL24 entry */
487 ip = IPv4(128, 0, 0, 0);
491 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
492 TEST_LPM_ASSERT(lpm != NULL);
494 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
495 TEST_LPM_ASSERT(status == 0);
497 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
498 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
500 status = rte_lpm_delete(lpm, ip, depth);
501 TEST_LPM_ASSERT(status == 0);
503 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
504 TEST_LPM_ASSERT(status == -ENOENT);
506 rte_lpm_delete_all(lpm);
508 /* Add & lookup to hit valid TBL24 entry not extended */
509 ip = IPv4(128, 0, 0, 0);
513 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
514 TEST_LPM_ASSERT(status == 0);
516 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
517 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
522 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
523 TEST_LPM_ASSERT(status == 0);
525 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
526 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
530 status = rte_lpm_delete(lpm, ip, depth);
531 TEST_LPM_ASSERT(status == 0);
535 status = rte_lpm_delete(lpm, ip, depth);
536 TEST_LPM_ASSERT(status == 0);
538 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
539 TEST_LPM_ASSERT(status == -ENOENT);
541 rte_lpm_delete_all(lpm);
543 /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
545 ip = IPv4(128, 0, 0, 0);
549 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
550 TEST_LPM_ASSERT(status == 0);
552 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
553 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
555 ip = IPv4(128, 0, 0, 5);
559 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
560 TEST_LPM_ASSERT(status == 0);
562 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
563 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
565 status = rte_lpm_delete(lpm, ip, depth);
566 TEST_LPM_ASSERT(status == 0);
568 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
569 TEST_LPM_ASSERT(status == -ENOENT);
571 ip = IPv4(128, 0, 0, 0);
575 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
576 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
578 status = rte_lpm_delete(lpm, ip, depth);
579 TEST_LPM_ASSERT(status == 0);
581 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
582 TEST_LPM_ASSERT(status == -ENOENT);
584 rte_lpm_delete_all(lpm);
586 /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
588 ip_1 = IPv4(128, 0, 0, 0);
590 next_hop_add_1 = 101;
592 ip_2 = IPv4(128, 0, 0, 5);
594 next_hop_add_2 = 102;
598 status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
599 TEST_LPM_ASSERT(status == 0);
601 status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
602 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
604 status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
605 TEST_LPM_ASSERT(status == 0);
607 status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
608 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
610 status = rte_lpm_delete(lpm, ip_2, depth_2);
611 TEST_LPM_ASSERT(status == 0);
613 status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
614 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
616 status = rte_lpm_delete(lpm, ip_1, depth_1);
617 TEST_LPM_ASSERT(status == 0);
619 status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
620 TEST_LPM_ASSERT(status == -ENOENT);
629 * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
631 * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
632 * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
634 * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
635 * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
636 * - Delete a rule that is not present in the TBL24 & lookup
637 * - Delete a rule that is not present in the TBL8 & lookup
644 struct rte_lpm *lpm = NULL;
645 struct rte_lpm_config config;
647 config.max_rules = MAX_RULES;
648 config.number_tbl8s = NUMBER_TBL8S;
650 uint32_t ip, next_hop_add, next_hop_return;
654 /* Add rule that covers a TBL24 range previously invalid & lookup
655 * (& delete & lookup) */
656 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
657 TEST_LPM_ASSERT(lpm != NULL);
659 ip = IPv4(128, 0, 0, 0);
663 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
664 TEST_LPM_ASSERT(status == 0);
666 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
667 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
669 status = rte_lpm_delete(lpm, ip, depth);
670 TEST_LPM_ASSERT(status == 0);
672 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
673 TEST_LPM_ASSERT(status == -ENOENT);
675 rte_lpm_delete_all(lpm);
677 ip = IPv4(128, 0, 0, 0);
681 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
682 TEST_LPM_ASSERT(status == 0);
684 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
685 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
687 status = rte_lpm_delete(lpm, ip, depth);
688 TEST_LPM_ASSERT(status == 0);
690 rte_lpm_delete_all(lpm);
692 /* Add rule that extends a TBL24 valid entry & lookup for both rules
693 * (& delete & lookup) */
695 ip = IPv4(128, 0, 0, 0);
699 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
700 TEST_LPM_ASSERT(status == 0);
702 ip = IPv4(128, 0, 0, 10);
706 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
707 TEST_LPM_ASSERT(status == 0);
709 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
710 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
712 ip = IPv4(128, 0, 0, 0);
715 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
716 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
718 ip = IPv4(128, 0, 0, 0);
721 status = rte_lpm_delete(lpm, ip, depth);
722 TEST_LPM_ASSERT(status == 0);
724 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
725 TEST_LPM_ASSERT(status == -ENOENT);
727 ip = IPv4(128, 0, 0, 10);
730 status = rte_lpm_delete(lpm, ip, depth);
731 TEST_LPM_ASSERT(status == 0);
733 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
734 TEST_LPM_ASSERT(status == -ENOENT);
736 rte_lpm_delete_all(lpm);
738 /* Add rule that updates the next hop in TBL24 & lookup
739 * (& delete & lookup) */
741 ip = IPv4(128, 0, 0, 0);
745 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
746 TEST_LPM_ASSERT(status == 0);
748 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
749 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
753 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
754 TEST_LPM_ASSERT(status == 0);
756 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
757 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
759 status = rte_lpm_delete(lpm, ip, depth);
760 TEST_LPM_ASSERT(status == 0);
762 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
763 TEST_LPM_ASSERT(status == -ENOENT);
765 rte_lpm_delete_all(lpm);
767 /* Add rule that updates the next hop in TBL8 & lookup
768 * (& delete & lookup) */
770 ip = IPv4(128, 0, 0, 0);
774 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
775 TEST_LPM_ASSERT(status == 0);
777 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
778 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
782 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
783 TEST_LPM_ASSERT(status == 0);
785 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
786 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
788 status = rte_lpm_delete(lpm, ip, depth);
789 TEST_LPM_ASSERT(status == 0);
791 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
792 TEST_LPM_ASSERT(status == -ENOENT);
794 rte_lpm_delete_all(lpm);
796 /* Delete a rule that is not present in the TBL24 & lookup */
798 ip = IPv4(128, 0, 0, 0);
801 status = rte_lpm_delete(lpm, ip, depth);
802 TEST_LPM_ASSERT(status < 0);
804 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
805 TEST_LPM_ASSERT(status == -ENOENT);
807 rte_lpm_delete_all(lpm);
809 /* Delete a rule that is not present in the TBL8 & lookup */
811 ip = IPv4(128, 0, 0, 0);
814 status = rte_lpm_delete(lpm, ip, depth);
815 TEST_LPM_ASSERT(status < 0);
817 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
818 TEST_LPM_ASSERT(status == -ENOENT);
826 * Add two rules, lookup to hit the more specific one, lookup to hit the less
827 * specific one delete the less specific rule and lookup previous values again;
828 * add a more specific rule than the existing rule, lookup again
835 struct rte_lpm *lpm = NULL;
836 struct rte_lpm_config config;
838 config.max_rules = MAX_RULES;
839 config.number_tbl8s = NUMBER_TBL8S;
841 uint32_t ip, next_hop_add, next_hop_return;
845 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
846 TEST_LPM_ASSERT(lpm != NULL);
848 ip = IPv4(128, 0, 0, 0);
852 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
853 TEST_LPM_ASSERT(status == 0);
855 ip = IPv4(128, 0, 0, 10);
859 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
860 TEST_LPM_ASSERT(status == 0);
862 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
863 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
865 ip = IPv4(128, 0, 0, 0);
868 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
869 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
871 ip = IPv4(128, 0, 0, 0);
874 status = rte_lpm_delete(lpm, ip, depth);
875 TEST_LPM_ASSERT(status == 0);
877 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
878 TEST_LPM_ASSERT(status == -ENOENT);
880 ip = IPv4(128, 0, 0, 10);
883 status = rte_lpm_delete(lpm, ip, depth);
884 TEST_LPM_ASSERT(status == 0);
886 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
887 TEST_LPM_ASSERT(status == -ENOENT);
895 * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
896 * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
906 struct rte_lpm *lpm = NULL;
907 struct rte_lpm_config config;
909 config.max_rules = MAX_RULES;
910 config.number_tbl8s = NUMBER_TBL8S;
912 uint32_t ip, i, next_hop_add, next_hop_return;
916 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
917 TEST_LPM_ASSERT(lpm != NULL);
919 ip = IPv4(128, 0, 0, 0);
923 for (i = 0; i < 1000; i++) {
924 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
925 TEST_LPM_ASSERT(status == 0);
927 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
928 TEST_LPM_ASSERT((status == 0) &&
929 (next_hop_return == next_hop_add));
931 ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
932 rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
933 TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
934 TEST_LPM_ASSERT(hop[1] == next_hop_add);
935 TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
936 TEST_LPM_ASSERT(hop[3] == next_hop_add);
938 status = rte_lpm_delete(lpm, ip, depth);
939 TEST_LPM_ASSERT(status == 0);
941 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
942 TEST_LPM_ASSERT(status == -ENOENT);
951 * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
952 * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
953 * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
954 * extension and contraction.
961 struct rte_lpm *lpm = NULL;
962 struct rte_lpm_config config;
964 config.max_rules = MAX_RULES;
965 config.number_tbl8s = NUMBER_TBL8S;
967 uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
971 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
972 TEST_LPM_ASSERT(lpm != NULL);
974 ip = IPv4(128, 0, 0, 0);
976 next_hop_add_1 = 100;
978 status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
979 TEST_LPM_ASSERT(status == 0);
981 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
982 TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
985 next_hop_add_2 = 101;
987 for (i = 0; i < 1000; i++) {
988 status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
989 TEST_LPM_ASSERT(status == 0);
991 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
992 TEST_LPM_ASSERT((status == 0) &&
993 (next_hop_return == next_hop_add_2));
995 status = rte_lpm_delete(lpm, ip, depth);
996 TEST_LPM_ASSERT(status == 0);
998 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
999 TEST_LPM_ASSERT((status == 0) &&
1000 (next_hop_return == next_hop_add_1));
1005 status = rte_lpm_delete(lpm, ip, depth);
1006 TEST_LPM_ASSERT(status == 0);
1008 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1009 TEST_LPM_ASSERT(status == -ENOENT);
1017 * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
1018 * No more tbl8 extensions will be allowed. Now add one more rule that required
1019 * a tbl8 extension and get fail.
1025 /* We only use depth = 32 in the loop below so we must make sure
1026 * that we have enough storage for all rules at that depth*/
1028 struct rte_lpm *lpm = NULL;
1029 struct rte_lpm_config config;
1031 config.max_rules = 256 * 32;
1032 config.number_tbl8s = NUMBER_TBL8S;
1034 uint32_t ip, next_hop_add, next_hop_return;
1038 /* Add enough space for 256 rules for every depth */
1039 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1040 TEST_LPM_ASSERT(lpm != NULL);
1044 ip = IPv4(0, 0, 0, 0);
1046 /* Add 256 rules that require a tbl8 extension */
1047 for (; ip <= IPv4(0, 0, 255, 0); ip += 256) {
1048 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
1049 TEST_LPM_ASSERT(status == 0);
1051 status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1052 TEST_LPM_ASSERT((status == 0) &&
1053 (next_hop_return == next_hop_add));
1056 /* All tbl8 extensions have been used above. Try to add one more and
1058 ip = IPv4(1, 0, 0, 0);
1061 status = rte_lpm_add(lpm, ip, depth, next_hop_add);
1062 TEST_LPM_ASSERT(status < 0);
1070 * Sequence of operations for find existing lpm table
1073 * - find existing table: hit
1074 * - find non-existing table: miss
1080 struct rte_lpm *lpm = NULL, *result = NULL;
1081 struct rte_lpm_config config;
1083 config.max_rules = 256 * 32;
1084 config.number_tbl8s = NUMBER_TBL8S;
1088 lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1089 TEST_LPM_ASSERT(lpm != NULL);
1091 /* Try to find existing lpm */
1092 result = rte_lpm_find_existing("lpm_find_existing");
1093 TEST_LPM_ASSERT(result == lpm);
1095 /* Try to find non-existing lpm */
1096 result = rte_lpm_find_existing("lpm_find_non_existing");
1097 TEST_LPM_ASSERT(result == NULL);
1100 rte_lpm_delete_all(lpm);
1107 * test failure condition of overloading the tbl8 so no more will fit
1108 * Check we get an error return value in that case
1114 struct rte_lpm_config config;
1116 config.max_rules = 256 * 32;
1117 config.number_tbl8s = NUMBER_TBL8S;
1119 struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1121 /* ip loops through all possibilities for top 24 bits of address */
1122 for (ip = 0; ip < 0xFFFFFF; ip++) {
1123 /* add an entry within a different tbl8 each time, since
1124 * depth >24 and the top 24 bits are different */
1125 if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
1129 if (ip != NUMBER_TBL8S) {
1130 printf("Error, unexpected failure with filling tbl8 groups\n");
1131 printf("Failed after %u additions, expected after %u\n",
1132 (unsigned)ip, (unsigned)NUMBER_TBL8S);
1140 * Test for overwriting of tbl8:
1141 * - add rule /32 and lookup
1142 * - add new rule /24 and lookup
1143 * - add third rule /25 and lookup
1144 * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1149 struct rte_lpm *lpm = NULL;
1150 struct rte_lpm_config config;
1152 config.max_rules = MAX_RULES;
1153 config.number_tbl8s = NUMBER_TBL8S;
1155 const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
1156 const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
1157 const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
1158 const uint8_t d_ip_10_32 = 32,
1161 const uint32_t next_hop_ip_10_32 = 100,
1162 next_hop_ip_10_24 = 105,
1163 next_hop_ip_20_25 = 111;
1164 uint32_t next_hop_return = 0;
1167 lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1168 TEST_LPM_ASSERT(lpm != NULL);
1170 if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
1171 next_hop_ip_10_32)) < 0)
1174 status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1175 uint32_t test_hop_10_32 = next_hop_return;
1176 TEST_LPM_ASSERT(status == 0);
1177 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1179 if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
1180 next_hop_ip_10_24)) < 0)
1183 status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1184 uint32_t test_hop_10_24 = next_hop_return;
1185 TEST_LPM_ASSERT(status == 0);
1186 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1188 if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
1189 next_hop_ip_20_25)) < 0)
1192 status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
1193 uint32_t test_hop_20_25 = next_hop_return;
1194 TEST_LPM_ASSERT(status == 0);
1195 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1197 if (test_hop_10_32 == test_hop_10_24) {
1198 printf("Next hop return equal\n");
1202 if (test_hop_10_24 == test_hop_20_25) {
1203 printf("Next hop return equal\n");
1207 status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1208 TEST_LPM_ASSERT(status == 0);
1209 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1211 status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1212 TEST_LPM_ASSERT(status == 0);
1213 TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1221 * Do all unit tests.
1228 int status, global_status = 0;
1230 for (i = 0; i < NUM_LPM_TESTS; i++) {
1231 status = tests[i]();
1233 printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i]));
1234 global_status = status;
1238 return global_status;
1241 REGISTER_TEST_COMMAND(lpm_autotest, test_lpm);