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