Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
3 : : * Copyright(c) 2019 Intel Corporation
4 : : */
5 : :
6 : : #include <stdio.h>
7 : : #include <stdint.h>
8 : : #include <stdlib.h>
9 : :
10 : : #include <rte_memory.h>
11 : : #include <rte_log.h>
12 : : #include <rte_rib6.h>
13 : : #include <rte_fib6.h>
14 : :
15 : : #include "test.h"
16 : :
17 : : typedef int32_t (*rte_fib6_test)(void);
18 : :
19 : : static int32_t test_create_invalid(void);
20 : : static int32_t test_multiple_create(void);
21 : : static int32_t test_free_null(void);
22 : : static int32_t test_add_del_invalid(void);
23 : : static int32_t test_get_invalid(void);
24 : : static int32_t test_lookup(void);
25 : :
26 : : #define MAX_ROUTES (1 << 16)
27 : : /** Maximum number of tbl8 for 2-byte entries */
28 : : #define MAX_TBL8 (1 << 15)
29 : :
30 : : /*
31 : : * Check that rte_fib6_create fails gracefully for incorrect user input
32 : : * arguments
33 : : */
34 : : int32_t
35 : 1 : test_create_invalid(void)
36 : : {
37 : : struct rte_fib6 *fib = NULL;
38 : : struct rte_fib6_conf config;
39 : :
40 : 1 : config.max_routes = MAX_ROUTES;
41 : 1 : config.rib_ext_sz = 0;
42 : 1 : config.default_nh = 0;
43 : 1 : config.type = RTE_FIB6_DUMMY;
44 : :
45 : : /* rte_fib6_create: fib name == NULL */
46 : 1 : fib = rte_fib6_create(NULL, SOCKET_ID_ANY, &config);
47 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
48 : : "Call succeeded with invalid parameters\n");
49 : :
50 : : /* rte_fib6_create: config == NULL */
51 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, NULL);
52 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
53 : : "Call succeeded with invalid parameters\n");
54 : :
55 : : /* socket_id < -1 is invalid */
56 : 1 : fib = rte_fib6_create(__func__, -2, &config);
57 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
58 : : "Call succeeded with invalid parameters\n");
59 : :
60 : : /* rte_fib6_create: max_routes = 0 */
61 : 1 : config.max_routes = 0;
62 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
63 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
64 : : "Call succeeded with invalid parameters\n");
65 : 1 : config.max_routes = MAX_ROUTES;
66 : :
67 : 1 : config.type = RTE_FIB6_TRIE + 1;
68 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
69 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
70 : : "Call succeeded with invalid parameters\n");
71 : :
72 : 1 : config.type = RTE_FIB6_TRIE;
73 : 1 : config.trie.num_tbl8 = MAX_TBL8;
74 : :
75 : 1 : config.trie.nh_sz = RTE_FIB6_TRIE_8B + 1;
76 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
77 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
78 : : "Call succeeded with invalid parameters\n");
79 : 1 : config.trie.nh_sz = RTE_FIB6_TRIE_8B;
80 : :
81 : 1 : config.trie.num_tbl8 = 0;
82 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
83 [ - + ]: 1 : RTE_TEST_ASSERT(fib == NULL,
84 : : "Call succeeded with invalid parameters\n");
85 : :
86 : : return TEST_SUCCESS;
87 : : }
88 : :
89 : : /*
90 : : * Create fib table then delete fib table 10 times
91 : : * Use a slightly different rules size each time
92 : : */
93 : : int32_t
94 : 0 : test_multiple_create(void)
95 : : {
96 : : struct rte_fib6 *fib = NULL;
97 : : struct rte_fib6_conf config;
98 : : int32_t i;
99 : :
100 : 0 : config.rib_ext_sz = 0;
101 : 0 : config.default_nh = 0;
102 : 0 : config.type = RTE_FIB6_DUMMY;
103 : :
104 [ # # ]: 0 : for (i = 0; i < 100; i++) {
105 : 0 : config.max_routes = MAX_ROUTES - i;
106 : 0 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
107 [ # # ]: 0 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
108 : 0 : rte_fib6_free(fib);
109 : : }
110 : : /* Can not test free so return success */
111 : : return TEST_SUCCESS;
112 : : }
113 : :
114 : : /*
115 : : * Call rte_fib6_free for NULL pointer user input. Note: free has no return and
116 : : * therefore it is impossible to check for failure but this test is added to
117 : : * increase function coverage metrics and to validate that freeing null does
118 : : * not crash.
119 : : */
120 : : int32_t
121 : 1 : test_free_null(void)
122 : : {
123 : : struct rte_fib6 *fib = NULL;
124 : : struct rte_fib6_conf config;
125 : :
126 : 1 : config.max_routes = MAX_ROUTES;
127 : 1 : config.rib_ext_sz = 0;
128 : 1 : config.default_nh = 0;
129 : 1 : config.type = RTE_FIB6_DUMMY;
130 : :
131 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
132 [ - + ]: 1 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
133 : :
134 : 1 : rte_fib6_free(fib);
135 : 1 : rte_fib6_free(NULL);
136 : :
137 : 1 : return TEST_SUCCESS;
138 : : }
139 : :
140 : : /*
141 : : * Check that rte_fib6_add and rte_fib6_delete fails gracefully
142 : : * for incorrect user input arguments
143 : : */
144 : : int32_t
145 : 1 : test_add_del_invalid(void)
146 : : {
147 : : struct rte_fib6 *fib = NULL;
148 : : struct rte_fib6_conf config;
149 : : uint64_t nh = 100;
150 : 1 : uint8_t ip[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
151 : : int ret;
152 : : uint8_t depth = 24;
153 : :
154 : 1 : config.max_routes = MAX_ROUTES;
155 : 1 : config.rib_ext_sz = 0;
156 : 1 : config.default_nh = 0;
157 : 1 : config.type = RTE_FIB6_DUMMY;
158 : :
159 : : /* rte_fib6_add: fib == NULL */
160 : 1 : ret = rte_fib6_add(NULL, ip, depth, nh);
161 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
162 : : "Call succeeded with invalid parameters\n");
163 : :
164 : : /* rte_fib6_delete: fib == NULL */
165 : 1 : ret = rte_fib6_delete(NULL, ip, depth);
166 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
167 : : "Call succeeded with invalid parameters\n");
168 : :
169 : : /*Create valid fib to use in rest of test. */
170 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
171 [ - + ]: 1 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
172 : :
173 : : /* rte_fib6_add: depth > RTE_FIB6_MAXDEPTH */
174 : 1 : ret = rte_fib6_add(fib, ip, RTE_FIB6_MAXDEPTH + 1, nh);
175 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
176 : : "Call succeeded with invalid parameters\n");
177 : :
178 : : /* rte_fib6_delete: depth > RTE_FIB6_MAXDEPTH */
179 : 1 : ret = rte_fib6_delete(fib, ip, RTE_FIB6_MAXDEPTH + 1);
180 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
181 : : "Call succeeded with invalid parameters\n");
182 : :
183 : 1 : rte_fib6_free(fib);
184 : :
185 : 1 : return TEST_SUCCESS;
186 : : }
187 : :
188 : : /*
189 : : * Check that rte_fib6_get_dp and rte_fib6_get_rib fails gracefully
190 : : * for incorrect user input arguments
191 : : */
192 : : int32_t
193 : 1 : test_get_invalid(void)
194 : : {
195 : : void *p;
196 : :
197 : 1 : p = rte_fib6_get_dp(NULL);
198 [ - + ]: 1 : RTE_TEST_ASSERT(p == NULL,
199 : : "Call succeeded with invalid parameters\n");
200 : :
201 : 1 : p = rte_fib6_get_rib(NULL);
202 [ - + ]: 1 : RTE_TEST_ASSERT(p == NULL,
203 : : "Call succeeded with invalid parameters\n");
204 : :
205 : : return TEST_SUCCESS;
206 : : }
207 : :
208 : : /*
209 : : * Add routes for one supernet with all possible depths and do lookup
210 : : * on each step
211 : : * After delete routes with doing lookup on each step
212 : : */
213 : : static int
214 : 1020 : lookup_and_check_asc(struct rte_fib6 *fib,
215 : : uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE],
216 : : uint8_t ip_missing[][RTE_FIB6_IPV6_ADDR_SIZE], uint64_t def_nh,
217 : : uint32_t n)
218 : : {
219 : : uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
220 : : int ret;
221 : : uint32_t i = 0;
222 : :
223 : 1020 : ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB6_MAXDEPTH);
224 [ - + ]: 1020 : RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
225 : :
226 [ + + ]: 67064 : for (; i <= RTE_FIB6_MAXDEPTH - n; i++)
227 [ - + ]: 66044 : RTE_TEST_ASSERT(nh_arr[i] == n,
228 : : "Failed to get proper nexthop\n");
229 : :
230 [ + + ]: 65536 : for (; i < RTE_FIB6_MAXDEPTH; i++)
231 [ - + ]: 64516 : RTE_TEST_ASSERT(nh_arr[i] == --n,
232 : : "Failed to get proper nexthop\n");
233 : :
234 : 1020 : ret = rte_fib6_lookup_bulk(fib, ip_missing, nh_arr, 1);
235 [ + - - + ]: 1020 : RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
236 : : "Failed to get proper nexthop\n");
237 : :
238 : : return TEST_SUCCESS;
239 : : }
240 : :
241 : : static int
242 : 1032 : lookup_and_check_desc(struct rte_fib6 *fib,
243 : : uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE],
244 : : uint8_t ip_missing[][RTE_FIB6_IPV6_ADDR_SIZE], uint64_t def_nh,
245 : : uint32_t n)
246 : : {
247 : : uint64_t nh_arr[RTE_FIB6_MAXDEPTH];
248 : : int ret;
249 : : uint32_t i = 0;
250 : :
251 : 1032 : ret = rte_fib6_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB6_MAXDEPTH);
252 [ - + ]: 1032 : RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
253 : :
254 [ + + ]: 66568 : for (; i < n; i++)
255 [ - + ]: 65536 : RTE_TEST_ASSERT(nh_arr[i] == RTE_FIB6_MAXDEPTH - i,
256 : : "Failed to get proper nexthop\n");
257 : :
258 [ + + ]: 67592 : for (; i < RTE_FIB6_MAXDEPTH; i++)
259 [ - + ]: 66560 : RTE_TEST_ASSERT(nh_arr[i] == def_nh,
260 : : "Failed to get proper nexthop\n");
261 : :
262 : 1032 : ret = rte_fib6_lookup_bulk(fib, ip_missing, nh_arr, 1);
263 [ + - - + ]: 1032 : RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
264 : : "Failed to get proper nexthop\n");
265 : :
266 : : return TEST_SUCCESS;
267 : : }
268 : :
269 : : static int
270 : 4 : check_fib(struct rte_fib6 *fib)
271 : : {
272 : : uint64_t def_nh = 100;
273 : : uint8_t ip_arr[RTE_FIB6_MAXDEPTH][RTE_FIB6_IPV6_ADDR_SIZE];
274 : 4 : uint8_t ip_add[RTE_FIB6_IPV6_ADDR_SIZE] = {0};
275 : 4 : uint8_t ip_missing[1][RTE_FIB6_IPV6_ADDR_SIZE] = { {255} };
276 : : uint32_t i, j;
277 : : int ret;
278 : :
279 : 4 : ip_add[0] = 128;
280 : 4 : ip_missing[0][0] = 127;
281 [ + + ]: 516 : for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
282 [ + + ]: 8704 : for (j = 0; j < RTE_FIB6_IPV6_ADDR_SIZE; j++) {
283 : 8192 : ip_arr[i][j] = ip_add[j] |
284 : 8192 : ~get_msk_part(RTE_FIB6_MAXDEPTH - i, j);
285 : : }
286 : : }
287 : :
288 : 4 : ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
289 [ - + ]: 4 : RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
290 : :
291 [ + + ]: 516 : for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
292 : 512 : ret = rte_fib6_add(fib, ip_add, i, i);
293 [ - + ]: 512 : RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
294 : 512 : ret = lookup_and_check_asc(fib, ip_arr, ip_missing, def_nh, i);
295 [ - + ]: 512 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
296 : : "Lookup and check fails\n");
297 : : }
298 : :
299 [ + + ]: 512 : for (i = RTE_FIB6_MAXDEPTH; i > 1; i--) {
300 : 508 : ret = rte_fib6_delete(fib, ip_add, i);
301 [ - + ]: 508 : RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
302 : 508 : ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
303 : : def_nh, i - 1);
304 : :
305 [ - + ]: 508 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
306 : : "Lookup and check fails\n");
307 : : }
308 : 4 : ret = rte_fib6_delete(fib, ip_add, i);
309 [ - + ]: 4 : RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
310 : 4 : ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
311 [ - + ]: 4 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
312 : : "Lookup and check fails\n");
313 : :
314 [ + + ]: 516 : for (i = 0; i < RTE_FIB6_MAXDEPTH; i++) {
315 : 512 : ret = rte_fib6_add(fib, ip_add, RTE_FIB6_MAXDEPTH - i,
316 : 512 : RTE_FIB6_MAXDEPTH - i);
317 [ - + ]: 512 : RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
318 : 512 : ret = lookup_and_check_desc(fib, ip_arr, ip_missing,
319 : : def_nh, i + 1);
320 [ - + ]: 512 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
321 : : "Lookup and check fails\n");
322 : : }
323 : :
324 [ + + ]: 516 : for (i = 1; i <= RTE_FIB6_MAXDEPTH; i++) {
325 : 512 : ret = rte_fib6_delete(fib, ip_add, i);
326 [ - + ]: 512 : RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
327 : 512 : ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh,
328 : : RTE_FIB6_MAXDEPTH - i);
329 [ - + ]: 512 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
330 : : "Lookup and check fails\n");
331 : : }
332 : :
333 : : return TEST_SUCCESS;
334 : : }
335 : :
336 : : int32_t
337 : 1 : test_lookup(void)
338 : : {
339 : : struct rte_fib6 *fib = NULL;
340 : : struct rte_fib6_conf config;
341 : : uint64_t def_nh = 100;
342 : : int ret;
343 : :
344 : 1 : config.max_routes = MAX_ROUTES;
345 : 1 : config.rib_ext_sz = 0;
346 : 1 : config.default_nh = def_nh;
347 : 1 : config.type = RTE_FIB6_DUMMY;
348 : :
349 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
350 [ - + ]: 1 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
351 : 1 : ret = check_fib(fib);
352 [ - + ]: 1 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
353 : : "Check_fib fails for DUMMY type\n");
354 : 1 : rte_fib6_free(fib);
355 : :
356 : 1 : config.type = RTE_FIB6_TRIE;
357 : :
358 : 1 : config.trie.nh_sz = RTE_FIB6_TRIE_2B;
359 : 1 : config.trie.num_tbl8 = MAX_TBL8 - 1;
360 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
361 [ - + ]: 1 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
362 : 1 : ret = check_fib(fib);
363 [ - + ]: 1 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
364 : : "Check_fib fails for TRIE_2B type\n");
365 : 1 : rte_fib6_free(fib);
366 : :
367 : 1 : config.trie.nh_sz = RTE_FIB6_TRIE_4B;
368 : 1 : config.trie.num_tbl8 = MAX_TBL8;
369 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
370 [ - + ]: 1 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
371 : 1 : ret = check_fib(fib);
372 [ - + ]: 1 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
373 : : "Check_fib fails for TRIE_4B type\n");
374 : 1 : rte_fib6_free(fib);
375 : :
376 : 1 : config.trie.nh_sz = RTE_FIB6_TRIE_8B;
377 : 1 : config.trie.num_tbl8 = MAX_TBL8;
378 : 1 : fib = rte_fib6_create(__func__, SOCKET_ID_ANY, &config);
379 [ - + ]: 1 : RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
380 : 1 : ret = check_fib(fib);
381 [ - + ]: 1 : RTE_TEST_ASSERT(ret == TEST_SUCCESS,
382 : : "Check_fib fails for TRIE_8B type\n");
383 : 1 : rte_fib6_free(fib);
384 : :
385 : 1 : return TEST_SUCCESS;
386 : : }
387 : :
388 : : static struct unit_test_suite fib6_fast_tests = {
389 : : .suite_name = "fib6 autotest",
390 : : .setup = NULL,
391 : : .teardown = NULL,
392 : : .unit_test_cases = {
393 : : TEST_CASE(test_create_invalid),
394 : : TEST_CASE(test_free_null),
395 : : TEST_CASE(test_add_del_invalid),
396 : : TEST_CASE(test_get_invalid),
397 : : TEST_CASE(test_lookup),
398 : : TEST_CASES_END()
399 : : }
400 : : };
401 : :
402 : : static struct unit_test_suite fib6_slow_tests = {
403 : : .suite_name = "fib6 slow autotest",
404 : : .setup = NULL,
405 : : .teardown = NULL,
406 : : .unit_test_cases = {
407 : : TEST_CASE(test_multiple_create),
408 : : TEST_CASES_END()
409 : : }
410 : : };
411 : :
412 : : /*
413 : : * Do all unit tests.
414 : : */
415 : : static int
416 : 1 : test_fib6(void)
417 : : {
418 : 1 : return unit_test_suite_runner(&fib6_fast_tests);
419 : : }
420 : :
421 : : static int
422 : 0 : test_slow_fib6(void)
423 : : {
424 : 0 : return unit_test_suite_runner(&fib6_slow_tests);
425 : : }
426 : :
427 : 238 : REGISTER_FAST_TEST(fib6_autotest, true, true, test_fib6);
428 : 238 : REGISTER_PERF_TEST(fib6_slow_autotest, test_slow_fib6);
|