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