Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 Huawei Technologies Co., Ltd
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <stdarg.h>
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include <stdint.h>
10 : : #include <inttypes.h>
11 : : #include <errno.h>
12 : : #include <sys/queue.h>
13 : :
14 : : #include <rte_common.h>
15 : : #include <rte_log.h>
16 : : #include <rte_memory.h>
17 : : #include <rte_launch.h>
18 : : #include <rte_cycles.h>
19 : : #include <rte_eal.h>
20 : : #include <rte_per_lcore.h>
21 : : #include <rte_lcore.h>
22 : : #include <rte_branch_prediction.h>
23 : : #include <rte_malloc.h>
24 : : #include <rte_random.h>
25 : : #include <rte_errno.h>
26 : : #include <rte_hexdump.h>
27 : :
28 : : #include <rte_soring.h>
29 : :
30 : : #include "test.h"
31 : :
32 : : #define MAX_ACQUIRED 20
33 : :
34 : : #define SORING_TEST_ASSERT(val, expected) do { \
35 : : RTE_TEST_ASSERT(expected == val, \
36 : : "%s: expected %u got %u\n", #val, expected, val); \
37 : : } while (0)
38 : :
39 : : static void
40 : : set_soring_init_param(struct rte_soring_param *prm,
41 : : const char *name, uint32_t esize, uint32_t elems,
42 : : uint32_t stages, uint32_t stsize,
43 : : enum rte_ring_sync_type rst_prod,
44 : : enum rte_ring_sync_type rst_cons)
45 : : {
46 : 12 : prm->name = name;
47 : 12 : prm->elem_size = esize;
48 : 12 : prm->elems = elems;
49 : 12 : prm->stages = stages;
50 : 11 : prm->meta_size = stsize;
51 : 8 : prm->prod_synt = rst_prod;
52 : 8 : prm->cons_synt = rst_cons;
53 : : }
54 : :
55 : : static int
56 : 2 : move_forward_stage(struct rte_soring *sor,
57 : : uint32_t num_packets, uint32_t stage)
58 : : {
59 : : uint32_t acquired;
60 : : uint32_t ftoken;
61 : : uint32_t *acquired_objs[MAX_ACQUIRED];
62 : :
63 : 2 : acquired = rte_soring_acquire_bulk(sor, acquired_objs, stage,
64 : : num_packets, &ftoken, NULL);
65 [ - + ]: 2 : SORING_TEST_ASSERT(acquired, num_packets);
66 : 2 : rte_soring_release(sor, NULL, stage, num_packets,
67 : : ftoken);
68 : :
69 : 2 : return 0;
70 : : }
71 : :
72 : : /*
73 : : * struct rte_soring_param param checking.
74 : : */
75 : : static int
76 : 1 : test_soring_init(void)
77 : : {
78 : : struct rte_soring *sor = NULL;
79 : : struct rte_soring_param prm;
80 : : int rc;
81 : : size_t sz;
82 : : memset(&prm, 0, sizeof(prm));
83 : :
84 : : /* init memory */
85 : : set_soring_init_param(&prm, "alloc_memory", sizeof(uintptr_t),
86 : : 4, 1, 4, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
87 : 1 : sz = rte_soring_get_memsize(&prm);
88 : 1 : sor = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
89 [ - + ]: 1 : RTE_TEST_ASSERT_NOT_NULL(sor, "could not allocate memory for soring");
90 : :
91 : : set_soring_init_param(&prm, "test_invalid_stages", sizeof(uintptr_t),
92 : : 4, 0, 4, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
93 : 1 : rc = rte_soring_init(sor, &prm);
94 [ - + ]: 1 : RTE_TEST_ASSERT_FAIL(rc, "initted soring with invalid num stages");
95 : :
96 : : set_soring_init_param(&prm, "test_invalid_esize", 0,
97 : : 4, 1, 4, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
98 : 1 : rc = rte_soring_init(sor, &prm);
99 [ - + ]: 1 : RTE_TEST_ASSERT_FAIL(rc, "initted soring with 0 esize");
100 : :
101 : : set_soring_init_param(&prm, "test_invalid_esize", 9,
102 : : 4, 1, 4, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
103 : 1 : rc = rte_soring_init(sor, &prm);
104 [ - + ]: 1 : RTE_TEST_ASSERT_FAIL(rc, "initted soring with esize not multiple of 4");
105 : :
106 : : set_soring_init_param(&prm, "test_invalid_rsize", sizeof(uintptr_t),
107 : : 4, 1, 3, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
108 : 1 : rc = rte_soring_init(sor, &prm);
109 [ - + ]: 1 : RTE_TEST_ASSERT_FAIL(rc, "initted soring with rcsize not multiple of 4");
110 : :
111 : : set_soring_init_param(&prm, "test_invalid_elems", sizeof(uintptr_t),
112 : : RTE_SORING_ELEM_MAX + 1, 1, 4, RTE_RING_SYNC_MT,
113 : : RTE_RING_SYNC_MT);
114 : 1 : rc = rte_soring_init(sor, &prm);
115 [ - + ]: 1 : RTE_TEST_ASSERT_FAIL(rc, "initted soring with invalid num elements");
116 : :
117 : 1 : rte_free(sor);
118 : 1 : return 0;
119 : : }
120 : :
121 : : static int
122 : 1 : test_soring_get_memsize(void)
123 : : {
124 : :
125 : : struct rte_soring_param prm;
126 : : ssize_t sz;
127 : :
128 : : set_soring_init_param(&prm, "memsize", sizeof(uint32_t *),
129 : : 10, 1, 0, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
130 : 1 : sz = rte_soring_get_memsize(&prm);
131 [ - + ]: 1 : RTE_TEST_ASSERT(sz > 0, "failed to calculate size");
132 : :
133 : : set_soring_init_param(&prm, "memsize", sizeof(uint8_t),
134 : : 16, UINT32_MAX, sizeof(uint32_t), RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
135 : 1 : sz = rte_soring_get_memsize(&prm);
136 [ - + ]: 1 : RTE_TEST_ASSERT_EQUAL(sz, -EINVAL, "calculated size incorrect");
137 : :
138 : : set_soring_init_param(&prm, "memsize", 0,
139 : : 16, UINT32_MAX, sizeof(uint32_t), RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
140 : 1 : sz = rte_soring_get_memsize(&prm);
141 [ - + ]: 1 : RTE_TEST_ASSERT_EQUAL(sz, -EINVAL, "calculated size incorrect");
142 : :
143 : : return 0;
144 : :
145 : : }
146 : :
147 : : static int
148 : 1 : test_soring_stages(void)
149 : : {
150 : : struct rte_soring *sor = NULL;
151 : : struct rte_soring_param prm;
152 : : uint32_t objs[32];
153 : : uint32_t rcs[32];
154 : : uint32_t acquired_objs[32];
155 : : uint32_t acquired_rcs[32];
156 : : uint32_t dequeued_rcs[32];
157 : : uint32_t dequeued_objs[32];
158 : : size_t ssz;
159 : : uint32_t stage, enqueued, dequeued, acquired;
160 : : uint32_t i, ftoken;
161 : :
162 : : memset(&prm, 0, sizeof(prm));
163 : : set_soring_init_param(&prm, "stages", sizeof(uint32_t), 32,
164 : : 10000, sizeof(uint32_t), RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
165 : 1 : ssz = rte_soring_get_memsize(&prm);
166 [ - + ]: 1 : RTE_TEST_ASSERT(ssz > 0, "parameter error calculating ring size");
167 : 1 : sor = rte_zmalloc(NULL, ssz, RTE_CACHE_LINE_SIZE);
168 [ - + ]: 1 : RTE_TEST_ASSERT_NOT_NULL(sor, "couldn't allocate memory for soring");
169 : 1 : rte_soring_init(sor, &prm);
170 : :
171 [ + + ]: 33 : for (i = 0; i < 32; i++) {
172 : 32 : rcs[i] = i;
173 : 32 : objs[i] = i + 32;
174 : : }
175 : :
176 : 1 : enqueued = rte_soring_enqueux_burst(sor, objs, rcs, 32, NULL);
177 [ - + ]: 1 : SORING_TEST_ASSERT(enqueued, 32);
178 : :
179 [ + + ]: 10001 : for (stage = 0; stage < 10000; stage++) {
180 : : int j;
181 : 10000 : dequeued = rte_soring_dequeue_bulk(sor, dequeued_objs,
182 : : 32, NULL);
183 : : /* check none at end stage */
184 [ - + ]: 10000 : SORING_TEST_ASSERT(dequeued, 0);
185 : :
186 : 10000 : acquired = rte_soring_acquirx_bulk(sor, acquired_objs,
187 : : acquired_rcs, stage, 32, &ftoken, NULL);
188 [ - + ]: 10000 : SORING_TEST_ASSERT(acquired, 32);
189 : :
190 [ + + ]: 330000 : for (j = 0; j < 32; j++) {
191 [ - + ]: 320000 : SORING_TEST_ASSERT(acquired_rcs[j], j + stage);
192 [ - + ]: 320000 : SORING_TEST_ASSERT(acquired_objs[j], j + stage + 32);
193 : : /* modify both queue object and rc */
194 : 320000 : acquired_objs[j]++;
195 : 320000 : acquired_rcs[j]++;
196 : : }
197 : :
198 : 10000 : rte_soring_releasx(sor, acquired_objs,
199 : : acquired_rcs, stage, 32,
200 : : ftoken);
201 : : }
202 : :
203 : 1 : dequeued = rte_soring_dequeux_bulk(sor, dequeued_objs, dequeued_rcs,
204 : : 32, NULL);
205 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 32);
206 [ + + ]: 33 : for (i = 0; i < 32; i++) {
207 : : /* ensure we ended up with the expected values in order */
208 [ - + ]: 32 : SORING_TEST_ASSERT(dequeued_rcs[i], i + 10000);
209 [ - + ]: 32 : SORING_TEST_ASSERT(dequeued_objs[i], i + 32 + 10000);
210 : : }
211 : 1 : rte_free(sor);
212 : 1 : return 0;
213 : : }
214 : :
215 : : static int
216 : 1 : test_soring_enqueue_dequeue(void)
217 : : {
218 : : struct rte_soring *sor = NULL;
219 : : struct rte_soring_param prm;
220 : : int rc;
221 : : uint32_t i;
222 : : size_t sz;
223 : : uint32_t queue_objs[10];
224 : : uint32_t *queue_objs_p[10];
225 : : uint32_t free_space;
226 : : uint32_t enqueued, dequeued;
227 : : uint32_t *dequeued_objs[10];
228 : :
229 : : memset(&prm, 0, sizeof(prm));
230 [ + + ]: 11 : for (i = 0; i < 10; i++) {
231 : 10 : queue_objs[i] = i + 1;
232 : 10 : queue_objs_p[i] = &queue_objs[i];
233 : : }
234 : :
235 : : /* init memory */
236 : : set_soring_init_param(&prm, "enqueue/dequeue", sizeof(uint32_t *),
237 : : 10, 1, 0, RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
238 : 1 : sz = rte_soring_get_memsize(&prm);
239 : 1 : sor = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
240 [ - + ]: 1 : RTE_TEST_ASSERT_NOT_NULL(sor, "alloc failed for soring");
241 : 1 : rc = rte_soring_init(sor, &prm);
242 [ - + ]: 1 : RTE_TEST_ASSERT_SUCCESS(rc, "Failed to init soring");
243 : :
244 : 1 : free_space = 0;
245 : :
246 : 1 : enqueued = rte_soring_enqueue_burst(sor, queue_objs_p, 5, &free_space);
247 : :
248 [ - + ]: 1 : SORING_TEST_ASSERT(free_space, 5);
249 [ - + ]: 1 : SORING_TEST_ASSERT(enqueued, 5);
250 : :
251 : : /* fixed amount enqueue */
252 : 1 : enqueued = rte_soring_enqueue_bulk(sor, queue_objs_p, 7, &free_space);
253 : :
254 [ - + ]: 1 : SORING_TEST_ASSERT(free_space, 5);
255 [ - + ]: 1 : SORING_TEST_ASSERT(enqueued, 0);
256 : :
257 : : /* variable amount enqueue */
258 : 1 : enqueued = rte_soring_enqueue_burst(sor, queue_objs_p + 5, 7,
259 : : &free_space);
260 [ - + ]: 1 : SORING_TEST_ASSERT(free_space, 0);
261 [ - + ]: 1 : SORING_TEST_ASSERT(enqueued, 5);
262 : :
263 : : /* test no dequeue while stage 0 has not completed */
264 : 1 : dequeued = rte_soring_dequeue_bulk(sor, dequeued_objs, 10, NULL);
265 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 0);
266 : 1 : dequeued = rte_soring_dequeue_burst(sor, dequeued_objs, 10, NULL);
267 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 0);
268 : :
269 : 1 : move_forward_stage(sor, 8, 0);
270 : :
271 : : /* can only dequeue as many as have completed stage */
272 : 1 : dequeued = rte_soring_dequeue_bulk(sor, dequeued_objs, 10, NULL);
273 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 0);
274 : 1 : dequeued = rte_soring_dequeue_burst(sor, dequeued_objs, 10, NULL);
275 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 8);
276 : : /* packets remain in order */
277 [ + + ]: 9 : for (i = 0; i < dequeued; i++) {
278 [ - + ]: 8 : RTE_TEST_ASSERT_EQUAL(dequeued_objs[i],
279 : : queue_objs_p[i], "dequeued != enqueued");
280 : : }
281 : :
282 : 1 : dequeued = rte_soring_dequeue_burst(sor, dequeued_objs, 1, NULL);
283 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 0);
284 : :
285 : 1 : move_forward_stage(sor, 2, 0);
286 : 1 : dequeued = rte_soring_dequeue_burst(sor, dequeued_objs, 2, NULL);
287 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 2);
288 : : /* packets remain in order */
289 [ + + ]: 3 : for (i = 0; i < dequeued; i++) {
290 [ - + ]: 2 : RTE_TEST_ASSERT_EQUAL(dequeued_objs[i],
291 : : queue_objs_p[i + 8], "dequeued != enqueued");
292 : : }
293 : :
294 : 1 : rte_soring_dump(stdout, sor);
295 : 1 : rte_free(sor);
296 : 1 : return 0;
297 : : }
298 : :
299 : : static int
300 : 1 : test_soring_acquire_release(void)
301 : : {
302 : :
303 : : struct rte_soring *sor = NULL;
304 : : struct rte_soring_param prm;
305 : : int rc, i;
306 : : size_t sz;
307 : :
308 : : memset(&prm, 0, sizeof(prm));
309 : : uint32_t queue_objs[10];
310 : : uint32_t rc_objs[10];
311 : : uint32_t acquired_objs[10];
312 : : uint32_t dequeued_objs[10];
313 : : uint32_t dequeued_rcs[10];
314 : : uint32_t s1_acquired_rcs[10];
315 : : uint32_t free_space, enqueued, ftoken, acquired, dequeued;
316 : :
317 [ + + ]: 11 : for (i = 0; i < 10; i++) {
318 : 10 : queue_objs[i] = i + 5;
319 : 10 : rc_objs[i] = i + 10;
320 : : }
321 : :
322 : : /*init memory*/
323 : : set_soring_init_param(&prm, "test_acquire_release", sizeof(uint32_t),
324 : : 20, 2, sizeof(uint32_t), RTE_RING_SYNC_MT, RTE_RING_SYNC_MT);
325 : 1 : sz = rte_soring_get_memsize(&prm);
326 : 1 : sor = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
327 [ - + ]: 1 : if (sor == NULL) {
328 : 0 : printf("%s: alloc(%zu) for FIFO with %u elems failed",
329 : : __func__, sz, prm.elems);
330 : 0 : return -ENOMEM;
331 : : }
332 : :
333 : : /* init ring */
334 : 1 : rc = rte_soring_init(sor, &prm);
335 [ - + ]: 1 : RTE_TEST_ASSERT_SUCCESS(rc, "failed to init soring");
336 : :
337 : : /* enqueue with associated rc */
338 : 1 : enqueued = rte_soring_enqueux_burst(sor, queue_objs, rc_objs, 5,
339 : : &free_space);
340 [ - + ]: 1 : SORING_TEST_ASSERT(enqueued, 5);
341 : : /* enqueue without associated rc */
342 : 1 : enqueued = rte_soring_enqueue_burst(sor, queue_objs + 5, 5,
343 : : &free_space);
344 [ - + ]: 1 : SORING_TEST_ASSERT(enqueued, 5);
345 : :
346 : : /* acquire the objects with rc's and ensure they are as expected */
347 : 1 : acquired = rte_soring_acquirx_burst(sor, acquired_objs,
348 : : s1_acquired_rcs, 0, 5, &ftoken, NULL);
349 [ - + ]: 1 : SORING_TEST_ASSERT(acquired, 5);
350 [ + + ]: 6 : for (i = 0; i < 5; i++) {
351 [ - + ]: 5 : RTE_TEST_ASSERT_EQUAL(s1_acquired_rcs[i], rc_objs[i],
352 : : "acquired rc[%d]: %u != enqueued rc: %u",
353 : : i, s1_acquired_rcs[i], rc_objs[i]);
354 [ - + ]: 5 : RTE_TEST_ASSERT_EQUAL(acquired_objs[i], queue_objs[i],
355 : : "acquired obj[%d]: %u != enqueued obj %u",
356 : : i, acquired_objs[i], queue_objs[i]);
357 : : }
358 : 1 : rte_soring_release(sor, NULL, 0, 5, ftoken);
359 : :
360 : : /* acquire the objects without rc's and ensure they are as expected */
361 : 1 : acquired = rte_soring_acquirx_burst(sor, acquired_objs,
362 : : s1_acquired_rcs, 0, 5, &ftoken, NULL);
363 [ - + ]: 1 : SORING_TEST_ASSERT(acquired, 5);
364 [ + + ]: 6 : for (i = 0; i < 5; i++) {
365 : : /* as the rc area of memory is zero'd at init this is true
366 : : * but this is a detail of implementation rather than
367 : : * a guarantee.
368 : : */
369 [ - + ]: 5 : RTE_TEST_ASSERT_EQUAL(s1_acquired_rcs[i], 0,
370 : : "acquired rc not empty");
371 [ - + ]: 5 : RTE_TEST_ASSERT_EQUAL(acquired_objs[i], queue_objs[i + 5],
372 : : "acquired obj[%d]: %u != enqueued obj %u",
373 : : i, acquired_objs[i], queue_objs[i + 5]);
374 : : }
375 : : /*release the objects, adding rc's */
376 : 1 : rte_soring_releasx(sor, NULL, rc_objs + 5, 0, 5,
377 : : ftoken);
378 : :
379 : 1 : acquired = rte_soring_acquirx_burst(sor, acquired_objs,
380 : : s1_acquired_rcs, 1, 10, &ftoken, NULL);
381 [ - + ]: 1 : SORING_TEST_ASSERT(acquired, 10);
382 [ + + ]: 11 : for (i = 0; i < 10; i++) {
383 : : /* ensure the associated rc's are the ones added at release */
384 [ - + ]: 10 : RTE_TEST_ASSERT_EQUAL(s1_acquired_rcs[i], rc_objs[i],
385 : : "acquired rc[%d]: %u != enqueued rc: %u",
386 : : i, s1_acquired_rcs[i], rc_objs[i]);
387 [ - + ]: 10 : RTE_TEST_ASSERT_EQUAL(acquired_objs[i], queue_objs[i],
388 : : "acquired obj[%d]: %u != enqueued obj %u",
389 : : i, acquired_objs[i], queue_objs[i]);
390 : : }
391 : : /* release the objects, with rc's set to NULL */
392 : 1 : rte_soring_release(sor, NULL, 1, 10, ftoken);
393 : :
394 : 1 : dequeued = rte_soring_dequeux_burst(sor, dequeued_objs, dequeued_rcs,
395 : : 10, NULL);
396 [ - + ]: 1 : SORING_TEST_ASSERT(dequeued, 10);
397 [ + + ]: 11 : for (i = 0; i < 10; i++) {
398 : : /* ensure the associated rc's are the ones added at release */
399 [ - + ]: 10 : RTE_TEST_ASSERT_EQUAL(dequeued_rcs[i], rc_objs[i],
400 : : "dequeued rc[%d]: %u != enqueued rc: %u",
401 : : i, dequeued_rcs[i], rc_objs[i]);
402 [ - + ]: 10 : RTE_TEST_ASSERT_EQUAL(acquired_objs[i], queue_objs[i],
403 : : "acquired obj[%d]: %u != enqueued obj %u",
404 : : i, acquired_objs[i], queue_objs[i]);
405 : : }
406 : 1 : rte_soring_dump(stdout, sor);
407 : 1 : rte_free(sor);
408 : 1 : return 0;
409 : : }
410 : :
411 : : static int
412 : 1 : test_soring(void)
413 : : {
414 : :
415 : : /* Negative test cases */
416 [ - + ]: 1 : if (test_soring_init() < 0)
417 : 0 : goto test_fail;
418 : :
419 : : /* Memory calculations */
420 [ - + ]: 1 : if (test_soring_get_memsize() < 0)
421 : 0 : goto test_fail;
422 : :
423 : : /* Basic enqueue/dequeue operations */
424 [ - + ]: 1 : if (test_soring_enqueue_dequeue() < 0)
425 : 0 : goto test_fail;
426 : :
427 : : /* Acquire/release */
428 [ - + ]: 1 : if (test_soring_acquire_release() < 0)
429 : 0 : goto test_fail;
430 : :
431 : : /* Test large number of stages */
432 [ - + ]: 1 : if (test_soring_stages() < 0)
433 : 0 : goto test_fail;
434 : :
435 : : return 0;
436 : :
437 : : test_fail:
438 : : return -1;
439 : : }
440 : :
441 : 252 : REGISTER_FAST_TEST(soring_autotest, true, true, test_soring);
|