Branch data Line data Source code
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 : 1 : test0(void)
101 : : {
102 : : struct rte_lpm6 *lpm = NULL;
103 : : struct rte_lpm6_config config;
104 : :
105 : 1 : config.max_rules = MAX_RULES;
106 : 1 : config.number_tbl8s = NUMBER_TBL8S;
107 : 1 : config.flags = 0;
108 : :
109 : : /* rte_lpm6_create: lpm name == NULL */
110 : 1 : lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, &config);
111 [ - + ]: 1 : 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 : 1 : config.max_rules = 0;
116 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
117 [ - + ]: 1 : TEST_LPM_ASSERT(lpm == NULL);
118 : :
119 : : /* socket_id < -1 is invalid */
120 : 1 : config.max_rules = MAX_RULES;
121 : 1 : lpm = rte_lpm6_create(__func__, -2, &config);
122 [ - + ]: 1 : TEST_LPM_ASSERT(lpm == NULL);
123 : :
124 : : /* rte_lpm6_create: number_tbl8s is bigger than the maximum */
125 : 1 : config.number_tbl8s = MAX_NUM_TBL8S + 1;
126 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
127 [ - + ]: 1 : TEST_LPM_ASSERT(lpm == NULL);
128 : :
129 : : /* rte_lpm6_create: config = NULL */
130 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, NULL);
131 [ - + ]: 1 : 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 : 1 : test1(void)
143 : : {
144 : : struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
145 : : struct rte_lpm6_config config;
146 : :
147 : 1 : config.max_rules = MAX_RULES;
148 : 1 : config.number_tbl8s = NUMBER_TBL8S;
149 : 1 : config.flags = 0;
150 : :
151 : : /* rte_lpm6_create: lpm name == LPM1 */
152 : 1 : lpm1 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
153 [ - + ]: 1 : TEST_LPM_ASSERT(lpm1 != NULL);
154 : :
155 : : /* rte_lpm6_create: lpm name == LPM2 */
156 : 1 : lpm2 = rte_lpm6_create("LPM2", SOCKET_ID_ANY, &config);
157 [ - + ]: 1 : TEST_LPM_ASSERT(lpm2 != NULL);
158 : :
159 : : /* rte_lpm6_create: lpm name == LPM2 */
160 : 1 : lpm3 = rte_lpm6_create("LPM1", SOCKET_ID_ANY, &config);
161 [ - + ]: 1 : TEST_LPM_ASSERT(lpm3 == NULL);
162 : :
163 : 1 : rte_lpm6_free(lpm1);
164 : 1 : rte_lpm6_free(lpm2);
165 : :
166 : 1 : 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 : 1 : test2(void)
175 : : {
176 : : struct rte_lpm6 *lpm = NULL;
177 : : struct rte_lpm6_config config;
178 : : int32_t i;
179 : :
180 : 1 : config.number_tbl8s = NUMBER_TBL8S;
181 : 1 : config.flags = 0;
182 : :
183 : : /* rte_lpm6_free: Free NULL */
184 [ + + ]: 21 : for (i = 0; i < 20; i++) {
185 : 20 : config.max_rules = MAX_RULES - i;
186 : 20 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
187 [ - + ]: 20 : TEST_LPM_ASSERT(lpm != NULL);
188 : :
189 : 20 : 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 : 1 : test3(void)
204 : : {
205 : : struct rte_lpm6 *lpm = NULL;
206 : : struct rte_lpm6_config config;
207 : :
208 : 1 : config.max_rules = MAX_RULES;
209 : 1 : config.number_tbl8s = NUMBER_TBL8S;
210 : 1 : config.flags = 0;
211 : :
212 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
213 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
214 : :
215 : 1 : rte_lpm6_free(lpm);
216 : 1 : rte_lpm6_free(NULL);
217 : 1 : return PASS;
218 : : }
219 : :
220 : : /*
221 : : * Check that rte_lpm6_add fails gracefully for incorrect user input arguments
222 : : */
223 : : int32_t
224 : 1 : test4(void)
225 : : {
226 : : struct rte_lpm6 *lpm = NULL;
227 : : struct rte_lpm6_config config;
228 : :
229 : 1 : struct rte_ipv6_addr ip = RTE_IPV6_ADDR_UNSPEC;
230 : : uint8_t depth = 24, next_hop = 100;
231 : : int32_t status = 0;
232 : :
233 : 1 : config.max_rules = MAX_RULES;
234 : 1 : config.number_tbl8s = NUMBER_TBL8S;
235 : 1 : config.flags = 0;
236 : :
237 : : /* rte_lpm6_add: lpm == NULL */
238 : 1 : status = rte_lpm6_add(NULL, &ip, depth, next_hop);
239 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
240 : :
241 : : /*Create valid lpm to use in rest of test. */
242 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
243 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
244 : :
245 : : /* rte_lpm6_add: depth < 1 */
246 : 1 : status = rte_lpm6_add(lpm, &ip, 0, next_hop);
247 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
248 : :
249 : : /* rte_lpm6_add: depth > MAX_DEPTH */
250 : 1 : status = rte_lpm6_add(lpm, &ip, (MAX_DEPTH + 1), next_hop);
251 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
252 : :
253 : 1 : rte_lpm6_free(lpm);
254 : :
255 : 1 : return PASS;
256 : : }
257 : :
258 : : /*
259 : : * Check that rte_lpm6_delete fails gracefully for incorrect user input
260 : : * arguments
261 : : */
262 : : int32_t
263 : 1 : test5(void)
264 : : {
265 : : struct rte_lpm6 *lpm = NULL;
266 : : struct rte_lpm6_config config;
267 : 1 : struct rte_ipv6_addr ip = RTE_IPV6_ADDR_UNSPEC;
268 : : uint8_t depth = 24;
269 : : int32_t status = 0;
270 : :
271 : 1 : config.max_rules = MAX_RULES;
272 : 1 : config.number_tbl8s = NUMBER_TBL8S;
273 : 1 : config.flags = 0;
274 : :
275 : : /* rte_lpm_delete: lpm == NULL */
276 : 1 : status = rte_lpm6_delete(NULL, &ip, depth);
277 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
278 : :
279 : : /*Create valid lpm to use in rest of test. */
280 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
281 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
282 : :
283 : : /* rte_lpm_delete: depth < 1 */
284 : 1 : status = rte_lpm6_delete(lpm, &ip, 0);
285 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
286 : :
287 : : /* rte_lpm_delete: depth > MAX_DEPTH */
288 : 1 : status = rte_lpm6_delete(lpm, &ip, (MAX_DEPTH + 1));
289 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
290 : :
291 : 1 : rte_lpm6_free(lpm);
292 : :
293 : 1 : return PASS;
294 : : }
295 : :
296 : : /*
297 : : * Check that rte_lpm6_lookup fails gracefully for incorrect user input
298 : : * arguments
299 : : */
300 : : int32_t
301 : 1 : test6(void)
302 : : {
303 : : struct rte_lpm6 *lpm = NULL;
304 : : struct rte_lpm6_config config;
305 : 1 : struct rte_ipv6_addr ip = RTE_IPV6_ADDR_UNSPEC;
306 : 1 : uint32_t next_hop_return = 0;
307 : : int32_t status = 0;
308 : :
309 : 1 : config.max_rules = MAX_RULES;
310 : 1 : config.number_tbl8s = NUMBER_TBL8S;
311 : 1 : config.flags = 0;
312 : :
313 : : /* rte_lpm6_lookup: lpm == NULL */
314 : 1 : status = rte_lpm6_lookup(NULL, &ip, &next_hop_return);
315 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
316 : :
317 : : /*Create valid lpm to use in rest of test. */
318 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
319 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
320 : :
321 : : /* rte_lpm6_lookup: ip = NULL */
322 : 1 : status = rte_lpm6_lookup(lpm, NULL, &next_hop_return);
323 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
324 : :
325 : : /* rte_lpm6_lookup: next_hop = NULL */
326 : 1 : status = rte_lpm6_lookup(lpm, &ip, NULL);
327 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
328 : :
329 : 1 : rte_lpm6_free(lpm);
330 : :
331 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
348 : 1 : config.number_tbl8s = NUMBER_TBL8S;
349 : 1 : config.flags = 0;
350 : :
351 : : /* rte_lpm6_lookup: lpm == NULL */
352 : 1 : status = rte_lpm6_lookup_bulk_func(NULL, ips, next_hop_return, RTE_DIM(ips));
353 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
354 : :
355 : : /*Create valid lpm to use in rest of test. */
356 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
357 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
358 : :
359 : : /* rte_lpm6_lookup: ip = NULL */
360 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, NULL, next_hop_return, RTE_DIM(ips));
361 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
362 : :
363 : : /* rte_lpm6_lookup: next_hop = NULL */
364 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ips, NULL, RTE_DIM(ips));
365 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
366 : :
367 : 1 : rte_lpm6_free(lpm);
368 : :
369 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
386 : 1 : config.number_tbl8s = NUMBER_TBL8S;
387 : 1 : config.flags = 0;
388 : :
389 : : /* rte_lpm6_delete: lpm == NULL */
390 : 1 : status = rte_lpm6_delete_bulk_func(NULL, ips, depth, RTE_DIM(ips));
391 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
392 : :
393 : : /*Create valid lpm to use in rest of test. */
394 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
395 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
396 : :
397 : : /* rte_lpm6_delete: ip = NULL */
398 : 1 : status = rte_lpm6_delete_bulk_func(lpm, NULL, depth, RTE_DIM(ips));
399 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
400 : :
401 : : /* rte_lpm6_delete: next_hop = NULL */
402 : 1 : status = rte_lpm6_delete_bulk_func(lpm, ips, NULL, RTE_DIM(ips));
403 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
404 : :
405 : 1 : rte_lpm6_free(lpm);
406 : :
407 : 1 : 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 : 1 : test9(void)
417 : : {
418 : : struct rte_lpm6 *lpm = NULL;
419 : : struct rte_lpm6_config config;
420 : 1 : struct rte_ipv6_addr ip = RTE_IPV6_ADDR_UNSPEC;
421 : : uint8_t depth = 16;
422 : 1 : uint32_t next_hop_add = 100, next_hop_return = 0;
423 : : int32_t status = 0;
424 : : uint8_t i;
425 : :
426 : 1 : config.max_rules = MAX_RULES;
427 : 1 : config.number_tbl8s = NUMBER_TBL8S;
428 : 1 : config.flags = 0;
429 : :
430 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
431 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
432 : :
433 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
434 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
435 : :
436 [ + + ]: 256 : for (i = 0; i < UINT8_MAX; i++) {
437 : 255 : ip.a[2] = i;
438 : 255 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
439 [ + - - + ]: 255 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
440 : : }
441 : :
442 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
443 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
444 : :
445 [ + + ]: 256 : for (i = 0; i < UINT8_MAX; i++) {
446 : 255 : ip.a[2] = i;
447 : 255 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
448 [ - + ]: 255 : TEST_LPM_ASSERT(status == -ENOENT);
449 : : }
450 : :
451 : 1 : rte_lpm6_free(lpm);
452 : :
453 : 1 : 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 : 1 : test10(void)
462 : : {
463 : : struct rte_lpm6 *lpm = NULL;
464 : : struct rte_lpm6_config config;
465 : 1 : 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 : 1 : config.max_rules = 127;
472 : 1 : config.number_tbl8s = NUMBER_TBL8S;
473 : 1 : config.flags = 0;
474 : :
475 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
476 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
477 : :
478 [ + + ]: 128 : for (i = 1; i < 128; i++) {
479 : : depth = (uint8_t)i;
480 : 127 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
481 [ - + ]: 127 : TEST_LPM_ASSERT(status == 0);
482 : : }
483 : :
484 : : depth = 128;
485 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
486 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOSPC);
487 : :
488 : : depth = 127;
489 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
490 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
491 : :
492 : : depth = 128;
493 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
494 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
495 : :
496 : 1 : rte_lpm6_free(lpm);
497 : :
498 : 1 : 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 : 1 : test11(void)
507 : : {
508 : : struct rte_lpm6 *lpm = NULL;
509 : : struct rte_lpm6_config config;
510 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
516 : 1 : config.number_tbl8s = 16;
517 : 1 : config.flags = 0;
518 : :
519 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
520 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
521 : :
522 : : depth = 128;
523 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
524 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
525 : :
526 : 1 : ip.a[0] = 1;
527 : : depth = 25;
528 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
529 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
530 : :
531 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
532 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
533 : :
534 : : depth = 33;
535 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
536 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
537 : :
538 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
539 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
540 : :
541 : : depth = 41;
542 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
543 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
544 : :
545 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
546 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
547 : :
548 : : depth = 49;
549 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
550 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOSPC);
551 : :
552 : : depth = 41;
553 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
554 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
555 : :
556 : 1 : rte_lpm6_free(lpm);
557 : :
558 : 1 : 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 : 1 : test12(void)
568 : : {
569 : : struct rte_lpm6 *lpm = NULL;
570 : : struct rte_lpm6_config config;
571 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
577 : 1 : config.number_tbl8s = 16;
578 : 1 : config.flags = 0;
579 : :
580 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
581 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
582 : :
583 : : depth = 128;
584 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
585 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
586 : :
587 : 1 : ip.a[0] = 1;
588 : : depth = 41;
589 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
590 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
591 : :
592 : : depth = 49;
593 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
594 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOSPC);
595 : :
596 : 1 : rte_lpm6_free(lpm);
597 : :
598 : 1 : 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 : 1 : test13(void)
607 : : {
608 : : struct rte_lpm6 *lpm = NULL;
609 : : struct rte_lpm6_config config;
610 : 1 : 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 : 1 : config.max_rules = 2;
616 : 1 : config.number_tbl8s = NUMBER_TBL8S;
617 : 1 : config.flags = 0;
618 : :
619 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
620 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
621 : :
622 : : depth = 1;
623 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
624 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
625 : :
626 : : depth = 2;
627 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
628 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
629 : :
630 : : depth = 3;
631 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
632 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOSPC);
633 : :
634 : : depth = 2;
635 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
636 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
637 : :
638 : : depth = 3;
639 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
640 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
641 : :
642 : 1 : rte_lpm6_free(lpm);
643 : :
644 : 1 : 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 : 1 : test14(void)
655 : : {
656 : : struct rte_lpm6 *lpm = NULL;
657 : : struct rte_lpm6_config config;
658 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
665 : 1 : config.number_tbl8s = 256;
666 : 1 : config.flags = 0;
667 : :
668 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
669 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
670 : :
671 [ + + ]: 257 : for (i = 0; i < 256; i++) {
672 : 256 : ip.a[0] = (uint8_t)i;
673 : 256 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
674 [ - + ]: 256 : TEST_LPM_ASSERT(status == 0);
675 : : }
676 : :
677 : 1 : ip.a[0] = 255;
678 : 1 : ip.a[1] = 1;
679 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
680 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOSPC);
681 : :
682 : 1 : ip.a[0] = 255;
683 : 1 : ip.a[1] = 0;
684 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
685 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
686 : :
687 : 1 : ip.a[0] = 255;
688 : 1 : ip.a[1] = 1;
689 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
690 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
691 : :
692 : 1 : rte_lpm6_free(lpm);
693 : :
694 : 1 : return PASS;
695 : : }
696 : :
697 : : /*
698 : : * Call add, lookup and delete for a single rule with depth = 24
699 : : */
700 : : int32_t
701 : 1 : test15(void)
702 : : {
703 : : struct rte_lpm6 *lpm = NULL;
704 : : struct rte_lpm6_config config;
705 : 1 : struct rte_ipv6_addr ip = RTE_IPV6_ADDR_UNSPEC;
706 : : uint8_t depth = 24;
707 : 1 : uint32_t next_hop_add = 100, next_hop_return = 0;
708 : : int32_t status = 0;
709 : :
710 : 1 : config.max_rules = MAX_RULES;
711 : 1 : config.number_tbl8s = NUMBER_TBL8S;
712 : 1 : config.flags = 0;
713 : :
714 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
715 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
716 : :
717 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
718 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
719 : :
720 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
721 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
722 : :
723 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
724 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
725 : :
726 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
727 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
728 : :
729 : 1 : rte_lpm6_free(lpm);
730 : :
731 : 1 : return PASS;
732 : : }
733 : :
734 : : /*
735 : : * Call add, lookup and delete for a single rule with depth > 24
736 : : */
737 : : int32_t
738 : 1 : test16(void)
739 : : {
740 : : struct rte_lpm6 *lpm = NULL;
741 : : struct rte_lpm6_config config;
742 : 1 : struct rte_ipv6_addr ip = RTE_IPV6(0x0c0c, 0x0100, 0, 0, 0, 0, 0, 0);
743 : : uint8_t depth = 128;
744 : 1 : uint32_t next_hop_add = 100, next_hop_return = 0;
745 : : int32_t status = 0;
746 : :
747 : 1 : config.max_rules = MAX_RULES;
748 : 1 : config.number_tbl8s = NUMBER_TBL8S;
749 : 1 : config.flags = 0;
750 : :
751 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
752 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
753 : :
754 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
755 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
756 : :
757 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
758 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
759 : :
760 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
761 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
762 : :
763 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
764 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
765 : :
766 : 1 : rte_lpm6_free(lpm);
767 : :
768 : 1 : 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 : 1 : test17(void)
782 : : {
783 : : struct rte_lpm6 *lpm = NULL;
784 : : struct rte_lpm6_config config;
785 : 1 : struct rte_ipv6_addr ip1 =
786 : : RTE_IPV6(0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff);
787 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
793 : 1 : config.number_tbl8s = NUMBER_TBL8S;
794 : 1 : config.flags = 0;
795 : :
796 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
797 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
798 : :
799 : : /* Loop with rte_lpm6_add. */
800 [ + + ]: 17 : for (depth = 1; depth <= 16; depth++) {
801 : : /* Let the next_hop_add value = depth. Just for change. */
802 : 16 : next_hop_add = depth;
803 : :
804 : 16 : status = rte_lpm6_add(lpm, &ip2, depth, next_hop_add);
805 [ - + ]: 16 : TEST_LPM_ASSERT(status == 0);
806 : :
807 : : /* Check IP in first half of tbl24 which should be empty. */
808 : 16 : status = rte_lpm6_lookup(lpm, &ip1, &next_hop_return);
809 [ - + ]: 16 : TEST_LPM_ASSERT(status == -ENOENT);
810 : :
811 : 16 : status = rte_lpm6_lookup(lpm, &ip2, &next_hop_return);
812 [ + - - + ]: 16 : TEST_LPM_ASSERT((status == 0) &&
813 : : (next_hop_return == next_hop_add));
814 : : }
815 : :
816 : : /* Loop with rte_lpm6_delete. */
817 [ + + ]: 17 : for (depth = 16; depth >= 1; depth--) {
818 : 16 : next_hop_add = (depth - 1);
819 : :
820 : 16 : status = rte_lpm6_delete(lpm, &ip2, depth);
821 [ - + ]: 16 : TEST_LPM_ASSERT(status == 0);
822 : :
823 : 16 : status = rte_lpm6_lookup(lpm, &ip2, &next_hop_return);
824 : :
825 [ + + ]: 16 : if (depth != 1) {
826 [ + - - + ]: 15 : TEST_LPM_ASSERT((status == 0) &&
827 : : (next_hop_return == next_hop_add));
828 : : }
829 : : else {
830 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
831 : : }
832 : :
833 : 16 : status = rte_lpm6_lookup(lpm, &ip1, &next_hop_return);
834 [ - + ]: 16 : TEST_LPM_ASSERT(status == -ENOENT);
835 : : }
836 : :
837 : 1 : rte_lpm6_free(lpm);
838 : :
839 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
860 : 1 : config.number_tbl8s = NUMBER_TBL8S;
861 : 1 : config.flags = 0;
862 : :
863 : : /* Add & lookup to hit invalid TBL24 entry */
864 : 1 : 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 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
869 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
870 : :
871 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
872 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
873 : :
874 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
875 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
876 : :
877 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
878 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
879 : :
880 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
881 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
882 : :
883 : 1 : rte_lpm6_delete_all(lpm);
884 : :
885 : : /* Add & lookup to hit valid TBL24 entry not extended */
886 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
891 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
892 : :
893 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
894 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
895 : :
896 : : depth = 24;
897 : : next_hop_add = 101;
898 : :
899 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
900 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
901 : :
902 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
903 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
904 : :
905 : : depth = 24;
906 : :
907 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
908 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
909 : :
910 : : depth = 23;
911 : :
912 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
913 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
914 : :
915 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
916 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
917 : :
918 : 1 : rte_lpm6_delete_all(lpm);
919 : :
920 : : /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
921 : : * entry.
922 : : */
923 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
928 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
929 : :
930 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
931 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
932 : :
933 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
938 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
939 : :
940 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
941 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
942 : :
943 : 1 : 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 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
948 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
949 : :
950 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
951 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
952 : :
953 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
954 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
955 : :
956 : 1 : rte_lpm6_delete_all(lpm);
957 : :
958 : : /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
959 : : * entry
960 : : */
961 : 1 : 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 : 1 : 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 : 1 : next_hop_return = 0;
970 : :
971 : 1 : status = rte_lpm6_add(lpm, &ip_1, depth_1, next_hop_add_1);
972 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
973 : :
974 : 1 : status = rte_lpm6_lookup(lpm, &ip_1, &next_hop_return);
975 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
976 : :
977 : 1 : status = rte_lpm6_add(lpm, &ip_2, depth_2, next_hop_add_2);
978 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
979 : :
980 : 1 : status = rte_lpm6_lookup(lpm, &ip_2, &next_hop_return);
981 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
982 : :
983 : 1 : status = rte_lpm6_delete(lpm, &ip_2, depth_2);
984 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
985 : :
986 : 1 : status = rte_lpm6_lookup(lpm, &ip_2, &next_hop_return);
987 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
988 : :
989 : 1 : status = rte_lpm6_delete(lpm, &ip_1, depth_1);
990 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
991 : :
992 : 1 : status = rte_lpm6_lookup(lpm, &ip_1, &next_hop_return);
993 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
994 : :
995 : 1 : rte_lpm6_free(lpm);
996 : :
997 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1022 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1023 : 1 : config.flags = 0;
1024 : :
1025 : : /* Add rule that covers a TBL24 range previously invalid & lookup
1026 : : * (& delete & lookup)
1027 : : */
1028 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1029 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1030 : :
1031 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1036 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1037 : :
1038 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1039 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1040 : :
1041 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1042 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1043 : :
1044 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1045 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1046 : :
1047 : 1 : rte_lpm6_delete_all(lpm);
1048 : :
1049 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1054 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1055 : :
1056 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1057 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1058 : :
1059 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1060 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1061 : :
1062 : 1 : 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 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1074 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1075 : :
1076 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1081 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1082 : :
1083 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1084 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1085 : :
1086 : 1 : ip = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0, 0, 0, 0, 0, 0);
1087 : : next_hop_add = 100;
1088 : :
1089 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1090 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1091 : :
1092 : 1 : ip = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0, 0, 0, 0, 0, 0);
1093 : : depth = 24;
1094 : :
1095 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1096 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1097 : :
1098 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1099 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1100 : :
1101 : 1 : ip = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0x000a, 0, 0, 0, 0, 0, 0);
1102 : : depth = 32;
1103 : :
1104 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1105 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1106 : :
1107 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1108 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1109 : :
1110 : 1 : rte_lpm6_delete_all(lpm);
1111 : :
1112 : : /*
1113 : : * Add rule that updates the next hop in TBL24 & lookup
1114 : : * (& delete & lookup)
1115 : : */
1116 : :
1117 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1122 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1123 : :
1124 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1125 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1126 : :
1127 : : next_hop_add = 101;
1128 : :
1129 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1130 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1131 : :
1132 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1133 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1134 : :
1135 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1136 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1137 : :
1138 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1139 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1140 : :
1141 : 1 : rte_lpm6_delete_all(lpm);
1142 : :
1143 : : /*
1144 : : * Add rule that updates the next hop in TBL8 & lookup
1145 : : * (& delete & lookup)
1146 : : */
1147 : :
1148 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1153 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1154 : :
1155 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1156 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1157 : :
1158 : : next_hop_add = 101;
1159 : :
1160 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1161 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1162 : :
1163 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1164 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1165 : :
1166 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1167 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1168 : :
1169 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1170 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1171 : :
1172 : 1 : rte_lpm6_delete_all(lpm);
1173 : :
1174 : : /* Delete a rule that is not present in the TBL24 & lookup */
1175 : :
1176 : 1 : 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 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1181 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
1182 : :
1183 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1184 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1185 : :
1186 : 1 : rte_lpm6_delete_all(lpm);
1187 : :
1188 : : /* Delete a rule that is not present in the TBL8 & lookup */
1189 : :
1190 : 1 : 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 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1195 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
1196 : :
1197 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1198 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1199 : :
1200 : 1 : rte_lpm6_free(lpm);
1201 : :
1202 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1221 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1222 : 1 : config.flags = 0;
1223 : :
1224 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1225 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1226 : :
1227 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1232 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1233 : :
1234 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1239 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1240 : :
1241 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1242 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1243 : :
1244 : 1 : ip = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0, 0, 0, 0, 0, 0);
1245 : : next_hop_add = 100;
1246 : :
1247 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1248 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1249 : :
1250 : 1 : ip = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0, 0, 0, 0, 0, 0);
1251 : : depth = 24;
1252 : :
1253 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1254 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1255 : :
1256 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1257 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1258 : :
1259 : 1 : ip = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0, 0, 0, 0, 0, 0x000a);
1260 : : depth = 128;
1261 : :
1262 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1263 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1264 : :
1265 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1266 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
1267 : :
1268 : 1 : rte_lpm6_free(lpm);
1269 : :
1270 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1290 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1291 : 1 : config.flags = 0;
1292 : :
1293 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1294 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1295 : :
1296 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip_batch[0], depth, next_hop_add);
1301 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1302 : :
1303 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip_batch[1], depth, next_hop_add);
1308 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1309 : :
1310 : 1 : 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 : 1 : status = rte_lpm6_add(lpm, &ip_batch[2], depth, next_hop_add);
1315 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1316 : :
1317 : 1 : ip_batch[3] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0004, 0, 0, 0, 0, 0);
1318 : :
1319 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1320 : : next_hop_return, 4);
1321 [ + - + - : 1 : 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 : 1 : rte_lpm6_free(lpm);
1326 : :
1327 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1349 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1350 : 1 : config.flags = 0;
1351 : :
1352 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1353 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1354 : :
1355 : : /* Adds 5 rules and look them up */
1356 : :
1357 : 1 : ip_batch[0] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0001, 0, 0, 0, 0, 0);
1358 : 1 : depth[0] = 48;
1359 : : next_hop_add = 101;
1360 : :
1361 : 1 : status = rte_lpm6_add(lpm, &ip_batch[0], depth[0], next_hop_add);
1362 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1363 : :
1364 : 1 : ip_batch[1] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0002, 0, 0, 0, 0, 0);
1365 : 1 : depth[1] = 48;
1366 : : next_hop_add = 102;
1367 : :
1368 : 1 : status = rte_lpm6_add(lpm, &ip_batch[1], depth[1], next_hop_add);
1369 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1370 : :
1371 : 1 : ip_batch[2] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0003, 0, 0, 0, 0, 0);
1372 : 1 : depth[2] = 48;
1373 : : next_hop_add = 103;
1374 : :
1375 : 1 : status = rte_lpm6_add(lpm, &ip_batch[2], depth[2], next_hop_add);
1376 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1377 : :
1378 : 1 : ip_batch[3] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0004, 0, 0, 0, 0, 0);
1379 : 1 : depth[3] = 48;
1380 : : next_hop_add = 104;
1381 : :
1382 : 1 : status = rte_lpm6_add(lpm, &ip_batch[3], depth[3], next_hop_add);
1383 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1384 : :
1385 : 1 : ip_batch[4] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0005, 0, 0, 0, 0, 0);
1386 : 1 : depth[4] = 48;
1387 : : next_hop_add = 105;
1388 : :
1389 : 1 : status = rte_lpm6_add(lpm, &ip_batch[4], depth[4], next_hop_add);
1390 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1391 : :
1392 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1393 : : next_hop_return, 5);
1394 [ + - + - : 1 : 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 : 1 : status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[0], depth, 2);
1401 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1402 : :
1403 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1404 : : next_hop_return, 5);
1405 [ + - + - : 1 : 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 : 1 : status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[2], depth, 1);
1412 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1413 : :
1414 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1415 : : next_hop_return, 5);
1416 [ + - + - : 1 : 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 : 1 : ip_batch[4] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0006, 0, 0, 0, 0, 0);
1423 : 1 : status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[3], depth, 2);
1424 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1425 : :
1426 : 1 : ip_batch[4] = (struct rte_ipv6_addr)RTE_IPV6(0x8000, 0, 0x0005, 0, 0, 0, 0, 0);
1427 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1428 : : next_hop_return, 5);
1429 [ + - + - : 1 : 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 : 1 : status = rte_lpm6_delete_bulk_func(lpm, &ip_batch[4], depth, 1);
1436 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1437 : :
1438 : 1 : status = rte_lpm6_lookup_bulk_func(lpm, ip_batch,
1439 : : next_hop_return, 5);
1440 [ + - + - : 1 : 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 : 1 : rte_lpm6_free(lpm);
1445 : :
1446 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1466 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1467 : 1 : config.flags = 0;
1468 : :
1469 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1470 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1471 : :
1472 : 1 : 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 [ + + ]: 31 : for (i = 0; i < 30; i++) {
1477 : 30 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1478 [ - + ]: 30 : TEST_LPM_ASSERT(status == 0);
1479 : :
1480 : 30 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1481 [ + - - + ]: 30 : TEST_LPM_ASSERT((status == 0) &&
1482 : : (next_hop_return == next_hop_add));
1483 : :
1484 : 30 : status = rte_lpm6_delete(lpm, &ip, depth);
1485 [ - + ]: 30 : TEST_LPM_ASSERT(status == 0);
1486 : :
1487 : 30 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1488 [ - + ]: 30 : TEST_LPM_ASSERT(status == -ENOENT);
1489 : : }
1490 : :
1491 : 1 : rte_lpm6_free(lpm);
1492 : :
1493 : 1 : 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 : 1 : test24(void)
1505 : : {
1506 : : struct rte_lpm6 *lpm = NULL, *result = NULL;
1507 : : struct rte_lpm6_config config;
1508 : :
1509 : 1 : config.max_rules = 256 * 32;
1510 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1511 : 1 : config.flags = 0;
1512 : :
1513 : : /* Create lpm */
1514 : 1 : lpm = rte_lpm6_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1515 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1516 : :
1517 : : /* Try to find existing lpm */
1518 : 1 : result = rte_lpm6_find_existing("lpm_find_existing");
1519 [ - + ]: 1 : TEST_LPM_ASSERT(result == lpm);
1520 : :
1521 : : /* Try to find non-existing lpm */
1522 : 1 : result = rte_lpm6_find_existing("lpm_find_non_existing");
1523 [ - + ]: 1 : TEST_LPM_ASSERT(result == NULL);
1524 : :
1525 : : /* Cleanup. */
1526 : 1 : rte_lpm6_delete_all(lpm);
1527 : 1 : rte_lpm6_free(lpm);
1528 : :
1529 : 1 : 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 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1551 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1552 : 1 : config.flags = 0;
1553 : :
1554 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1555 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1556 : :
1557 [ + + ]: 1001 : for (i = 0; i < 1000; i++) {
1558 : 1000 : ip = large_route_table[i].ip;
1559 : 1000 : depth = large_route_table[i].depth;
1560 : 1000 : next_hop_add = large_route_table[i].next_hop;
1561 : 1000 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1562 [ - + ]: 1000 : TEST_LPM_ASSERT(status == 0);
1563 : : }
1564 : :
1565 : : /* generate large IPS table and expected next_hops */
1566 : 1 : generate_large_ips_table(1);
1567 : :
1568 [ + + ]: 100001 : for (i = 0; i < 100000; i++) {
1569 : 100000 : ip = large_ips_table[i].ip;
1570 : 100000 : next_hop_expected = large_ips_table[i].next_hop;
1571 : :
1572 : 100000 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1573 [ + - - + ]: 100000 : TEST_LPM_ASSERT((status == 0) &&
1574 : : (next_hop_return == next_hop_expected));
1575 : : }
1576 : :
1577 : 1 : rte_lpm6_free(lpm);
1578 : :
1579 : 1 : 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 : 1 : test26(void)
1591 : : {
1592 : : struct rte_lpm6 *lpm = NULL;
1593 : : struct rte_lpm6_config config;
1594 : 1 : struct rte_ipv6_addr ip_10_32 = RTE_IPV6(0x0a0a, 0x0a02, 0, 0, 0, 0, 0, 0);
1595 : 1 : struct rte_ipv6_addr ip_10_24 = RTE_IPV6(0x0a0a, 0x0a00, 0, 0, 0, 0, 0, 0);
1596 : 1 : 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 : 1 : uint32_t next_hop_return = 0;
1604 : : int32_t status = 0;
1605 : :
1606 : 1 : config.max_rules = MAX_RULES;
1607 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1608 : 1 : config.flags = 0;
1609 : :
1610 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1611 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1612 : :
1613 : 1 : status = rte_lpm6_add(lpm, &ip_10_32, d_ip_10_32, next_hop_ip_10_32);
1614 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1615 : :
1616 : 1 : status = rte_lpm6_lookup(lpm, &ip_10_32, &next_hop_return);
1617 : 1 : uint32_t test_hop_10_32 = next_hop_return;
1618 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1619 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1620 : :
1621 : 1 : status = rte_lpm6_add(lpm, &ip_10_24, d_ip_10_24, next_hop_ip_10_24);
1622 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1623 : :
1624 : 1 : status = rte_lpm6_lookup(lpm, &ip_10_24, &next_hop_return);
1625 : 1 : uint32_t test_hop_10_24 = next_hop_return;
1626 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1627 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1628 : :
1629 : 1 : status = rte_lpm6_add(lpm, &ip_20_25, d_ip_20_25, next_hop_ip_20_25);
1630 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1631 : :
1632 : 1 : status = rte_lpm6_lookup(lpm, &ip_20_25, &next_hop_return);
1633 : 1 : uint32_t test_hop_20_25 = next_hop_return;
1634 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1635 [ - + ]: 1 : 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 : 1 : status = rte_lpm6_lookup(lpm, &ip_10_32, &next_hop_return);
1648 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1649 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1650 : :
1651 : 1 : status = rte_lpm6_lookup(lpm, &ip_10_24, &next_hop_return);
1652 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1653 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1654 : :
1655 : 1 : rte_lpm6_free(lpm);
1656 : :
1657 : 1 : 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 : 1 : test27(void)
1668 : : {
1669 : : struct rte_lpm6 *lpm = NULL;
1670 : : struct rte_lpm6_config config;
1671 : 1 : 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 : 1 : config.max_rules = MAX_RULES;
1679 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1680 : 1 : config.flags = 0;
1681 : :
1682 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1683 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1684 : :
1685 : : depth = 128;
1686 : : next_hop_add = 128;
1687 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1688 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1689 : :
1690 : : depth = 112;
1691 : : next_hop_add = 112;
1692 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1693 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1694 : :
1695 [ + + ]: 257 : for (i = 0; i < 256; i++) {
1696 : 256 : ip.a[14] = i;
1697 [ + + ]: 65792 : for (j = 0; j < 256; j++) {
1698 : 65536 : ip.a[15] = j;
1699 : 65536 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1700 [ + + ]: 65536 : if (i == 0 && j == 0)
1701 [ + - - + ]: 1 : TEST_LPM_ASSERT(status == 0 && next_hop_return == 128);
1702 : : else
1703 [ + - - + ]: 65535 : TEST_LPM_ASSERT(status == 0 && next_hop_return == 112);
1704 : : }
1705 : : }
1706 : :
1707 : 1 : rte_lpm6_free(lpm);
1708 : :
1709 : 1 : 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 : 1 : test28(void)
1720 : : {
1721 : : struct rte_lpm6 *lpm = NULL;
1722 : : struct rte_lpm6_config config;
1723 : 1 : struct rte_ipv6_addr ip = RTE_IPV6(0, 0, 0, 0, 0, 0, 0, 0);
1724 : : uint8_t depth = 16;
1725 : 1 : uint32_t next_hop_add = 0x001FFFFF, next_hop_return = 0;
1726 : : int32_t status = 0;
1727 : :
1728 : 1 : config.max_rules = MAX_RULES;
1729 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1730 : 1 : config.flags = 0;
1731 : :
1732 : 1 : lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, &config);
1733 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1734 : :
1735 : 1 : status = rte_lpm6_add(lpm, &ip, depth, next_hop_add);
1736 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1737 : :
1738 : 1 : status = rte_lpm6_lookup(lpm, &ip, &next_hop_return);
1739 [ + - - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
1740 : :
1741 : 1 : status = rte_lpm6_delete(lpm, &ip, depth);
1742 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1743 : 1 : rte_lpm6_free(lpm);
1744 : :
1745 : 1 : return PASS;
1746 : : }
1747 : :
1748 : : /*
1749 : : * Do all unit tests.
1750 : : */
1751 : : static int
1752 : 1 : test_lpm6(void)
1753 : : {
1754 : : unsigned i;
1755 : : int status = -1, global_status = 0;
1756 : :
1757 [ + + ]: 30 : for (i = 0; i < RTE_DIM(tests6); i++) {
1758 : : printf("# test %02d\n", i);
1759 : 29 : status = tests6[i]();
1760 : :
1761 [ - + ]: 29 : if (status < 0) {
1762 : : printf("ERROR: LPM Test %s: FAIL\n", RTE_STR(tests6[i]));
1763 : : global_status = status;
1764 : : }
1765 : : }
1766 : :
1767 : 1 : return global_status;
1768 : : }
1769 : :
1770 : 252 : REGISTER_FAST_TEST(lpm6_autotest, true, true, test_lpm6);
|