Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2014 Intel Corporation
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <stdint.h>
7 : : #include <stdlib.h>
8 : :
9 : : #include <rte_ip.h>
10 : : #include <rte_lpm.h>
11 : : #include <rte_malloc.h>
12 : :
13 : : #include "test.h"
14 : : #include "test_xmmt_ops.h"
15 : :
16 : : #define TEST_LPM_ASSERT(cond) do { \
17 : : if (!(cond)) { \
18 : : printf("Error at line %d: \n", __LINE__); \
19 : : return -1; \
20 : : } \
21 : : } while(0)
22 : :
23 : : typedef int32_t (*rte_lpm_test)(void);
24 : :
25 : : static int32_t test0(void);
26 : : static int32_t test1(void);
27 : : static int32_t test2(void);
28 : : static int32_t test3(void);
29 : : static int32_t test4(void);
30 : : static int32_t test5(void);
31 : : static int32_t test6(void);
32 : : static int32_t test7(void);
33 : : static int32_t test8(void);
34 : : static int32_t test9(void);
35 : : static int32_t test10(void);
36 : : static int32_t test11(void);
37 : : static int32_t test12(void);
38 : : static int32_t test13(void);
39 : : static int32_t test14(void);
40 : : static int32_t test15(void);
41 : : static int32_t test16(void);
42 : : static int32_t test17(void);
43 : : static int32_t test18(void);
44 : : static int32_t test19(void);
45 : : static int32_t test20(void);
46 : : static int32_t test21(void);
47 : :
48 : : rte_lpm_test tests[] = {
49 : : /* Test Cases */
50 : : test0,
51 : : test1,
52 : : test2,
53 : : test3,
54 : : test4,
55 : : test5,
56 : : test6,
57 : : test7,
58 : : test8,
59 : : test9,
60 : : test10,
61 : : test11,
62 : : test12,
63 : : test13,
64 : : test14,
65 : : test15,
66 : : test16,
67 : : test17,
68 : : test18,
69 : : test19,
70 : : test20,
71 : : test21
72 : : };
73 : :
74 : : #define MAX_DEPTH 32
75 : : #define MAX_RULES 256
76 : : #define NUMBER_TBL8S 256
77 : : #define PASS 0
78 : :
79 : : /*
80 : : * Check that rte_lpm_create fails gracefully for incorrect user input
81 : : * arguments
82 : : */
83 : : int32_t
84 : 1 : test0(void)
85 : : {
86 : : struct rte_lpm *lpm = NULL;
87 : : struct rte_lpm_config config;
88 : :
89 : 1 : config.max_rules = MAX_RULES;
90 : 1 : config.number_tbl8s = NUMBER_TBL8S;
91 : 1 : config.flags = 0;
92 : :
93 : : /* rte_lpm_create: lpm name == NULL */
94 : 1 : lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
95 [ - + ]: 1 : TEST_LPM_ASSERT(lpm == NULL);
96 : :
97 : : /* rte_lpm_create: max_rules = 0 */
98 : : /* Note: __func__ inserts the function name, in this case "test0". */
99 : 1 : config.max_rules = 0;
100 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
101 [ - + ]: 1 : TEST_LPM_ASSERT(lpm == NULL);
102 : :
103 : : /* socket_id < -1 is invalid */
104 : 1 : config.max_rules = MAX_RULES;
105 : 1 : lpm = rte_lpm_create(__func__, -2, &config);
106 [ - + ]: 1 : TEST_LPM_ASSERT(lpm == NULL);
107 : :
108 : : return PASS;
109 : : }
110 : :
111 : : /*
112 : : * Create lpm table then delete lpm table 100 times
113 : : * Use a slightly different rules size each time
114 : : * */
115 : : int32_t
116 : 1 : test1(void)
117 : : {
118 : : struct rte_lpm *lpm = NULL;
119 : : struct rte_lpm_config config;
120 : :
121 : 1 : config.number_tbl8s = NUMBER_TBL8S;
122 : 1 : config.flags = 0;
123 : : int32_t i;
124 : :
125 : : /* rte_lpm_free: Free NULL */
126 [ + + ]: 101 : for (i = 0; i < 100; i++) {
127 : 100 : config.max_rules = MAX_RULES - i;
128 : 100 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
129 [ - + ]: 100 : TEST_LPM_ASSERT(lpm != NULL);
130 : :
131 : 100 : rte_lpm_free(lpm);
132 : : }
133 : :
134 : : /* Can not test free so return success */
135 : : return PASS;
136 : : }
137 : :
138 : : /*
139 : : * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
140 : : * therefore it is impossible to check for failure but this test is added to
141 : : * increase function coverage metrics and to validate that freeing null does
142 : : * not crash.
143 : : */
144 : : int32_t
145 : 1 : test2(void)
146 : : {
147 : : struct rte_lpm *lpm = NULL;
148 : : struct rte_lpm_config config;
149 : :
150 : 1 : config.max_rules = MAX_RULES;
151 : 1 : config.number_tbl8s = NUMBER_TBL8S;
152 : 1 : config.flags = 0;
153 : :
154 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
155 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
156 : :
157 : 1 : rte_lpm_free(lpm);
158 : 1 : rte_lpm_free(NULL);
159 : 1 : return PASS;
160 : : }
161 : :
162 : : /*
163 : : * Check that rte_lpm_add fails gracefully for incorrect user input arguments
164 : : */
165 : : int32_t
166 : 1 : test3(void)
167 : : {
168 : : struct rte_lpm *lpm = NULL;
169 : : struct rte_lpm_config config;
170 : :
171 : 1 : config.max_rules = MAX_RULES;
172 : 1 : config.number_tbl8s = NUMBER_TBL8S;
173 : 1 : config.flags = 0;
174 : : uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop = 100;
175 : : uint8_t depth = 24;
176 : : int32_t status = 0;
177 : :
178 : : /* rte_lpm_add: lpm == NULL */
179 : 1 : status = rte_lpm_add(NULL, ip, depth, next_hop);
180 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
181 : :
182 : : /*Create valid lpm to use in rest of test. */
183 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
184 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
185 : :
186 : : /* rte_lpm_add: depth < 1 */
187 : 1 : status = rte_lpm_add(lpm, ip, 0, next_hop);
188 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
189 : :
190 : : /* rte_lpm_add: depth > MAX_DEPTH */
191 : 1 : status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
192 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
193 : :
194 : 1 : rte_lpm_free(lpm);
195 : :
196 : 1 : return PASS;
197 : : }
198 : :
199 : : /*
200 : : * Check that rte_lpm_delete fails gracefully for incorrect user input
201 : : * arguments
202 : : */
203 : : int32_t
204 : 1 : test4(void)
205 : : {
206 : : struct rte_lpm *lpm = NULL;
207 : : struct rte_lpm_config config;
208 : :
209 : 1 : config.max_rules = MAX_RULES;
210 : 1 : config.number_tbl8s = NUMBER_TBL8S;
211 : 1 : config.flags = 0;
212 : : uint32_t ip = RTE_IPV4(0, 0, 0, 0);
213 : : uint8_t depth = 24;
214 : : int32_t status = 0;
215 : :
216 : : /* rte_lpm_delete: lpm == NULL */
217 : 1 : status = rte_lpm_delete(NULL, ip, depth);
218 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
219 : :
220 : : /*Create valid lpm to use in rest of test. */
221 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
222 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
223 : :
224 : : /* rte_lpm_delete: depth < 1 */
225 : 1 : status = rte_lpm_delete(lpm, ip, 0);
226 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
227 : :
228 : : /* rte_lpm_delete: depth > MAX_DEPTH */
229 : 1 : status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
230 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
231 : :
232 : 1 : rte_lpm_free(lpm);
233 : :
234 : 1 : return PASS;
235 : : }
236 : :
237 : : /*
238 : : * Check that rte_lpm_lookup fails gracefully for incorrect user input
239 : : * arguments
240 : : */
241 : : int32_t
242 : 1 : test5(void)
243 : : {
244 : : #if defined(RTE_LIBRTE_LPM_DEBUG)
245 : : struct rte_lpm *lpm = NULL;
246 : : struct rte_lpm_config config;
247 : :
248 : : config.max_rules = MAX_RULES;
249 : : config.number_tbl8s = NUMBER_TBL8S;
250 : : config.flags = 0;
251 : : uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_return = 0;
252 : : int32_t status = 0;
253 : :
254 : : /* rte_lpm_lookup: lpm == NULL */
255 : : status = rte_lpm_lookup(NULL, ip, &next_hop_return);
256 : : TEST_LPM_ASSERT(status < 0);
257 : :
258 : : /*Create valid lpm to use in rest of test. */
259 : : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
260 : : TEST_LPM_ASSERT(lpm != NULL);
261 : :
262 : : /* rte_lpm_lookup: depth < 1 */
263 : : status = rte_lpm_lookup(lpm, ip, NULL);
264 : : TEST_LPM_ASSERT(status < 0);
265 : :
266 : : rte_lpm_free(lpm);
267 : : #endif
268 : 1 : return PASS;
269 : : }
270 : :
271 : :
272 : :
273 : : /*
274 : : * Call add, lookup and delete for a single rule with depth <= 24
275 : : */
276 : : int32_t
277 : 1 : test6(void)
278 : : {
279 : : struct rte_lpm *lpm = NULL;
280 : : struct rte_lpm_config config;
281 : :
282 : 1 : config.max_rules = MAX_RULES;
283 : 1 : config.number_tbl8s = NUMBER_TBL8S;
284 : 1 : config.flags = 0;
285 : : uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
286 : : uint8_t depth = 24;
287 : : int32_t status = 0;
288 : :
289 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
290 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
291 : :
292 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
293 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
294 : :
295 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
296 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
297 : :
298 : 1 : status = rte_lpm_delete(lpm, ip, depth);
299 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
300 : :
301 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
302 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
303 : :
304 : 1 : rte_lpm_free(lpm);
305 : :
306 : 1 : return PASS;
307 : : }
308 : :
309 : : /*
310 : : * Call add, lookup and delete for a single rule with depth > 24
311 : : */
312 : :
313 : : int32_t
314 : 1 : test7(void)
315 : : {
316 : : xmm_t ipx4;
317 : : uint32_t hop[4];
318 : : struct rte_lpm *lpm = NULL;
319 : : struct rte_lpm_config config;
320 : :
321 : 1 : config.max_rules = MAX_RULES;
322 : 1 : config.number_tbl8s = NUMBER_TBL8S;
323 : 1 : config.flags = 0;
324 : : uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
325 : : uint8_t depth = 32;
326 : : int32_t status = 0;
327 : :
328 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
329 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
330 : :
331 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
332 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
333 : :
334 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
335 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
336 : :
337 : : ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
338 : 1 : rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
339 [ - + ]: 1 : TEST_LPM_ASSERT(hop[0] == next_hop_add);
340 [ - + ]: 1 : TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
341 [ - + ]: 1 : TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
342 [ - + ]: 1 : TEST_LPM_ASSERT(hop[3] == next_hop_add);
343 : :
344 : 1 : status = rte_lpm_delete(lpm, ip, depth);
345 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
346 : :
347 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
348 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
349 : :
350 : 1 : rte_lpm_free(lpm);
351 : :
352 : 1 : return PASS;
353 : : }
354 : :
355 : : /*
356 : : * Use rte_lpm_add to add rules which effect only the second half of the lpm
357 : : * table. Use all possible depths ranging from 1..32. Set the next hop = to the
358 : : * depth. Check lookup hit for on every add and check for lookup miss on the
359 : : * first half of the lpm table after each add. Finally delete all rules going
360 : : * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
361 : : * delete. The lookup should return the next_hop_add value related to the
362 : : * previous depth value (i.e. depth -1).
363 : : */
364 : : int32_t
365 : 1 : test8(void)
366 : : {
367 : : xmm_t ipx4;
368 : : uint32_t hop[4];
369 : : struct rte_lpm *lpm = NULL;
370 : : struct rte_lpm_config config;
371 : :
372 : 1 : config.max_rules = MAX_RULES;
373 : 1 : config.number_tbl8s = NUMBER_TBL8S;
374 : 1 : config.flags = 0;
375 : : uint32_t ip1 = RTE_IPV4(127, 255, 255, 255), ip2 = RTE_IPV4(128, 0, 0, 0);
376 : : uint32_t next_hop_add, next_hop_return;
377 : : uint8_t depth;
378 : : int32_t status = 0;
379 : :
380 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
381 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
382 : :
383 : : /* Loop with rte_lpm_add. */
384 [ + + ]: 33 : for (depth = 1; depth <= 32; depth++) {
385 : : /* Let the next_hop_add value = depth. Just for change. */
386 : 32 : next_hop_add = depth;
387 : :
388 : 32 : status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
389 [ - + ]: 32 : TEST_LPM_ASSERT(status == 0);
390 : :
391 : : /* Check IP in first half of tbl24 which should be empty. */
392 : : status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
393 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
394 : :
395 : : status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
396 [ - + ]: 32 : TEST_LPM_ASSERT((status == 0) &&
397 : : (next_hop_return == next_hop_add));
398 : :
399 : : ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
400 : 32 : rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
401 [ - + ]: 32 : TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
402 [ - + ]: 32 : TEST_LPM_ASSERT(hop[1] == next_hop_add);
403 [ - + ]: 32 : TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
404 [ - + ]: 32 : TEST_LPM_ASSERT(hop[3] == next_hop_add);
405 : : }
406 : :
407 : : /* Loop with rte_lpm_delete. */
408 [ + + ]: 33 : for (depth = 32; depth >= 1; depth--) {
409 : 32 : next_hop_add = (uint8_t) (depth - 1);
410 : :
411 : 32 : status = rte_lpm_delete(lpm, ip2, depth);
412 [ - + ]: 32 : TEST_LPM_ASSERT(status == 0);
413 : :
414 : : status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
415 : :
416 [ + + ]: 32 : if (depth != 1) {
417 [ + - - + ]: 31 : TEST_LPM_ASSERT((status == 0) &&
418 : : (next_hop_return == next_hop_add));
419 : : } else {
420 [ - + ]: 1 : TEST_LPM_ASSERT(status == -ENOENT);
421 : : }
422 : :
423 : : status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
424 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
425 : :
426 : : ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
427 : 32 : rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
428 [ + + ]: 32 : if (depth != 1) {
429 [ - + ]: 31 : TEST_LPM_ASSERT(hop[0] == next_hop_add);
430 [ - + ]: 31 : TEST_LPM_ASSERT(hop[1] == next_hop_add);
431 : : } else {
432 [ - + ]: 1 : TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
433 [ - + ]: 1 : TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
434 : : }
435 [ - + ]: 32 : TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
436 [ - + ]: 32 : TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
437 : : }
438 : :
439 : 1 : rte_lpm_free(lpm);
440 : :
441 : 1 : return PASS;
442 : : }
443 : :
444 : : /*
445 : : * - Add & lookup to hit invalid TBL24 entry
446 : : * - Add & lookup to hit valid TBL24 entry not extended
447 : : * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
448 : : * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
449 : : *
450 : : */
451 : : int32_t
452 : 1 : test9(void)
453 : : {
454 : : struct rte_lpm *lpm = NULL;
455 : : struct rte_lpm_config config;
456 : :
457 : 1 : config.max_rules = MAX_RULES;
458 : 1 : config.number_tbl8s = NUMBER_TBL8S;
459 : 1 : config.flags = 0;
460 : : uint32_t ip, ip_1, ip_2;
461 : : uint8_t depth, depth_1, depth_2;
462 : : uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
463 : : int32_t status = 0;
464 : :
465 : : /* Add & lookup to hit invalid TBL24 entry */
466 : : ip = RTE_IPV4(128, 0, 0, 0);
467 : : depth = 24;
468 : : next_hop_add = 100;
469 : :
470 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
471 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
472 : :
473 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
474 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
475 : :
476 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
477 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
478 : :
479 : 1 : status = rte_lpm_delete(lpm, ip, depth);
480 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
481 : :
482 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
483 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
484 : :
485 : 1 : rte_lpm_delete_all(lpm);
486 : :
487 : : /* Add & lookup to hit valid TBL24 entry not extended */
488 : : ip = RTE_IPV4(128, 0, 0, 0);
489 : : depth = 23;
490 : : next_hop_add = 100;
491 : :
492 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
493 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
494 : :
495 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
496 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
497 : :
498 : : depth = 24;
499 : : next_hop_add = 101;
500 : :
501 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
502 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
503 : :
504 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
505 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
506 : :
507 : : depth = 24;
508 : :
509 : 1 : status = rte_lpm_delete(lpm, ip, depth);
510 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
511 : :
512 : : depth = 23;
513 : :
514 : 1 : status = rte_lpm_delete(lpm, ip, depth);
515 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
516 : :
517 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
518 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
519 : :
520 : 1 : rte_lpm_delete_all(lpm);
521 : :
522 : : /* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
523 : : * entry */
524 : : ip = RTE_IPV4(128, 0, 0, 0);
525 : : depth = 32;
526 : : next_hop_add = 100;
527 : :
528 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
529 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
530 : :
531 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
532 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
533 : :
534 : : ip = RTE_IPV4(128, 0, 0, 5);
535 : : depth = 32;
536 : : next_hop_add = 101;
537 : :
538 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
539 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
540 : :
541 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
542 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
543 : :
544 : 1 : status = rte_lpm_delete(lpm, ip, depth);
545 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
546 : :
547 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
548 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
549 : :
550 : : ip = RTE_IPV4(128, 0, 0, 0);
551 : : depth = 32;
552 : : next_hop_add = 100;
553 : :
554 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
555 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
556 : :
557 : 1 : status = rte_lpm_delete(lpm, ip, depth);
558 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
559 : :
560 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
561 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
562 : :
563 : 1 : rte_lpm_delete_all(lpm);
564 : :
565 : : /* Add & lookup to hit valid extended TBL24 entry with valid TBL8
566 : : * entry */
567 : : ip_1 = RTE_IPV4(128, 0, 0, 0);
568 : : depth_1 = 25;
569 : : next_hop_add_1 = 101;
570 : :
571 : : ip_2 = RTE_IPV4(128, 0, 0, 5);
572 : : depth_2 = 32;
573 : : next_hop_add_2 = 102;
574 : :
575 : : next_hop_return = 0;
576 : :
577 : 1 : status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
578 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
579 : :
580 : : status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
581 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
582 : :
583 : 1 : status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
584 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
585 : :
586 : : status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
587 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
588 : :
589 : 1 : status = rte_lpm_delete(lpm, ip_2, depth_2);
590 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
591 : :
592 : : status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
593 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
594 : :
595 : 1 : status = rte_lpm_delete(lpm, ip_1, depth_1);
596 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
597 : :
598 : : status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
599 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
600 : :
601 : 1 : rte_lpm_free(lpm);
602 : :
603 : 1 : return PASS;
604 : : }
605 : :
606 : :
607 : : /*
608 : : * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
609 : : * lookup)
610 : : * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
611 : : * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
612 : : * delete & lookup)
613 : : * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
614 : : * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
615 : : * - Delete a rule that is not present in the TBL24 & lookup
616 : : * - Delete a rule that is not present in the TBL8 & lookup
617 : : *
618 : : */
619 : : int32_t
620 : 1 : test10(void)
621 : : {
622 : :
623 : : struct rte_lpm *lpm = NULL;
624 : : struct rte_lpm_config config;
625 : :
626 : 1 : config.max_rules = MAX_RULES;
627 : 1 : config.number_tbl8s = NUMBER_TBL8S;
628 : 1 : config.flags = 0;
629 : : uint32_t ip, next_hop_add, next_hop_return;
630 : : uint8_t depth;
631 : : int32_t status = 0;
632 : :
633 : : /* Add rule that covers a TBL24 range previously invalid & lookup
634 : : * (& delete & lookup) */
635 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
636 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
637 : :
638 : : ip = RTE_IPV4(128, 0, 0, 0);
639 : : depth = 16;
640 : : next_hop_add = 100;
641 : :
642 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
643 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
644 : :
645 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
646 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
647 : :
648 : 1 : status = rte_lpm_delete(lpm, ip, depth);
649 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
650 : :
651 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
652 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
653 : :
654 : 1 : rte_lpm_delete_all(lpm);
655 : :
656 : : ip = RTE_IPV4(128, 0, 0, 0);
657 : : depth = 25;
658 : : next_hop_add = 100;
659 : :
660 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
661 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
662 : :
663 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
664 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
665 : :
666 : 1 : status = rte_lpm_delete(lpm, ip, depth);
667 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
668 : :
669 : 1 : rte_lpm_delete_all(lpm);
670 : :
671 : : /* Add rule that extends a TBL24 valid entry & lookup for both rules
672 : : * (& delete & lookup) */
673 : :
674 : : ip = RTE_IPV4(128, 0, 0, 0);
675 : : depth = 24;
676 : : next_hop_add = 100;
677 : :
678 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
679 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
680 : :
681 : : ip = RTE_IPV4(128, 0, 0, 10);
682 : : depth = 32;
683 : : next_hop_add = 101;
684 : :
685 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
686 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
687 : :
688 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
689 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
690 : :
691 : : ip = RTE_IPV4(128, 0, 0, 0);
692 : : next_hop_add = 100;
693 : :
694 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
695 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
696 : :
697 : : ip = RTE_IPV4(128, 0, 0, 0);
698 : : depth = 24;
699 : :
700 : 1 : status = rte_lpm_delete(lpm, ip, depth);
701 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
702 : :
703 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
704 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
705 : :
706 : : ip = RTE_IPV4(128, 0, 0, 10);
707 : : depth = 32;
708 : :
709 : 1 : status = rte_lpm_delete(lpm, ip, depth);
710 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
711 : :
712 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
713 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
714 : :
715 : 1 : rte_lpm_delete_all(lpm);
716 : :
717 : : /* Add rule that updates the next hop in TBL24 & lookup
718 : : * (& delete & lookup) */
719 : :
720 : : ip = RTE_IPV4(128, 0, 0, 0);
721 : : depth = 24;
722 : : next_hop_add = 100;
723 : :
724 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
725 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
726 : :
727 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
728 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
729 : :
730 : : next_hop_add = 101;
731 : :
732 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
733 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
734 : :
735 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
736 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
737 : :
738 : 1 : status = rte_lpm_delete(lpm, ip, depth);
739 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
740 : :
741 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
742 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
743 : :
744 : 1 : rte_lpm_delete_all(lpm);
745 : :
746 : : /* Add rule that updates the next hop in TBL8 & lookup
747 : : * (& delete & lookup) */
748 : :
749 : : ip = RTE_IPV4(128, 0, 0, 0);
750 : : depth = 32;
751 : : next_hop_add = 100;
752 : :
753 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
754 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
755 : :
756 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
757 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
758 : :
759 : : next_hop_add = 101;
760 : :
761 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
762 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
763 : :
764 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
765 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
766 : :
767 : 1 : status = rte_lpm_delete(lpm, ip, depth);
768 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
769 : :
770 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
771 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
772 : :
773 : 1 : rte_lpm_delete_all(lpm);
774 : :
775 : : /* Delete a rule that is not present in the TBL24 & lookup */
776 : :
777 : : ip = RTE_IPV4(128, 0, 0, 0);
778 : : depth = 24;
779 : :
780 : 1 : status = rte_lpm_delete(lpm, ip, depth);
781 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
782 : :
783 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
784 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
785 : :
786 : 1 : rte_lpm_delete_all(lpm);
787 : :
788 : : /* Delete a rule that is not present in the TBL8 & lookup */
789 : :
790 : : ip = RTE_IPV4(128, 0, 0, 0);
791 : : depth = 32;
792 : :
793 : 1 : status = rte_lpm_delete(lpm, ip, depth);
794 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
795 : :
796 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
797 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
798 : :
799 : 1 : rte_lpm_free(lpm);
800 : :
801 : 1 : return PASS;
802 : : }
803 : :
804 : : /*
805 : : * Add two rules, lookup to hit the more specific one, lookup to hit the less
806 : : * specific one delete the less specific rule and lookup previous values again;
807 : : * add a more specific rule than the existing rule, lookup again
808 : : *
809 : : * */
810 : : int32_t
811 : 1 : test11(void)
812 : : {
813 : :
814 : : struct rte_lpm *lpm = NULL;
815 : : struct rte_lpm_config config;
816 : :
817 : 1 : config.max_rules = MAX_RULES;
818 : 1 : config.number_tbl8s = NUMBER_TBL8S;
819 : 1 : config.flags = 0;
820 : : uint32_t ip, next_hop_add, next_hop_return;
821 : : uint8_t depth;
822 : : int32_t status = 0;
823 : :
824 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
825 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
826 : :
827 : : ip = RTE_IPV4(128, 0, 0, 0);
828 : : depth = 24;
829 : : next_hop_add = 100;
830 : :
831 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
832 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
833 : :
834 : : ip = RTE_IPV4(128, 0, 0, 10);
835 : : depth = 32;
836 : : next_hop_add = 101;
837 : :
838 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
839 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
840 : :
841 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
842 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
843 : :
844 : : ip = RTE_IPV4(128, 0, 0, 0);
845 : : next_hop_add = 100;
846 : :
847 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
848 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
849 : :
850 : : ip = RTE_IPV4(128, 0, 0, 0);
851 : : depth = 24;
852 : :
853 : 1 : status = rte_lpm_delete(lpm, ip, depth);
854 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
855 : :
856 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
857 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
858 : :
859 : : ip = RTE_IPV4(128, 0, 0, 10);
860 : : depth = 32;
861 : :
862 : 1 : status = rte_lpm_delete(lpm, ip, depth);
863 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
864 : :
865 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
866 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
867 : :
868 : 1 : rte_lpm_free(lpm);
869 : :
870 : 1 : return PASS;
871 : : }
872 : :
873 : : /*
874 : : * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
875 : : * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
876 : : * and contraction.
877 : : *
878 : : * */
879 : :
880 : : int32_t
881 : 1 : test12(void)
882 : : {
883 : : xmm_t ipx4;
884 : : uint32_t hop[4];
885 : : struct rte_lpm *lpm = NULL;
886 : : struct rte_lpm_config config;
887 : :
888 : 1 : config.max_rules = MAX_RULES;
889 : 1 : config.number_tbl8s = NUMBER_TBL8S;
890 : 1 : config.flags = 0;
891 : : uint32_t ip, i, next_hop_add, next_hop_return;
892 : : uint8_t depth;
893 : : int32_t status = 0;
894 : :
895 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
896 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
897 : :
898 : : ip = RTE_IPV4(128, 0, 0, 0);
899 : : depth = 32;
900 : : next_hop_add = 100;
901 : :
902 [ + + ]: 1001 : for (i = 0; i < 1000; i++) {
903 : 1000 : status = rte_lpm_add(lpm, ip, depth, next_hop_add);
904 [ - + ]: 1000 : TEST_LPM_ASSERT(status == 0);
905 : :
906 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
907 [ - + ]: 1000 : TEST_LPM_ASSERT((status == 0) &&
908 : : (next_hop_return == next_hop_add));
909 : :
910 : : ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
911 : 1000 : rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
912 [ - + ]: 1000 : TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
913 [ - + ]: 1000 : TEST_LPM_ASSERT(hop[1] == next_hop_add);
914 [ - + ]: 1000 : TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
915 [ - + ]: 1000 : TEST_LPM_ASSERT(hop[3] == next_hop_add);
916 : :
917 : 1000 : status = rte_lpm_delete(lpm, ip, depth);
918 [ - + ]: 1000 : TEST_LPM_ASSERT(status == 0);
919 : :
920 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
921 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
922 : : }
923 : :
924 : 1 : rte_lpm_free(lpm);
925 : :
926 : 1 : return PASS;
927 : : }
928 : :
929 : : /*
930 : : * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
931 : : * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
932 : : * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
933 : : * extension and contraction.
934 : : *
935 : : * */
936 : :
937 : : int32_t
938 : 1 : test13(void)
939 : : {
940 : : struct rte_lpm *lpm = NULL;
941 : : struct rte_lpm_config config;
942 : :
943 : 1 : config.max_rules = MAX_RULES;
944 : 1 : config.number_tbl8s = NUMBER_TBL8S;
945 : 1 : config.flags = 0;
946 : : uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
947 : : uint8_t depth;
948 : : int32_t status = 0;
949 : :
950 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
951 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
952 : :
953 : : ip = RTE_IPV4(128, 0, 0, 0);
954 : : depth = 24;
955 : : next_hop_add_1 = 100;
956 : :
957 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
958 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
959 : :
960 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
961 [ - + ]: 1 : TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
962 : :
963 : : depth = 32;
964 : : next_hop_add_2 = 101;
965 : :
966 [ + + ]: 1001 : for (i = 0; i < 1000; i++) {
967 : 1000 : status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
968 [ - + ]: 1000 : TEST_LPM_ASSERT(status == 0);
969 : :
970 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
971 [ - + ]: 1000 : TEST_LPM_ASSERT((status == 0) &&
972 : : (next_hop_return == next_hop_add_2));
973 : :
974 : 1000 : status = rte_lpm_delete(lpm, ip, depth);
975 [ - + ]: 1000 : TEST_LPM_ASSERT(status == 0);
976 : :
977 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
978 [ - + ]: 1000 : TEST_LPM_ASSERT((status == 0) &&
979 : : (next_hop_return == next_hop_add_1));
980 : : }
981 : :
982 : : depth = 24;
983 : :
984 : 1 : status = rte_lpm_delete(lpm, ip, depth);
985 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
986 : :
987 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
988 : 0 : TEST_LPM_ASSERT(status == -ENOENT);
989 : :
990 : 1 : rte_lpm_free(lpm);
991 : :
992 : 1 : return PASS;
993 : : }
994 : :
995 : : /*
996 : : * For TBL8 extension exhaustion. Add 512 rules that require a tbl8 extension.
997 : : * No more tbl8 extensions will be allowed. Now add one more rule that required
998 : : * a tbl8 extension and get fail.
999 : : * */
1000 : : int32_t
1001 : 1 : test14(void)
1002 : : {
1003 : :
1004 : : /* We only use depth = 32 in the loop below so we must make sure
1005 : : * that we have enough storage for all rules at that depth*/
1006 : :
1007 : : struct rte_lpm *lpm = NULL;
1008 : : struct rte_lpm_config config;
1009 : :
1010 : 1 : config.max_rules = 256 * 32;
1011 : 1 : config.number_tbl8s = 512;
1012 : 1 : config.flags = 0;
1013 : : uint32_t ip, next_hop_base, next_hop_return;
1014 : : uint8_t depth;
1015 : : int32_t status = 0;
1016 : : xmm_t ipx4;
1017 : : uint32_t hop[4];
1018 : :
1019 : : /* Add enough space for 256 rules for every depth */
1020 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1021 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1022 : :
1023 : : depth = 32;
1024 : : next_hop_base = 100;
1025 : : ip = RTE_IPV4(0, 0, 0, 0);
1026 : :
1027 : : /* Add 256 rules that require a tbl8 extension */
1028 [ + + ]: 513 : for (; ip <= RTE_IPV4(0, 1, 255, 0); ip += 256) {
1029 : 512 : status = rte_lpm_add(lpm, ip, depth, next_hop_base + ip);
1030 [ - + ]: 512 : TEST_LPM_ASSERT(status == 0);
1031 : :
1032 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1033 [ - + ]: 512 : TEST_LPM_ASSERT((status == 0) &&
1034 : : (next_hop_return == next_hop_base + ip));
1035 : :
1036 : 512 : ipx4 = vect_set_epi32(ip + 3, ip + 2, ip + 1, ip);
1037 : 512 : rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
1038 [ - + ]: 512 : TEST_LPM_ASSERT(hop[0] == next_hop_base + ip);
1039 [ - + ]: 512 : TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
1040 [ - + ]: 512 : TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
1041 [ - + ]: 512 : TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
1042 : : }
1043 : :
1044 : : /* All tbl8 extensions have been used above. Try to add one more and
1045 : : * we get a fail */
1046 : : ip = RTE_IPV4(1, 0, 0, 0);
1047 : : depth = 32;
1048 : :
1049 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop_base + ip);
1050 [ - + ]: 1 : TEST_LPM_ASSERT(status < 0);
1051 : :
1052 : 1 : rte_lpm_free(lpm);
1053 : :
1054 : 1 : return PASS;
1055 : : }
1056 : :
1057 : : /*
1058 : : * Sequence of operations for find existing lpm table
1059 : : *
1060 : : * - create table
1061 : : * - find existing table: hit
1062 : : * - find non-existing table: miss
1063 : : *
1064 : : */
1065 : : int32_t
1066 : 1 : test15(void)
1067 : : {
1068 : : struct rte_lpm *lpm = NULL, *result = NULL;
1069 : : struct rte_lpm_config config;
1070 : :
1071 : 1 : config.max_rules = 256 * 32;
1072 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1073 : 1 : config.flags = 0;
1074 : :
1075 : : /* Create lpm */
1076 : 1 : lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
1077 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1078 : :
1079 : : /* Try to find existing lpm */
1080 : 1 : result = rte_lpm_find_existing("lpm_find_existing");
1081 [ - + ]: 1 : TEST_LPM_ASSERT(result == lpm);
1082 : :
1083 : : /* Try to find non-existing lpm */
1084 : 1 : result = rte_lpm_find_existing("lpm_find_non_existing");
1085 [ - + ]: 1 : TEST_LPM_ASSERT(result == NULL);
1086 : :
1087 : : /* Cleanup. */
1088 : 1 : rte_lpm_delete_all(lpm);
1089 : 1 : rte_lpm_free(lpm);
1090 : :
1091 : 1 : return PASS;
1092 : : }
1093 : :
1094 : : /*
1095 : : * test failure condition of overloading the tbl8 so no more will fit
1096 : : * Check we get an error return value in that case
1097 : : */
1098 : : int32_t
1099 : 1 : test16(void)
1100 : : {
1101 : : uint32_t ip;
1102 : : struct rte_lpm_config config;
1103 : :
1104 : 1 : config.max_rules = 256 * 32;
1105 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1106 : 1 : config.flags = 0;
1107 : 1 : struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1108 : :
1109 : : /* ip loops through all possibilities for top 24 bits of address */
1110 [ + - ]: 257 : for (ip = 0; ip < 0xFFFFFF; ip++) {
1111 : : /* add an entry within a different tbl8 each time, since
1112 : : * depth >24 and the top 24 bits are different */
1113 [ + + ]: 257 : if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
1114 : : break;
1115 : : }
1116 : :
1117 [ - + ]: 1 : if (ip != NUMBER_TBL8S) {
1118 : : printf("Error, unexpected failure with filling tbl8 groups\n");
1119 : : printf("Failed after %u additions, expected after %u\n",
1120 : : (unsigned)ip, (unsigned)NUMBER_TBL8S);
1121 : : }
1122 : :
1123 : 1 : rte_lpm_free(lpm);
1124 : 1 : return 0;
1125 : : }
1126 : :
1127 : : /*
1128 : : * Test for overwriting of tbl8:
1129 : : * - add rule /32 and lookup
1130 : : * - add new rule /24 and lookup
1131 : : * - add third rule /25 and lookup
1132 : : * - lookup /32 and /24 rule to ensure the table has not been overwritten.
1133 : : */
1134 : : int32_t
1135 : 1 : test17(void)
1136 : : {
1137 : : struct rte_lpm *lpm = NULL;
1138 : : struct rte_lpm_config config;
1139 : :
1140 : 1 : config.max_rules = MAX_RULES;
1141 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1142 : 1 : config.flags = 0;
1143 : : const uint32_t ip_10_32 = RTE_IPV4(10, 10, 10, 2);
1144 : : const uint32_t ip_10_24 = RTE_IPV4(10, 10, 10, 0);
1145 : : const uint32_t ip_20_25 = RTE_IPV4(10, 10, 20, 2);
1146 : : const uint8_t d_ip_10_32 = 32,
1147 : : d_ip_10_24 = 24,
1148 : : d_ip_20_25 = 25;
1149 : : const uint32_t next_hop_ip_10_32 = 100,
1150 : : next_hop_ip_10_24 = 105,
1151 : : next_hop_ip_20_25 = 111;
1152 : : uint32_t next_hop_return = 0;
1153 : : int32_t status = 0;
1154 : :
1155 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1156 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1157 : :
1158 [ + - ]: 1 : if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
1159 : : next_hop_ip_10_32)) < 0)
1160 : : return -1;
1161 : :
1162 : : status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1163 : : uint32_t test_hop_10_32 = next_hop_return;
1164 : 0 : TEST_LPM_ASSERT(status == 0);
1165 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1166 : :
1167 [ + - ]: 1 : if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
1168 : : next_hop_ip_10_24)) < 0)
1169 : : return -1;
1170 : :
1171 : : status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1172 : : uint32_t test_hop_10_24 = next_hop_return;
1173 : 0 : TEST_LPM_ASSERT(status == 0);
1174 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1175 : :
1176 [ + - ]: 1 : if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
1177 : : next_hop_ip_20_25)) < 0)
1178 : : return -1;
1179 : :
1180 : : status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
1181 : : uint32_t test_hop_20_25 = next_hop_return;
1182 : 0 : TEST_LPM_ASSERT(status == 0);
1183 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
1184 : :
1185 : : if (test_hop_10_32 == test_hop_10_24) {
1186 : : printf("Next hop return equal\n");
1187 : : return -1;
1188 : : }
1189 : :
1190 : : if (test_hop_10_24 == test_hop_20_25) {
1191 : : printf("Next hop return equal\n");
1192 : : return -1;
1193 : : }
1194 : :
1195 : : status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
1196 : 0 : TEST_LPM_ASSERT(status == 0);
1197 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
1198 : :
1199 : : status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
1200 : 0 : TEST_LPM_ASSERT(status == 0);
1201 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
1202 : :
1203 : 1 : rte_lpm_free(lpm);
1204 : :
1205 : 1 : return PASS;
1206 : : }
1207 : :
1208 : : /*
1209 : : * Test for recycle of tbl8
1210 : : * - step 1: add a rule with depth=28 (> 24)
1211 : : * - step 2: add a rule with same 24-bit prefix and depth=23 (< 24)
1212 : : * - step 3: delete the first rule
1213 : : * - step 4: check tbl8 is freed
1214 : : * - step 5: add a rule same as the first one (depth=28)
1215 : : * - step 6: check same tbl8 is allocated
1216 : : * - step 7: add a rule with same 24-bit prefix and depth=24
1217 : : * - step 8: delete the rule (depth=28) added in step 5
1218 : : * - step 9: check tbl8 is freed
1219 : : * - step 10: add a rule with same 24-bit prefix and depth = 28
1220 : : * - setp 11: check same tbl8 is allocated again
1221 : : */
1222 : : int32_t
1223 : 1 : test18(void)
1224 : : {
1225 : : #define group_idx next_hop
1226 : : struct rte_lpm *lpm = NULL;
1227 : : struct rte_lpm_config config;
1228 : : uint32_t ip, next_hop;
1229 : : uint8_t depth;
1230 : : uint32_t tbl8_group_index;
1231 : :
1232 : 1 : config.max_rules = MAX_RULES;
1233 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1234 : 1 : config.flags = 0;
1235 : :
1236 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1237 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1238 : :
1239 : : ip = RTE_IPV4(192, 168, 100, 100);
1240 : : depth = 28;
1241 : : next_hop = 1;
1242 : 1 : rte_lpm_add(lpm, ip, depth, next_hop);
1243 : :
1244 [ - + ]: 1 : TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1245 : 1 : tbl8_group_index = lpm->tbl24[ip>>8].group_idx;
1246 : :
1247 : : depth = 23;
1248 : : next_hop = 2;
1249 : 1 : rte_lpm_add(lpm, ip, depth, next_hop);
1250 [ - + ]: 1 : TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1251 : :
1252 : : depth = 28;
1253 : 1 : rte_lpm_delete(lpm, ip, depth);
1254 : :
1255 [ - + ]: 1 : TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
1256 : :
1257 : : next_hop = 3;
1258 : 1 : rte_lpm_add(lpm, ip, depth, next_hop);
1259 : :
1260 [ - + ]: 1 : TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1261 [ - + ]: 1 : TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
1262 : :
1263 : : depth = 24;
1264 : : next_hop = 4;
1265 : 1 : rte_lpm_add(lpm, ip, depth, next_hop);
1266 [ - + ]: 1 : TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1267 : :
1268 : : depth = 28;
1269 : 1 : rte_lpm_delete(lpm, ip, depth);
1270 : :
1271 [ - + ]: 1 : TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
1272 : :
1273 : : next_hop = 5;
1274 : 1 : rte_lpm_add(lpm, ip, depth, next_hop);
1275 : :
1276 [ - + ]: 1 : TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1277 [ - + ]: 1 : TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
1278 : :
1279 : 1 : rte_lpm_free(lpm);
1280 : : #undef group_idx
1281 : 1 : return PASS;
1282 : : }
1283 : :
1284 : : /*
1285 : : * rte_lpm_rcu_qsbr_add positive and negative tests.
1286 : : * - Add RCU QSBR variable to LPM
1287 : : * - Add another RCU QSBR variable to LPM
1288 : : * - Check returns
1289 : : */
1290 : : int32_t
1291 : 1 : test19(void)
1292 : : {
1293 : : struct rte_lpm *lpm = NULL;
1294 : : struct rte_lpm_config config;
1295 : : size_t sz;
1296 : : struct rte_rcu_qsbr *qsv;
1297 : : struct rte_rcu_qsbr *qsv2;
1298 : : int32_t status;
1299 : 1 : struct rte_lpm_rcu_config rcu_cfg = {0};
1300 : :
1301 : 1 : config.max_rules = MAX_RULES;
1302 : 1 : config.number_tbl8s = NUMBER_TBL8S;
1303 : 1 : config.flags = 0;
1304 : :
1305 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1306 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1307 : :
1308 : : /* Create RCU QSBR variable */
1309 : 1 : sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
1310 : 1 : qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1311 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1312 [ - + ]: 1 : TEST_LPM_ASSERT(qsv != NULL);
1313 : :
1314 : 1 : status = rte_rcu_qsbr_init(qsv, RTE_MAX_LCORE);
1315 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1316 : :
1317 : 1 : rcu_cfg.v = qsv;
1318 : : /* Invalid QSBR mode */
1319 : 1 : rcu_cfg.mode = 2;
1320 : 1 : status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1321 [ - + ]: 1 : TEST_LPM_ASSERT(status != 0);
1322 : :
1323 : 1 : rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
1324 : : /* Attach RCU QSBR to LPM table */
1325 : 1 : status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1326 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1327 : :
1328 : : /* Create and attach another RCU QSBR to LPM table */
1329 : 1 : qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1330 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1331 [ - + ]: 1 : TEST_LPM_ASSERT(qsv2 != NULL);
1332 : :
1333 : 1 : rcu_cfg.v = qsv2;
1334 : 1 : rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
1335 : 1 : status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1336 [ - + ]: 1 : TEST_LPM_ASSERT(status != 0);
1337 : :
1338 : 1 : rte_lpm_free(lpm);
1339 : 1 : rte_free(qsv);
1340 : 1 : rte_free(qsv2);
1341 : :
1342 : 1 : return PASS;
1343 : : }
1344 : :
1345 : : /*
1346 : : * rte_lpm_rcu_qsbr_add DQ mode functional test.
1347 : : * Reader and writer are in the same thread in this test.
1348 : : * - Create LPM which supports 1 tbl8 group at max
1349 : : * - Add RCU QSBR variable to LPM
1350 : : * - Add a rule with depth=28 (> 24)
1351 : : * - Register a reader thread (not a real thread)
1352 : : * - Reader lookup existing rule
1353 : : * - Writer delete the rule
1354 : : * - Reader lookup the rule
1355 : : * - Writer re-add the rule (no available tbl8 group)
1356 : : * - Reader report quiescent state and unregister
1357 : : * - Writer re-add the rule
1358 : : * - Reader lookup the rule
1359 : : */
1360 : : int32_t
1361 : 1 : test20(void)
1362 : : {
1363 : : struct rte_lpm *lpm = NULL;
1364 : : struct rte_lpm_config config;
1365 : : size_t sz;
1366 : : struct rte_rcu_qsbr *qsv;
1367 : : int32_t status;
1368 : : uint32_t ip, next_hop, next_hop_return;
1369 : : uint8_t depth;
1370 : 1 : struct rte_lpm_rcu_config rcu_cfg = {0};
1371 : :
1372 : 1 : config.max_rules = MAX_RULES;
1373 : 1 : config.number_tbl8s = 1;
1374 : 1 : config.flags = 0;
1375 : :
1376 : 1 : lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1377 [ - + ]: 1 : TEST_LPM_ASSERT(lpm != NULL);
1378 : :
1379 : : /* Create RCU QSBR variable */
1380 : 1 : sz = rte_rcu_qsbr_get_memsize(1);
1381 : 1 : qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1382 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1383 [ - + ]: 1 : TEST_LPM_ASSERT(qsv != NULL);
1384 : :
1385 : 1 : status = rte_rcu_qsbr_init(qsv, 1);
1386 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1387 : :
1388 : 1 : rcu_cfg.v = qsv;
1389 : 1 : rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
1390 : : /* Attach RCU QSBR to LPM table */
1391 : 1 : status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1392 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1393 : :
1394 : : ip = RTE_IPV4(192, 0, 2, 100);
1395 : : depth = 28;
1396 : : next_hop = 1;
1397 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop);
1398 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1399 [ - + ]: 1 : TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1400 : :
1401 : : /* Register pseudo reader */
1402 : 1 : status = rte_rcu_qsbr_thread_register(qsv, 0);
1403 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1404 : : rte_rcu_qsbr_thread_online(qsv, 0);
1405 : :
1406 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1407 : 0 : TEST_LPM_ASSERT(status == 0);
1408 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop);
1409 : :
1410 : : /* Writer update */
1411 : 1 : status = rte_lpm_delete(lpm, ip, depth);
1412 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1413 [ - + ]: 1 : TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid);
1414 : :
1415 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1416 : 0 : TEST_LPM_ASSERT(status != 0);
1417 : :
1418 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop);
1419 [ - + ]: 1 : TEST_LPM_ASSERT(status != 0);
1420 : :
1421 : : /* Reader quiescent */
1422 : : rte_rcu_qsbr_quiescent(qsv, 0);
1423 : :
1424 : 1 : status = rte_lpm_add(lpm, ip, depth, next_hop);
1425 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1426 : :
1427 : : rte_rcu_qsbr_thread_offline(qsv, 0);
1428 : 1 : status = rte_rcu_qsbr_thread_unregister(qsv, 0);
1429 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1430 : :
1431 : : status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1432 : 0 : TEST_LPM_ASSERT(status == 0);
1433 [ - + ]: 1 : TEST_LPM_ASSERT(next_hop_return == next_hop);
1434 : :
1435 : 1 : rte_lpm_free(lpm);
1436 : 1 : rte_free(qsv);
1437 : :
1438 : 1 : return PASS;
1439 : : }
1440 : :
1441 : : static struct rte_lpm *g_lpm;
1442 : : static struct rte_rcu_qsbr *g_v;
1443 : : static uint32_t g_ip = RTE_IPV4(192, 0, 2, 100);
1444 : : static volatile uint8_t writer_done;
1445 : : /* Report quiescent state interval every 1024 lookups. Larger critical
1446 : : * sections in reader will result in writer polling multiple times.
1447 : : */
1448 : : #define QSBR_REPORTING_INTERVAL 1024
1449 : : #define WRITER_ITERATIONS 512
1450 : :
1451 : : /*
1452 : : * Reader thread using rte_lpm data structure with RCU.
1453 : : */
1454 : : static int
1455 : 1 : test_lpm_rcu_qsbr_reader(void *arg)
1456 : : {
1457 : : int i;
1458 : : uint32_t next_hop_return = 0;
1459 : :
1460 : : RTE_SET_USED(arg);
1461 : : /* Register this thread to report quiescent state */
1462 : 1 : rte_rcu_qsbr_thread_register(g_v, 0);
1463 : 1 : rte_rcu_qsbr_thread_online(g_v, 0);
1464 : :
1465 : : do {
1466 : : for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
1467 : : rte_lpm_lookup(g_lpm, g_ip, &next_hop_return);
1468 : :
1469 : : /* Update quiescent state */
1470 [ + + ]: 190673 : rte_rcu_qsbr_quiescent(g_v, 0);
1471 [ + + ]: 190673 : } while (!writer_done);
1472 : :
1473 : 1 : rte_rcu_qsbr_thread_offline(g_v, 0);
1474 : 1 : rte_rcu_qsbr_thread_unregister(g_v, 0);
1475 : :
1476 : 1 : return 0;
1477 : : }
1478 : :
1479 : : /*
1480 : : * rte_lpm_rcu_qsbr_add sync mode functional test.
1481 : : * 1 Reader and 1 writer. They cannot be in the same thread in this test.
1482 : : * - Create LPM which supports 1 tbl8 group at max
1483 : : * - Add RCU QSBR variable with sync mode to LPM
1484 : : * - Register a reader thread. Reader keeps looking up a specific rule.
1485 : : * - Writer keeps adding and deleting a specific rule with depth=28 (> 24)
1486 : : */
1487 : : int32_t
1488 : 1 : test21(void)
1489 : : {
1490 : : struct rte_lpm_config config;
1491 : : size_t sz;
1492 : : int32_t status;
1493 : : uint32_t i, next_hop;
1494 : : uint8_t depth;
1495 : 1 : struct rte_lpm_rcu_config rcu_cfg = {0};
1496 : :
1497 [ - + ]: 1 : if (rte_lcore_count() < 2) {
1498 : : printf("Not enough cores for %s, expecting at least 2\n",
1499 : : __func__);
1500 : 0 : return TEST_SKIPPED;
1501 : : }
1502 : :
1503 : 1 : config.max_rules = MAX_RULES;
1504 : 1 : config.number_tbl8s = 1;
1505 : 1 : config.flags = 0;
1506 : :
1507 : 1 : g_lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1508 [ - + ]: 1 : TEST_LPM_ASSERT(g_lpm != NULL);
1509 : :
1510 : : /* Create RCU QSBR variable */
1511 : 1 : sz = rte_rcu_qsbr_get_memsize(1);
1512 : 1 : g_v = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1513 : : RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1514 [ - + ]: 1 : TEST_LPM_ASSERT(g_v != NULL);
1515 : :
1516 : 1 : status = rte_rcu_qsbr_init(g_v, 1);
1517 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1518 : :
1519 : 1 : rcu_cfg.v = g_v;
1520 : 1 : rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
1521 : : /* Attach RCU QSBR to LPM table */
1522 : 1 : status = rte_lpm_rcu_qsbr_add(g_lpm, &rcu_cfg);
1523 [ - + ]: 1 : TEST_LPM_ASSERT(status == 0);
1524 : :
1525 : 1 : writer_done = 0;
1526 : : /* Launch reader thread */
1527 : 1 : rte_eal_remote_launch(test_lpm_rcu_qsbr_reader, NULL,
1528 : : rte_get_next_lcore(-1, 1, 0));
1529 : :
1530 : : depth = 28;
1531 : : next_hop = 1;
1532 : 1 : status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
1533 [ - + ]: 1 : if (status != 0) {
1534 : : printf("%s: Failed to add rule\n", __func__);
1535 : 0 : goto error;
1536 : : }
1537 : :
1538 : : /* Writer update */
1539 [ + + ]: 513 : for (i = 0; i < WRITER_ITERATIONS; i++) {
1540 : 512 : status = rte_lpm_delete(g_lpm, g_ip, depth);
1541 [ - + ]: 512 : if (status != 0) {
1542 : : printf("%s: Failed to delete rule at iteration %d\n",
1543 : : __func__, i);
1544 : 0 : goto error;
1545 : : }
1546 : :
1547 : 512 : status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
1548 [ - + ]: 512 : if (status != 0) {
1549 : : printf("%s: Failed to add rule at iteration %d\n",
1550 : : __func__, i);
1551 : 0 : goto error;
1552 : : }
1553 : : }
1554 : :
1555 : 1 : error:
1556 : 1 : writer_done = 1;
1557 : : /* Wait until reader exited. */
1558 : 1 : rte_eal_mp_wait_lcore();
1559 : :
1560 : 1 : rte_lpm_free(g_lpm);
1561 : 1 : rte_free(g_v);
1562 : :
1563 [ - + ]: 1 : return (status == 0) ? PASS : -1;
1564 : : }
1565 : :
1566 : : /*
1567 : : * Do all unit tests.
1568 : : */
1569 : :
1570 : : static int
1571 : 1 : test_lpm(void)
1572 : : {
1573 : : unsigned i;
1574 : : int status, global_status = 0;
1575 : :
1576 [ + + ]: 23 : for (i = 0; i < RTE_DIM(tests); i++) {
1577 : 22 : status = tests[i]();
1578 [ - + ]: 22 : if (status < 0) {
1579 : : printf("ERROR: LPM Test %u: FAIL\n", i);
1580 : : global_status = status;
1581 : : }
1582 : : }
1583 : :
1584 : 1 : return global_status;
1585 : : }
1586 : :
1587 : 251 : REGISTER_FAST_TEST(lpm_autotest, true, true, test_lpm);
|