]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <string.h> | |
35 | #include <stdarg.h> | |
36 | #include <stdio.h> | |
37 | #include <stdlib.h> | |
38 | #include <stdint.h> | |
39 | #include <inttypes.h> | |
40 | #include <errno.h> | |
41 | #include <sys/queue.h> | |
42 | ||
43 | #include <rte_common.h> | |
44 | #include <rte_log.h> | |
45 | #include <rte_memory.h> | |
46 | #include <rte_memzone.h> | |
47 | #include <rte_launch.h> | |
48 | #include <rte_cycles.h> | |
49 | #include <rte_eal.h> | |
50 | #include <rte_per_lcore.h> | |
51 | #include <rte_lcore.h> | |
52 | #include <rte_atomic.h> | |
53 | #include <rte_branch_prediction.h> | |
54 | #include <rte_malloc.h> | |
55 | #include <rte_ring.h> | |
56 | #include <rte_random.h> | |
57 | #include <rte_common.h> | |
58 | #include <rte_errno.h> | |
59 | #include <rte_hexdump.h> | |
60 | ||
61 | #include "test.h" | |
62 | ||
63 | /* | |
64 | * Ring | |
65 | * ==== | |
66 | * | |
67 | * #. Basic tests: done on one core: | |
68 | * | |
69 | * - Using single producer/single consumer functions: | |
70 | * | |
71 | * - Enqueue one object, two objects, MAX_BULK objects | |
72 | * - Dequeue one object, two objects, MAX_BULK objects | |
73 | * - Check that dequeued pointers are correct | |
74 | * | |
75 | * - Using multi producers/multi consumers functions: | |
76 | * | |
77 | * - Enqueue one object, two objects, MAX_BULK objects | |
78 | * - Dequeue one object, two objects, MAX_BULK objects | |
79 | * - Check that dequeued pointers are correct | |
80 | * | |
81 | * - Test watermark and default bulk enqueue/dequeue: | |
82 | * | |
83 | * - Set watermark | |
84 | * - Set default bulk value | |
85 | * - Enqueue objects, check that -EDQUOT is returned when | |
86 | * watermark is exceeded | |
87 | * - Check that dequeued pointers are correct | |
88 | * | |
89 | * #. Check live watermark change | |
90 | * | |
91 | * - Start a loop on another lcore that will enqueue and dequeue | |
92 | * objects in a ring. It will monitor the value of watermark. | |
93 | * - At the same time, change the watermark on the master lcore. | |
94 | * - The slave lcore will check that watermark changes from 16 to 32. | |
95 | * | |
96 | * #. Performance tests. | |
97 | * | |
98 | * Tests done in test_ring_perf.c | |
99 | */ | |
100 | ||
101 | #define RING_SIZE 4096 | |
102 | #define MAX_BULK 32 | |
103 | ||
104 | static rte_atomic32_t synchro; | |
105 | ||
106 | static struct rte_ring *r; | |
107 | ||
108 | #define TEST_RING_VERIFY(exp) \ | |
109 | if (!(exp)) { \ | |
110 | printf("error at %s:%d\tcondition " #exp " failed\n", \ | |
111 | __func__, __LINE__); \ | |
112 | rte_ring_dump(stdout, r); \ | |
113 | return -1; \ | |
114 | } | |
115 | ||
116 | #define TEST_RING_FULL_EMTPY_ITER 8 | |
117 | ||
118 | static int | |
119 | check_live_watermark_change(__attribute__((unused)) void *dummy) | |
120 | { | |
121 | uint64_t hz = rte_get_timer_hz(); | |
122 | void *obj_table[MAX_BULK]; | |
123 | unsigned watermark, watermark_old = 16; | |
124 | uint64_t cur_time, end_time; | |
125 | int64_t diff = 0; | |
126 | int i, ret; | |
127 | unsigned count = 4; | |
128 | ||
129 | /* init the object table */ | |
130 | memset(obj_table, 0, sizeof(obj_table)); | |
131 | end_time = rte_get_timer_cycles() + (hz / 4); | |
132 | ||
133 | /* check that bulk and watermark are 4 and 32 (respectively) */ | |
134 | while (diff >= 0) { | |
135 | ||
136 | /* add in ring until we reach watermark */ | |
137 | ret = 0; | |
138 | for (i = 0; i < 16; i ++) { | |
139 | if (ret != 0) | |
140 | break; | |
141 | ret = rte_ring_enqueue_bulk(r, obj_table, count); | |
142 | } | |
143 | ||
144 | if (ret != -EDQUOT) { | |
145 | printf("Cannot enqueue objects, or watermark not " | |
146 | "reached (ret=%d)\n", ret); | |
147 | return -1; | |
148 | } | |
149 | ||
150 | /* read watermark, the only change allowed is from 16 to 32 */ | |
151 | watermark = r->prod.watermark; | |
152 | if (watermark != watermark_old && | |
153 | (watermark_old != 16 || watermark != 32)) { | |
154 | printf("Bad watermark change %u -> %u\n", watermark_old, | |
155 | watermark); | |
156 | return -1; | |
157 | } | |
158 | watermark_old = watermark; | |
159 | ||
160 | /* dequeue objects from ring */ | |
161 | while (i--) { | |
162 | ret = rte_ring_dequeue_bulk(r, obj_table, count); | |
163 | if (ret != 0) { | |
164 | printf("Cannot dequeue (ret=%d)\n", ret); | |
165 | return -1; | |
166 | } | |
167 | } | |
168 | ||
169 | cur_time = rte_get_timer_cycles(); | |
170 | diff = end_time - cur_time; | |
171 | } | |
172 | ||
173 | if (watermark_old != 32 ) { | |
174 | printf(" watermark was not updated (wm=%u)\n", | |
175 | watermark_old); | |
176 | return -1; | |
177 | } | |
178 | ||
179 | return 0; | |
180 | } | |
181 | ||
182 | static int | |
183 | test_live_watermark_change(void) | |
184 | { | |
185 | unsigned lcore_id = rte_lcore_id(); | |
186 | unsigned lcore_id2 = rte_get_next_lcore(lcore_id, 0, 1); | |
187 | ||
188 | printf("Test watermark live modification\n"); | |
189 | rte_ring_set_water_mark(r, 16); | |
190 | ||
191 | /* launch a thread that will enqueue and dequeue, checking | |
192 | * watermark and quota */ | |
193 | rte_eal_remote_launch(check_live_watermark_change, NULL, lcore_id2); | |
194 | ||
195 | rte_delay_ms(100); | |
196 | rte_ring_set_water_mark(r, 32); | |
197 | rte_delay_ms(100); | |
198 | ||
199 | if (rte_eal_wait_lcore(lcore_id2) < 0) | |
200 | return -1; | |
201 | ||
202 | return 0; | |
203 | } | |
204 | ||
205 | /* Test for catch on invalid watermark values */ | |
206 | static int | |
207 | test_set_watermark( void ){ | |
208 | unsigned count; | |
209 | int setwm; | |
210 | ||
211 | struct rte_ring *r = rte_ring_lookup("test_ring_basic_ex"); | |
212 | if(r == NULL){ | |
213 | printf( " ring lookup failed\n" ); | |
214 | goto error; | |
215 | } | |
216 | count = r->prod.size*2; | |
217 | setwm = rte_ring_set_water_mark(r, count); | |
218 | if (setwm != -EINVAL){ | |
219 | printf("Test failed to detect invalid watermark count value\n"); | |
220 | goto error; | |
221 | } | |
222 | ||
223 | count = 0; | |
224 | rte_ring_set_water_mark(r, count); | |
225 | if (r->prod.watermark != r->prod.size) { | |
226 | printf("Test failed to detect invalid watermark count value\n"); | |
227 | goto error; | |
228 | } | |
229 | return 0; | |
230 | ||
231 | error: | |
232 | return -1; | |
233 | } | |
234 | ||
235 | /* | |
236 | * helper routine for test_ring_basic | |
237 | */ | |
238 | static int | |
239 | test_ring_basic_full_empty(void * const src[], void *dst[]) | |
240 | { | |
241 | unsigned i, rand; | |
242 | const unsigned rsz = RING_SIZE - 1; | |
243 | ||
244 | printf("Basic full/empty test\n"); | |
245 | ||
246 | for (i = 0; TEST_RING_FULL_EMTPY_ITER != i; i++) { | |
247 | ||
248 | /* random shift in the ring */ | |
249 | rand = RTE_MAX(rte_rand() % RING_SIZE, 1UL); | |
250 | printf("%s: iteration %u, random shift: %u;\n", | |
251 | __func__, i, rand); | |
252 | TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src, | |
253 | rand)); | |
254 | TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rand)); | |
255 | ||
256 | /* fill the ring */ | |
257 | TEST_RING_VERIFY(-ENOBUFS != rte_ring_enqueue_bulk(r, src, | |
258 | rsz)); | |
259 | TEST_RING_VERIFY(0 == rte_ring_free_count(r)); | |
260 | TEST_RING_VERIFY(rsz == rte_ring_count(r)); | |
261 | TEST_RING_VERIFY(rte_ring_full(r)); | |
262 | TEST_RING_VERIFY(0 == rte_ring_empty(r)); | |
263 | ||
264 | /* empty the ring */ | |
265 | TEST_RING_VERIFY(0 == rte_ring_dequeue_bulk(r, dst, rsz)); | |
266 | TEST_RING_VERIFY(rsz == rte_ring_free_count(r)); | |
267 | TEST_RING_VERIFY(0 == rte_ring_count(r)); | |
268 | TEST_RING_VERIFY(0 == rte_ring_full(r)); | |
269 | TEST_RING_VERIFY(rte_ring_empty(r)); | |
270 | ||
271 | /* check data */ | |
272 | TEST_RING_VERIFY(0 == memcmp(src, dst, rsz)); | |
273 | rte_ring_dump(stdout, r); | |
274 | } | |
275 | return 0; | |
276 | } | |
277 | ||
278 | static int | |
279 | test_ring_basic(void) | |
280 | { | |
281 | void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; | |
282 | int ret; | |
283 | unsigned i, num_elems; | |
284 | ||
285 | /* alloc dummy object pointers */ | |
286 | src = malloc(RING_SIZE*2*sizeof(void *)); | |
287 | if (src == NULL) | |
288 | goto fail; | |
289 | ||
290 | for (i = 0; i < RING_SIZE*2 ; i++) { | |
291 | src[i] = (void *)(unsigned long)i; | |
292 | } | |
293 | cur_src = src; | |
294 | ||
295 | /* alloc some room for copied objects */ | |
296 | dst = malloc(RING_SIZE*2*sizeof(void *)); | |
297 | if (dst == NULL) | |
298 | goto fail; | |
299 | ||
300 | memset(dst, 0, RING_SIZE*2*sizeof(void *)); | |
301 | cur_dst = dst; | |
302 | ||
303 | printf("enqueue 1 obj\n"); | |
304 | ret = rte_ring_sp_enqueue_bulk(r, cur_src, 1); | |
305 | cur_src += 1; | |
306 | if (ret != 0) | |
307 | goto fail; | |
308 | ||
309 | printf("enqueue 2 objs\n"); | |
310 | ret = rte_ring_sp_enqueue_bulk(r, cur_src, 2); | |
311 | cur_src += 2; | |
312 | if (ret != 0) | |
313 | goto fail; | |
314 | ||
315 | printf("enqueue MAX_BULK objs\n"); | |
316 | ret = rte_ring_sp_enqueue_bulk(r, cur_src, MAX_BULK); | |
317 | cur_src += MAX_BULK; | |
318 | if (ret != 0) | |
319 | goto fail; | |
320 | ||
321 | printf("dequeue 1 obj\n"); | |
322 | ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 1); | |
323 | cur_dst += 1; | |
324 | if (ret != 0) | |
325 | goto fail; | |
326 | ||
327 | printf("dequeue 2 objs\n"); | |
328 | ret = rte_ring_sc_dequeue_bulk(r, cur_dst, 2); | |
329 | cur_dst += 2; | |
330 | if (ret != 0) | |
331 | goto fail; | |
332 | ||
333 | printf("dequeue MAX_BULK objs\n"); | |
334 | ret = rte_ring_sc_dequeue_bulk(r, cur_dst, MAX_BULK); | |
335 | cur_dst += MAX_BULK; | |
336 | if (ret != 0) | |
337 | goto fail; | |
338 | ||
339 | /* check data */ | |
340 | if (memcmp(src, dst, cur_dst - dst)) { | |
341 | rte_hexdump(stdout, "src", src, cur_src - src); | |
342 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
343 | printf("data after dequeue is not the same\n"); | |
344 | goto fail; | |
345 | } | |
346 | cur_src = src; | |
347 | cur_dst = dst; | |
348 | ||
349 | printf("enqueue 1 obj\n"); | |
350 | ret = rte_ring_mp_enqueue_bulk(r, cur_src, 1); | |
351 | cur_src += 1; | |
352 | if (ret != 0) | |
353 | goto fail; | |
354 | ||
355 | printf("enqueue 2 objs\n"); | |
356 | ret = rte_ring_mp_enqueue_bulk(r, cur_src, 2); | |
357 | cur_src += 2; | |
358 | if (ret != 0) | |
359 | goto fail; | |
360 | ||
361 | printf("enqueue MAX_BULK objs\n"); | |
362 | ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK); | |
363 | cur_src += MAX_BULK; | |
364 | if (ret != 0) | |
365 | goto fail; | |
366 | ||
367 | printf("dequeue 1 obj\n"); | |
368 | ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 1); | |
369 | cur_dst += 1; | |
370 | if (ret != 0) | |
371 | goto fail; | |
372 | ||
373 | printf("dequeue 2 objs\n"); | |
374 | ret = rte_ring_mc_dequeue_bulk(r, cur_dst, 2); | |
375 | cur_dst += 2; | |
376 | if (ret != 0) | |
377 | goto fail; | |
378 | ||
379 | printf("dequeue MAX_BULK objs\n"); | |
380 | ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK); | |
381 | cur_dst += MAX_BULK; | |
382 | if (ret != 0) | |
383 | goto fail; | |
384 | ||
385 | /* check data */ | |
386 | if (memcmp(src, dst, cur_dst - dst)) { | |
387 | rte_hexdump(stdout, "src", src, cur_src - src); | |
388 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
389 | printf("data after dequeue is not the same\n"); | |
390 | goto fail; | |
391 | } | |
392 | cur_src = src; | |
393 | cur_dst = dst; | |
394 | ||
395 | printf("fill and empty the ring\n"); | |
396 | for (i = 0; i<RING_SIZE/MAX_BULK; i++) { | |
397 | ret = rte_ring_mp_enqueue_bulk(r, cur_src, MAX_BULK); | |
398 | cur_src += MAX_BULK; | |
399 | if (ret != 0) | |
400 | goto fail; | |
401 | ret = rte_ring_mc_dequeue_bulk(r, cur_dst, MAX_BULK); | |
402 | cur_dst += MAX_BULK; | |
403 | if (ret != 0) | |
404 | goto fail; | |
405 | } | |
406 | ||
407 | /* check data */ | |
408 | if (memcmp(src, dst, cur_dst - dst)) { | |
409 | rte_hexdump(stdout, "src", src, cur_src - src); | |
410 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
411 | printf("data after dequeue is not the same\n"); | |
412 | goto fail; | |
413 | } | |
414 | ||
415 | if (test_ring_basic_full_empty(src, dst) != 0) | |
416 | goto fail; | |
417 | ||
418 | cur_src = src; | |
419 | cur_dst = dst; | |
420 | ||
421 | printf("test watermark and default bulk enqueue / dequeue\n"); | |
422 | rte_ring_set_water_mark(r, 20); | |
423 | num_elems = 16; | |
424 | ||
425 | cur_src = src; | |
426 | cur_dst = dst; | |
427 | ||
428 | ret = rte_ring_enqueue_bulk(r, cur_src, num_elems); | |
429 | cur_src += num_elems; | |
430 | if (ret != 0) { | |
431 | printf("Cannot enqueue\n"); | |
432 | goto fail; | |
433 | } | |
434 | ret = rte_ring_enqueue_bulk(r, cur_src, num_elems); | |
435 | cur_src += num_elems; | |
436 | if (ret != -EDQUOT) { | |
437 | printf("Watermark not exceeded\n"); | |
438 | goto fail; | |
439 | } | |
440 | ret = rte_ring_dequeue_bulk(r, cur_dst, num_elems); | |
441 | cur_dst += num_elems; | |
442 | if (ret != 0) { | |
443 | printf("Cannot dequeue\n"); | |
444 | goto fail; | |
445 | } | |
446 | ret = rte_ring_dequeue_bulk(r, cur_dst, num_elems); | |
447 | cur_dst += num_elems; | |
448 | if (ret != 0) { | |
449 | printf("Cannot dequeue2\n"); | |
450 | goto fail; | |
451 | } | |
452 | ||
453 | /* check data */ | |
454 | if (memcmp(src, dst, cur_dst - dst)) { | |
455 | rte_hexdump(stdout, "src", src, cur_src - src); | |
456 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
457 | printf("data after dequeue is not the same\n"); | |
458 | goto fail; | |
459 | } | |
460 | ||
461 | cur_src = src; | |
462 | cur_dst = dst; | |
463 | ||
464 | ret = rte_ring_mp_enqueue(r, cur_src); | |
465 | if (ret != 0) | |
466 | goto fail; | |
467 | ||
468 | ret = rte_ring_mc_dequeue(r, cur_dst); | |
469 | if (ret != 0) | |
470 | goto fail; | |
471 | ||
472 | free(src); | |
473 | free(dst); | |
474 | return 0; | |
475 | ||
476 | fail: | |
477 | free(src); | |
478 | free(dst); | |
479 | return -1; | |
480 | } | |
481 | ||
482 | static int | |
483 | test_ring_burst_basic(void) | |
484 | { | |
485 | void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; | |
486 | int ret; | |
487 | unsigned i; | |
488 | ||
489 | /* alloc dummy object pointers */ | |
490 | src = malloc(RING_SIZE*2*sizeof(void *)); | |
491 | if (src == NULL) | |
492 | goto fail; | |
493 | ||
494 | for (i = 0; i < RING_SIZE*2 ; i++) { | |
495 | src[i] = (void *)(unsigned long)i; | |
496 | } | |
497 | cur_src = src; | |
498 | ||
499 | /* alloc some room for copied objects */ | |
500 | dst = malloc(RING_SIZE*2*sizeof(void *)); | |
501 | if (dst == NULL) | |
502 | goto fail; | |
503 | ||
504 | memset(dst, 0, RING_SIZE*2*sizeof(void *)); | |
505 | cur_dst = dst; | |
506 | ||
507 | printf("Test SP & SC basic functions \n"); | |
508 | printf("enqueue 1 obj\n"); | |
509 | ret = rte_ring_sp_enqueue_burst(r, cur_src, 1); | |
510 | cur_src += 1; | |
511 | if ((ret & RTE_RING_SZ_MASK) != 1) | |
512 | goto fail; | |
513 | ||
514 | printf("enqueue 2 objs\n"); | |
515 | ret = rte_ring_sp_enqueue_burst(r, cur_src, 2); | |
516 | cur_src += 2; | |
517 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
518 | goto fail; | |
519 | ||
520 | printf("enqueue MAX_BULK objs\n"); | |
521 | ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK) ; | |
522 | cur_src += MAX_BULK; | |
523 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
524 | goto fail; | |
525 | ||
526 | printf("dequeue 1 obj\n"); | |
527 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, 1) ; | |
528 | cur_dst += 1; | |
529 | if ((ret & RTE_RING_SZ_MASK) != 1) | |
530 | goto fail; | |
531 | ||
532 | printf("dequeue 2 objs\n"); | |
533 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, 2); | |
534 | cur_dst += 2; | |
535 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
536 | goto fail; | |
537 | ||
538 | printf("dequeue MAX_BULK objs\n"); | |
539 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK); | |
540 | cur_dst += MAX_BULK; | |
541 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
542 | goto fail; | |
543 | ||
544 | /* check data */ | |
545 | if (memcmp(src, dst, cur_dst - dst)) { | |
546 | rte_hexdump(stdout, "src", src, cur_src - src); | |
547 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
548 | printf("data after dequeue is not the same\n"); | |
549 | goto fail; | |
550 | } | |
551 | ||
552 | cur_src = src; | |
553 | cur_dst = dst; | |
554 | ||
555 | printf("Test enqueue without enough memory space \n"); | |
556 | for (i = 0; i< (RING_SIZE/MAX_BULK - 1); i++) { | |
557 | ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); | |
558 | cur_src += MAX_BULK; | |
559 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) { | |
560 | goto fail; | |
561 | } | |
562 | } | |
563 | ||
564 | printf("Enqueue 2 objects, free entries = MAX_BULK - 2 \n"); | |
565 | ret = rte_ring_sp_enqueue_burst(r, cur_src, 2); | |
566 | cur_src += 2; | |
567 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
568 | goto fail; | |
569 | ||
570 | printf("Enqueue the remaining entries = MAX_BULK - 2 \n"); | |
571 | /* Always one free entry left */ | |
572 | ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); | |
573 | cur_src += MAX_BULK - 3; | |
574 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3) | |
575 | goto fail; | |
576 | ||
577 | printf("Test if ring is full \n"); | |
578 | if (rte_ring_full(r) != 1) | |
579 | goto fail; | |
580 | ||
581 | printf("Test enqueue for a full entry \n"); | |
582 | ret = rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); | |
583 | if ((ret & RTE_RING_SZ_MASK) != 0) | |
584 | goto fail; | |
585 | ||
586 | printf("Test dequeue without enough objects \n"); | |
587 | for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) { | |
588 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK); | |
589 | cur_dst += MAX_BULK; | |
590 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
591 | goto fail; | |
592 | } | |
593 | ||
594 | /* Available memory space for the exact MAX_BULK entries */ | |
595 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, 2); | |
596 | cur_dst += 2; | |
597 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
598 | goto fail; | |
599 | ||
600 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK); | |
601 | cur_dst += MAX_BULK - 3; | |
602 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3) | |
603 | goto fail; | |
604 | ||
605 | printf("Test if ring is empty \n"); | |
606 | /* Check if ring is empty */ | |
607 | if (1 != rte_ring_empty(r)) | |
608 | goto fail; | |
609 | ||
610 | /* check data */ | |
611 | if (memcmp(src, dst, cur_dst - dst)) { | |
612 | rte_hexdump(stdout, "src", src, cur_src - src); | |
613 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
614 | printf("data after dequeue is not the same\n"); | |
615 | goto fail; | |
616 | } | |
617 | ||
618 | cur_src = src; | |
619 | cur_dst = dst; | |
620 | ||
621 | printf("Test MP & MC basic functions \n"); | |
622 | ||
623 | printf("enqueue 1 obj\n"); | |
624 | ret = rte_ring_mp_enqueue_burst(r, cur_src, 1); | |
625 | cur_src += 1; | |
626 | if ((ret & RTE_RING_SZ_MASK) != 1) | |
627 | goto fail; | |
628 | ||
629 | printf("enqueue 2 objs\n"); | |
630 | ret = rte_ring_mp_enqueue_burst(r, cur_src, 2); | |
631 | cur_src += 2; | |
632 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
633 | goto fail; | |
634 | ||
635 | printf("enqueue MAX_BULK objs\n"); | |
636 | ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK); | |
637 | cur_src += MAX_BULK; | |
638 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
639 | goto fail; | |
640 | ||
641 | printf("dequeue 1 obj\n"); | |
642 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, 1); | |
643 | cur_dst += 1; | |
644 | if ((ret & RTE_RING_SZ_MASK) != 1) | |
645 | goto fail; | |
646 | ||
647 | printf("dequeue 2 objs\n"); | |
648 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, 2); | |
649 | cur_dst += 2; | |
650 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
651 | goto fail; | |
652 | ||
653 | printf("dequeue MAX_BULK objs\n"); | |
654 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK); | |
655 | cur_dst += MAX_BULK; | |
656 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
657 | goto fail; | |
658 | ||
659 | /* check data */ | |
660 | if (memcmp(src, dst, cur_dst - dst)) { | |
661 | rte_hexdump(stdout, "src", src, cur_src - src); | |
662 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
663 | printf("data after dequeue is not the same\n"); | |
664 | goto fail; | |
665 | } | |
666 | ||
667 | cur_src = src; | |
668 | cur_dst = dst; | |
669 | ||
670 | printf("fill and empty the ring\n"); | |
671 | for (i = 0; i<RING_SIZE/MAX_BULK; i++) { | |
672 | ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK); | |
673 | cur_src += MAX_BULK; | |
674 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
675 | goto fail; | |
676 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK); | |
677 | cur_dst += MAX_BULK; | |
678 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
679 | goto fail; | |
680 | } | |
681 | ||
682 | /* check data */ | |
683 | if (memcmp(src, dst, cur_dst - dst)) { | |
684 | rte_hexdump(stdout, "src", src, cur_src - src); | |
685 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
686 | printf("data after dequeue is not the same\n"); | |
687 | goto fail; | |
688 | } | |
689 | ||
690 | cur_src = src; | |
691 | cur_dst = dst; | |
692 | ||
693 | printf("Test enqueue without enough memory space \n"); | |
694 | for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) { | |
695 | ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK); | |
696 | cur_src += MAX_BULK; | |
697 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
698 | goto fail; | |
699 | } | |
700 | ||
701 | /* Available memory space for the exact MAX_BULK objects */ | |
702 | ret = rte_ring_mp_enqueue_burst(r, cur_src, 2); | |
703 | cur_src += 2; | |
704 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
705 | goto fail; | |
706 | ||
707 | ret = rte_ring_mp_enqueue_burst(r, cur_src, MAX_BULK); | |
708 | cur_src += MAX_BULK - 3; | |
709 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3) | |
710 | goto fail; | |
711 | ||
712 | ||
713 | printf("Test dequeue without enough objects \n"); | |
714 | for (i = 0; i<RING_SIZE/MAX_BULK - 1; i++) { | |
715 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK); | |
716 | cur_dst += MAX_BULK; | |
717 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK) | |
718 | goto fail; | |
719 | } | |
720 | ||
721 | /* Available objects - the exact MAX_BULK */ | |
722 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, 2); | |
723 | cur_dst += 2; | |
724 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
725 | goto fail; | |
726 | ||
727 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, MAX_BULK); | |
728 | cur_dst += MAX_BULK - 3; | |
729 | if ((ret & RTE_RING_SZ_MASK) != MAX_BULK - 3) | |
730 | goto fail; | |
731 | ||
732 | /* check data */ | |
733 | if (memcmp(src, dst, cur_dst - dst)) { | |
734 | rte_hexdump(stdout, "src", src, cur_src - src); | |
735 | rte_hexdump(stdout, "dst", dst, cur_dst - dst); | |
736 | printf("data after dequeue is not the same\n"); | |
737 | goto fail; | |
738 | } | |
739 | ||
740 | cur_src = src; | |
741 | cur_dst = dst; | |
742 | ||
743 | printf("Covering rte_ring_enqueue_burst functions \n"); | |
744 | ||
745 | ret = rte_ring_enqueue_burst(r, cur_src, 2); | |
746 | cur_src += 2; | |
747 | if ((ret & RTE_RING_SZ_MASK) != 2) | |
748 | goto fail; | |
749 | ||
750 | ret = rte_ring_dequeue_burst(r, cur_dst, 2); | |
751 | cur_dst += 2; | |
752 | if (ret != 2) | |
753 | goto fail; | |
754 | ||
755 | /* Free memory before test completed */ | |
756 | free(src); | |
757 | free(dst); | |
758 | return 0; | |
759 | ||
760 | fail: | |
761 | free(src); | |
762 | free(dst); | |
763 | return -1; | |
764 | } | |
765 | ||
766 | static int | |
767 | test_ring_stats(void) | |
768 | { | |
769 | ||
770 | #ifndef RTE_LIBRTE_RING_DEBUG | |
771 | printf("Enable RTE_LIBRTE_RING_DEBUG to test ring stats.\n"); | |
772 | return 0; | |
773 | #else | |
774 | void **src = NULL, **cur_src = NULL, **dst = NULL, **cur_dst = NULL; | |
775 | int ret; | |
776 | unsigned i; | |
777 | unsigned num_items = 0; | |
778 | unsigned failed_enqueue_ops = 0; | |
779 | unsigned failed_enqueue_items = 0; | |
780 | unsigned failed_dequeue_ops = 0; | |
781 | unsigned failed_dequeue_items = 0; | |
782 | unsigned last_enqueue_ops = 0; | |
783 | unsigned last_enqueue_items = 0; | |
784 | unsigned last_quota_ops = 0; | |
785 | unsigned last_quota_items = 0; | |
786 | unsigned lcore_id = rte_lcore_id(); | |
787 | struct rte_ring_debug_stats *ring_stats = &r->stats[lcore_id]; | |
788 | ||
789 | printf("Test the ring stats.\n"); | |
790 | ||
791 | /* Reset the watermark in case it was set in another test. */ | |
792 | rte_ring_set_water_mark(r, 0); | |
793 | ||
794 | /* Reset the ring stats. */ | |
795 | memset(&r->stats[lcore_id], 0, sizeof(r->stats[lcore_id])); | |
796 | ||
797 | /* Allocate some dummy object pointers. */ | |
798 | src = malloc(RING_SIZE*2*sizeof(void *)); | |
799 | if (src == NULL) | |
800 | goto fail; | |
801 | ||
802 | for (i = 0; i < RING_SIZE*2 ; i++) { | |
803 | src[i] = (void *)(unsigned long)i; | |
804 | } | |
805 | ||
806 | /* Allocate some memory for copied objects. */ | |
807 | dst = malloc(RING_SIZE*2*sizeof(void *)); | |
808 | if (dst == NULL) | |
809 | goto fail; | |
810 | ||
811 | memset(dst, 0, RING_SIZE*2*sizeof(void *)); | |
812 | ||
813 | /* Set the head and tail pointers. */ | |
814 | cur_src = src; | |
815 | cur_dst = dst; | |
816 | ||
817 | /* Do Enqueue tests. */ | |
818 | printf("Test the dequeue stats.\n"); | |
819 | ||
820 | /* Fill the ring up to RING_SIZE -1. */ | |
821 | printf("Fill the ring.\n"); | |
822 | for (i = 0; i< (RING_SIZE/MAX_BULK); i++) { | |
823 | rte_ring_sp_enqueue_burst(r, cur_src, MAX_BULK); | |
824 | cur_src += MAX_BULK; | |
825 | } | |
826 | ||
827 | /* Adjust for final enqueue = MAX_BULK -1. */ | |
828 | cur_src--; | |
829 | ||
830 | printf("Verify that the ring is full.\n"); | |
831 | if (rte_ring_full(r) != 1) | |
832 | goto fail; | |
833 | ||
834 | ||
835 | printf("Verify the enqueue success stats.\n"); | |
836 | /* Stats should match above enqueue operations to fill the ring. */ | |
837 | if (ring_stats->enq_success_bulk != (RING_SIZE/MAX_BULK)) | |
838 | goto fail; | |
839 | ||
840 | /* Current max objects is RING_SIZE -1. */ | |
841 | if (ring_stats->enq_success_objs != RING_SIZE -1) | |
842 | goto fail; | |
843 | ||
844 | /* Shouldn't have any failures yet. */ | |
845 | if (ring_stats->enq_fail_bulk != 0) | |
846 | goto fail; | |
847 | if (ring_stats->enq_fail_objs != 0) | |
848 | goto fail; | |
849 | ||
850 | ||
851 | printf("Test stats for SP burst enqueue to a full ring.\n"); | |
852 | num_items = 2; | |
853 | ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); | |
854 | if ((ret & RTE_RING_SZ_MASK) != 0) | |
855 | goto fail; | |
856 | ||
857 | failed_enqueue_ops += 1; | |
858 | failed_enqueue_items += num_items; | |
859 | ||
860 | /* The enqueue should have failed. */ | |
861 | if (ring_stats->enq_fail_bulk != failed_enqueue_ops) | |
862 | goto fail; | |
863 | if (ring_stats->enq_fail_objs != failed_enqueue_items) | |
864 | goto fail; | |
865 | ||
866 | ||
867 | printf("Test stats for SP bulk enqueue to a full ring.\n"); | |
868 | num_items = 4; | |
869 | ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items); | |
870 | if (ret != -ENOBUFS) | |
871 | goto fail; | |
872 | ||
873 | failed_enqueue_ops += 1; | |
874 | failed_enqueue_items += num_items; | |
875 | ||
876 | /* The enqueue should have failed. */ | |
877 | if (ring_stats->enq_fail_bulk != failed_enqueue_ops) | |
878 | goto fail; | |
879 | if (ring_stats->enq_fail_objs != failed_enqueue_items) | |
880 | goto fail; | |
881 | ||
882 | ||
883 | printf("Test stats for MP burst enqueue to a full ring.\n"); | |
884 | num_items = 8; | |
885 | ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items); | |
886 | if ((ret & RTE_RING_SZ_MASK) != 0) | |
887 | goto fail; | |
888 | ||
889 | failed_enqueue_ops += 1; | |
890 | failed_enqueue_items += num_items; | |
891 | ||
892 | /* The enqueue should have failed. */ | |
893 | if (ring_stats->enq_fail_bulk != failed_enqueue_ops) | |
894 | goto fail; | |
895 | if (ring_stats->enq_fail_objs != failed_enqueue_items) | |
896 | goto fail; | |
897 | ||
898 | ||
899 | printf("Test stats for MP bulk enqueue to a full ring.\n"); | |
900 | num_items = 16; | |
901 | ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items); | |
902 | if (ret != -ENOBUFS) | |
903 | goto fail; | |
904 | ||
905 | failed_enqueue_ops += 1; | |
906 | failed_enqueue_items += num_items; | |
907 | ||
908 | /* The enqueue should have failed. */ | |
909 | if (ring_stats->enq_fail_bulk != failed_enqueue_ops) | |
910 | goto fail; | |
911 | if (ring_stats->enq_fail_objs != failed_enqueue_items) | |
912 | goto fail; | |
913 | ||
914 | ||
915 | /* Do Dequeue tests. */ | |
916 | printf("Test the dequeue stats.\n"); | |
917 | ||
918 | printf("Empty the ring.\n"); | |
919 | for (i = 0; i<RING_SIZE/MAX_BULK; i++) { | |
920 | rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK); | |
921 | cur_dst += MAX_BULK; | |
922 | } | |
923 | ||
924 | /* There was only RING_SIZE -1 objects to dequeue. */ | |
925 | cur_dst++; | |
926 | ||
927 | printf("Verify ring is empty.\n"); | |
928 | if (1 != rte_ring_empty(r)) | |
929 | goto fail; | |
930 | ||
931 | printf("Verify the dequeue success stats.\n"); | |
932 | /* Stats should match above dequeue operations. */ | |
933 | if (ring_stats->deq_success_bulk != (RING_SIZE/MAX_BULK)) | |
934 | goto fail; | |
935 | ||
936 | /* Objects dequeued is RING_SIZE -1. */ | |
937 | if (ring_stats->deq_success_objs != RING_SIZE -1) | |
938 | goto fail; | |
939 | ||
940 | /* Shouldn't have any dequeue failure stats yet. */ | |
941 | if (ring_stats->deq_fail_bulk != 0) | |
942 | goto fail; | |
943 | ||
944 | printf("Test stats for SC burst dequeue with an empty ring.\n"); | |
945 | num_items = 2; | |
946 | ret = rte_ring_sc_dequeue_burst(r, cur_dst, num_items); | |
947 | if ((ret & RTE_RING_SZ_MASK) != 0) | |
948 | goto fail; | |
949 | ||
950 | failed_dequeue_ops += 1; | |
951 | failed_dequeue_items += num_items; | |
952 | ||
953 | /* The dequeue should have failed. */ | |
954 | if (ring_stats->deq_fail_bulk != failed_dequeue_ops) | |
955 | goto fail; | |
956 | if (ring_stats->deq_fail_objs != failed_dequeue_items) | |
957 | goto fail; | |
958 | ||
959 | ||
960 | printf("Test stats for SC bulk dequeue with an empty ring.\n"); | |
961 | num_items = 4; | |
962 | ret = rte_ring_sc_dequeue_bulk(r, cur_dst, num_items); | |
963 | if (ret != -ENOENT) | |
964 | goto fail; | |
965 | ||
966 | failed_dequeue_ops += 1; | |
967 | failed_dequeue_items += num_items; | |
968 | ||
969 | /* The dequeue should have failed. */ | |
970 | if (ring_stats->deq_fail_bulk != failed_dequeue_ops) | |
971 | goto fail; | |
972 | if (ring_stats->deq_fail_objs != failed_dequeue_items) | |
973 | goto fail; | |
974 | ||
975 | ||
976 | printf("Test stats for MC burst dequeue with an empty ring.\n"); | |
977 | num_items = 8; | |
978 | ret = rte_ring_mc_dequeue_burst(r, cur_dst, num_items); | |
979 | if ((ret & RTE_RING_SZ_MASK) != 0) | |
980 | goto fail; | |
981 | failed_dequeue_ops += 1; | |
982 | failed_dequeue_items += num_items; | |
983 | ||
984 | /* The dequeue should have failed. */ | |
985 | if (ring_stats->deq_fail_bulk != failed_dequeue_ops) | |
986 | goto fail; | |
987 | if (ring_stats->deq_fail_objs != failed_dequeue_items) | |
988 | goto fail; | |
989 | ||
990 | ||
991 | printf("Test stats for MC bulk dequeue with an empty ring.\n"); | |
992 | num_items = 16; | |
993 | ret = rte_ring_mc_dequeue_bulk(r, cur_dst, num_items); | |
994 | if (ret != -ENOENT) | |
995 | goto fail; | |
996 | ||
997 | failed_dequeue_ops += 1; | |
998 | failed_dequeue_items += num_items; | |
999 | ||
1000 | /* The dequeue should have failed. */ | |
1001 | if (ring_stats->deq_fail_bulk != failed_dequeue_ops) | |
1002 | goto fail; | |
1003 | if (ring_stats->deq_fail_objs != failed_dequeue_items) | |
1004 | goto fail; | |
1005 | ||
1006 | ||
1007 | printf("Test total enqueue/dequeue stats.\n"); | |
1008 | /* At this point the enqueue and dequeue stats should be the same. */ | |
1009 | if (ring_stats->enq_success_bulk != ring_stats->deq_success_bulk) | |
1010 | goto fail; | |
1011 | if (ring_stats->enq_success_objs != ring_stats->deq_success_objs) | |
1012 | goto fail; | |
1013 | if (ring_stats->enq_fail_bulk != ring_stats->deq_fail_bulk) | |
1014 | goto fail; | |
1015 | if (ring_stats->enq_fail_objs != ring_stats->deq_fail_objs) | |
1016 | goto fail; | |
1017 | ||
1018 | ||
1019 | /* Watermark Tests. */ | |
1020 | printf("Test the watermark/quota stats.\n"); | |
1021 | ||
1022 | printf("Verify the initial watermark stats.\n"); | |
1023 | /* Watermark stats should be 0 since there is no watermark. */ | |
1024 | if (ring_stats->enq_quota_bulk != 0) | |
1025 | goto fail; | |
1026 | if (ring_stats->enq_quota_objs != 0) | |
1027 | goto fail; | |
1028 | ||
1029 | /* Set a watermark. */ | |
1030 | rte_ring_set_water_mark(r, 16); | |
1031 | ||
1032 | /* Reset pointers. */ | |
1033 | cur_src = src; | |
1034 | cur_dst = dst; | |
1035 | ||
1036 | last_enqueue_ops = ring_stats->enq_success_bulk; | |
1037 | last_enqueue_items = ring_stats->enq_success_objs; | |
1038 | ||
1039 | ||
1040 | printf("Test stats for SP burst enqueue below watermark.\n"); | |
1041 | num_items = 8; | |
1042 | ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); | |
1043 | if ((ret & RTE_RING_SZ_MASK) != num_items) | |
1044 | goto fail; | |
1045 | ||
1046 | /* Watermark stats should still be 0. */ | |
1047 | if (ring_stats->enq_quota_bulk != 0) | |
1048 | goto fail; | |
1049 | if (ring_stats->enq_quota_objs != 0) | |
1050 | goto fail; | |
1051 | ||
1052 | /* Success stats should have increased. */ | |
1053 | if (ring_stats->enq_success_bulk != last_enqueue_ops + 1) | |
1054 | goto fail; | |
1055 | if (ring_stats->enq_success_objs != last_enqueue_items + num_items) | |
1056 | goto fail; | |
1057 | ||
1058 | last_enqueue_ops = ring_stats->enq_success_bulk; | |
1059 | last_enqueue_items = ring_stats->enq_success_objs; | |
1060 | ||
1061 | ||
1062 | printf("Test stats for SP burst enqueue at watermark.\n"); | |
1063 | num_items = 8; | |
1064 | ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); | |
1065 | if ((ret & RTE_RING_SZ_MASK) != num_items) | |
1066 | goto fail; | |
1067 | ||
1068 | /* Watermark stats should have changed. */ | |
1069 | if (ring_stats->enq_quota_bulk != 1) | |
1070 | goto fail; | |
1071 | if (ring_stats->enq_quota_objs != num_items) | |
1072 | goto fail; | |
1073 | ||
1074 | last_quota_ops = ring_stats->enq_quota_bulk; | |
1075 | last_quota_items = ring_stats->enq_quota_objs; | |
1076 | ||
1077 | ||
1078 | printf("Test stats for SP burst enqueue above watermark.\n"); | |
1079 | num_items = 1; | |
1080 | ret = rte_ring_sp_enqueue_burst(r, cur_src, num_items); | |
1081 | if ((ret & RTE_RING_SZ_MASK) != num_items) | |
1082 | goto fail; | |
1083 | ||
1084 | /* Watermark stats should have changed. */ | |
1085 | if (ring_stats->enq_quota_bulk != last_quota_ops +1) | |
1086 | goto fail; | |
1087 | if (ring_stats->enq_quota_objs != last_quota_items + num_items) | |
1088 | goto fail; | |
1089 | ||
1090 | last_quota_ops = ring_stats->enq_quota_bulk; | |
1091 | last_quota_items = ring_stats->enq_quota_objs; | |
1092 | ||
1093 | ||
1094 | printf("Test stats for MP burst enqueue above watermark.\n"); | |
1095 | num_items = 2; | |
1096 | ret = rte_ring_mp_enqueue_burst(r, cur_src, num_items); | |
1097 | if ((ret & RTE_RING_SZ_MASK) != num_items) | |
1098 | goto fail; | |
1099 | ||
1100 | /* Watermark stats should have changed. */ | |
1101 | if (ring_stats->enq_quota_bulk != last_quota_ops +1) | |
1102 | goto fail; | |
1103 | if (ring_stats->enq_quota_objs != last_quota_items + num_items) | |
1104 | goto fail; | |
1105 | ||
1106 | last_quota_ops = ring_stats->enq_quota_bulk; | |
1107 | last_quota_items = ring_stats->enq_quota_objs; | |
1108 | ||
1109 | ||
1110 | printf("Test stats for SP bulk enqueue above watermark.\n"); | |
1111 | num_items = 4; | |
1112 | ret = rte_ring_sp_enqueue_bulk(r, cur_src, num_items); | |
1113 | if (ret != -EDQUOT) | |
1114 | goto fail; | |
1115 | ||
1116 | /* Watermark stats should have changed. */ | |
1117 | if (ring_stats->enq_quota_bulk != last_quota_ops +1) | |
1118 | goto fail; | |
1119 | if (ring_stats->enq_quota_objs != last_quota_items + num_items) | |
1120 | goto fail; | |
1121 | ||
1122 | last_quota_ops = ring_stats->enq_quota_bulk; | |
1123 | last_quota_items = ring_stats->enq_quota_objs; | |
1124 | ||
1125 | ||
1126 | printf("Test stats for MP bulk enqueue above watermark.\n"); | |
1127 | num_items = 8; | |
1128 | ret = rte_ring_mp_enqueue_bulk(r, cur_src, num_items); | |
1129 | if (ret != -EDQUOT) | |
1130 | goto fail; | |
1131 | ||
1132 | /* Watermark stats should have changed. */ | |
1133 | if (ring_stats->enq_quota_bulk != last_quota_ops +1) | |
1134 | goto fail; | |
1135 | if (ring_stats->enq_quota_objs != last_quota_items + num_items) | |
1136 | goto fail; | |
1137 | ||
1138 | printf("Test watermark success stats.\n"); | |
1139 | /* Success stats should be same as last non-watermarked enqueue. */ | |
1140 | if (ring_stats->enq_success_bulk != last_enqueue_ops) | |
1141 | goto fail; | |
1142 | if (ring_stats->enq_success_objs != last_enqueue_items) | |
1143 | goto fail; | |
1144 | ||
1145 | ||
1146 | /* Cleanup. */ | |
1147 | ||
1148 | /* Empty the ring. */ | |
1149 | for (i = 0; i<RING_SIZE/MAX_BULK; i++) { | |
1150 | rte_ring_sc_dequeue_burst(r, cur_dst, MAX_BULK); | |
1151 | cur_dst += MAX_BULK; | |
1152 | } | |
1153 | ||
1154 | /* Reset the watermark. */ | |
1155 | rte_ring_set_water_mark(r, 0); | |
1156 | ||
1157 | /* Reset the ring stats. */ | |
1158 | memset(&r->stats[lcore_id], 0, sizeof(r->stats[lcore_id])); | |
1159 | ||
1160 | /* Free memory before test completed */ | |
1161 | free(src); | |
1162 | free(dst); | |
1163 | return 0; | |
1164 | ||
1165 | fail: | |
1166 | free(src); | |
1167 | free(dst); | |
1168 | return -1; | |
1169 | #endif | |
1170 | } | |
1171 | ||
1172 | /* | |
1173 | * it will always fail to create ring with a wrong ring size number in this function | |
1174 | */ | |
1175 | static int | |
1176 | test_ring_creation_with_wrong_size(void) | |
1177 | { | |
1178 | struct rte_ring * rp = NULL; | |
1179 | ||
1180 | /* Test if ring size is not power of 2 */ | |
1181 | rp = rte_ring_create("test_bad_ring_size", RING_SIZE + 1, SOCKET_ID_ANY, 0); | |
1182 | if (NULL != rp) { | |
1183 | return -1; | |
1184 | } | |
1185 | ||
1186 | /* Test if ring size is exceeding the limit */ | |
1187 | rp = rte_ring_create("test_bad_ring_size", (RTE_RING_SZ_MASK + 1), SOCKET_ID_ANY, 0); | |
1188 | if (NULL != rp) { | |
1189 | return -1; | |
1190 | } | |
1191 | return 0; | |
1192 | } | |
1193 | ||
1194 | /* | |
1195 | * it tests if it would always fail to create ring with an used ring name | |
1196 | */ | |
1197 | static int | |
1198 | test_ring_creation_with_an_used_name(void) | |
1199 | { | |
1200 | struct rte_ring * rp; | |
1201 | ||
1202 | rp = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0); | |
1203 | if (NULL != rp) | |
1204 | return -1; | |
1205 | ||
1206 | return 0; | |
1207 | } | |
1208 | ||
1209 | /* | |
1210 | * Test to if a non-power of 2 count causes the create | |
1211 | * function to fail correctly | |
1212 | */ | |
1213 | static int | |
1214 | test_create_count_odd(void) | |
1215 | { | |
1216 | struct rte_ring *r = rte_ring_create("test_ring_count", | |
1217 | 4097, SOCKET_ID_ANY, 0 ); | |
1218 | if(r != NULL){ | |
1219 | return -1; | |
1220 | } | |
1221 | return 0; | |
1222 | } | |
1223 | ||
1224 | static int | |
1225 | test_lookup_null(void) | |
1226 | { | |
1227 | struct rte_ring *rlp = rte_ring_lookup("ring_not_found"); | |
1228 | if (rlp ==NULL) | |
1229 | if (rte_errno != ENOENT){ | |
1230 | printf( "test failed to returnn error on null pointer\n"); | |
1231 | return -1; | |
1232 | } | |
1233 | return 0; | |
1234 | } | |
1235 | ||
1236 | /* | |
1237 | * it tests some more basic ring operations | |
1238 | */ | |
1239 | static int | |
1240 | test_ring_basic_ex(void) | |
1241 | { | |
1242 | int ret = -1; | |
1243 | unsigned i; | |
1244 | struct rte_ring * rp; | |
1245 | void **obj = NULL; | |
1246 | ||
1247 | obj = rte_calloc("test_ring_basic_ex_malloc", RING_SIZE, sizeof(void *), 0); | |
1248 | if (obj == NULL) { | |
1249 | printf("test_ring_basic_ex fail to rte_malloc\n"); | |
1250 | goto fail_test; | |
1251 | } | |
1252 | ||
1253 | rp = rte_ring_create("test_ring_basic_ex", RING_SIZE, SOCKET_ID_ANY, | |
1254 | RING_F_SP_ENQ | RING_F_SC_DEQ); | |
1255 | if (rp == NULL) { | |
1256 | printf("test_ring_basic_ex fail to create ring\n"); | |
1257 | goto fail_test; | |
1258 | } | |
1259 | ||
1260 | if (rte_ring_lookup("test_ring_basic_ex") != rp) { | |
1261 | goto fail_test; | |
1262 | } | |
1263 | ||
1264 | if (rte_ring_empty(rp) != 1) { | |
1265 | printf("test_ring_basic_ex ring is not empty but it should be\n"); | |
1266 | goto fail_test; | |
1267 | } | |
1268 | ||
1269 | printf("%u ring entries are now free\n", rte_ring_free_count(rp)); | |
1270 | ||
1271 | for (i = 0; i < RING_SIZE; i ++) { | |
1272 | rte_ring_enqueue(rp, obj[i]); | |
1273 | } | |
1274 | ||
1275 | if (rte_ring_full(rp) != 1) { | |
1276 | printf("test_ring_basic_ex ring is not full but it should be\n"); | |
1277 | goto fail_test; | |
1278 | } | |
1279 | ||
1280 | for (i = 0; i < RING_SIZE; i ++) { | |
1281 | rte_ring_dequeue(rp, &obj[i]); | |
1282 | } | |
1283 | ||
1284 | if (rte_ring_empty(rp) != 1) { | |
1285 | printf("test_ring_basic_ex ring is not empty but it should be\n"); | |
1286 | goto fail_test; | |
1287 | } | |
1288 | ||
1289 | /* Covering the ring burst operation */ | |
1290 | ret = rte_ring_enqueue_burst(rp, obj, 2); | |
1291 | if ((ret & RTE_RING_SZ_MASK) != 2) { | |
1292 | printf("test_ring_basic_ex: rte_ring_enqueue_burst fails \n"); | |
1293 | goto fail_test; | |
1294 | } | |
1295 | ||
1296 | ret = rte_ring_dequeue_burst(rp, obj, 2); | |
1297 | if (ret != 2) { | |
1298 | printf("test_ring_basic_ex: rte_ring_dequeue_burst fails \n"); | |
1299 | goto fail_test; | |
1300 | } | |
1301 | ||
1302 | ret = 0; | |
1303 | fail_test: | |
1304 | if (obj != NULL) | |
1305 | rte_free(obj); | |
1306 | ||
1307 | return ret; | |
1308 | } | |
1309 | ||
1310 | static int | |
1311 | test_ring(void) | |
1312 | { | |
1313 | /* some more basic operations */ | |
1314 | if (test_ring_basic_ex() < 0) | |
1315 | return -1; | |
1316 | ||
1317 | rte_atomic32_init(&synchro); | |
1318 | ||
1319 | if (r == NULL) | |
1320 | r = rte_ring_create("test", RING_SIZE, SOCKET_ID_ANY, 0); | |
1321 | if (r == NULL) | |
1322 | return -1; | |
1323 | ||
1324 | /* retrieve the ring from its name */ | |
1325 | if (rte_ring_lookup("test") != r) { | |
1326 | printf("Cannot lookup ring from its name\n"); | |
1327 | return -1; | |
1328 | } | |
1329 | ||
1330 | /* burst operations */ | |
1331 | if (test_ring_burst_basic() < 0) | |
1332 | return -1; | |
1333 | ||
1334 | /* basic operations */ | |
1335 | if (test_ring_basic() < 0) | |
1336 | return -1; | |
1337 | ||
1338 | /* ring stats */ | |
1339 | if (test_ring_stats() < 0) | |
1340 | return -1; | |
1341 | ||
1342 | /* basic operations */ | |
1343 | if (test_live_watermark_change() < 0) | |
1344 | return -1; | |
1345 | ||
1346 | if ( test_set_watermark() < 0){ | |
1347 | printf ("Test failed to detect invalid parameter\n"); | |
1348 | return -1; | |
1349 | } | |
1350 | else | |
1351 | printf ( "Test detected forced bad watermark values\n"); | |
1352 | ||
1353 | if ( test_create_count_odd() < 0){ | |
1354 | printf ("Test failed to detect odd count\n"); | |
1355 | return -1; | |
1356 | } | |
1357 | else | |
1358 | printf ( "Test detected odd count\n"); | |
1359 | ||
1360 | if ( test_lookup_null() < 0){ | |
1361 | printf ("Test failed to detect NULL ring lookup\n"); | |
1362 | return -1; | |
1363 | } | |
1364 | else | |
1365 | printf ( "Test detected NULL ring lookup \n"); | |
1366 | ||
1367 | /* test of creating ring with wrong size */ | |
1368 | if (test_ring_creation_with_wrong_size() < 0) | |
1369 | return -1; | |
1370 | ||
1371 | /* test of creation ring with an used name */ | |
1372 | if (test_ring_creation_with_an_used_name() < 0) | |
1373 | return -1; | |
1374 | ||
1375 | /* dump the ring status */ | |
1376 | rte_ring_list_dump(stdout); | |
1377 | ||
1378 | return 0; | |
1379 | } | |
1380 | ||
1381 | REGISTER_TEST_COMMAND(ring_autotest, test_ring); |