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