mempool: add event callbacks
[dpdk.git] / app / test / test_mempool.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <inttypes.h>
10 #include <stdarg.h>
11 #include <errno.h>
12 #include <sys/queue.h>
13
14 #include <rte_common.h>
15 #include <rte_log.h>
16 #include <rte_debug.h>
17 #include <rte_errno.h>
18 #include <rte_memory.h>
19 #include <rte_launch.h>
20 #include <rte_cycles.h>
21 #include <rte_eal.h>
22 #include <rte_per_lcore.h>
23 #include <rte_lcore.h>
24 #include <rte_branch_prediction.h>
25 #include <rte_mempool.h>
26 #include <rte_spinlock.h>
27 #include <rte_malloc.h>
28 #include <rte_mbuf_pool_ops.h>
29 #include <rte_mbuf.h>
30
31 #include "test.h"
32
33 /*
34  * Mempool
35  * =======
36  *
37  * Basic tests: done on one core with and without cache:
38  *
39  *    - Get one object, put one object
40  *    - Get two objects, put two objects
41  *    - Get all objects, test that their content is not modified and
42  *      put them back in the pool.
43  */
44
45 #define MEMPOOL_ELT_SIZE 2048
46 #define MAX_KEEP 16
47 #define MEMPOOL_SIZE ((rte_lcore_count()*(MAX_KEEP+RTE_MEMPOOL_CACHE_MAX_SIZE))-1)
48
49 #define LOG_ERR() printf("test failed at %s():%d\n", __func__, __LINE__)
50 #define RET_ERR() do {                                                  \
51                 LOG_ERR();                                              \
52                 return -1;                                              \
53         } while (0)
54 #define GOTO_ERR(var, label) do {                                       \
55                 LOG_ERR();                                              \
56                 var = -1;                                               \
57                 goto label;                                             \
58         } while (0)
59
60 /*
61  * save the object number in the first 4 bytes of object data. All
62  * other bytes are set to 0.
63  */
64 static void
65 my_obj_init(struct rte_mempool *mp, __rte_unused void *arg,
66             void *obj, unsigned i)
67 {
68         uint32_t *objnum = obj;
69
70         memset(obj, 0, mp->elt_size);
71         *objnum = i;
72 }
73
74 /* basic tests (done on one core) */
75 static int
76 test_mempool_basic(struct rte_mempool *mp, int use_external_cache)
77 {
78         uint32_t *objnum;
79         void **objtable;
80         void *obj, *obj2;
81         char *obj_data;
82         int ret = 0;
83         unsigned i, j;
84         int offset;
85         struct rte_mempool_cache *cache;
86
87         if (use_external_cache) {
88                 /* Create a user-owned mempool cache. */
89                 cache = rte_mempool_cache_create(RTE_MEMPOOL_CACHE_MAX_SIZE,
90                                                  SOCKET_ID_ANY);
91                 if (cache == NULL)
92                         RET_ERR();
93         } else {
94                 /* May be NULL if cache is disabled. */
95                 cache = rte_mempool_default_cache(mp, rte_lcore_id());
96         }
97
98         /* dump the mempool status */
99         rte_mempool_dump(stdout, mp);
100
101         printf("get an object\n");
102         if (rte_mempool_generic_get(mp, &obj, 1, cache) < 0)
103                 GOTO_ERR(ret, out);
104         rte_mempool_dump(stdout, mp);
105
106         /* tests that improve coverage */
107         printf("get object count\n");
108         /* We have to count the extra caches, one in this case. */
109         offset = use_external_cache ? 1 * cache->len : 0;
110         if (rte_mempool_avail_count(mp) + offset != MEMPOOL_SIZE - 1)
111                 GOTO_ERR(ret, out);
112
113         printf("get private data\n");
114         if (rte_mempool_get_priv(mp) != (char *)mp +
115                         MEMPOOL_HEADER_SIZE(mp, mp->cache_size))
116                 GOTO_ERR(ret, out);
117
118 #ifndef RTE_EXEC_ENV_FREEBSD /* rte_mem_virt2iova() not supported on bsd */
119         printf("get physical address of an object\n");
120         if (rte_mempool_virt2iova(obj) != rte_mem_virt2iova(obj))
121                 GOTO_ERR(ret, out);
122 #endif
123
124         printf("put the object back\n");
125         rte_mempool_generic_put(mp, &obj, 1, cache);
126         rte_mempool_dump(stdout, mp);
127
128         printf("get 2 objects\n");
129         if (rte_mempool_generic_get(mp, &obj, 1, cache) < 0)
130                 GOTO_ERR(ret, out);
131         if (rte_mempool_generic_get(mp, &obj2, 1, cache) < 0) {
132                 rte_mempool_generic_put(mp, &obj, 1, cache);
133                 GOTO_ERR(ret, out);
134         }
135         rte_mempool_dump(stdout, mp);
136
137         printf("put the objects back\n");
138         rte_mempool_generic_put(mp, &obj, 1, cache);
139         rte_mempool_generic_put(mp, &obj2, 1, cache);
140         rte_mempool_dump(stdout, mp);
141
142         /*
143          * get many objects: we cannot get them all because the cache
144          * on other cores may not be empty.
145          */
146         objtable = malloc(MEMPOOL_SIZE * sizeof(void *));
147         if (objtable == NULL)
148                 GOTO_ERR(ret, out);
149
150         for (i = 0; i < MEMPOOL_SIZE; i++) {
151                 if (rte_mempool_generic_get(mp, &objtable[i], 1, cache) < 0)
152                         break;
153         }
154
155         /*
156          * for each object, check that its content was not modified,
157          * and put objects back in pool
158          */
159         while (i--) {
160                 obj = objtable[i];
161                 obj_data = obj;
162                 objnum = obj;
163                 if (*objnum > MEMPOOL_SIZE) {
164                         printf("bad object number(%d)\n", *objnum);
165                         ret = -1;
166                         break;
167                 }
168                 for (j = sizeof(*objnum); j < mp->elt_size; j++) {
169                         if (obj_data[j] != 0)
170                                 ret = -1;
171                 }
172
173                 rte_mempool_generic_put(mp, &objtable[i], 1, cache);
174         }
175
176         free(objtable);
177         if (ret == -1)
178                 printf("objects were modified!\n");
179
180 out:
181         if (use_external_cache) {
182                 rte_mempool_cache_flush(cache, mp);
183                 rte_mempool_cache_free(cache);
184         }
185
186         return ret;
187 }
188
189 static int test_mempool_creation_with_exceeded_cache_size(void)
190 {
191         struct rte_mempool *mp_cov;
192
193         mp_cov = rte_mempool_create("test_mempool_cache_too_big",
194                 MEMPOOL_SIZE,
195                 MEMPOOL_ELT_SIZE,
196                 RTE_MEMPOOL_CACHE_MAX_SIZE + 32, 0,
197                 NULL, NULL,
198                 my_obj_init, NULL,
199                 SOCKET_ID_ANY, 0);
200
201         if (mp_cov != NULL) {
202                 rte_mempool_free(mp_cov);
203                 RET_ERR();
204         }
205
206         return 0;
207 }
208
209 static int test_mempool_creation_with_unknown_flag(void)
210 {
211         struct rte_mempool *mp_cov;
212
213         mp_cov = rte_mempool_create("test_mempool_unknown_flag", MEMPOOL_SIZE,
214                 MEMPOOL_ELT_SIZE, 0, 0,
215                 NULL, NULL,
216                 NULL, NULL,
217                 SOCKET_ID_ANY, MEMPOOL_F_NO_IOVA_CONTIG << 1);
218
219         if (mp_cov != NULL) {
220                 rte_mempool_free(mp_cov);
221                 RET_ERR();
222         }
223
224         return 0;
225 }
226
227 static struct rte_mempool *mp_spsc;
228 static rte_spinlock_t scsp_spinlock;
229 static void *scsp_obj_table[MAX_KEEP];
230
231 /*
232  * single producer function
233  */
234 static int test_mempool_single_producer(void)
235 {
236         unsigned int i;
237         void *obj = NULL;
238         uint64_t start_cycles, end_cycles;
239         uint64_t duration = rte_get_timer_hz() / 4;
240
241         start_cycles = rte_get_timer_cycles();
242         while (1) {
243                 end_cycles = rte_get_timer_cycles();
244                 /* duration uses up, stop producing */
245                 if (start_cycles + duration < end_cycles)
246                         break;
247                 rte_spinlock_lock(&scsp_spinlock);
248                 for (i = 0; i < MAX_KEEP; i ++) {
249                         if (NULL != scsp_obj_table[i]) {
250                                 obj = scsp_obj_table[i];
251                                 break;
252                         }
253                 }
254                 rte_spinlock_unlock(&scsp_spinlock);
255                 if (i >= MAX_KEEP) {
256                         continue;
257                 }
258                 if (rte_mempool_from_obj(obj) != mp_spsc) {
259                         printf("obj not owned by this mempool\n");
260                         RET_ERR();
261                 }
262                 rte_mempool_put(mp_spsc, obj);
263                 rte_spinlock_lock(&scsp_spinlock);
264                 scsp_obj_table[i] = NULL;
265                 rte_spinlock_unlock(&scsp_spinlock);
266         }
267
268         return 0;
269 }
270
271 /*
272  * single consumer function
273  */
274 static int test_mempool_single_consumer(void)
275 {
276         unsigned int i;
277         void * obj;
278         uint64_t start_cycles, end_cycles;
279         uint64_t duration = rte_get_timer_hz() / 8;
280
281         start_cycles = rte_get_timer_cycles();
282         while (1) {
283                 end_cycles = rte_get_timer_cycles();
284                 /* duration uses up, stop consuming */
285                 if (start_cycles + duration < end_cycles)
286                         break;
287                 rte_spinlock_lock(&scsp_spinlock);
288                 for (i = 0; i < MAX_KEEP; i ++) {
289                         if (NULL == scsp_obj_table[i])
290                                 break;
291                 }
292                 rte_spinlock_unlock(&scsp_spinlock);
293                 if (i >= MAX_KEEP)
294                         continue;
295                 if (rte_mempool_get(mp_spsc, &obj) < 0)
296                         break;
297                 rte_spinlock_lock(&scsp_spinlock);
298                 scsp_obj_table[i] = obj;
299                 rte_spinlock_unlock(&scsp_spinlock);
300         }
301
302         return 0;
303 }
304
305 /*
306  * test function for mempool test based on singple consumer and single producer,
307  * can run on one lcore only
308  */
309 static int
310 test_mempool_launch_single_consumer(__rte_unused void *arg)
311 {
312         return test_mempool_single_consumer();
313 }
314
315 static void
316 my_mp_init(struct rte_mempool *mp, __rte_unused void *arg)
317 {
318         printf("mempool name is %s\n", mp->name);
319         /* nothing to be implemented here*/
320         return ;
321 }
322
323 /*
324  * it tests the mempool operations based on singple producer and single consumer
325  */
326 static int
327 test_mempool_sp_sc(void)
328 {
329         int ret = 0;
330         unsigned lcore_id = rte_lcore_id();
331         unsigned lcore_next;
332
333         /* create a mempool with single producer/consumer ring */
334         if (mp_spsc == NULL) {
335                 mp_spsc = rte_mempool_create("test_mempool_sp_sc", MEMPOOL_SIZE,
336                         MEMPOOL_ELT_SIZE, 0, 0,
337                         my_mp_init, NULL,
338                         my_obj_init, NULL,
339                         SOCKET_ID_ANY,
340                         MEMPOOL_F_NO_CACHE_ALIGN | MEMPOOL_F_SP_PUT |
341                         MEMPOOL_F_SC_GET);
342                 if (mp_spsc == NULL)
343                         RET_ERR();
344         }
345         if (rte_mempool_lookup("test_mempool_sp_sc") != mp_spsc) {
346                 printf("Cannot lookup mempool from its name\n");
347                 ret = -1;
348                 goto err;
349         }
350         lcore_next = rte_get_next_lcore(lcore_id, 0, 1);
351         if (lcore_next >= RTE_MAX_LCORE) {
352                 ret = -1;
353                 goto err;
354         }
355         if (rte_eal_lcore_role(lcore_next) != ROLE_RTE) {
356                 ret = -1;
357                 goto err;
358         }
359         rte_spinlock_init(&scsp_spinlock);
360         memset(scsp_obj_table, 0, sizeof(scsp_obj_table));
361         rte_eal_remote_launch(test_mempool_launch_single_consumer, NULL,
362                 lcore_next);
363         if (test_mempool_single_producer() < 0)
364                 ret = -1;
365
366         if (rte_eal_wait_lcore(lcore_next) < 0)
367                 ret = -1;
368
369 err:
370         rte_mempool_free(mp_spsc);
371         mp_spsc = NULL;
372
373         return ret;
374 }
375
376 /*
377  * it tests some more basic of mempool
378  */
379 static int
380 test_mempool_basic_ex(struct rte_mempool *mp)
381 {
382         unsigned i;
383         void **obj;
384         void *err_obj;
385         int ret = -1;
386
387         if (mp == NULL)
388                 return ret;
389
390         obj = rte_calloc("test_mempool_basic_ex", MEMPOOL_SIZE,
391                 sizeof(void *), 0);
392         if (obj == NULL) {
393                 printf("test_mempool_basic_ex fail to rte_malloc\n");
394                 return ret;
395         }
396         printf("test_mempool_basic_ex now mempool (%s) has %u free entries\n",
397                 mp->name, rte_mempool_in_use_count(mp));
398         if (rte_mempool_full(mp) != 1) {
399                 printf("test_mempool_basic_ex the mempool should be full\n");
400                 goto fail_mp_basic_ex;
401         }
402
403         for (i = 0; i < MEMPOOL_SIZE; i ++) {
404                 if (rte_mempool_get(mp, &obj[i]) < 0) {
405                         printf("test_mp_basic_ex fail to get object for [%u]\n",
406                                 i);
407                         goto fail_mp_basic_ex;
408                 }
409         }
410         if (rte_mempool_get(mp, &err_obj) == 0) {
411                 printf("test_mempool_basic_ex get an impossible obj\n");
412                 goto fail_mp_basic_ex;
413         }
414         printf("number: %u\n", i);
415         if (rte_mempool_empty(mp) != 1) {
416                 printf("test_mempool_basic_ex the mempool should be empty\n");
417                 goto fail_mp_basic_ex;
418         }
419
420         for (i = 0; i < MEMPOOL_SIZE; i++)
421                 rte_mempool_put(mp, obj[i]);
422
423         if (rte_mempool_full(mp) != 1) {
424                 printf("test_mempool_basic_ex the mempool should be full\n");
425                 goto fail_mp_basic_ex;
426         }
427
428         ret = 0;
429
430 fail_mp_basic_ex:
431         if (obj != NULL)
432                 rte_free((void *)obj);
433
434         return ret;
435 }
436
437 static int
438 test_mempool_same_name_twice_creation(void)
439 {
440         struct rte_mempool *mp_tc, *mp_tc2;
441
442         mp_tc = rte_mempool_create("test_mempool_same_name", MEMPOOL_SIZE,
443                 MEMPOOL_ELT_SIZE, 0, 0,
444                 NULL, NULL,
445                 NULL, NULL,
446                 SOCKET_ID_ANY, 0);
447
448         if (mp_tc == NULL)
449                 RET_ERR();
450
451         mp_tc2 = rte_mempool_create("test_mempool_same_name", MEMPOOL_SIZE,
452                 MEMPOOL_ELT_SIZE, 0, 0,
453                 NULL, NULL,
454                 NULL, NULL,
455                 SOCKET_ID_ANY, 0);
456
457         if (mp_tc2 != NULL) {
458                 rte_mempool_free(mp_tc);
459                 rte_mempool_free(mp_tc2);
460                 RET_ERR();
461         }
462
463         rte_mempool_free(mp_tc);
464         return 0;
465 }
466
467 static void
468 walk_cb(struct rte_mempool *mp, void *userdata __rte_unused)
469 {
470         printf("\t%s\n", mp->name);
471 }
472
473 struct mp_data {
474         int16_t ret;
475 };
476
477 static void
478 test_mp_mem_init(struct rte_mempool *mp,
479                 __rte_unused void *opaque,
480                 __rte_unused struct rte_mempool_memhdr *memhdr,
481                 __rte_unused unsigned int mem_idx)
482 {
483         struct mp_data *data = opaque;
484
485         if (mp == NULL) {
486                 data->ret = -1;
487                 return;
488         }
489         /* nothing to be implemented here*/
490         data->ret = 0;
491 }
492
493 struct test_mempool_events_data {
494         struct rte_mempool *mp;
495         enum rte_mempool_event event;
496         bool invoked;
497 };
498
499 static void
500 test_mempool_events_cb(enum rte_mempool_event event,
501                        struct rte_mempool *mp, void *user_data)
502 {
503         struct test_mempool_events_data *data = user_data;
504
505         data->mp = mp;
506         data->event = event;
507         data->invoked = true;
508 }
509
510 static int
511 test_mempool_events(int (*populate)(struct rte_mempool *mp))
512 {
513 #pragma push_macro("RTE_TEST_TRACE_FAILURE")
514 #undef RTE_TEST_TRACE_FAILURE
515 #define RTE_TEST_TRACE_FAILURE(...) do { goto fail; } while (0)
516
517         static const size_t CB_NUM = 3;
518         static const size_t MP_NUM = 2;
519
520         struct test_mempool_events_data data[CB_NUM];
521         struct rte_mempool *mp[MP_NUM], *freed;
522         char name[RTE_MEMPOOL_NAMESIZE];
523         size_t i, j;
524         int ret;
525
526         memset(mp, 0, sizeof(mp));
527         for (i = 0; i < CB_NUM; i++) {
528                 ret = rte_mempool_event_callback_register
529                                 (test_mempool_events_cb, &data[i]);
530                 RTE_TEST_ASSERT_EQUAL(ret, 0, "Failed to register the callback %zu: %s",
531                                       i, rte_strerror(rte_errno));
532         }
533         ret = rte_mempool_event_callback_unregister(test_mempool_events_cb, mp);
534         RTE_TEST_ASSERT_NOT_EQUAL(ret, 0, "Unregistered a non-registered callback");
535         /* NULL argument has no special meaning in this API. */
536         ret = rte_mempool_event_callback_unregister(test_mempool_events_cb,
537                                                     NULL);
538         RTE_TEST_ASSERT_NOT_EQUAL(ret, 0, "Unregistered a non-registered callback with NULL argument");
539
540         /* Create mempool 0 that will be observed by all callbacks. */
541         memset(&data, 0, sizeof(data));
542         strcpy(name, "empty0");
543         mp[0] = rte_mempool_create_empty(name, MEMPOOL_SIZE,
544                                          MEMPOOL_ELT_SIZE, 0, 0,
545                                          SOCKET_ID_ANY, 0);
546         RTE_TEST_ASSERT_NOT_NULL(mp[0], "Cannot create mempool %s: %s",
547                                  name, rte_strerror(rte_errno));
548         for (j = 0; j < CB_NUM; j++)
549                 RTE_TEST_ASSERT_EQUAL(data[j].invoked, false,
550                                       "Callback %zu invoked on %s mempool creation",
551                                       j, name);
552
553         rte_mempool_set_ops_byname(mp[0], rte_mbuf_best_mempool_ops(), NULL);
554         ret = populate(mp[0]);
555         RTE_TEST_ASSERT_EQUAL(ret, (int)mp[0]->size, "Failed to populate mempool %s: %s",
556                               name, rte_strerror(-ret));
557         for (j = 0; j < CB_NUM; j++) {
558                 RTE_TEST_ASSERT_EQUAL(data[j].invoked, true,
559                                         "Callback %zu not invoked on mempool %s population",
560                                         j, name);
561                 RTE_TEST_ASSERT_EQUAL(data[j].event,
562                                         RTE_MEMPOOL_EVENT_READY,
563                                         "Wrong callback invoked, expected READY");
564                 RTE_TEST_ASSERT_EQUAL(data[j].mp, mp[0],
565                                         "Callback %zu invoked for a wrong mempool instead of %s",
566                                         j, name);
567         }
568
569         /* Check that unregistered callback 0 observes no events. */
570         ret = rte_mempool_event_callback_unregister(test_mempool_events_cb,
571                                                     &data[0]);
572         RTE_TEST_ASSERT_EQUAL(ret, 0, "Failed to unregister callback 0: %s",
573                               rte_strerror(rte_errno));
574         memset(&data, 0, sizeof(data));
575         strcpy(name, "empty1");
576         mp[1] = rte_mempool_create_empty(name, MEMPOOL_SIZE,
577                                          MEMPOOL_ELT_SIZE, 0, 0,
578                                          SOCKET_ID_ANY, 0);
579         RTE_TEST_ASSERT_NOT_NULL(mp[1], "Cannot create mempool %s: %s",
580                                  name, rte_strerror(rte_errno));
581         rte_mempool_set_ops_byname(mp[1], rte_mbuf_best_mempool_ops(), NULL);
582         ret = populate(mp[1]);
583         RTE_TEST_ASSERT_EQUAL(ret, (int)mp[1]->size, "Failed to populate mempool %s: %s",
584                               name, rte_strerror(-ret));
585         RTE_TEST_ASSERT_EQUAL(data[0].invoked, false,
586                               "Unregistered callback 0 invoked on %s mempool populaton",
587                               name);
588
589         for (i = 0; i < MP_NUM; i++) {
590                 memset(&data, 0, sizeof(data));
591                 sprintf(name, "empty%zu", i);
592                 rte_mempool_free(mp[i]);
593                 /*
594                  * Save pointer to check that it was passed to the callback,
595                  * but put NULL into the array in case cleanup is called early.
596                  */
597                 freed = mp[i];
598                 mp[i] = NULL;
599                 for (j = 1; j < CB_NUM; j++) {
600                         RTE_TEST_ASSERT_EQUAL(data[j].invoked, true,
601                                               "Callback %zu not invoked on mempool %s destruction",
602                                               j, name);
603                         RTE_TEST_ASSERT_EQUAL(data[j].event,
604                                               RTE_MEMPOOL_EVENT_DESTROY,
605                                               "Wrong callback invoked, expected DESTROY");
606                         RTE_TEST_ASSERT_EQUAL(data[j].mp, freed,
607                                               "Callback %zu invoked for a wrong mempool instead of %s",
608                                               j, name);
609                 }
610                 RTE_TEST_ASSERT_EQUAL(data[0].invoked, false,
611                                       "Unregistered callback 0 invoked on %s mempool destruction",
612                                       name);
613         }
614
615         for (j = 1; j < CB_NUM; j++) {
616                 ret = rte_mempool_event_callback_unregister
617                                         (test_mempool_events_cb, &data[j]);
618                 RTE_TEST_ASSERT_EQUAL(ret, 0, "Failed to unregister the callback %zu: %s",
619                                       j, rte_strerror(rte_errno));
620         }
621         return TEST_SUCCESS;
622
623 fail:
624         for (j = 0; j < CB_NUM; j++)
625                 rte_mempool_event_callback_unregister
626                                         (test_mempool_events_cb, &data[j]);
627         for (i = 0; i < MP_NUM; i++)
628                 rte_mempool_free(mp[i]);
629         return TEST_FAILED;
630
631 #pragma pop_macro("RTE_TEST_TRACE_FAILURE")
632 }
633
634 struct test_mempool_events_safety_data {
635         bool invoked;
636         int (*api_func)(rte_mempool_event_callback *func, void *user_data);
637         rte_mempool_event_callback *cb_func;
638         void *cb_user_data;
639         int ret;
640 };
641
642 static void
643 test_mempool_events_safety_cb(enum rte_mempool_event event,
644                               struct rte_mempool *mp, void *user_data)
645 {
646         struct test_mempool_events_safety_data *data = user_data;
647
648         RTE_SET_USED(event);
649         RTE_SET_USED(mp);
650         data->invoked = true;
651         data->ret = data->api_func(data->cb_func, data->cb_user_data);
652 }
653
654 static int
655 test_mempool_events_safety(void)
656 {
657 #pragma push_macro("RTE_TEST_TRACE_FAILURE")
658 #undef RTE_TEST_TRACE_FAILURE
659 #define RTE_TEST_TRACE_FAILURE(...) do { \
660                 ret = TEST_FAILED; \
661                 goto exit; \
662         } while (0)
663
664         struct test_mempool_events_data data;
665         struct test_mempool_events_safety_data sdata[2];
666         struct rte_mempool *mp;
667         size_t i;
668         int ret;
669
670         /* removes itself */
671         sdata[0].api_func = rte_mempool_event_callback_unregister;
672         sdata[0].cb_func = test_mempool_events_safety_cb;
673         sdata[0].cb_user_data = &sdata[0];
674         sdata[0].ret = -1;
675         rte_mempool_event_callback_register(test_mempool_events_safety_cb,
676                                             &sdata[0]);
677         /* inserts a callback after itself */
678         sdata[1].api_func = rte_mempool_event_callback_register;
679         sdata[1].cb_func = test_mempool_events_cb;
680         sdata[1].cb_user_data = &data;
681         sdata[1].ret = -1;
682         rte_mempool_event_callback_register(test_mempool_events_safety_cb,
683                                             &sdata[1]);
684
685         mp = rte_mempool_create_empty("empty", MEMPOOL_SIZE,
686                                       MEMPOOL_ELT_SIZE, 0, 0,
687                                       SOCKET_ID_ANY, 0);
688         RTE_TEST_ASSERT_NOT_NULL(mp, "Cannot create mempool: %s",
689                                  rte_strerror(rte_errno));
690         memset(&data, 0, sizeof(data));
691         ret = rte_mempool_populate_default(mp);
692         RTE_TEST_ASSERT_EQUAL(ret, (int)mp->size, "Failed to populate mempool: %s",
693                               rte_strerror(-ret));
694
695         RTE_TEST_ASSERT_EQUAL(sdata[0].ret, 0, "Callback failed to unregister itself: %s",
696                               rte_strerror(rte_errno));
697         RTE_TEST_ASSERT_EQUAL(sdata[1].ret, 0, "Failed to insert a new callback: %s",
698                               rte_strerror(rte_errno));
699         RTE_TEST_ASSERT_EQUAL(data.invoked, false,
700                               "Inserted callback is invoked on mempool population");
701
702         memset(&data, 0, sizeof(data));
703         sdata[0].invoked = false;
704         rte_mempool_free(mp);
705         mp = NULL;
706         RTE_TEST_ASSERT_EQUAL(sdata[0].invoked, false,
707                               "Callback that unregistered itself was called");
708         RTE_TEST_ASSERT_EQUAL(sdata[1].ret, -EEXIST,
709                               "New callback inserted twice");
710         RTE_TEST_ASSERT_EQUAL(data.invoked, true,
711                               "Inserted callback is not invoked on mempool destruction");
712
713         rte_mempool_event_callback_unregister(test_mempool_events_cb, &data);
714         for (i = 0; i < RTE_DIM(sdata); i++)
715                 rte_mempool_event_callback_unregister
716                                 (test_mempool_events_safety_cb, &sdata[i]);
717         ret = TEST_SUCCESS;
718
719 exit:
720         /* cleanup, don't care which callbacks are already removed */
721         rte_mempool_event_callback_unregister(test_mempool_events_cb, &data);
722         for (i = 0; i < RTE_DIM(sdata); i++)
723                 rte_mempool_event_callback_unregister
724                                 (test_mempool_events_safety_cb, &sdata[i]);
725         /* in case of failure before the planned destruction */
726         rte_mempool_free(mp);
727         return ret;
728
729 #pragma pop_macro("RTE_TEST_TRACE_FAILURE")
730 }
731
732 static int
733 test_mempool(void)
734 {
735         int ret = -1;
736         uint32_t nb_objs = 0;
737         uint32_t nb_mem_chunks = 0;
738         struct rte_mempool *mp_cache = NULL;
739         struct rte_mempool *mp_nocache = NULL;
740         struct rte_mempool *mp_stack_anon = NULL;
741         struct rte_mempool *mp_stack_mempool_iter = NULL;
742         struct rte_mempool *mp_stack = NULL;
743         struct rte_mempool *default_pool = NULL;
744         struct mp_data cb_arg = {
745                 .ret = -1
746         };
747         const char *default_pool_ops = rte_mbuf_best_mempool_ops();
748
749         /* create a mempool (without cache) */
750         mp_nocache = rte_mempool_create("test_nocache", MEMPOOL_SIZE,
751                 MEMPOOL_ELT_SIZE, 0, 0,
752                 NULL, NULL,
753                 my_obj_init, NULL,
754                 SOCKET_ID_ANY, 0);
755
756         if (mp_nocache == NULL) {
757                 printf("cannot allocate mp_nocache mempool\n");
758                 GOTO_ERR(ret, err);
759         }
760
761         /* create a mempool (with cache) */
762         mp_cache = rte_mempool_create("test_cache", MEMPOOL_SIZE,
763                 MEMPOOL_ELT_SIZE,
764                 RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
765                 NULL, NULL,
766                 my_obj_init, NULL,
767                 SOCKET_ID_ANY, 0);
768
769         if (mp_cache == NULL) {
770                 printf("cannot allocate mp_cache mempool\n");
771                 GOTO_ERR(ret, err);
772         }
773
774         /* create an empty mempool  */
775         mp_stack_anon = rte_mempool_create_empty("test_stack_anon",
776                 MEMPOOL_SIZE,
777                 MEMPOOL_ELT_SIZE,
778                 RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
779                 SOCKET_ID_ANY, 0);
780
781         if (mp_stack_anon == NULL)
782                 GOTO_ERR(ret, err);
783
784         /* populate an empty mempool */
785         ret = rte_mempool_populate_anon(mp_stack_anon);
786         printf("%s ret = %d\n", __func__, ret);
787         if (ret < 0)
788                 GOTO_ERR(ret, err);
789
790         /* Try to populate when already populated */
791         ret = rte_mempool_populate_anon(mp_stack_anon);
792         if (ret != 0)
793                 GOTO_ERR(ret, err);
794
795         /* create a mempool  */
796         mp_stack_mempool_iter = rte_mempool_create("test_iter_obj",
797                 MEMPOOL_SIZE,
798                 MEMPOOL_ELT_SIZE,
799                 RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
800                 NULL, NULL,
801                 my_obj_init, NULL,
802                 SOCKET_ID_ANY, 0);
803
804         if (mp_stack_mempool_iter == NULL)
805                 GOTO_ERR(ret, err);
806
807         /* test to initialize mempool objects and memory */
808         nb_objs = rte_mempool_obj_iter(mp_stack_mempool_iter, my_obj_init,
809                         NULL);
810         if (nb_objs == 0)
811                 GOTO_ERR(ret, err);
812
813         nb_mem_chunks = rte_mempool_mem_iter(mp_stack_mempool_iter,
814                         test_mp_mem_init, &cb_arg);
815         if (nb_mem_chunks == 0 || cb_arg.ret < 0)
816                 GOTO_ERR(ret, err);
817
818         /* create a mempool with an external handler */
819         mp_stack = rte_mempool_create_empty("test_stack",
820                 MEMPOOL_SIZE,
821                 MEMPOOL_ELT_SIZE,
822                 RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
823                 SOCKET_ID_ANY, 0);
824
825         if (mp_stack == NULL) {
826                 printf("cannot allocate mp_stack mempool\n");
827                 GOTO_ERR(ret, err);
828         }
829         if (rte_mempool_set_ops_byname(mp_stack, "stack", NULL) < 0) {
830                 printf("cannot set stack handler\n");
831                 GOTO_ERR(ret, err);
832         }
833         if (rte_mempool_populate_default(mp_stack) < 0) {
834                 printf("cannot populate mp_stack mempool\n");
835                 GOTO_ERR(ret, err);
836         }
837         rte_mempool_obj_iter(mp_stack, my_obj_init, NULL);
838
839         /* Create a mempool based on Default handler */
840         printf("Testing %s mempool handler\n", default_pool_ops);
841         default_pool = rte_mempool_create_empty("default_pool",
842                                                 MEMPOOL_SIZE,
843                                                 MEMPOOL_ELT_SIZE,
844                                                 RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
845                                                 SOCKET_ID_ANY, 0);
846
847         if (default_pool == NULL) {
848                 printf("cannot allocate default mempool\n");
849                 GOTO_ERR(ret, err);
850         }
851         if (rte_mempool_set_ops_byname(default_pool,
852                                 default_pool_ops, NULL) < 0) {
853                 printf("cannot set %s handler\n", default_pool_ops);
854                 GOTO_ERR(ret, err);
855         }
856         if (rte_mempool_populate_default(default_pool) < 0) {
857                 printf("cannot populate %s mempool\n", default_pool_ops);
858                 GOTO_ERR(ret, err);
859         }
860         rte_mempool_obj_iter(default_pool, my_obj_init, NULL);
861
862         /* retrieve the mempool from its name */
863         if (rte_mempool_lookup("test_nocache") != mp_nocache) {
864                 printf("Cannot lookup mempool from its name\n");
865                 GOTO_ERR(ret, err);
866         }
867
868         printf("Walk into mempools:\n");
869         rte_mempool_walk(walk_cb, NULL);
870
871         rte_mempool_list_dump(stdout);
872
873         /* basic tests without cache */
874         if (test_mempool_basic(mp_nocache, 0) < 0)
875                 GOTO_ERR(ret, err);
876
877         /* basic tests with cache */
878         if (test_mempool_basic(mp_cache, 0) < 0)
879                 GOTO_ERR(ret, err);
880
881         /* basic tests with user-owned cache */
882         if (test_mempool_basic(mp_nocache, 1) < 0)
883                 GOTO_ERR(ret, err);
884
885         /* more basic tests without cache */
886         if (test_mempool_basic_ex(mp_nocache) < 0)
887                 GOTO_ERR(ret, err);
888
889         /* mempool operation test based on single producer and single comsumer */
890         if (test_mempool_sp_sc() < 0)
891                 GOTO_ERR(ret, err);
892
893         if (test_mempool_creation_with_exceeded_cache_size() < 0)
894                 GOTO_ERR(ret, err);
895
896         if (test_mempool_creation_with_unknown_flag() < 0)
897                 GOTO_ERR(ret, err);
898
899         if (test_mempool_same_name_twice_creation() < 0)
900                 GOTO_ERR(ret, err);
901
902         /* test the stack handler */
903         if (test_mempool_basic(mp_stack, 1) < 0)
904                 GOTO_ERR(ret, err);
905
906         if (test_mempool_basic(default_pool, 1) < 0)
907                 GOTO_ERR(ret, err);
908
909         /* test mempool event callbacks */
910         if (test_mempool_events(rte_mempool_populate_default) < 0)
911                 GOTO_ERR(ret, err);
912         if (test_mempool_events(rte_mempool_populate_anon) < 0)
913                 GOTO_ERR(ret, err);
914         if (test_mempool_events_safety() < 0)
915                 GOTO_ERR(ret, err);
916
917         rte_mempool_list_dump(stdout);
918
919         ret = 0;
920
921 err:
922         rte_mempool_free(mp_nocache);
923         rte_mempool_free(mp_cache);
924         rte_mempool_free(mp_stack_anon);
925         rte_mempool_free(mp_stack_mempool_iter);
926         rte_mempool_free(mp_stack);
927         rte_mempool_free(default_pool);
928
929         return ret;
930 }
931
932 REGISTER_TEST_COMMAND(mempool_autotest, test_mempool);