xref: /dpdk/app/test/test_lpm6.c (revision cf435a07)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
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
16  *       distribution.
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.
20  *
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.
32  */
33 
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <rte_memory.h>
40 #include <rte_lpm6.h>
41 
42 #include "test.h"
43 #include "test_lpm6_routes.h"
44 
45 #define TEST_LPM_ASSERT(cond) do {                                            \
46 	if (!(cond)) {                                                        \
47 		printf("Error at line %d: \n", __LINE__);                     \
48 		return -1;                                                    \
49 	}                                                                     \
50 } while(0)
51 
52 typedef int32_t (* rte_lpm6_test)(void);
53 
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 
83 rte_lpm6_test tests6[] = {
84 /* Test Cases */
85 	test0,
86 	test1,
87 	test2,
88 	test3,
89 	test4,
90 	test5,
91 	test6,
92 	test7,
93 	test8,
94 	test9,
95 	test10,
96 	test11,
97 	test12,
98 	test13,
99 	test14,
100 	test15,
101 	test16,
102 	test17,
103 	test18,
104 	test19,
105 	test20,
106 	test21,
107 	test22,
108 	test23,
109 	test24,
110 	test25,
111 	test26,
112 	test27,
113 };
114 
115 #define NUM_LPM6_TESTS                (sizeof(tests6)/sizeof(tests6[0]))
116 #define MAX_DEPTH                                                    128
117 #define MAX_RULES                                                1000000
118 #define NUMBER_TBL8S                                           (1 << 16)
119 #define MAX_NUM_TBL8S                                          (1 << 21)
120 #define PASS 0
121 
122 static void
123 IPv6(uint8_t *ip, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5,
124 		uint8_t b6, uint8_t b7, uint8_t b8, uint8_t b9, uint8_t b10,
125 		uint8_t b11, uint8_t b12, uint8_t b13, uint8_t b14, uint8_t b15,
126 		uint8_t b16)
127 {
128 	ip[0] = b1;
129 	ip[1] = b2;
130 	ip[2] = b3;
131 	ip[3] = b4;
132 	ip[4] = b5;
133 	ip[5] = b6;
134 	ip[6] = b7;
135 	ip[7] = b8;
136 	ip[8] = b9;
137 	ip[9] = b10;
138 	ip[10] = b11;
139 	ip[11] = b12;
140 	ip[12] = b13;
141 	ip[13] = b14;
142 	ip[14] = b15;
143 	ip[15] = b16;
144 }
145 
146 /*
147  * Check that rte_lpm6_create fails gracefully for incorrect user input
148  * arguments
149  */
150 int32_t
151 test0(void)
152 {
153 	struct rte_lpm6 *lpm = NULL;
154 	struct rte_lpm6_config config;
155 
156 	config.max_rules = MAX_RULES;
157 	config.number_tbl8s = NUMBER_TBL8S;
158 	config.flags = 0;
159 
160 	/* rte_lpm6_create: lpm name == NULL */
161 	lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
162 	TEST_LPM_ASSERT(lpm == NULL);
163 
164 	/* rte_lpm6_create: max_rules = 0 */
165 	/* Note: __func__ inserts the function name, in this case "test0". */
166 	config.max_rules = 0;
167 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
168 	TEST_LPM_ASSERT(lpm == NULL);
169 
170 	/* socket_id < -1 is invalid */
171 	config.max_rules = MAX_RULES;
172 	lpm = rte_lpm6_create(__func__, -2, &config);
173 	TEST_LPM_ASSERT(lpm == NULL);
174 
175 	/* rte_lpm6_create: number_tbl8s is bigger than the maximum */
176 	config.number_tbl8s = MAX_NUM_TBL8S + 1;
177 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
178 	TEST_LPM_ASSERT(lpm == NULL);
179 
180 	/* rte_lpm6_create: config = NULL */
181 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
182 	TEST_LPM_ASSERT(lpm == NULL);
183 
184 	return PASS;
185 }
186 
187 /*
188  * Creates two different LPM tables. Tries to create a third one with the same
189  * name as the first one and expects the create function to return the same
190  * pointer.
191  */
192 int32_t
193 test1(void)
194 {
195 	struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
196 	struct rte_lpm6_config config;
197 
198 	config.max_rules = MAX_RULES;
199 	config.number_tbl8s = NUMBER_TBL8S;
200 	config.flags = 0;
201 
202 	/* rte_lpm6_create: lpm name == LPM1 */
203 	lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
204 	TEST_LPM_ASSERT(lpm1 != NULL);
205 
206 	/* rte_lpm6_create: lpm name == LPM2 */
207 	lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
208 	TEST_LPM_ASSERT(lpm2 != NULL);
209 
210 	/* rte_lpm6_create: lpm name == LPM2 */
211 	lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
212 	TEST_LPM_ASSERT(lpm3 == NULL);
213 
214 	rte_lpm6_free(lpm1);
215 	rte_lpm6_free(lpm2);
216 
217 	return PASS;
218 }
219 
220 /*
221  * Create lpm table then delete lpm table 20 times
222  * Use a slightly different rules size each time
223  */
224 int32_t
225 test2(void)
226 {
227 	struct rte_lpm6 *lpm = NULL;
228 	struct rte_lpm6_config config;
229 	int32_t i;
230 
231 	config.number_tbl8s = NUMBER_TBL8S;
232 	config.flags = 0;
233 
234 	/* rte_lpm6_free: Free NULL */
235 	for (i = 0; i < 20; i++) {
236 		config.max_rules = MAX_RULES - i;
237 		lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
238 		TEST_LPM_ASSERT(lpm != NULL);
239 
240 		rte_lpm6_free(lpm);
241 	}
242 
243 	/* Can not test free so return success */
244 	return PASS;
245 }
246 
247 /*
248  * Call rte_lpm6_free for NULL pointer user input. Note: free has no return and
249  * therefore it is impossible to check for failure but this test is added to
250  * increase function coverage metrics and to validate that freeing null does
251  * not crash.
252  */
253 int32_t
254 test3(void)
255 {
256 	struct rte_lpm6 *lpm = NULL;
257 	struct rte_lpm6_config config;
258 
259 	config.max_rules = MAX_RULES;
260 	config.number_tbl8s = NUMBER_TBL8S;
261 	config.flags = 0;
262 
263 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
264 	TEST_LPM_ASSERT(lpm != NULL);
265 
266 	rte_lpm6_free(lpm);
267 	rte_lpm6_free(NULL);
268 	return PASS;
269 }
270 
271 /*
272  * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
273  */
274 int32_t
275 test4(void)
276 {
277 	struct rte_lpm6 *lpm = NULL;
278 	struct rte_lpm6_config config;
279 
280 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
281 	uint8_t depth = 24, next_hop = 100;
282 	int32_t status = 0;
283 
284 	config.max_rules = MAX_RULES;
285 	config.number_tbl8s = NUMBER_TBL8S;
286 	config.flags = 0;
287 
288 	/* rte_lpm6_add: lpm == NULL */
289 	status = rte_lpm6_add(NULL, ip, depth, next_hop);
290 	TEST_LPM_ASSERT(status < 0);
291 
292 	/*Create vaild lpm to use in rest of test. */
293 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
294 	TEST_LPM_ASSERT(lpm != NULL);
295 
296 	/* rte_lpm6_add: depth < 1 */
297 	status = rte_lpm6_add(lpm, ip, 0, next_hop);
298 	TEST_LPM_ASSERT(status < 0);
299 
300 	/* rte_lpm6_add: depth > MAX_DEPTH */
301 	status = rte_lpm6_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
302 	TEST_LPM_ASSERT(status < 0);
303 
304 	rte_lpm6_free(lpm);
305 
306 	return PASS;
307 }
308 
309 /*
310  * Check that rte_lpm6_delete fails gracefully for incorrect user input
311  * arguments
312  */
313 int32_t
314 test5(void)
315 {
316 	struct rte_lpm6 *lpm = NULL;
317 	struct rte_lpm6_config config;
318 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
319 	uint8_t depth = 24;
320 	int32_t status = 0;
321 
322 	config.max_rules = MAX_RULES;
323 	config.number_tbl8s = NUMBER_TBL8S;
324 	config.flags = 0;
325 
326 	/* rte_lpm_delete: lpm == NULL */
327 	status = rte_lpm6_delete(NULL, ip, depth);
328 	TEST_LPM_ASSERT(status < 0);
329 
330 	/*Create vaild lpm to use in rest of test. */
331 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
332 	TEST_LPM_ASSERT(lpm != NULL);
333 
334 	/* rte_lpm_delete: depth < 1 */
335 	status = rte_lpm6_delete(lpm, ip, 0);
336 	TEST_LPM_ASSERT(status < 0);
337 
338 	/* rte_lpm_delete: depth > MAX_DEPTH */
339 	status = rte_lpm6_delete(lpm, ip, (MAX_DEPTH + 1));
340 	TEST_LPM_ASSERT(status < 0);
341 
342 	rte_lpm6_free(lpm);
343 
344 	return PASS;
345 }
346 
347 /*
348  * Check that rte_lpm6_lookup fails gracefully for incorrect user input
349  * arguments
350  */
351 int32_t
352 test6(void)
353 {
354 	struct rte_lpm6 *lpm = NULL;
355 	struct rte_lpm6_config config;
356 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
357 	uint8_t next_hop_return = 0;
358 	int32_t status = 0;
359 
360 	config.max_rules = MAX_RULES;
361 	config.number_tbl8s = NUMBER_TBL8S;
362 	config.flags = 0;
363 
364 	/* rte_lpm6_lookup: lpm == NULL */
365 	status = rte_lpm6_lookup(NULL, ip, &next_hop_return);
366 	TEST_LPM_ASSERT(status < 0);
367 
368 	/*Create vaild lpm to use in rest of test. */
369 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
370 	TEST_LPM_ASSERT(lpm != NULL);
371 
372 	/* rte_lpm6_lookup: ip = NULL */
373 	status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
374 	TEST_LPM_ASSERT(status < 0);
375 
376 	/* rte_lpm6_lookup: next_hop = NULL */
377 	status = rte_lpm6_lookup(lpm, ip, NULL);
378 	TEST_LPM_ASSERT(status < 0);
379 
380 	rte_lpm6_free(lpm);
381 
382 	return PASS;
383 }
384 
385 /*
386  * Checks that rte_lpm6_lookup_bulk_func fails gracefully for incorrect user
387  * input arguments
388  */
389 int32_t
390 test7(void)
391 {
392 	struct rte_lpm6 *lpm = NULL;
393 	struct rte_lpm6_config config;
394 	uint8_t ip[10][16];
395 	int16_t next_hop_return[10];
396 	int32_t status = 0;
397 
398 	config.max_rules = MAX_RULES;
399 	config.number_tbl8s = NUMBER_TBL8S;
400 	config.flags = 0;
401 
402 	/* rte_lpm6_lookup: lpm == NULL */
403 	status = rte_lpm6_lookup_bulk_func(NULL, ip, next_hop_return, 10);
404 	TEST_LPM_ASSERT(status < 0);
405 
406 	/*Create vaild lpm to use in rest of test. */
407 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
408 	TEST_LPM_ASSERT(lpm != NULL);
409 
410 	/* rte_lpm6_lookup: ip = NULL */
411 	status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, 10);
412 	TEST_LPM_ASSERT(status < 0);
413 
414 	/* rte_lpm6_lookup: next_hop = NULL */
415 	status = rte_lpm6_lookup_bulk_func(lpm, ip, NULL, 10);
416 	TEST_LPM_ASSERT(status < 0);
417 
418 	rte_lpm6_free(lpm);
419 
420 	return PASS;
421 }
422 
423 /*
424  * Checks that rte_lpm6_delete_bulk_func fails gracefully for incorrect user
425  * input arguments
426  */
427 int32_t
428 test8(void)
429 {
430 	struct rte_lpm6 *lpm = NULL;
431 	struct rte_lpm6_config config;
432 	uint8_t ip[10][16];
433 	uint8_t depth[10];
434 	int32_t status = 0;
435 
436 	config.max_rules = MAX_RULES;
437 	config.number_tbl8s = NUMBER_TBL8S;
438 	config.flags = 0;
439 
440 	/* rte_lpm6_delete: lpm == NULL */
441 	status = rte_lpm6_delete_bulk_func(NULL, ip, depth, 10);
442 	TEST_LPM_ASSERT(status < 0);
443 
444 	/*Create vaild lpm to use in rest of test. */
445 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
446 	TEST_LPM_ASSERT(lpm != NULL);
447 
448 	/* rte_lpm6_delete: ip = NULL */
449 	status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, 10);
450 	TEST_LPM_ASSERT(status < 0);
451 
452 	/* rte_lpm6_delete: next_hop = NULL */
453 	status = rte_lpm6_delete_bulk_func(lpm, ip, NULL, 10);
454 	TEST_LPM_ASSERT(status < 0);
455 
456 	rte_lpm6_free(lpm);
457 
458 	return PASS;
459 }
460 
461 /*
462  * Call add, lookup and delete for a single rule with depth < 24.
463  * Check all the combinations for the first three bytes that result in a hit.
464  * Delete the rule and check that the same test returs a miss.
465  */
466 int32_t
467 test9(void)
468 {
469 	struct rte_lpm6 *lpm = NULL;
470 	struct rte_lpm6_config config;
471 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
472 	uint8_t depth = 16, next_hop_add = 100, next_hop_return = 0;
473 	int32_t status = 0;
474 	uint8_t i;
475 
476 	config.max_rules = MAX_RULES;
477 	config.number_tbl8s = NUMBER_TBL8S;
478 	config.flags = 0;
479 
480 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
481 	TEST_LPM_ASSERT(lpm != NULL);
482 
483 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
484 	TEST_LPM_ASSERT(status == 0);
485 
486 	for (i = 0; i < UINT8_MAX; i++) {
487 		ip[2] = i;
488 		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
489 		TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
490 	}
491 
492 	status = rte_lpm6_delete(lpm, ip, depth);
493 	TEST_LPM_ASSERT(status == 0);
494 
495 	for (i = 0; i < UINT8_MAX; i++) {
496 		ip[2] = i;
497 		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
498 		TEST_LPM_ASSERT(status == -ENOENT);
499 	}
500 
501 	rte_lpm6_free(lpm);
502 
503 	return PASS;
504 }
505 
506 /*
507  * Adds max_rules + 1 and expects a failure. Deletes a rule, then adds
508  * another one and expects success.
509  */
510 int32_t
511 test10(void)
512 {
513 	struct rte_lpm6 *lpm = NULL;
514 	struct rte_lpm6_config config;
515 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
516 	uint8_t depth, next_hop_add = 100;
517 	int32_t status = 0;
518 	int i;
519 
520 	config.max_rules = 127;
521 	config.number_tbl8s = NUMBER_TBL8S;
522 	config.flags = 0;
523 
524 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
525 	TEST_LPM_ASSERT(lpm != NULL);
526 
527 	for (i = 1; i < 128; i++) {
528 		depth = (uint8_t)i;
529 		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
530 		TEST_LPM_ASSERT(status == 0);
531 	}
532 
533 	depth = 128;
534 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
535 	TEST_LPM_ASSERT(status == -ENOSPC);
536 
537 	depth = 127;
538 	status = rte_lpm6_delete(lpm, ip, depth);
539 	TEST_LPM_ASSERT(status == 0);
540 
541 	depth = 128;
542 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
543 	TEST_LPM_ASSERT(status == 0);
544 
545 	rte_lpm6_free(lpm);
546 
547 	return PASS;
548 }
549 
550 /*
551  * Creates an LPM table with a small number of tbl8s and exhaust them in the
552  * middle of the process of creating a rule.
553  */
554 int32_t
555 test11(void)
556 {
557 	struct rte_lpm6 *lpm = NULL;
558 	struct rte_lpm6_config config;
559 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
560 	uint8_t depth, next_hop_add = 100;
561 	int32_t status = 0;
562 
563 	config.max_rules = MAX_RULES;
564 	config.number_tbl8s = 16;
565 	config.flags = 0;
566 
567 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
568 	TEST_LPM_ASSERT(lpm != NULL);
569 
570 	depth = 128;
571 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
572 	TEST_LPM_ASSERT(status == 0);
573 
574 	ip[0] = 1;
575 	depth = 25;
576 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
577 	TEST_LPM_ASSERT(status == 0);
578 
579 	status = rte_lpm6_delete(lpm, ip, depth);
580 	TEST_LPM_ASSERT(status == 0);
581 
582 	depth = 33;
583 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
584 	TEST_LPM_ASSERT(status == 0);
585 
586 	status = rte_lpm6_delete(lpm, ip, depth);
587 	TEST_LPM_ASSERT(status == 0);
588 
589 	depth = 41;
590 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
591 	TEST_LPM_ASSERT(status == 0);
592 
593 	status = rte_lpm6_delete(lpm, ip, depth);
594 	TEST_LPM_ASSERT(status == 0);
595 
596 	depth = 49;
597 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
598 	TEST_LPM_ASSERT(status == -ENOSPC);
599 
600 	depth = 41;
601 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
602 	TEST_LPM_ASSERT(status == 0);
603 
604 	rte_lpm6_free(lpm);
605 
606 	return PASS;
607 }
608 
609 /*
610  * Creates an LPM table with a small number of tbl8s and exhaust them in the
611  * middle of the process of adding a rule when there is already an existing rule
612  * in that position and needs to be extended.
613  */
614 int32_t
615 test12(void)
616 {
617 	struct rte_lpm6 *lpm = NULL;
618 	struct rte_lpm6_config config;
619 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
620 	uint8_t depth, next_hop_add = 100;
621 	int32_t status = 0;
622 
623 	config.max_rules = MAX_RULES;
624 	config.number_tbl8s = 16;
625 	config.flags = 0;
626 
627 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
628 	TEST_LPM_ASSERT(lpm != NULL);
629 
630 	depth = 128;
631 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
632 	TEST_LPM_ASSERT(status == 0);
633 
634 	ip[0] = 1;
635 	depth = 41;
636 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
637 	TEST_LPM_ASSERT(status == 0);
638 
639 	depth = 49;
640 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
641 	TEST_LPM_ASSERT(status == -ENOSPC);
642 
643 	rte_lpm6_free(lpm);
644 
645 	return PASS;
646 }
647 
648 /*
649  * Creates an LPM table with max_rules = 2 and tries to add 3 rules.
650  * Delete one of the rules and tries to add the third one again.
651  */
652 int32_t
653 test13(void)
654 {
655 	struct rte_lpm6 *lpm = NULL;
656 	struct rte_lpm6_config config;
657 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
658 	uint8_t depth, next_hop_add = 100;
659 	int32_t status = 0;
660 
661 	config.max_rules = 2;
662 	config.number_tbl8s = NUMBER_TBL8S;
663 	config.flags = 0;
664 
665 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
666 	TEST_LPM_ASSERT(lpm != NULL);
667 
668 	depth = 1;
669 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
670 	TEST_LPM_ASSERT(status == 0);
671 
672 	depth = 2;
673 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
674 	TEST_LPM_ASSERT(status == 0);
675 
676 	depth = 3;
677 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
678 	TEST_LPM_ASSERT(status == -ENOSPC);
679 
680 	depth = 2;
681 	status = rte_lpm6_delete(lpm, ip, depth);
682 	TEST_LPM_ASSERT(status == 0);
683 
684 	depth = 3;
685 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
686 	TEST_LPM_ASSERT(status == 0);
687 
688 	rte_lpm6_free(lpm);
689 
690 	return PASS;
691 }
692 
693 /*
694  * Add 2^12 routes with different first 12 bits and depth 25.
695  * Add one more route with the same depth and check that results in a failure.
696  * After that delete the last rule and create the one that was attempted to be
697  * created. This checks tbl8 exhaustion.
698  */
699 int32_t
700 test14(void)
701 {
702 	struct rte_lpm6 *lpm = NULL;
703 	struct rte_lpm6_config config;
704 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
705 	uint8_t depth = 25, next_hop_add = 100;
706 	int32_t status = 0;
707 	int i;
708 
709 	config.max_rules = MAX_RULES;
710 	config.number_tbl8s = 256;
711 	config.flags = 0;
712 
713 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
714 	TEST_LPM_ASSERT(lpm != NULL);
715 
716 	for (i = 0; i < 256; i++) {
717 		ip[0] = (uint8_t)i;
718 		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
719 		TEST_LPM_ASSERT(status == 0);
720 	}
721 
722 	ip[0] = 255;
723 	ip[1] = 1;
724 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
725 	TEST_LPM_ASSERT(status == -ENOSPC);
726 
727 	ip[0] = 255;
728 	ip[1] = 0;
729 	status = rte_lpm6_delete(lpm, ip, depth);
730 	TEST_LPM_ASSERT(status == 0);
731 
732 	ip[0] = 255;
733 	ip[1] = 1;
734 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
735 	TEST_LPM_ASSERT(status == 0);
736 
737 	rte_lpm6_free(lpm);
738 
739 	return PASS;
740 }
741 
742 /*
743  * Call add, lookup and delete for a single rule with depth = 24
744  */
745 int32_t
746 test15(void)
747 {
748 	struct rte_lpm6 *lpm = NULL;
749 	struct rte_lpm6_config config;
750 	uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
751 	uint8_t depth = 24, next_hop_add = 100, next_hop_return = 0;
752 	int32_t status = 0;
753 
754 	config.max_rules = MAX_RULES;
755 	config.number_tbl8s = NUMBER_TBL8S;
756 	config.flags = 0;
757 
758 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
759 	TEST_LPM_ASSERT(lpm != NULL);
760 
761 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
762 	TEST_LPM_ASSERT(status == 0);
763 
764 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
765 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
766 
767 	status = rte_lpm6_delete(lpm, ip, depth);
768 	TEST_LPM_ASSERT(status == 0);
769 
770 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
771 	TEST_LPM_ASSERT(status == -ENOENT);
772 
773 	rte_lpm6_free(lpm);
774 
775 	return PASS;
776 }
777 
778 /*
779  * Call add, lookup and delete for a single rule with depth > 24
780  */
781 int32_t
782 test16(void)
783 {
784 	struct rte_lpm6 *lpm = NULL;
785 	struct rte_lpm6_config config;
786 	uint8_t ip[] = {12,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
787 	uint8_t depth = 128, next_hop_add = 100, next_hop_return = 0;
788 	int32_t status = 0;
789 
790 	config.max_rules = MAX_RULES;
791 	config.number_tbl8s = NUMBER_TBL8S;
792 	config.flags = 0;
793 
794 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
795 	TEST_LPM_ASSERT(lpm != NULL);
796 
797 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
798 	TEST_LPM_ASSERT(status == 0);
799 
800 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
801 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
802 
803 	status = rte_lpm6_delete(lpm, ip, depth);
804 	TEST_LPM_ASSERT(status == 0);
805 
806 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
807 	TEST_LPM_ASSERT(status == -ENOENT);
808 
809 	rte_lpm6_free(lpm);
810 
811 	return PASS;
812 }
813 
814 /*
815  * Use rte_lpm6_add to add rules which effect only the second half of the lpm
816  * table. Use all possible depths ranging from 1..32. Set the next hop = to the
817  * depth. Check lookup hit for on every add and check for lookup miss on the
818  * first half of the lpm table after each add. Finally delete all rules going
819  * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
820  * delete. The lookup should return the next_hop_add value related to the
821  * previous depth value (i.e. depth -1).
822  */
823 int32_t
824 test17(void)
825 {
826 	struct rte_lpm6 *lpm = NULL;
827 	struct rte_lpm6_config config;
828 	uint8_t ip1[] = {127,255,255,255,255,255,255,255,255,
829 			255,255,255,255,255,255,255};
830 	uint8_t ip2[] = {128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
831 	uint8_t depth, next_hop_add, next_hop_return;
832 	int32_t status = 0;
833 
834 	config.max_rules = MAX_RULES;
835 	config.number_tbl8s = NUMBER_TBL8S;
836 	config.flags = 0;
837 
838 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
839 	TEST_LPM_ASSERT(lpm != NULL);
840 
841 	/* Loop with rte_lpm6_add. */
842 	for (depth = 1; depth <= 16; depth++) {
843 		/* Let the next_hop_add value = depth. Just for change. */
844 		next_hop_add = depth;
845 
846 		status = rte_lpm6_add(lpm, ip2, depth, next_hop_add);
847 		TEST_LPM_ASSERT(status == 0);
848 
849 		/* Check IP in first half of tbl24 which should be empty. */
850 		status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
851 		TEST_LPM_ASSERT(status == -ENOENT);
852 
853 		status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
854 		TEST_LPM_ASSERT((status == 0) &&
855 			(next_hop_return == next_hop_add));
856 	}
857 
858 	/* Loop with rte_lpm6_delete. */
859 	for (depth = 16; depth >= 1; depth--) {
860 		next_hop_add = (uint8_t) (depth - 1);
861 
862 		status = rte_lpm6_delete(lpm, ip2, depth);
863 		TEST_LPM_ASSERT(status == 0);
864 
865 		status = rte_lpm6_lookup(lpm, ip2, &next_hop_return);
866 
867 		if (depth != 1) {
868 			TEST_LPM_ASSERT((status == 0) &&
869 				(next_hop_return == next_hop_add));
870 		}
871 		else {
872 			TEST_LPM_ASSERT(status == -ENOENT);
873 		}
874 
875 		status = rte_lpm6_lookup(lpm, ip1, &next_hop_return);
876 		TEST_LPM_ASSERT(status == -ENOENT);
877 	}
878 
879 	rte_lpm6_free(lpm);
880 
881 	return PASS;
882 }
883 
884 /*
885  * - Add & lookup to hit invalid TBL24 entry
886  * - Add & lookup to hit valid TBL24 entry not extended
887  * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
888  * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
889  */
890 int32_t
891 test18(void)
892 {
893 	struct rte_lpm6 *lpm = NULL;
894 	struct rte_lpm6_config config;
895 	uint8_t ip[16], ip_1[16], ip_2[16];
896 	uint8_t depth, depth_1, depth_2, next_hop_add, next_hop_add_1,
897 		next_hop_add_2, next_hop_return;
898 	int32_t status = 0;
899 
900 	config.max_rules = MAX_RULES;
901 	config.number_tbl8s = NUMBER_TBL8S;
902 	config.flags = 0;
903 
904 	/* Add & lookup to hit invalid TBL24 entry */
905 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
906 	depth = 24;
907 	next_hop_add = 100;
908 
909 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
910 	TEST_LPM_ASSERT(lpm != NULL);
911 
912 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
913 	TEST_LPM_ASSERT(status == 0);
914 
915 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
916 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
917 
918 	status = rte_lpm6_delete(lpm, ip, depth);
919 	TEST_LPM_ASSERT(status == 0);
920 
921 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
922 	TEST_LPM_ASSERT(status == -ENOENT);
923 
924 	rte_lpm6_delete_all(lpm);
925 
926 	/* Add & lookup to hit valid TBL24 entry not extended */
927 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
928 	depth = 23;
929 	next_hop_add = 100;
930 
931 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
932 	TEST_LPM_ASSERT(status == 0);
933 
934 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
935 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
936 
937 	depth = 24;
938 	next_hop_add = 101;
939 
940 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
941 	TEST_LPM_ASSERT(status == 0);
942 
943 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
944 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
945 
946 	depth = 24;
947 
948 	status = rte_lpm6_delete(lpm, ip, depth);
949 	TEST_LPM_ASSERT(status == 0);
950 
951 	depth = 23;
952 
953 	status = rte_lpm6_delete(lpm, ip, depth);
954 	TEST_LPM_ASSERT(status == 0);
955 
956 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
957 	TEST_LPM_ASSERT(status == -ENOENT);
958 
959 	rte_lpm6_delete_all(lpm);
960 
961 	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
962 	 * entry.
963 	 */
964 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
965 	depth = 32;
966 	next_hop_add = 100;
967 
968 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
969 	TEST_LPM_ASSERT(status == 0);
970 
971 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
972 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
973 
974 	IPv6(ip, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
975 	depth = 32;
976 	next_hop_add = 101;
977 
978 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
979 	TEST_LPM_ASSERT(status == 0);
980 
981 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
982 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
983 
984 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
985 	depth = 32;
986 	next_hop_add = 100;
987 
988 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
989 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
990 
991 	status = rte_lpm6_delete(lpm, ip, depth);
992 	TEST_LPM_ASSERT(status == 0);
993 
994 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
995 	TEST_LPM_ASSERT(status == -ENOENT);
996 
997 	rte_lpm6_delete_all(lpm);
998 
999 	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
1000 	 * entry
1001 	 */
1002 	IPv6(ip_1, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1003 	depth_1 = 25;
1004 	next_hop_add_1 = 101;
1005 
1006 	IPv6(ip_2, 128, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1007 	depth_2 = 32;
1008 	next_hop_add_2 = 102;
1009 
1010 	next_hop_return = 0;
1011 
1012 	status = rte_lpm6_add(lpm, ip_1, depth_1, next_hop_add_1);
1013 	TEST_LPM_ASSERT(status == 0);
1014 
1015 	status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1016 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1017 
1018 	status = rte_lpm6_add(lpm, ip_2, depth_2, next_hop_add_2);
1019 	TEST_LPM_ASSERT(status == 0);
1020 
1021 	status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1022 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
1023 
1024 	status = rte_lpm6_delete(lpm, ip_2, depth_2);
1025 	TEST_LPM_ASSERT(status == 0);
1026 
1027 	status = rte_lpm6_lookup(lpm, ip_2, &next_hop_return);
1028 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
1029 
1030 	status = rte_lpm6_delete(lpm, ip_1, depth_1);
1031 	TEST_LPM_ASSERT(status == 0);
1032 
1033 	status = rte_lpm6_lookup(lpm, ip_1, &next_hop_return);
1034 	TEST_LPM_ASSERT(status == -ENOENT);
1035 
1036 	rte_lpm6_free(lpm);
1037 
1038 	return PASS;
1039 }
1040 
1041 /*
1042  * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
1043  *   lookup)
1044  * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
1045  * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
1046  *   delete & lookup)
1047  * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
1048  * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
1049  * - Delete a rule that is not present in the TBL24 & lookup
1050  * - Delete a rule that is not present in the TBL8 & lookup
1051  */
1052 int32_t
1053 test19(void)
1054 {
1055 	struct rte_lpm6 *lpm = NULL;
1056 	struct rte_lpm6_config config;
1057 	uint8_t ip[16];
1058 	uint8_t depth, next_hop_add, next_hop_return;
1059 	int32_t status = 0;
1060 
1061 	config.max_rules = MAX_RULES;
1062 	config.number_tbl8s = NUMBER_TBL8S;
1063 	config.flags = 0;
1064 
1065 	/* Add rule that covers a TBL24 range previously invalid & lookup
1066 	 * (& delete & lookup)
1067 	 */
1068 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1069 	TEST_LPM_ASSERT(lpm != NULL);
1070 
1071 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1072 	depth = 16;
1073 	next_hop_add = 100;
1074 
1075 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1076 	TEST_LPM_ASSERT(status == 0);
1077 
1078 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1079 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1080 
1081 	status = rte_lpm6_delete(lpm, ip, depth);
1082 	TEST_LPM_ASSERT(status == 0);
1083 
1084 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1085 	TEST_LPM_ASSERT(status == -ENOENT);
1086 
1087 	rte_lpm6_delete_all(lpm);
1088 
1089 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1090 	depth = 25;
1091 	next_hop_add = 100;
1092 
1093 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1094 	TEST_LPM_ASSERT(status == 0);
1095 
1096 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1097 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1098 
1099 	status = rte_lpm6_delete(lpm, ip, depth);
1100 	TEST_LPM_ASSERT(status == 0);
1101 
1102 	rte_lpm6_delete_all(lpm);
1103 
1104 	/*
1105 	 * Add rule that extends a TBL24 valid entry & lookup for both rules
1106 	 * (& delete & lookup)
1107 	 */
1108 
1109 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1110 	depth = 24;
1111 	next_hop_add = 100;
1112 
1113 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1114 	TEST_LPM_ASSERT(status == 0);
1115 
1116 	IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1117 	depth = 32;
1118 	next_hop_add = 101;
1119 
1120 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1121 	TEST_LPM_ASSERT(status == 0);
1122 
1123 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1124 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1125 
1126 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1127 	next_hop_add = 100;
1128 
1129 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1130 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1131 
1132 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1133 	depth = 24;
1134 
1135 	status = rte_lpm6_delete(lpm, ip, depth);
1136 	TEST_LPM_ASSERT(status == 0);
1137 
1138 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1139 	TEST_LPM_ASSERT(status == -ENOENT);
1140 
1141 	IPv6(ip, 128, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1142 	depth = 32;
1143 
1144 	status = rte_lpm6_delete(lpm, ip, depth);
1145 	TEST_LPM_ASSERT(status == 0);
1146 
1147 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1148 	TEST_LPM_ASSERT(status == -ENOENT);
1149 
1150 	rte_lpm6_delete_all(lpm);
1151 
1152 	/*
1153 	 * Add rule that updates the next hop in TBL24 & lookup
1154 	 * (& delete & lookup)
1155 	 */
1156 
1157 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1158 	depth = 24;
1159 	next_hop_add = 100;
1160 
1161 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1162 	TEST_LPM_ASSERT(status == 0);
1163 
1164 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1165 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1166 
1167 	next_hop_add = 101;
1168 
1169 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1170 	TEST_LPM_ASSERT(status == 0);
1171 
1172 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1173 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1174 
1175 	status = rte_lpm6_delete(lpm, ip, depth);
1176 	TEST_LPM_ASSERT(status == 0);
1177 
1178 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1179 	TEST_LPM_ASSERT(status == -ENOENT);
1180 
1181 	rte_lpm6_delete_all(lpm);
1182 
1183 	/*
1184 	 * Add rule that updates the next hop in TBL8 & lookup
1185 	 * (& delete & lookup)
1186 	 */
1187 
1188 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1189 	depth = 32;
1190 	next_hop_add = 100;
1191 
1192 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1193 	TEST_LPM_ASSERT(status == 0);
1194 
1195 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1196 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1197 
1198 	next_hop_add = 101;
1199 
1200 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1201 	TEST_LPM_ASSERT(status == 0);
1202 
1203 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1204 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1205 
1206 	status = rte_lpm6_delete(lpm, ip, depth);
1207 	TEST_LPM_ASSERT(status == 0);
1208 
1209 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1210 	TEST_LPM_ASSERT(status == -ENOENT);
1211 
1212 	rte_lpm6_delete_all(lpm);
1213 
1214 	/* Delete a rule that is not present in the TBL24 & lookup */
1215 
1216 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1217 	depth = 24;
1218 	next_hop_add = 100;
1219 
1220 	status = rte_lpm6_delete(lpm, ip, depth);
1221 	TEST_LPM_ASSERT(status < 0);
1222 
1223 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1224 	TEST_LPM_ASSERT(status == -ENOENT);
1225 
1226 	rte_lpm6_delete_all(lpm);
1227 
1228 	/* Delete a rule that is not present in the TBL8 & lookup */
1229 
1230 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1231 	depth = 32;
1232 	next_hop_add = 100;
1233 
1234 	status = rte_lpm6_delete(lpm, ip, depth);
1235 	TEST_LPM_ASSERT(status < 0);
1236 
1237 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1238 	TEST_LPM_ASSERT(status == -ENOENT);
1239 
1240 	rte_lpm6_free(lpm);
1241 
1242 	return PASS;
1243 }
1244 
1245 /*
1246  * Add two rules, lookup to hit the more specific one, lookup to hit the less
1247  * specific one delete the less specific rule and lookup previous values again;
1248  * add a more specific rule than the existing rule, lookup again
1249  */
1250 int32_t
1251 test20(void)
1252 {
1253 	struct rte_lpm6 *lpm = NULL;
1254 	struct rte_lpm6_config config;
1255 	uint8_t ip[16];
1256 	uint8_t depth, next_hop_add, next_hop_return;
1257 	int32_t status = 0;
1258 
1259 	config.max_rules = MAX_RULES;
1260 	config.number_tbl8s = NUMBER_TBL8S;
1261 	config.flags = 0;
1262 
1263 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1264 	TEST_LPM_ASSERT(lpm != NULL);
1265 
1266 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1267 	depth = 24;
1268 	next_hop_add = 100;
1269 
1270 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1271 	TEST_LPM_ASSERT(status == 0);
1272 
1273 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1274 	depth = 128;
1275 	next_hop_add = 101;
1276 
1277 	status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1278 	TEST_LPM_ASSERT(status == 0);
1279 
1280 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1281 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1282 
1283 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1284 	next_hop_add = 100;
1285 
1286 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1287 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1288 
1289 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1290 	depth = 24;
1291 
1292 	status = rte_lpm6_delete(lpm, ip, depth);
1293 	TEST_LPM_ASSERT(status == 0);
1294 
1295 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1296 	TEST_LPM_ASSERT(status == -ENOENT);
1297 
1298 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10);
1299 	depth = 128;
1300 
1301 	status = rte_lpm6_delete(lpm, ip, depth);
1302 	TEST_LPM_ASSERT(status == 0);
1303 
1304 	status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1305 	TEST_LPM_ASSERT(status == -ENOENT);
1306 
1307 	rte_lpm6_free(lpm);
1308 
1309 	return PASS;
1310 }
1311 
1312 /*
1313  * Adds 3 rules and look them up through the lookup_bulk function.
1314  * Includes in the lookup a fourth IP address that won't match
1315  * and checks that the result is as expected.
1316  */
1317 int32_t
1318 test21(void)
1319 {
1320 	struct rte_lpm6 *lpm = NULL;
1321 	struct rte_lpm6_config config;
1322 	uint8_t ip_batch[4][16];
1323 	uint8_t depth, next_hop_add;
1324 	int16_t next_hop_return[4];
1325 	int32_t status = 0;
1326 
1327 	config.max_rules = MAX_RULES;
1328 	config.number_tbl8s = NUMBER_TBL8S;
1329 	config.flags = 0;
1330 
1331 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1332 	TEST_LPM_ASSERT(lpm != NULL);
1333 
1334 	IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1335 	depth = 48;
1336 	next_hop_add = 100;
1337 
1338 	status = rte_lpm6_add(lpm, ip_batch[0], depth, next_hop_add);
1339 	TEST_LPM_ASSERT(status == 0);
1340 
1341 	IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1342 	depth = 48;
1343 	next_hop_add = 101;
1344 
1345 	status = rte_lpm6_add(lpm, ip_batch[1], depth, next_hop_add);
1346 	TEST_LPM_ASSERT(status == 0);
1347 
1348 	IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1349 	depth = 48;
1350 	next_hop_add = 102;
1351 
1352 	status = rte_lpm6_add(lpm, ip_batch[2], depth, next_hop_add);
1353 	TEST_LPM_ASSERT(status == 0);
1354 
1355 	IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1356 
1357 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1358 			next_hop_return, 4);
1359 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 100
1360 			&& next_hop_return[1] == 101 && next_hop_return[2] == 102
1361 			&& next_hop_return[3] == -1);
1362 
1363 	rte_lpm6_free(lpm);
1364 
1365 	return PASS;
1366 }
1367 
1368 /*
1369  * Adds 5 rules and look them up.
1370  * Use the delete_bulk function to delete two of them. Lookup again.
1371  * Use the delete_bulk function to delete one more. Lookup again.
1372  * Use the delete_bulk function to delete two more, one invalid. Lookup again.
1373  * Use the delete_bulk function to delete the remaining one. Lookup again.
1374  */
1375 int32_t
1376 test22(void)
1377 {
1378 	struct rte_lpm6 *lpm = NULL;
1379 	struct rte_lpm6_config config;
1380 	uint8_t ip_batch[5][16];
1381 	uint8_t depth[5], next_hop_add;
1382 	int16_t next_hop_return[5];
1383 	int32_t status = 0;
1384 
1385 	config.max_rules = MAX_RULES;
1386 	config.number_tbl8s = NUMBER_TBL8S;
1387 	config.flags = 0;
1388 
1389 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1390 	TEST_LPM_ASSERT(lpm != NULL);
1391 
1392 	/* Adds 5 rules and look them up */
1393 
1394 	IPv6(ip_batch[0], 128, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1395 	depth[0] = 48;
1396 	next_hop_add = 101;
1397 
1398 	status = rte_lpm6_add(lpm, ip_batch[0], depth[0], next_hop_add);
1399 	TEST_LPM_ASSERT(status == 0);
1400 
1401 	IPv6(ip_batch[1], 128, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1402 	depth[1] = 48;
1403 	next_hop_add = 102;
1404 
1405 	status = rte_lpm6_add(lpm, ip_batch[1], depth[1], next_hop_add);
1406 	TEST_LPM_ASSERT(status == 0);
1407 
1408 	IPv6(ip_batch[2], 128, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1409 	depth[2] = 48;
1410 	next_hop_add = 103;
1411 
1412 	status = rte_lpm6_add(lpm, ip_batch[2], depth[2], next_hop_add);
1413 	TEST_LPM_ASSERT(status == 0);
1414 
1415 	IPv6(ip_batch[3], 128, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1416 	depth[3] = 48;
1417 	next_hop_add = 104;
1418 
1419 	status = rte_lpm6_add(lpm, ip_batch[3], depth[3], next_hop_add);
1420 	TEST_LPM_ASSERT(status == 0);
1421 
1422 	IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1423 	depth[4] = 48;
1424 	next_hop_add = 105;
1425 
1426 	status = rte_lpm6_add(lpm, ip_batch[4], depth[4], next_hop_add);
1427 	TEST_LPM_ASSERT(status == 0);
1428 
1429 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1430 			next_hop_return, 5);
1431 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == 101
1432 			&& next_hop_return[1] == 102 && next_hop_return[2] == 103
1433 			&& next_hop_return[3] == 104 && next_hop_return[4] == 105);
1434 
1435 	/* Use the delete_bulk function to delete two of them. Lookup again */
1436 
1437 	status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1438 	TEST_LPM_ASSERT(status == 0);
1439 
1440 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1441 			next_hop_return, 5);
1442 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1443 			&& next_hop_return[1] == -1 && next_hop_return[2] == 103
1444 			&& next_hop_return[3] == 104 && next_hop_return[4] == 105);
1445 
1446 	/* Use the delete_bulk function to delete one more. Lookup again */
1447 
1448 	status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1449 	TEST_LPM_ASSERT(status == 0);
1450 
1451 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1452 			next_hop_return, 5);
1453 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1454 			&& next_hop_return[1] == -1 && next_hop_return[2] == -1
1455 			&& next_hop_return[3] == 104 && next_hop_return[4] == 105);
1456 
1457 	/* Use the delete_bulk function to delete two, one invalid. Lookup again */
1458 
1459 	IPv6(ip_batch[4], 128, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1460 	status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1461 	TEST_LPM_ASSERT(status == 0);
1462 
1463 	IPv6(ip_batch[4], 128, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1464 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1465 			next_hop_return, 5);
1466 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1467 			&& next_hop_return[1] == -1 && next_hop_return[2] == -1
1468 			&& next_hop_return[3] == -1 && next_hop_return[4] == 105);
1469 
1470 	/* Use the delete_bulk function to delete the remaining one. Lookup again */
1471 
1472 	status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1473 	TEST_LPM_ASSERT(status == 0);
1474 
1475 	status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1476 			next_hop_return, 5);
1477 	TEST_LPM_ASSERT(status == 0 && next_hop_return[0] == -1
1478 			&& next_hop_return[1] == -1 && next_hop_return[2] == -1
1479 			&& next_hop_return[3] == -1 && next_hop_return[4] == -1);
1480 
1481 	rte_lpm6_free(lpm);
1482 
1483 	return PASS;
1484 }
1485 
1486 /*
1487  * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
1488  * lookup (miss) in a for loop of 30 times. This will check tbl8 extension
1489  * and contraction.
1490  */
1491 int32_t
1492 test23(void)
1493 {
1494 	struct rte_lpm6 *lpm = NULL;
1495 	struct rte_lpm6_config config;
1496 	uint32_t i;
1497 	uint8_t ip[16];
1498 	uint8_t depth, next_hop_add, next_hop_return;
1499 	int32_t status = 0;
1500 
1501 	config.max_rules = MAX_RULES;
1502 	config.number_tbl8s = NUMBER_TBL8S;
1503 	config.flags = 0;
1504 
1505 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1506 	TEST_LPM_ASSERT(lpm != NULL);
1507 
1508 	IPv6(ip, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1509 	depth = 128;
1510 	next_hop_add = 100;
1511 
1512 	for (i = 0; i < 30; i++) {
1513 		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1514 		TEST_LPM_ASSERT(status == 0);
1515 
1516 		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1517 		TEST_LPM_ASSERT((status == 0) &&
1518 				(next_hop_return == next_hop_add));
1519 
1520 		status = rte_lpm6_delete(lpm, ip, depth);
1521 		TEST_LPM_ASSERT(status == 0);
1522 
1523 		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1524 		TEST_LPM_ASSERT(status == -ENOENT);
1525 	}
1526 
1527 	rte_lpm6_free(lpm);
1528 
1529 	return PASS;
1530 }
1531 
1532 /*
1533  * Sequence of operations for find existing lpm table
1534  *
1535  *  - create table
1536  *  - find existing table: hit
1537  *  - find non-existing table: miss
1538  */
1539 int32_t
1540 test24(void)
1541 {
1542 	struct rte_lpm6 *lpm = NULL, *result = NULL;
1543 	struct rte_lpm6_config config;
1544 
1545 	config.max_rules = 256 * 32;
1546 	config.number_tbl8s = NUMBER_TBL8S;
1547 	config.flags = 0;
1548 
1549 	/* Create lpm  */
1550 	lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1551 	TEST_LPM_ASSERT(lpm != NULL);
1552 
1553 	/* Try to find existing lpm */
1554 	result = rte_lpm6_find_existing("lpm_find_existing");
1555 	TEST_LPM_ASSERT(result == lpm);
1556 
1557 	/* Try to find non-existing lpm */
1558 	result = rte_lpm6_find_existing("lpm_find_non_existing");
1559 	TEST_LPM_ASSERT(result == NULL);
1560 
1561 	/* Cleanup. */
1562 	rte_lpm6_delete_all(lpm);
1563 	rte_lpm6_free(lpm);
1564 
1565 	return PASS;
1566 }
1567 
1568 /*
1569  * Add a set of random routes with random depths.
1570  * Lookup different IP addresses that match the routes previously added.
1571  * Checks that the next hop is the expected one.
1572  * The routes, IP addresses and expected result for every case have been
1573  * precalculated by using a python script and stored in a .h file.
1574  */
1575 int32_t
1576 test25(void)
1577 {
1578 	struct rte_lpm6 *lpm = NULL;
1579 	struct rte_lpm6_config config;
1580 	uint8_t ip[16];
1581 	uint32_t i;
1582 	uint8_t depth, next_hop_add, next_hop_return, next_hop_expected;
1583 	int32_t status = 0;
1584 
1585 	config.max_rules = MAX_RULES;
1586 	config.number_tbl8s = NUMBER_TBL8S;
1587 	config.flags = 0;
1588 
1589 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1590 	TEST_LPM_ASSERT(lpm != NULL);
1591 
1592 	for (i = 0; i < 1000; i++) {
1593 		memcpy(ip, large_route_table[i].ip, 16);
1594 		depth = large_route_table[i].depth;
1595 		next_hop_add = large_route_table[i].next_hop;
1596 		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1597 		TEST_LPM_ASSERT(status == 0);
1598 	}
1599 
1600 	for (i = 0; i < 100000; i++) {
1601 		memcpy(ip, large_ips_table[i].ip, 16);
1602 		next_hop_expected = large_ips_table[i].next_hop;
1603 
1604 		status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1605 		TEST_LPM_ASSERT((status == 0) &&
1606 				(next_hop_return == next_hop_expected));
1607 	}
1608 
1609 	rte_lpm6_free(lpm);
1610 
1611 	return PASS;
1612 }
1613 
1614 /*
1615  * Test for overwriting of tbl8:
1616  *  - add rule /32 and lookup
1617  *  - add new rule /24 and lookup
1618  *	- add third rule /25 and lookup
1619  *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
1620  */
1621 int32_t
1622 test26(void)
1623 {
1624 	struct rte_lpm6 *lpm = NULL;
1625 	struct rte_lpm6_config config;
1626 	uint8_t ip_10_32[] = {10, 10, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1627 	uint8_t ip_10_24[] = {10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1628 	uint8_t ip_20_25[] = {10, 10, 20, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1629 	uint8_t d_ip_10_32 = 32;
1630 	uint8_t	d_ip_10_24 = 24;
1631 	uint8_t	d_ip_20_25 = 25;
1632 	uint8_t next_hop_ip_10_32 = 100;
1633 	uint8_t	next_hop_ip_10_24 = 105;
1634 	uint8_t	next_hop_ip_20_25 = 111;
1635 	uint8_t next_hop_return = 0;
1636 	int32_t status = 0;
1637 
1638 	config.max_rules = MAX_RULES;
1639 	config.number_tbl8s = NUMBER_TBL8S;
1640 	config.flags = 0;
1641 
1642 	lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1643 	TEST_LPM_ASSERT(lpm != NULL);
1644 
1645 	if ((status = rte_lpm6_add(lpm, ip_10_32, d_ip_10_32,
1646 			next_hop_ip_10_32)) < 0)
1647 		return -1;
1648 
1649 	status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1650 	uint8_t test_hop_10_32 = next_hop_return;
1651 	TEST_LPM_ASSERT(status == 0);
1652 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1653 
1654 	if ((status = rte_lpm6_add(lpm, ip_10_24, d_ip_10_24,
1655 			next_hop_ip_10_24)) < 0)
1656 			return -1;
1657 
1658 	status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1659 	uint8_t test_hop_10_24 = next_hop_return;
1660 	TEST_LPM_ASSERT(status == 0);
1661 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1662 
1663 	if ((status = rte_lpm6_add(lpm, ip_20_25, d_ip_20_25,
1664 			next_hop_ip_20_25)) < 0)
1665 		return -1;
1666 
1667 	status = rte_lpm6_lookup(lpm, ip_20_25, &next_hop_return);
1668 	uint8_t test_hop_20_25 = next_hop_return;
1669 	TEST_LPM_ASSERT(status == 0);
1670 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1671 
1672 	if (test_hop_10_32 == test_hop_10_24) {
1673 		printf("Next hop return equal\n");
1674 		return -1;
1675 	}
1676 
1677 	if (test_hop_10_24 == test_hop_20_25){
1678 		printf("Next hop return equal\n");
1679 		return -1;
1680 	}
1681 
1682 	status = rte_lpm6_lookup(lpm, ip_10_32, &next_hop_return);
1683 	TEST_LPM_ASSERT(status == 0);
1684 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1685 
1686 	status = rte_lpm6_lookup(lpm, ip_10_24, &next_hop_return);
1687 	TEST_LPM_ASSERT(status == 0);
1688 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1689 
1690 	rte_lpm6_free(lpm);
1691 
1692 	return PASS;
1693 }
1694 
1695 /*
1696  * Add a rule that reaches the end of the tree.
1697  * Add a rule that is more generic than the first one.
1698  * Check every possible combination that produces a match for the second rule.
1699  * This tests tbl expansion.
1700  */
1701 int32_t
1702 test27(void)
1703 {
1704 		struct rte_lpm6 *lpm = NULL;
1705 		struct rte_lpm6_config config;
1706 		uint8_t ip[] = {128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0};
1707 		uint8_t depth = 128, next_hop_add = 100, next_hop_return;
1708 		int32_t status = 0;
1709 		int i, j;
1710 
1711 		config.max_rules = MAX_RULES;
1712 		config.number_tbl8s = NUMBER_TBL8S;
1713 		config.flags = 0;
1714 
1715 		lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1716 		TEST_LPM_ASSERT(lpm != NULL);
1717 
1718 		depth = 128;
1719 		next_hop_add = 128;
1720 		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1721 		TEST_LPM_ASSERT(status == 0);
1722 
1723 		depth = 112;
1724 		next_hop_add = 112;
1725 		status = rte_lpm6_add(lpm, ip, depth, next_hop_add);
1726 		TEST_LPM_ASSERT(status == 0);
1727 
1728 		for (i = 0; i < 256; i++) {
1729 			ip[14] = (uint8_t)i;
1730 			for (j = 0; j < 256; j++) {
1731 				ip[15] = (uint8_t)j;
1732 				status = rte_lpm6_lookup(lpm, ip, &next_hop_return);
1733 				if (i == 0 && j == 0)
1734 					TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1735 				else
1736 					TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1737 				}
1738 		}
1739 
1740 		rte_lpm6_free(lpm);
1741 
1742 		return PASS;
1743 }
1744 
1745 /*
1746  * Do all unit tests.
1747  */
1748 static int
1749 test_lpm6(void)
1750 {
1751 	unsigned i;
1752 	int status = -1, global_status = 0;
1753 
1754 	for (i = 0; i < NUM_LPM6_TESTS; i++) {
1755 		printf("# test %02d\n", i);
1756 		status = tests6[i]();
1757 
1758 		if (status < 0) {
1759 			printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1760 			global_status = status;
1761 		}
1762 	}
1763 
1764 	return global_status;
1765 }
1766 
1767 REGISTER_TEST_COMMAND(lpm6_autotest, test_lpm6);
1768