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