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 : : #include <rte_ip.h>
10 : : #include <rte_rib6.h>
11 : :
12 : : #include "test.h"
13 : :
14 : : typedef int32_t (*rte_rib6_test)(void);
15 : :
16 : : static int32_t test_create_invalid(void);
17 : : static int32_t test_multiple_create(void);
18 : : static int32_t test_free_null(void);
19 : : static int32_t test_insert_invalid(void);
20 : : static int32_t test_get_fn(void);
21 : : static int32_t test_basic(void);
22 : : static int32_t test_tree_traversal(void);
23 : :
24 : : #define MAX_DEPTH 128
25 : : #define MAX_RULES (1 << 22)
26 : :
27 : : /*
28 : : * Check that rte_rib6_create fails gracefully for incorrect user input
29 : : * arguments
30 : : */
31 : : int32_t
32 : 1 : test_create_invalid(void)
33 : : {
34 : : struct rte_rib6 *rib = NULL;
35 : : struct rte_rib6_conf config;
36 : :
37 : 1 : config.max_nodes = MAX_RULES;
38 : 1 : config.ext_sz = 0;
39 : :
40 : : /* rte_rib6_create: rib name == NULL */
41 : 1 : rib = rte_rib6_create(NULL, SOCKET_ID_ANY, &config);
42 [ - + ]: 1 : RTE_TEST_ASSERT(rib == NULL,
43 : : "Call succeeded with invalid parameters\n");
44 : :
45 : : /* rte_rib6_create: config == NULL */
46 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, NULL);
47 [ - + ]: 1 : RTE_TEST_ASSERT(rib == NULL,
48 : : "Call succeeded with invalid parameters\n");
49 : :
50 : : /* socket_id < -1 is invalid */
51 : 1 : rib = rte_rib6_create(__func__, -2, &config);
52 [ - + ]: 1 : RTE_TEST_ASSERT(rib == NULL,
53 : : "Call succeeded with invalid parameters\n");
54 : :
55 : : /* rte_rib6_create: max_nodes = 0 */
56 : 1 : config.max_nodes = 0;
57 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
58 [ - + ]: 1 : RTE_TEST_ASSERT(rib == NULL,
59 : : "Call succeeded with invalid parameters\n");
60 : : config.max_nodes = MAX_RULES;
61 : :
62 : : return TEST_SUCCESS;
63 : : }
64 : :
65 : : /*
66 : : * Create rib table then delete rib table 10 times
67 : : * Use a slightly different rules size each time
68 : : */
69 : : int32_t
70 : 0 : test_multiple_create(void)
71 : : {
72 : : struct rte_rib6 *rib = NULL;
73 : : struct rte_rib6_conf config;
74 : : int32_t i;
75 : :
76 : 0 : config.ext_sz = 0;
77 : :
78 [ # # ]: 0 : for (i = 0; i < 100; i++) {
79 : 0 : config.max_nodes = MAX_RULES - i;
80 : 0 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
81 [ # # ]: 0 : RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
82 : 0 : rte_rib6_free(rib);
83 : : }
84 : : /* Can not test free so return success */
85 : : return TEST_SUCCESS;
86 : : }
87 : :
88 : : /*
89 : : * Call rte_rib6_free for NULL pointer user input. Note: free has no return and
90 : : * therefore it is impossible to check for failure but this test is added to
91 : : * increase function coverage metrics and to validate that freeing null does
92 : : * not crash.
93 : : */
94 : : int32_t
95 : 1 : test_free_null(void)
96 : : {
97 : : struct rte_rib6 *rib = NULL;
98 : : struct rte_rib6_conf config;
99 : :
100 : 1 : config.max_nodes = MAX_RULES;
101 : 1 : config.ext_sz = 0;
102 : :
103 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
104 [ - + ]: 1 : RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
105 : :
106 : 1 : rte_rib6_free(rib);
107 : 1 : rte_rib6_free(NULL);
108 : 1 : return TEST_SUCCESS;
109 : : }
110 : :
111 : : /*
112 : : * Check that rte_rib6_insert fails gracefully
113 : : * for incorrect user input arguments
114 : : */
115 : : int32_t
116 : 1 : test_insert_invalid(void)
117 : : {
118 : : struct rte_rib6 *rib = NULL;
119 : : struct rte_rib6_node *node, *node1;
120 : : struct rte_rib6_conf config;
121 : 1 : uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {0};
122 : : uint8_t depth = 24;
123 : :
124 : 1 : config.max_nodes = MAX_RULES;
125 : 1 : config.ext_sz = 0;
126 : :
127 : : /* rte_rib6_insert: rib == NULL */
128 : 1 : node = rte_rib6_insert(NULL, ip, depth);
129 [ - + ]: 1 : RTE_TEST_ASSERT(node == NULL,
130 : : "Call succeeded with invalid parameters\n");
131 : :
132 : : /*Create valid rib to use in rest of test. */
133 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
134 [ - + ]: 1 : RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
135 : :
136 : : /* rte_rib6_insert: depth > MAX_DEPTH */
137 : 1 : node = rte_rib6_insert(rib, ip, MAX_DEPTH + 1);
138 [ - + ]: 1 : RTE_TEST_ASSERT(node == NULL,
139 : : "Call succeeded with invalid parameters\n");
140 : :
141 : : /* insert the same ip/depth twice*/
142 : 1 : node = rte_rib6_insert(rib, ip, depth);
143 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
144 : 1 : node1 = rte_rib6_insert(rib, ip, depth);
145 [ - + ]: 1 : RTE_TEST_ASSERT(node1 == NULL,
146 : : "Call succeeded with invalid parameters\n");
147 : :
148 : 1 : rte_rib6_free(rib);
149 : :
150 : 1 : return TEST_SUCCESS;
151 : : }
152 : :
153 : : /*
154 : : * Call rte_rib6_node access functions with incorrect input.
155 : : * After call rte_rib6_node access functions with correct args
156 : : * and check the return values for correctness
157 : : */
158 : : int32_t
159 : 1 : test_get_fn(void)
160 : : {
161 : : struct rte_rib6 *rib = NULL;
162 : : struct rte_rib6_node *node;
163 : : struct rte_rib6_conf config;
164 : : void *ext;
165 : 1 : uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {192, 0, 2, 0, 0, 0, 0, 0,
166 : : 0, 0, 0, 0, 0, 0, 0, 0};
167 : : uint8_t ip_ret[RTE_RIB6_IPV6_ADDR_SIZE];
168 : : uint64_t nh_set = 10;
169 : : uint64_t nh_ret;
170 : : uint8_t depth = 24;
171 : : uint8_t depth_ret;
172 : : int ret;
173 : :
174 : 1 : config.max_nodes = MAX_RULES;
175 : 1 : config.ext_sz = 0;
176 : :
177 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
178 [ - + ]: 1 : RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
179 : :
180 : 1 : node = rte_rib6_insert(rib, ip, depth);
181 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
182 : :
183 : : /* test rte_rib6_get_ip() with incorrect args */
184 : 1 : ret = rte_rib6_get_ip(NULL, ip_ret);
185 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
186 : : "Call succeeded with invalid parameters\n");
187 : 1 : ret = rte_rib6_get_ip(node, NULL);
188 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
189 : : "Call succeeded with invalid parameters\n");
190 : :
191 : : /* test rte_rib6_get_depth() with incorrect args */
192 : 1 : ret = rte_rib6_get_depth(NULL, &depth_ret);
193 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
194 : : "Call succeeded with invalid parameters\n");
195 : 1 : ret = rte_rib6_get_depth(node, NULL);
196 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
197 : : "Call succeeded with invalid parameters\n");
198 : :
199 : : /* test rte_rib6_set_nh() with incorrect args */
200 : 1 : ret = rte_rib6_set_nh(NULL, nh_set);
201 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
202 : : "Call succeeded with invalid parameters\n");
203 : :
204 : : /* test rte_rib6_get_nh() with incorrect args */
205 : 1 : ret = rte_rib6_get_nh(NULL, &nh_ret);
206 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
207 : : "Call succeeded with invalid parameters\n");
208 : 1 : ret = rte_rib6_get_nh(node, NULL);
209 [ - + ]: 1 : RTE_TEST_ASSERT(ret < 0,
210 : : "Call succeeded with invalid parameters\n");
211 : :
212 : : /* test rte_rib6_get_ext() with incorrect args */
213 : 1 : ext = rte_rib6_get_ext(NULL);
214 [ - + ]: 1 : RTE_TEST_ASSERT(ext == NULL,
215 : : "Call succeeded with invalid parameters\n");
216 : :
217 : : /* check the return values */
218 : 1 : ret = rte_rib6_get_ip(node, ip_ret);
219 [ + - - + ]: 2 : RTE_TEST_ASSERT((ret == 0) && (rte_rib6_is_equal(ip_ret, ip)),
220 : : "Failed to get proper node ip\n");
221 : 1 : ret = rte_rib6_get_depth(node, &depth_ret);
222 [ + - - + ]: 1 : RTE_TEST_ASSERT((ret == 0) && (depth_ret == depth),
223 : : "Failed to get proper node depth\n");
224 : 1 : ret = rte_rib6_set_nh(node, nh_set);
225 [ - + ]: 1 : RTE_TEST_ASSERT(ret == 0,
226 : : "Failed to set rte_rib_node nexthop\n");
227 : 1 : ret = rte_rib6_get_nh(node, &nh_ret);
228 [ + - - + ]: 1 : RTE_TEST_ASSERT((ret == 0) && (nh_ret == nh_set),
229 : : "Failed to get proper nexthop\n");
230 : :
231 : 1 : rte_rib6_free(rib);
232 : :
233 : 1 : return TEST_SUCCESS;
234 : : }
235 : :
236 : : /*
237 : : * Call insert, lookup/lookup_exact and delete for a single rule
238 : : */
239 : : int32_t
240 : 1 : test_basic(void)
241 : : {
242 : : struct rte_rib6 *rib = NULL;
243 : : struct rte_rib6_node *node;
244 : : struct rte_rib6_conf config;
245 : :
246 : 1 : uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {192, 0, 2, 0, 0, 0, 0, 0,
247 : : 0, 0, 0, 0, 0, 0, 0, 0};
248 : : uint64_t next_hop_add = 10;
249 : : uint64_t next_hop_return;
250 : : uint8_t depth = 24;
251 : : uint32_t status = 0;
252 : :
253 : 1 : config.max_nodes = MAX_RULES;
254 : 1 : config.ext_sz = 0;
255 : :
256 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
257 [ - + ]: 1 : RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
258 : :
259 : 1 : node = rte_rib6_insert(rib, ip, depth);
260 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
261 : :
262 : 1 : status = rte_rib6_set_nh(node, next_hop_add);
263 [ - + ]: 1 : RTE_TEST_ASSERT(status == 0,
264 : : "Failed to set rte_rib_node field\n");
265 : :
266 : 1 : node = rte_rib6_lookup(rib, ip);
267 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to lookup\n");
268 : :
269 : 1 : status = rte_rib6_get_nh(node, &next_hop_return);
270 [ + - - + ]: 1 : RTE_TEST_ASSERT((status == 0) && (next_hop_add == next_hop_return),
271 : : "Failed to get proper nexthop\n");
272 : :
273 : 1 : node = rte_rib6_lookup_exact(rib, ip, depth);
274 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL,
275 : : "Failed to lookup\n");
276 : :
277 : 1 : status = rte_rib6_get_nh(node, &next_hop_return);
278 [ + - - + ]: 1 : RTE_TEST_ASSERT((status == 0) && (next_hop_add == next_hop_return),
279 : : "Failed to get proper nexthop\n");
280 : :
281 : 1 : rte_rib6_remove(rib, ip, depth);
282 : :
283 : 1 : node = rte_rib6_lookup(rib, ip);
284 [ - + ]: 1 : RTE_TEST_ASSERT(node == NULL,
285 : : "Lookup returns non existent rule\n");
286 : 1 : node = rte_rib6_lookup_exact(rib, ip, depth);
287 [ - + ]: 1 : RTE_TEST_ASSERT(node == NULL,
288 : : "Lookup returns non existent rule\n");
289 : :
290 : 1 : rte_rib6_free(rib);
291 : :
292 : 1 : return TEST_SUCCESS;
293 : : }
294 : :
295 : : int32_t
296 : 1 : test_tree_traversal(void)
297 : : {
298 : : struct rte_rib6 *rib = NULL;
299 : : struct rte_rib6_node *node;
300 : : struct rte_rib6_conf config;
301 : :
302 : 1 : uint8_t ip[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 130, 0, 0, 0, 0,
303 : : 0, 0, 0, 0, 0, 0, 0, 0};
304 : 1 : uint8_t ip1[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 0, 0, 0, 0, 0,
305 : : 0, 0, 0, 0, 0, 0, 0, 0};
306 : 1 : uint8_t ip2[RTE_RIB6_IPV6_ADDR_SIZE] = {10, 0, 2, 130, 0, 0, 0, 0,
307 : : 0, 0, 0, 0, 0, 0, 0, 80};
308 : : uint8_t depth = 126;
309 : :
310 : 1 : config.max_nodes = MAX_RULES;
311 : 1 : config.ext_sz = 0;
312 : :
313 : 1 : rib = rte_rib6_create(__func__, SOCKET_ID_ANY, &config);
314 [ - + ]: 1 : RTE_TEST_ASSERT(rib != NULL, "Failed to create RIB\n");
315 : :
316 : 1 : node = rte_rib6_insert(rib, ip1, depth);
317 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
318 : 1 : node = rte_rib6_insert(rib, ip2, depth);
319 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to insert rule\n");
320 : :
321 : : node = NULL;
322 : 1 : node = rte_rib6_get_nxt(rib, ip, 32, node, RTE_RIB6_GET_NXT_ALL);
323 [ - + ]: 1 : RTE_TEST_ASSERT(node != NULL, "Failed to get rib_node\n");
324 : :
325 : 1 : rte_rib6_free(rib);
326 : :
327 : 1 : return TEST_SUCCESS;
328 : : }
329 : :
330 : : static struct unit_test_suite rib6_tests = {
331 : : .suite_name = "rib6 autotest",
332 : : .setup = NULL,
333 : : .teardown = NULL,
334 : : .unit_test_cases = {
335 : : TEST_CASE(test_create_invalid),
336 : : TEST_CASE(test_free_null),
337 : : TEST_CASE(test_insert_invalid),
338 : : TEST_CASE(test_get_fn),
339 : : TEST_CASE(test_basic),
340 : : TEST_CASE(test_tree_traversal),
341 : : TEST_CASES_END()
342 : : }
343 : : };
344 : :
345 : : static struct unit_test_suite rib6_slow_tests = {
346 : : .suite_name = "rib6 slow autotest",
347 : : .setup = NULL,
348 : : .teardown = NULL,
349 : : .unit_test_cases = {
350 : : TEST_CASE(test_multiple_create),
351 : : TEST_CASES_END()
352 : : }
353 : : };
354 : :
355 : : /*
356 : : * Do all unit tests.
357 : : */
358 : : static int
359 : 1 : test_rib6(void)
360 : : {
361 : 1 : return unit_test_suite_runner(&rib6_tests);
362 : : }
363 : :
364 : : static int
365 : 0 : test_slow_rib6(void)
366 : : {
367 : 0 : return unit_test_suite_runner(&rib6_slow_tests);
368 : : }
369 : :
370 : 235 : REGISTER_FAST_TEST(rib6_autotest, true, true, test_rib6);
371 : 235 : REGISTER_PERF_TEST(rib6_slow_autotest, test_slow_rib6);
|