xref: /dpdk/app/test/test_lpm.c (revision cf435a07)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <stdio.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 
38 #include <rte_lpm.h>
39 
40 #include "test.h"
41 #include "test_lpm_routes.h"
42 #include "test_xmmt_ops.h"
43 
44 #define TEST_LPM_ASSERT(cond) do {                                            \
45 	if (!(cond)) {                                                        \
46 		printf("Error at line %d: \n", __LINE__);                     \
47 		return -1;                                                    \
48 	}                                                                     \
49 } while(0)
50 
51 typedef int32_t (*rte_lpm_test)(void);
52 
53 static int32_t test0(void);
54 static int32_t test1(void);
55 static int32_t test2(void);
56 static int32_t test3(void);
57 static int32_t test4(void);
58 static int32_t test5(void);
59 static int32_t test6(void);
60 static int32_t test7(void);
61 static int32_t test8(void);
62 static int32_t test9(void);
63 static int32_t test10(void);
64 static int32_t test11(void);
65 static int32_t test12(void);
66 static int32_t test13(void);
67 static int32_t test14(void);
68 static int32_t test15(void);
69 static int32_t test16(void);
70 static int32_t test17(void);
71 
72 rte_lpm_test tests[] = {
73 /* Test Cases */
74 	test0,
75 	test1,
76 	test2,
77 	test3,
78 	test4,
79 	test5,
80 	test6,
81 	test7,
82 	test8,
83 	test9,
84 	test10,
85 	test11,
86 	test12,
87 	test13,
88 	test14,
89 	test15,
90 	test16,
91 	test17,
92 };
93 
94 #define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
95 #define MAX_DEPTH 32
96 #define MAX_RULES 256
97 #define NUMBER_TBL8S 256
98 #define PASS 0
99 
100 /*
101  * Check that rte_lpm_create fails gracefully for incorrect user input
102  * arguments
103  */
104 int32_t
105 test0(void)
106 {
107 	struct rte_lpm *lpm = NULL;
108 	struct rte_lpm_config config;
109 
110 	config.max_rules = MAX_RULES;
111 	config.number_tbl8s = NUMBER_TBL8S;
112 	config.flags = 0;
113 
114 	/* rte_lpm_create: lpm name == NULL */
115 	lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
116 	TEST_LPM_ASSERT(lpm == NULL);
117 
118 	/* rte_lpm_create: max_rules = 0 */
119 	/* Note: __func__ inserts the function name, in this case "test0". */
120 	config.max_rules = 0;
121 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
122 	TEST_LPM_ASSERT(lpm == NULL);
123 
124 	/* socket_id < -1 is invalid */
125 	config.max_rules = MAX_RULES;
126 	lpm = rte_lpm_create(__func__, -2, &config);
127 	TEST_LPM_ASSERT(lpm == NULL);
128 
129 	return PASS;
130 }
131 
132 /*
133  * Create lpm table then delete lpm table 100 times
134  * Use a slightly different rules size each time
135  * */
136 int32_t
137 test1(void)
138 {
139 	struct rte_lpm *lpm = NULL;
140 	struct rte_lpm_config config;
141 
142 	config.number_tbl8s = NUMBER_TBL8S;
143 	config.flags = 0;
144 	int32_t i;
145 
146 	/* rte_lpm_free: Free NULL */
147 	for (i = 0; i < 100; i++) {
148 		config.max_rules = MAX_RULES - i;
149 		lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
150 		TEST_LPM_ASSERT(lpm != NULL);
151 
152 		rte_lpm_free(lpm);
153 	}
154 
155 	/* Can not test free so return success */
156 	return PASS;
157 }
158 
159 /*
160  * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
161  * therefore it is impossible to check for failure but this test is added to
162  * increase function coverage metrics and to validate that freeing null does
163  * not crash.
164  */
165 int32_t
166 test2(void)
167 {
168 	struct rte_lpm *lpm = NULL;
169 	struct rte_lpm_config config;
170 
171 	config.max_rules = MAX_RULES;
172 	config.number_tbl8s = NUMBER_TBL8S;
173 	config.flags = 0;
174 
175 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
176 	TEST_LPM_ASSERT(lpm != NULL);
177 
178 	rte_lpm_free(lpm);
179 	rte_lpm_free(NULL);
180 	return PASS;
181 }
182 
183 /*
184  * Check that rte_lpm_add fails gracefully for incorrect user input arguments
185  */
186 int32_t
187 test3(void)
188 {
189 	struct rte_lpm *lpm = NULL;
190 	struct rte_lpm_config config;
191 
192 	config.max_rules = MAX_RULES;
193 	config.number_tbl8s = NUMBER_TBL8S;
194 	config.flags = 0;
195 	uint32_t ip = IPv4(0, 0, 0, 0), next_hop = 100;
196 	uint8_t depth = 24;
197 	int32_t status = 0;
198 
199 	/* rte_lpm_add: lpm == NULL */
200 	status = rte_lpm_add(NULL, ip, depth, next_hop);
201 	TEST_LPM_ASSERT(status < 0);
202 
203 	/*Create vaild lpm to use in rest of test. */
204 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
205 	TEST_LPM_ASSERT(lpm != NULL);
206 
207 	/* rte_lpm_add: depth < 1 */
208 	status = rte_lpm_add(lpm, ip, 0, next_hop);
209 	TEST_LPM_ASSERT(status < 0);
210 
211 	/* rte_lpm_add: depth > MAX_DEPTH */
212 	status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
213 	TEST_LPM_ASSERT(status < 0);
214 
215 	rte_lpm_free(lpm);
216 
217 	return PASS;
218 }
219 
220 /*
221  * Check that rte_lpm_delete fails gracefully for incorrect user input
222  * arguments
223  */
224 int32_t
225 test4(void)
226 {
227 	struct rte_lpm *lpm = NULL;
228 	struct rte_lpm_config config;
229 
230 	config.max_rules = MAX_RULES;
231 	config.number_tbl8s = NUMBER_TBL8S;
232 	config.flags = 0;
233 	uint32_t ip = IPv4(0, 0, 0, 0);
234 	uint8_t depth = 24;
235 	int32_t status = 0;
236 
237 	/* rte_lpm_delete: lpm == NULL */
238 	status = rte_lpm_delete(NULL, ip, depth);
239 	TEST_LPM_ASSERT(status < 0);
240 
241 	/*Create vaild lpm to use in rest of test. */
242 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
243 	TEST_LPM_ASSERT(lpm != NULL);
244 
245 	/* rte_lpm_delete: depth < 1 */
246 	status = rte_lpm_delete(lpm, ip, 0);
247 	TEST_LPM_ASSERT(status < 0);
248 
249 	/* rte_lpm_delete: depth > MAX_DEPTH */
250 	status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
251 	TEST_LPM_ASSERT(status < 0);
252 
253 	rte_lpm_free(lpm);
254 
255 	return PASS;
256 }
257 
258 /*
259  * Check that rte_lpm_lookup fails gracefully for incorrect user input
260  * arguments
261  */
262 int32_t
263 test5(void)
264 {
265 #if defined(RTE_LIBRTE_LPM_DEBUG)
266 	struct rte_lpm *lpm = NULL;
267 	struct rte_lpm_config config;
268 
269 	config.max_rules = MAX_RULES;
270 	config.number_tbl8s = NUMBER_TBL8S;
271 	config.flags = 0;
272 	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_return = 0;
273 	int32_t status = 0;
274 
275 	/* rte_lpm_lookup: lpm == NULL */
276 	status = rte_lpm_lookup(NULL, ip, &next_hop_return);
277 	TEST_LPM_ASSERT(status < 0);
278 
279 	/*Create vaild lpm to use in rest of test. */
280 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
281 	TEST_LPM_ASSERT(lpm != NULL);
282 
283 	/* rte_lpm_lookup: depth < 1 */
284 	status = rte_lpm_lookup(lpm, ip, NULL);
285 	TEST_LPM_ASSERT(status < 0);
286 
287 	rte_lpm_free(lpm);
288 #endif
289 	return PASS;
290 }
291 
292 
293 
294 /*
295  * Call add, lookup and delete for a single rule with depth <= 24
296  */
297 int32_t
298 test6(void)
299 {
300 	struct rte_lpm *lpm = NULL;
301 	struct rte_lpm_config config;
302 
303 	config.max_rules = MAX_RULES;
304 	config.number_tbl8s = NUMBER_TBL8S;
305 	config.flags = 0;
306 	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
307 	uint8_t depth = 24;
308 	int32_t status = 0;
309 
310 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
311 	TEST_LPM_ASSERT(lpm != NULL);
312 
313 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
314 	TEST_LPM_ASSERT(status == 0);
315 
316 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
317 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
318 
319 	status = rte_lpm_delete(lpm, ip, depth);
320 	TEST_LPM_ASSERT(status == 0);
321 
322 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
323 	TEST_LPM_ASSERT(status == -ENOENT);
324 
325 	rte_lpm_free(lpm);
326 
327 	return PASS;
328 }
329 
330 /*
331  * Call add, lookup and delete for a single rule with depth > 24
332  */
333 
334 int32_t
335 test7(void)
336 {
337 	xmm_t ipx4;
338 	uint32_t hop[4];
339 	struct rte_lpm *lpm = NULL;
340 	struct rte_lpm_config config;
341 
342 	config.max_rules = MAX_RULES;
343 	config.number_tbl8s = NUMBER_TBL8S;
344 	config.flags = 0;
345 	uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
346 	uint8_t depth = 32;
347 	int32_t status = 0;
348 
349 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
350 	TEST_LPM_ASSERT(lpm != NULL);
351 
352 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
353 	TEST_LPM_ASSERT(status == 0);
354 
355 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
356 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
357 
358 	ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
359 	rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
360 	TEST_LPM_ASSERT(hop[0] == next_hop_add);
361 	TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
362 	TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
363 	TEST_LPM_ASSERT(hop[3] == next_hop_add);
364 
365 	status = rte_lpm_delete(lpm, ip, depth);
366 	TEST_LPM_ASSERT(status == 0);
367 
368 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
369 	TEST_LPM_ASSERT(status == -ENOENT);
370 
371 	rte_lpm_free(lpm);
372 
373 	return PASS;
374 }
375 
376 /*
377  * Use rte_lpm_add to add rules which effect only the second half of the lpm
378  * table. Use all possible depths ranging from 1..32. Set the next hop = to the
379  * depth. Check lookup hit for on every add and check for lookup miss on the
380  * first half of the lpm table after each add. Finally delete all rules going
381  * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
382  * delete. The lookup should return the next_hop_add value related to the
383  * previous depth value (i.e. depth -1).
384  */
385 int32_t
386 test8(void)
387 {
388 	xmm_t ipx4;
389 	uint32_t hop[4];
390 	struct rte_lpm *lpm = NULL;
391 	struct rte_lpm_config config;
392 
393 	config.max_rules = MAX_RULES;
394 	config.number_tbl8s = NUMBER_TBL8S;
395 	config.flags = 0;
396 	uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
397 	uint32_t next_hop_add, next_hop_return;
398 	uint8_t depth;
399 	int32_t status = 0;
400 
401 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
402 	TEST_LPM_ASSERT(lpm != NULL);
403 
404 	/* Loop with rte_lpm_add. */
405 	for (depth = 1; depth <= 32; depth++) {
406 		/* Let the next_hop_add value = depth. Just for change. */
407 		next_hop_add = depth;
408 
409 		status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
410 		TEST_LPM_ASSERT(status == 0);
411 
412 		/* Check IP in first half of tbl24 which should be empty. */
413 		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
414 		TEST_LPM_ASSERT(status == -ENOENT);
415 
416 		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
417 		TEST_LPM_ASSERT((status == 0) &&
418 			(next_hop_return == next_hop_add));
419 
420 		ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
421 		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
422 		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
423 		TEST_LPM_ASSERT(hop[1] == next_hop_add);
424 		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
425 		TEST_LPM_ASSERT(hop[3] == next_hop_add);
426 	}
427 
428 	/* Loop with rte_lpm_delete. */
429 	for (depth = 32; depth >= 1; depth--) {
430 		next_hop_add = (uint8_t) (depth - 1);
431 
432 		status = rte_lpm_delete(lpm, ip2, depth);
433 		TEST_LPM_ASSERT(status == 0);
434 
435 		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
436 
437 		if (depth != 1) {
438 			TEST_LPM_ASSERT((status == 0) &&
439 				(next_hop_return == next_hop_add));
440 		} else {
441 			TEST_LPM_ASSERT(status == -ENOENT);
442 		}
443 
444 		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
445 		TEST_LPM_ASSERT(status == -ENOENT);
446 
447 		ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
448 		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
449 		if (depth != 1) {
450 			TEST_LPM_ASSERT(hop[0] == next_hop_add);
451 			TEST_LPM_ASSERT(hop[1] == next_hop_add);
452 		} else {
453 			TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
454 			TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
455 		}
456 		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
457 		TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
458 	}
459 
460 	rte_lpm_free(lpm);
461 
462 	return PASS;
463 }
464 
465 /*
466  * - Add & lookup to hit invalid TBL24 entry
467  * - Add & lookup to hit valid TBL24 entry not extended
468  * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
469  * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
470  *
471  */
472 int32_t
473 test9(void)
474 {
475 	struct rte_lpm *lpm = NULL;
476 	struct rte_lpm_config config;
477 
478 	config.max_rules = MAX_RULES;
479 	config.number_tbl8s = NUMBER_TBL8S;
480 	config.flags = 0;
481 	uint32_t ip, ip_1, ip_2;
482 	uint8_t depth, depth_1, depth_2;
483 	uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
484 	int32_t status = 0;
485 
486 	/* Add & lookup to hit invalid TBL24 entry */
487 	ip = IPv4(128, 0, 0, 0);
488 	depth = 24;
489 	next_hop_add = 100;
490 
491 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
492 	TEST_LPM_ASSERT(lpm != NULL);
493 
494 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
495 	TEST_LPM_ASSERT(status == 0);
496 
497 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
498 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
499 
500 	status = rte_lpm_delete(lpm, ip, depth);
501 	TEST_LPM_ASSERT(status == 0);
502 
503 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
504 	TEST_LPM_ASSERT(status == -ENOENT);
505 
506 	rte_lpm_delete_all(lpm);
507 
508 	/* Add & lookup to hit valid TBL24 entry not extended */
509 	ip = IPv4(128, 0, 0, 0);
510 	depth = 23;
511 	next_hop_add = 100;
512 
513 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
514 	TEST_LPM_ASSERT(status == 0);
515 
516 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
517 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
518 
519 	depth = 24;
520 	next_hop_add = 101;
521 
522 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
523 	TEST_LPM_ASSERT(status == 0);
524 
525 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
526 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
527 
528 	depth = 24;
529 
530 	status = rte_lpm_delete(lpm, ip, depth);
531 	TEST_LPM_ASSERT(status == 0);
532 
533 	depth = 23;
534 
535 	status = rte_lpm_delete(lpm, ip, depth);
536 	TEST_LPM_ASSERT(status == 0);
537 
538 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
539 	TEST_LPM_ASSERT(status == -ENOENT);
540 
541 	rte_lpm_delete_all(lpm);
542 
543 	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
544 	 * entry */
545 	ip = IPv4(128, 0, 0, 0);
546 	depth = 32;
547 	next_hop_add = 100;
548 
549 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
550 	TEST_LPM_ASSERT(status == 0);
551 
552 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
553 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
554 
555 	ip = IPv4(128, 0, 0, 5);
556 	depth = 32;
557 	next_hop_add = 101;
558 
559 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
560 	TEST_LPM_ASSERT(status == 0);
561 
562 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
563 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
564 
565 	status = rte_lpm_delete(lpm, ip, depth);
566 	TEST_LPM_ASSERT(status == 0);
567 
568 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
569 	TEST_LPM_ASSERT(status == -ENOENT);
570 
571 	ip = IPv4(128, 0, 0, 0);
572 	depth = 32;
573 	next_hop_add = 100;
574 
575 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
576 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
577 
578 	status = rte_lpm_delete(lpm, ip, depth);
579 	TEST_LPM_ASSERT(status == 0);
580 
581 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
582 	TEST_LPM_ASSERT(status == -ENOENT);
583 
584 	rte_lpm_delete_all(lpm);
585 
586 	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
587 	 * entry */
588 	ip_1 = IPv4(128, 0, 0, 0);
589 	depth_1 = 25;
590 	next_hop_add_1 = 101;
591 
592 	ip_2 = IPv4(128, 0, 0, 5);
593 	depth_2 = 32;
594 	next_hop_add_2 = 102;
595 
596 	next_hop_return = 0;
597 
598 	status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
599 	TEST_LPM_ASSERT(status == 0);
600 
601 	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
602 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
603 
604 	status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
605 	TEST_LPM_ASSERT(status == 0);
606 
607 	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
608 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
609 
610 	status = rte_lpm_delete(lpm, ip_2, depth_2);
611 	TEST_LPM_ASSERT(status == 0);
612 
613 	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
614 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
615 
616 	status = rte_lpm_delete(lpm, ip_1, depth_1);
617 	TEST_LPM_ASSERT(status == 0);
618 
619 	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
620 	TEST_LPM_ASSERT(status == -ENOENT);
621 
622 	rte_lpm_free(lpm);
623 
624 	return PASS;
625 }
626 
627 
628 /*
629  * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
630  *   lookup)
631  * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
632  * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
633  *   delete & lookup)
634  * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
635  * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
636  * - Delete a rule that is not present in the TBL24 & lookup
637  * - Delete a rule that is not present in the TBL8 & lookup
638  *
639  */
640 int32_t
641 test10(void)
642 {
643 
644 	struct rte_lpm *lpm = NULL;
645 	struct rte_lpm_config config;
646 
647 	config.max_rules = MAX_RULES;
648 	config.number_tbl8s = NUMBER_TBL8S;
649 	config.flags = 0;
650 	uint32_t ip, next_hop_add, next_hop_return;
651 	uint8_t depth;
652 	int32_t status = 0;
653 
654 	/* Add rule that covers a TBL24 range previously invalid & lookup
655 	 * (& delete & lookup) */
656 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
657 	TEST_LPM_ASSERT(lpm != NULL);
658 
659 	ip = IPv4(128, 0, 0, 0);
660 	depth = 16;
661 	next_hop_add = 100;
662 
663 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
664 	TEST_LPM_ASSERT(status == 0);
665 
666 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
667 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
668 
669 	status = rte_lpm_delete(lpm, ip, depth);
670 	TEST_LPM_ASSERT(status == 0);
671 
672 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
673 	TEST_LPM_ASSERT(status == -ENOENT);
674 
675 	rte_lpm_delete_all(lpm);
676 
677 	ip = IPv4(128, 0, 0, 0);
678 	depth = 25;
679 	next_hop_add = 100;
680 
681 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
682 	TEST_LPM_ASSERT(status == 0);
683 
684 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
685 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
686 
687 	status = rte_lpm_delete(lpm, ip, depth);
688 	TEST_LPM_ASSERT(status == 0);
689 
690 	rte_lpm_delete_all(lpm);
691 
692 	/* Add rule that extends a TBL24 valid entry & lookup for both rules
693 	 * (& delete & lookup) */
694 
695 	ip = IPv4(128, 0, 0, 0);
696 	depth = 24;
697 	next_hop_add = 100;
698 
699 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
700 	TEST_LPM_ASSERT(status == 0);
701 
702 	ip = IPv4(128, 0, 0, 10);
703 	depth = 32;
704 	next_hop_add = 101;
705 
706 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
707 	TEST_LPM_ASSERT(status == 0);
708 
709 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
710 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
711 
712 	ip = IPv4(128, 0, 0, 0);
713 	next_hop_add = 100;
714 
715 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
716 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
717 
718 	ip = IPv4(128, 0, 0, 0);
719 	depth = 24;
720 
721 	status = rte_lpm_delete(lpm, ip, depth);
722 	TEST_LPM_ASSERT(status == 0);
723 
724 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
725 	TEST_LPM_ASSERT(status == -ENOENT);
726 
727 	ip = IPv4(128, 0, 0, 10);
728 	depth = 32;
729 
730 	status = rte_lpm_delete(lpm, ip, depth);
731 	TEST_LPM_ASSERT(status == 0);
732 
733 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
734 	TEST_LPM_ASSERT(status == -ENOENT);
735 
736 	rte_lpm_delete_all(lpm);
737 
738 	/* Add rule that updates the next hop in TBL24 & lookup
739 	 * (& delete & lookup) */
740 
741 	ip = IPv4(128, 0, 0, 0);
742 	depth = 24;
743 	next_hop_add = 100;
744 
745 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
746 	TEST_LPM_ASSERT(status == 0);
747 
748 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
749 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
750 
751 	next_hop_add = 101;
752 
753 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
754 	TEST_LPM_ASSERT(status == 0);
755 
756 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
757 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
758 
759 	status = rte_lpm_delete(lpm, ip, depth);
760 	TEST_LPM_ASSERT(status == 0);
761 
762 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
763 	TEST_LPM_ASSERT(status == -ENOENT);
764 
765 	rte_lpm_delete_all(lpm);
766 
767 	/* Add rule that updates the next hop in TBL8 & lookup
768 	 * (& delete & lookup) */
769 
770 	ip = IPv4(128, 0, 0, 0);
771 	depth = 32;
772 	next_hop_add = 100;
773 
774 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
775 	TEST_LPM_ASSERT(status == 0);
776 
777 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
778 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
779 
780 	next_hop_add = 101;
781 
782 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
783 	TEST_LPM_ASSERT(status == 0);
784 
785 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
786 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
787 
788 	status = rte_lpm_delete(lpm, ip, depth);
789 	TEST_LPM_ASSERT(status == 0);
790 
791 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
792 	TEST_LPM_ASSERT(status == -ENOENT);
793 
794 	rte_lpm_delete_all(lpm);
795 
796 	/* Delete a rule that is not present in the TBL24 & lookup */
797 
798 	ip = IPv4(128, 0, 0, 0);
799 	depth = 24;
800 
801 	status = rte_lpm_delete(lpm, ip, depth);
802 	TEST_LPM_ASSERT(status < 0);
803 
804 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
805 	TEST_LPM_ASSERT(status == -ENOENT);
806 
807 	rte_lpm_delete_all(lpm);
808 
809 	/* Delete a rule that is not present in the TBL8 & lookup */
810 
811 	ip = IPv4(128, 0, 0, 0);
812 	depth = 32;
813 
814 	status = rte_lpm_delete(lpm, ip, depth);
815 	TEST_LPM_ASSERT(status < 0);
816 
817 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
818 	TEST_LPM_ASSERT(status == -ENOENT);
819 
820 	rte_lpm_free(lpm);
821 
822 	return PASS;
823 }
824 
825 /*
826  * Add two rules, lookup to hit the more specific one, lookup to hit the less
827  * specific one delete the less specific rule and lookup previous values again;
828  * add a more specific rule than the existing rule, lookup again
829  *
830  * */
831 int32_t
832 test11(void)
833 {
834 
835 	struct rte_lpm *lpm = NULL;
836 	struct rte_lpm_config config;
837 
838 	config.max_rules = MAX_RULES;
839 	config.number_tbl8s = NUMBER_TBL8S;
840 	config.flags = 0;
841 	uint32_t ip, next_hop_add, next_hop_return;
842 	uint8_t depth;
843 	int32_t status = 0;
844 
845 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
846 	TEST_LPM_ASSERT(lpm != NULL);
847 
848 	ip = IPv4(128, 0, 0, 0);
849 	depth = 24;
850 	next_hop_add = 100;
851 
852 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
853 	TEST_LPM_ASSERT(status == 0);
854 
855 	ip = IPv4(128, 0, 0, 10);
856 	depth = 32;
857 	next_hop_add = 101;
858 
859 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
860 	TEST_LPM_ASSERT(status == 0);
861 
862 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
863 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
864 
865 	ip = IPv4(128, 0, 0, 0);
866 	next_hop_add = 100;
867 
868 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
869 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
870 
871 	ip = IPv4(128, 0, 0, 0);
872 	depth = 24;
873 
874 	status = rte_lpm_delete(lpm, ip, depth);
875 	TEST_LPM_ASSERT(status == 0);
876 
877 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
878 	TEST_LPM_ASSERT(status == -ENOENT);
879 
880 	ip = IPv4(128, 0, 0, 10);
881 	depth = 32;
882 
883 	status = rte_lpm_delete(lpm, ip, depth);
884 	TEST_LPM_ASSERT(status == 0);
885 
886 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
887 	TEST_LPM_ASSERT(status == -ENOENT);
888 
889 	rte_lpm_free(lpm);
890 
891 	return PASS;
892 }
893 
894 /*
895  * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
896  * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
897  * and contraction.
898  *
899  * */
900 
901 int32_t
902 test12(void)
903 {
904 	xmm_t ipx4;
905 	uint32_t hop[4];
906 	struct rte_lpm *lpm = NULL;
907 	struct rte_lpm_config config;
908 
909 	config.max_rules = MAX_RULES;
910 	config.number_tbl8s = NUMBER_TBL8S;
911 	config.flags = 0;
912 	uint32_t ip, i, next_hop_add, next_hop_return;
913 	uint8_t depth;
914 	int32_t status = 0;
915 
916 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
917 	TEST_LPM_ASSERT(lpm != NULL);
918 
919 	ip = IPv4(128, 0, 0, 0);
920 	depth = 32;
921 	next_hop_add = 100;
922 
923 	for (i = 0; i < 1000; i++) {
924 		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
925 		TEST_LPM_ASSERT(status == 0);
926 
927 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
928 		TEST_LPM_ASSERT((status == 0) &&
929 				(next_hop_return == next_hop_add));
930 
931 		ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
932 		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
933 		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
934 		TEST_LPM_ASSERT(hop[1] == next_hop_add);
935 		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
936 		TEST_LPM_ASSERT(hop[3] == next_hop_add);
937 
938 		status = rte_lpm_delete(lpm, ip, depth);
939 		TEST_LPM_ASSERT(status == 0);
940 
941 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
942 		TEST_LPM_ASSERT(status == -ENOENT);
943 	}
944 
945 	rte_lpm_free(lpm);
946 
947 	return PASS;
948 }
949 
950 /*
951  * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
952  * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
953  * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
954  * extension and contraction.
955  *
956  * */
957 
958 int32_t
959 test13(void)
960 {
961 	struct rte_lpm *lpm = NULL;
962 	struct rte_lpm_config config;
963 
964 	config.max_rules = MAX_RULES;
965 	config.number_tbl8s = NUMBER_TBL8S;
966 	config.flags = 0;
967 	uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
968 	uint8_t depth;
969 	int32_t status = 0;
970 
971 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
972 	TEST_LPM_ASSERT(lpm != NULL);
973 
974 	ip = IPv4(128, 0, 0, 0);
975 	depth = 24;
976 	next_hop_add_1 = 100;
977 
978 	status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
979 	TEST_LPM_ASSERT(status == 0);
980 
981 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
982 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
983 
984 	depth = 32;
985 	next_hop_add_2 = 101;
986 
987 	for (i = 0; i < 1000; i++) {
988 		status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
989 		TEST_LPM_ASSERT(status == 0);
990 
991 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
992 		TEST_LPM_ASSERT((status == 0) &&
993 				(next_hop_return == next_hop_add_2));
994 
995 		status = rte_lpm_delete(lpm, ip, depth);
996 		TEST_LPM_ASSERT(status == 0);
997 
998 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
999 		TEST_LPM_ASSERT((status == 0) &&
1000 				(next_hop_return == next_hop_add_1));
1001 	}
1002 
1003 	depth = 24;
1004 
1005 	status = rte_lpm_delete(lpm, ip, depth);
1006 	TEST_LPM_ASSERT(status == 0);
1007 
1008 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1009 	TEST_LPM_ASSERT(status == -ENOENT);
1010 
1011 	rte_lpm_free(lpm);
1012 
1013 	return PASS;
1014 }
1015 
1016 /*
1017  * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
1018  * No more tbl8 extensions will be allowed. Now add one more rule that required
1019  * a tbl8 extension and get fail.
1020  * */
1021 int32_t
1022 test14(void)
1023 {
1024 
1025 	/* We only use depth = 32 in the loop below so we must make sure
1026 	 * that we have enough storage for all rules at that depth*/
1027 
1028 	struct rte_lpm *lpm = NULL;
1029 	struct rte_lpm_config config;
1030 
1031 	config.max_rules = 256 * 32;
1032 	config.number_tbl8s = NUMBER_TBL8S;
1033 	config.flags = 0;
1034 	uint32_t ip, next_hop_add, next_hop_return;
1035 	uint8_t depth;
1036 	int32_t status = 0;
1037 
1038 	/* Add enough space for 256 rules for every depth */
1039 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1040 	TEST_LPM_ASSERT(lpm != NULL);
1041 
1042 	depth = 32;
1043 	next_hop_add = 100;
1044 	ip = IPv4(0, 0, 0, 0);
1045 
1046 	/* Add 256 rules that require a tbl8 extension */
1047 	for (; ip <= IPv4(0, 0, 255, 0); ip += 256) {
1048 		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
1049 		TEST_LPM_ASSERT(status == 0);
1050 
1051 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1052 		TEST_LPM_ASSERT((status == 0) &&
1053 				(next_hop_return == next_hop_add));
1054 	}
1055 
1056 	/* All tbl8 extensions have been used above. Try to add one more and
1057 	 * we get a fail */
1058 	ip = IPv4(1, 0, 0, 0);
1059 	depth = 32;
1060 
1061 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
1062 	TEST_LPM_ASSERT(status < 0);
1063 
1064 	rte_lpm_free(lpm);
1065 
1066 	return PASS;
1067 }
1068 
1069 /*
1070  * Sequence of operations for find existing lpm table
1071  *
1072  *  - create table
1073  *  - find existing table: hit
1074  *  - find non-existing table: miss
1075  *
1076  */
1077 int32_t
1078 test15(void)
1079 {
1080 	struct rte_lpm *lpm = NULL, *result = NULL;
1081 	struct rte_lpm_config config;
1082 
1083 	config.max_rules = 256 * 32;
1084 	config.number_tbl8s = NUMBER_TBL8S;
1085 	config.flags = 0;
1086 
1087 	/* Create lpm  */
1088 	lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1089 	TEST_LPM_ASSERT(lpm != NULL);
1090 
1091 	/* Try to find existing lpm */
1092 	result = rte_lpm_find_existing("lpm_find_existing");
1093 	TEST_LPM_ASSERT(result == lpm);
1094 
1095 	/* Try to find non-existing lpm */
1096 	result = rte_lpm_find_existing("lpm_find_non_existing");
1097 	TEST_LPM_ASSERT(result == NULL);
1098 
1099 	/* Cleanup. */
1100 	rte_lpm_delete_all(lpm);
1101 	rte_lpm_free(lpm);
1102 
1103 	return PASS;
1104 }
1105 
1106 /*
1107  * test failure condition of overloading the tbl8 so no more will fit
1108  * Check we get an error return value in that case
1109  */
1110 int32_t
1111 test16(void)
1112 {
1113 	uint32_t ip;
1114 	struct rte_lpm_config config;
1115 
1116 	config.max_rules = 256 * 32;
1117 	config.number_tbl8s = NUMBER_TBL8S;
1118 	config.flags = 0;
1119 	struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1120 
1121 	/* ip loops through all possibilities for top 24 bits of address */
1122 	for (ip = 0; ip < 0xFFFFFF; ip++) {
1123 		/* add an entry within a different tbl8 each time, since
1124 		 * depth >24 and the top 24 bits are different */
1125 		if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
1126 			break;
1127 	}
1128 
1129 	if (ip != NUMBER_TBL8S) {
1130 		printf("Error, unexpected failure with filling tbl8 groups\n");
1131 		printf("Failed after %u additions, expected after %u\n",
1132 				(unsigned)ip, (unsigned)NUMBER_TBL8S);
1133 	}
1134 
1135 	rte_lpm_free(lpm);
1136 	return 0;
1137 }
1138 
1139 /*
1140  * Test for overwriting of tbl8:
1141  *  - add rule /32 and lookup
1142  *  - add new rule /24 and lookup
1143  *	- add third rule /25 and lookup
1144  *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
1145  */
1146 int32_t
1147 test17(void)
1148 {
1149 	struct rte_lpm *lpm = NULL;
1150 	struct rte_lpm_config config;
1151 
1152 	config.max_rules = MAX_RULES;
1153 	config.number_tbl8s = NUMBER_TBL8S;
1154 	config.flags = 0;
1155 	const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
1156 	const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
1157 	const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
1158 	const uint8_t d_ip_10_32 = 32,
1159 			d_ip_10_24 = 24,
1160 			d_ip_20_25 = 25;
1161 	const uint32_t next_hop_ip_10_32 = 100,
1162 			next_hop_ip_10_24 = 105,
1163 			next_hop_ip_20_25 = 111;
1164 	uint32_t next_hop_return = 0;
1165 	int32_t status = 0;
1166 
1167 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1168 	TEST_LPM_ASSERT(lpm != NULL);
1169 
1170 	if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
1171 			next_hop_ip_10_32)) < 0)
1172 		return -1;
1173 
1174 	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1175 	uint32_t test_hop_10_32 = next_hop_return;
1176 	TEST_LPM_ASSERT(status == 0);
1177 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1178 
1179 	if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
1180 			next_hop_ip_10_24)) < 0)
1181 			return -1;
1182 
1183 	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1184 	uint32_t test_hop_10_24 = next_hop_return;
1185 	TEST_LPM_ASSERT(status == 0);
1186 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1187 
1188 	if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
1189 			next_hop_ip_20_25)) < 0)
1190 		return -1;
1191 
1192 	status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
1193 	uint32_t test_hop_20_25 = next_hop_return;
1194 	TEST_LPM_ASSERT(status == 0);
1195 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1196 
1197 	if (test_hop_10_32 == test_hop_10_24) {
1198 		printf("Next hop return equal\n");
1199 		return -1;
1200 	}
1201 
1202 	if (test_hop_10_24 == test_hop_20_25) {
1203 		printf("Next hop return equal\n");
1204 		return -1;
1205 	}
1206 
1207 	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1208 	TEST_LPM_ASSERT(status == 0);
1209 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1210 
1211 	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1212 	TEST_LPM_ASSERT(status == 0);
1213 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1214 
1215 	rte_lpm_free(lpm);
1216 
1217 	return PASS;
1218 }
1219 
1220 /*
1221  * Do all unit tests.
1222  */
1223 
1224 static int
1225 test_lpm(void)
1226 {
1227 	unsigned i;
1228 	int status, global_status = 0;
1229 
1230 	for (i = 0; i < NUM_LPM_TESTS; i++) {
1231 		status = tests[i]();
1232 		if (status < 0) {
1233 			printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests[i]));
1234 			global_status = status;
1235 		}
1236 	}
1237 
1238 	return global_status;
1239 }
1240 
1241 REGISTER_TEST_COMMAND(lpm_autotest, test_lpm);
1242