mempool: rename functions with confusing names
[dpdk.git] / app / test / test_mbuf.c
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_debug.h>
45 #include <rte_log.h>
46 #include <rte_common.h>
47 #include <rte_memory.h>
48 #include <rte_memcpy.h>
49 #include <rte_memzone.h>
50 #include <rte_launch.h>
51 #include <rte_eal.h>
52 #include <rte_per_lcore.h>
53 #include <rte_lcore.h>
54 #include <rte_atomic.h>
55 #include <rte_branch_prediction.h>
56 #include <rte_ring.h>
57 #include <rte_mempool.h>
58 #include <rte_mbuf.h>
59 #include <rte_random.h>
60 #include <rte_cycles.h>
61
62 #include "test.h"
63
64 #define MBUF_DATA_SIZE          2048
65 #define NB_MBUF                 128
66 #define MBUF_TEST_DATA_LEN      1464
67 #define MBUF_TEST_DATA_LEN2     50
68 #define MBUF_TEST_HDR1_LEN      20
69 #define MBUF_TEST_HDR2_LEN      30
70 #define MBUF_TEST_ALL_HDRS_LEN  (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN)
71
72 /* size of private data for mbuf in pktmbuf_pool2 */
73 #define MBUF2_PRIV_SIZE         128
74
75 #define REFCNT_MAX_ITER         64
76 #define REFCNT_MAX_TIMEOUT      10
77 #define REFCNT_MAX_REF          (RTE_MAX_LCORE)
78 #define REFCNT_MBUF_NUM         64
79 #define REFCNT_RING_SIZE        (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
80
81 #define MAGIC_DATA              0x42424242
82
83 #define MAKE_STRING(x)          # x
84
85 static struct rte_mempool *pktmbuf_pool = NULL;
86 static struct rte_mempool *pktmbuf_pool2 = NULL;
87
88 #ifdef RTE_MBUF_REFCNT_ATOMIC
89
90 static struct rte_mempool *refcnt_pool = NULL;
91 static struct rte_ring *refcnt_mbuf_ring = NULL;
92 static volatile uint32_t refcnt_stop_slaves;
93 static unsigned refcnt_lcore[RTE_MAX_LCORE];
94
95 #endif
96
97 /*
98  * MBUF
99  * ====
100  *
101  * #. Allocate a mbuf pool.
102  *
103  *    - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
104  *      bytes long.
105  *
106  * #. Test multiple allocations of mbufs from this pool.
107  *
108  *    - Allocate NB_MBUF and store pointers in a table.
109  *    - If an allocation fails, return an error.
110  *    - Free all these mbufs.
111  *    - Repeat the same test to check that mbufs were freed correctly.
112  *
113  * #. Test data manipulation in pktmbuf.
114  *
115  *    - Alloc an mbuf.
116  *    - Append data using rte_pktmbuf_append().
117  *    - Test for error in rte_pktmbuf_append() when len is too large.
118  *    - Trim data at the end of mbuf using rte_pktmbuf_trim().
119  *    - Test for error in rte_pktmbuf_trim() when len is too large.
120  *    - Prepend a header using rte_pktmbuf_prepend().
121  *    - Test for error in rte_pktmbuf_prepend() when len is too large.
122  *    - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
123  *    - Test for error in rte_pktmbuf_adj() when len is too large.
124  *    - Check that appended data is not corrupt.
125  *    - Free the mbuf.
126  *    - Between all these tests, check data_len and pkt_len, and
127  *      that the mbuf is contiguous.
128  *    - Repeat the test to check that allocation operations
129  *      reinitialize the mbuf correctly.
130  *
131  * #. Test packet cloning
132  *    - Clone a mbuf and verify the data
133  *    - Clone the cloned mbuf and verify the data
134  *    - Attach a mbuf to another that does not have the same priv_size.
135  */
136
137 #define GOTO_FAIL(str, ...) do {                                        \
138                 printf("mbuf test FAILED (l.%d): <" str ">\n",          \
139                        __LINE__,  ##__VA_ARGS__);                       \
140                 goto fail;                                              \
141 } while(0)
142
143 /*
144  * test data manipulation in mbuf with non-ascii data
145  */
146 static int
147 test_pktmbuf_with_non_ascii_data(void)
148 {
149         struct rte_mbuf *m = NULL;
150         char *data;
151
152         m = rte_pktmbuf_alloc(pktmbuf_pool);
153         if (m == NULL)
154                 GOTO_FAIL("Cannot allocate mbuf");
155         if (rte_pktmbuf_pkt_len(m) != 0)
156                 GOTO_FAIL("Bad length");
157
158         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
159         if (data == NULL)
160                 GOTO_FAIL("Cannot append data");
161         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
162                 GOTO_FAIL("Bad pkt length");
163         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
164                 GOTO_FAIL("Bad data length");
165         memset(data, 0xff, rte_pktmbuf_pkt_len(m));
166         if (!rte_pktmbuf_is_contiguous(m))
167                 GOTO_FAIL("Buffer should be continuous");
168         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
169
170         rte_pktmbuf_free(m);
171
172         return 0;
173
174 fail:
175         if(m) {
176                 rte_pktmbuf_free(m);
177         }
178         return -1;
179 }
180
181 /*
182  * test data manipulation in mbuf
183  */
184 static int
185 test_one_pktmbuf(void)
186 {
187         struct rte_mbuf *m = NULL;
188         char *data, *data2, *hdr;
189         unsigned i;
190
191         printf("Test pktmbuf API\n");
192
193         /* alloc a mbuf */
194
195         m = rte_pktmbuf_alloc(pktmbuf_pool);
196         if (m == NULL)
197                 GOTO_FAIL("Cannot allocate mbuf");
198         if (rte_pktmbuf_pkt_len(m) != 0)
199                 GOTO_FAIL("Bad length");
200
201         rte_pktmbuf_dump(stdout, m, 0);
202
203         /* append data */
204
205         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
206         if (data == NULL)
207                 GOTO_FAIL("Cannot append data");
208         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
209                 GOTO_FAIL("Bad pkt length");
210         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
211                 GOTO_FAIL("Bad data length");
212         memset(data, 0x66, rte_pktmbuf_pkt_len(m));
213         if (!rte_pktmbuf_is_contiguous(m))
214                 GOTO_FAIL("Buffer should be continuous");
215         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
216         rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
217
218         /* this append should fail */
219
220         data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
221         if (data2 != NULL)
222                 GOTO_FAIL("Append should not succeed");
223
224         /* append some more data */
225
226         data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
227         if (data2 == NULL)
228                 GOTO_FAIL("Cannot append data");
229         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
230                 GOTO_FAIL("Bad pkt length");
231         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
232                 GOTO_FAIL("Bad data length");
233         if (!rte_pktmbuf_is_contiguous(m))
234                 GOTO_FAIL("Buffer should be continuous");
235
236         /* trim data at the end of mbuf */
237
238         if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
239                 GOTO_FAIL("Cannot trim data");
240         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
241                 GOTO_FAIL("Bad pkt length");
242         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
243                 GOTO_FAIL("Bad data length");
244         if (!rte_pktmbuf_is_contiguous(m))
245                 GOTO_FAIL("Buffer should be continuous");
246
247         /* this trim should fail */
248
249         if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
250                 GOTO_FAIL("trim should not succeed");
251
252         /* prepend one header */
253
254         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
255         if (hdr == NULL)
256                 GOTO_FAIL("Cannot prepend");
257         if (data - hdr != MBUF_TEST_HDR1_LEN)
258                 GOTO_FAIL("Prepend failed");
259         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
260                 GOTO_FAIL("Bad pkt length");
261         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
262                 GOTO_FAIL("Bad data length");
263         if (!rte_pktmbuf_is_contiguous(m))
264                 GOTO_FAIL("Buffer should be continuous");
265         memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
266
267         /* prepend another header */
268
269         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
270         if (hdr == NULL)
271                 GOTO_FAIL("Cannot prepend");
272         if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
273                 GOTO_FAIL("Prepend failed");
274         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
275                 GOTO_FAIL("Bad pkt length");
276         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
277                 GOTO_FAIL("Bad data length");
278         if (!rte_pktmbuf_is_contiguous(m))
279                 GOTO_FAIL("Buffer should be continuous");
280         memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
281
282         rte_mbuf_sanity_check(m, 1);
283         rte_mbuf_sanity_check(m, 0);
284         rte_pktmbuf_dump(stdout, m, 0);
285
286         /* this prepend should fail */
287
288         hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
289         if (hdr != NULL)
290                 GOTO_FAIL("prepend should not succeed");
291
292         /* remove data at beginning of mbuf (adj) */
293
294         if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
295                 GOTO_FAIL("rte_pktmbuf_adj failed");
296         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
297                 GOTO_FAIL("Bad pkt length");
298         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
299                 GOTO_FAIL("Bad data length");
300         if (!rte_pktmbuf_is_contiguous(m))
301                 GOTO_FAIL("Buffer should be continuous");
302
303         /* this adj should fail */
304
305         if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
306                 GOTO_FAIL("rte_pktmbuf_adj should not succeed");
307
308         /* check data */
309
310         if (!rte_pktmbuf_is_contiguous(m))
311                 GOTO_FAIL("Buffer should be continuous");
312
313         for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
314                 if (data[i] != 0x66)
315                         GOTO_FAIL("Data corrupted at offset %u", i);
316         }
317
318         /* free mbuf */
319
320         rte_pktmbuf_free(m);
321         m = NULL;
322         return 0;
323
324 fail:
325         if (m)
326                 rte_pktmbuf_free(m);
327         return -1;
328 }
329
330 static int
331 testclone_testupdate_testdetach(void)
332 {
333         struct rte_mbuf *m = NULL;
334         struct rte_mbuf *clone = NULL;
335         struct rte_mbuf *clone2 = NULL;
336         unaligned_uint32_t *data;
337
338         /* alloc a mbuf */
339         m = rte_pktmbuf_alloc(pktmbuf_pool);
340         if (m == NULL)
341                 GOTO_FAIL("ooops not allocating mbuf");
342
343         if (rte_pktmbuf_pkt_len(m) != 0)
344                 GOTO_FAIL("Bad length");
345
346         rte_pktmbuf_append(m, sizeof(uint32_t));
347         data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
348         *data = MAGIC_DATA;
349
350         /* clone the allocated mbuf */
351         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
352         if (clone == NULL)
353                 GOTO_FAIL("cannot clone data\n");
354
355         data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
356         if (*data != MAGIC_DATA)
357                 GOTO_FAIL("invalid data in clone\n");
358
359         if (rte_mbuf_refcnt_read(m) != 2)
360                 GOTO_FAIL("invalid refcnt in m\n");
361
362         /* free the clone */
363         rte_pktmbuf_free(clone);
364         clone = NULL;
365
366         /* same test with a chained mbuf */
367         m->next = rte_pktmbuf_alloc(pktmbuf_pool);
368         if (m->next == NULL)
369                 GOTO_FAIL("Next Pkt Null\n");
370
371         rte_pktmbuf_append(m->next, sizeof(uint32_t));
372         data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
373         *data = MAGIC_DATA;
374
375         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
376         if (clone == NULL)
377                 GOTO_FAIL("cannot clone data\n");
378
379         data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
380         if (*data != MAGIC_DATA)
381                 GOTO_FAIL("invalid data in clone\n");
382
383         data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
384         if (*data != MAGIC_DATA)
385                 GOTO_FAIL("invalid data in clone->next\n");
386
387         if (rte_mbuf_refcnt_read(m) != 2)
388                 GOTO_FAIL("invalid refcnt in m\n");
389
390         if (rte_mbuf_refcnt_read(m->next) != 2)
391                 GOTO_FAIL("invalid refcnt in m->next\n");
392
393         /* try to clone the clone */
394
395         clone2 = rte_pktmbuf_clone(clone, pktmbuf_pool);
396         if (clone2 == NULL)
397                 GOTO_FAIL("cannot clone the clone\n");
398
399         data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
400         if (*data != MAGIC_DATA)
401                 GOTO_FAIL("invalid data in clone2\n");
402
403         data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
404         if (*data != MAGIC_DATA)
405                 GOTO_FAIL("invalid data in clone2->next\n");
406
407         if (rte_mbuf_refcnt_read(m) != 3)
408                 GOTO_FAIL("invalid refcnt in m\n");
409
410         if (rte_mbuf_refcnt_read(m->next) != 3)
411                 GOTO_FAIL("invalid refcnt in m->next\n");
412
413         /* free mbuf */
414         rte_pktmbuf_free(m);
415         rte_pktmbuf_free(clone);
416         rte_pktmbuf_free(clone2);
417
418         m = NULL;
419         clone = NULL;
420         clone2 = NULL;
421         printf("%s ok\n", __func__);
422         return 0;
423
424 fail:
425         if (m)
426                 rte_pktmbuf_free(m);
427         if (clone)
428                 rte_pktmbuf_free(clone);
429         if (clone2)
430                 rte_pktmbuf_free(clone2);
431         return -1;
432 }
433
434 static int
435 test_attach_from_different_pool(void)
436 {
437         struct rte_mbuf *m = NULL;
438         struct rte_mbuf *clone = NULL;
439         struct rte_mbuf *clone2 = NULL;
440         char *data, *c_data, *c_data2;
441
442         /* alloc a mbuf */
443         m = rte_pktmbuf_alloc(pktmbuf_pool);
444         if (m == NULL)
445                 GOTO_FAIL("cannot allocate mbuf");
446
447         if (rte_pktmbuf_pkt_len(m) != 0)
448                 GOTO_FAIL("Bad length");
449
450         data = rte_pktmbuf_mtod(m, char *);
451
452         /* allocate a new mbuf from the second pool, and attach it to the first
453          * mbuf */
454         clone = rte_pktmbuf_alloc(pktmbuf_pool2);
455         if (clone == NULL)
456                 GOTO_FAIL("cannot allocate mbuf from second pool\n");
457
458         /* check data room size and priv size, and erase priv */
459         if (rte_pktmbuf_data_room_size(clone->pool) != 0)
460                 GOTO_FAIL("data room size should be 0\n");
461         if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE)
462                 GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
463         memset(clone + 1, 0, MBUF2_PRIV_SIZE);
464
465         /* save data pointer to compare it after detach() */
466         c_data = rte_pktmbuf_mtod(clone, char *);
467         if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE)
468                 GOTO_FAIL("bad data pointer in clone");
469         if (rte_pktmbuf_headroom(clone) != 0)
470                 GOTO_FAIL("bad headroom in clone");
471
472         rte_pktmbuf_attach(clone, m);
473
474         if (rte_pktmbuf_mtod(clone, char *) != data)
475                 GOTO_FAIL("clone was not attached properly\n");
476         if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM)
477                 GOTO_FAIL("bad headroom in clone after attach");
478         if (rte_mbuf_refcnt_read(m) != 2)
479                 GOTO_FAIL("invalid refcnt in m\n");
480
481         /* allocate a new mbuf from the second pool, and attach it to the first
482          * cloned mbuf */
483         clone2 = rte_pktmbuf_alloc(pktmbuf_pool2);
484         if (clone2 == NULL)
485                 GOTO_FAIL("cannot allocate clone2 from second pool\n");
486
487         /* check data room size and priv size, and erase priv */
488         if (rte_pktmbuf_data_room_size(clone2->pool) != 0)
489                 GOTO_FAIL("data room size should be 0\n");
490         if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE)
491                 GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
492         memset(clone2 + 1, 0, MBUF2_PRIV_SIZE);
493
494         /* save data pointer to compare it after detach() */
495         c_data2 = rte_pktmbuf_mtod(clone2, char *);
496         if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE)
497                 GOTO_FAIL("bad data pointer in clone2");
498         if (rte_pktmbuf_headroom(clone2) != 0)
499                 GOTO_FAIL("bad headroom in clone2");
500
501         rte_pktmbuf_attach(clone2, clone);
502
503         if (rte_pktmbuf_mtod(clone2, char *) != data)
504                 GOTO_FAIL("clone2 was not attached properly\n");
505         if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM)
506                 GOTO_FAIL("bad headroom in clone2 after attach");
507         if (rte_mbuf_refcnt_read(m) != 3)
508                 GOTO_FAIL("invalid refcnt in m\n");
509
510         /* detach the clones */
511         rte_pktmbuf_detach(clone);
512         if (c_data != rte_pktmbuf_mtod(clone, char *))
513                 GOTO_FAIL("clone was not detached properly\n");
514         if (rte_mbuf_refcnt_read(m) != 2)
515                 GOTO_FAIL("invalid refcnt in m\n");
516
517         rte_pktmbuf_detach(clone2);
518         if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
519                 GOTO_FAIL("clone2 was not detached properly\n");
520         if (rte_mbuf_refcnt_read(m) != 1)
521                 GOTO_FAIL("invalid refcnt in m\n");
522
523         /* free the clones and the initial mbuf */
524         rte_pktmbuf_free(clone2);
525         rte_pktmbuf_free(clone);
526         rte_pktmbuf_free(m);
527         printf("%s ok\n", __func__);
528         return 0;
529
530 fail:
531         if (m)
532                 rte_pktmbuf_free(m);
533         if (clone)
534                 rte_pktmbuf_free(clone);
535         if (clone2)
536                 rte_pktmbuf_free(clone2);
537         return -1;
538 }
539 #undef GOTO_FAIL
540
541 /*
542  * test allocation and free of mbufs
543  */
544 static int
545 test_pktmbuf_pool(void)
546 {
547         unsigned i;
548         struct rte_mbuf *m[NB_MBUF];
549         int ret = 0;
550
551         for (i=0; i<NB_MBUF; i++)
552                 m[i] = NULL;
553
554         /* alloc NB_MBUF mbufs */
555         for (i=0; i<NB_MBUF; i++) {
556                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
557                 if (m[i] == NULL) {
558                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
559                         ret = -1;
560                 }
561         }
562         struct rte_mbuf *extra = NULL;
563         extra = rte_pktmbuf_alloc(pktmbuf_pool);
564         if(extra != NULL) {
565                 printf("Error pool not empty");
566                 ret = -1;
567         }
568         extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
569         if(extra != NULL) {
570                 printf("Error pool not empty");
571                 ret = -1;
572         }
573         /* free them */
574         for (i=0; i<NB_MBUF; i++) {
575                 if (m[i] != NULL)
576                         rte_pktmbuf_free(m[i]);
577         }
578
579         return ret;
580 }
581
582 /*
583  * test that the pointer to the data on a packet mbuf is set properly
584  */
585 static int
586 test_pktmbuf_pool_ptr(void)
587 {
588         unsigned i;
589         struct rte_mbuf *m[NB_MBUF];
590         int ret = 0;
591
592         for (i=0; i<NB_MBUF; i++)
593                 m[i] = NULL;
594
595         /* alloc NB_MBUF mbufs */
596         for (i=0; i<NB_MBUF; i++) {
597                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
598                 if (m[i] == NULL) {
599                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
600                         ret = -1;
601                         break;
602                 }
603                 m[i]->data_off += 64;
604         }
605
606         /* free them */
607         for (i=0; i<NB_MBUF; i++) {
608                 if (m[i] != NULL)
609                         rte_pktmbuf_free(m[i]);
610         }
611
612         for (i=0; i<NB_MBUF; i++)
613                 m[i] = NULL;
614
615         /* alloc NB_MBUF mbufs */
616         for (i=0; i<NB_MBUF; i++) {
617                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
618                 if (m[i] == NULL) {
619                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
620                         ret = -1;
621                         break;
622                 }
623                 if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
624                         printf("invalid data_off\n");
625                         ret = -1;
626                 }
627         }
628
629         /* free them */
630         for (i=0; i<NB_MBUF; i++) {
631                 if (m[i] != NULL)
632                         rte_pktmbuf_free(m[i]);
633         }
634
635         return ret;
636 }
637
638 static int
639 test_pktmbuf_free_segment(void)
640 {
641         unsigned i;
642         struct rte_mbuf *m[NB_MBUF];
643         int ret = 0;
644
645         for (i=0; i<NB_MBUF; i++)
646                 m[i] = NULL;
647
648         /* alloc NB_MBUF mbufs */
649         for (i=0; i<NB_MBUF; i++) {
650                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
651                 if (m[i] == NULL) {
652                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
653                         ret = -1;
654                 }
655         }
656
657         /* free them */
658         for (i=0; i<NB_MBUF; i++) {
659                 if (m[i] != NULL) {
660                         struct rte_mbuf *mb, *mt;
661
662                         mb = m[i];
663                         while(mb != NULL) {
664                                 mt = mb;
665                                 mb = mb->next;
666                                 rte_pktmbuf_free_seg(mt);
667                         }
668                 }
669         }
670
671         return ret;
672 }
673
674 /*
675  * Stress test for rte_mbuf atomic refcnt.
676  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
677  * For more efficency, recomended to run with RTE_LIBRTE_MBUF_DEBUG defined.
678  */
679
680 #ifdef RTE_MBUF_REFCNT_ATOMIC
681
682 static int
683 test_refcnt_slave(__attribute__((unused)) void *arg)
684 {
685         unsigned lcore, free;
686         void *mp = 0;
687
688         lcore = rte_lcore_id();
689         printf("%s started at lcore %u\n", __func__, lcore);
690
691         free = 0;
692         while (refcnt_stop_slaves == 0) {
693                 if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
694                         free++;
695                         rte_pktmbuf_free((struct rte_mbuf *)mp);
696                 }
697         }
698
699         refcnt_lcore[lcore] += free;
700         printf("%s finished at lcore %u, "
701                "number of freed mbufs: %u\n",
702                __func__, lcore, free);
703         return 0;
704 }
705
706 static void
707 test_refcnt_iter(unsigned lcore, unsigned iter)
708 {
709         uint16_t ref;
710         unsigned i, n, tref, wn;
711         struct rte_mbuf *m;
712
713         tref = 0;
714
715         /* For each mbuf in the pool:
716          * - allocate mbuf,
717          * - increment it's reference up to N+1,
718          * - enqueue it N times into the ring for slave cores to free.
719          */
720         for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
721             i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
722             i++) {
723                 ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
724                 tref += ref;
725                 if ((ref & 1) != 0) {
726                         rte_pktmbuf_refcnt_update(m, ref);
727                         while (ref-- != 0)
728                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
729                 } else {
730                         while (ref-- != 0) {
731                                 rte_pktmbuf_refcnt_update(m, 1);
732                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
733                         }
734                 }
735                 rte_pktmbuf_free(m);
736         }
737
738         if (i != n)
739                 rte_panic("(lcore=%u, iter=%u): was able to allocate only "
740                           "%u from %u mbufs\n", lcore, iter, i, n);
741
742         /* wait till slave lcores  will consume all mbufs */
743         while (!rte_ring_empty(refcnt_mbuf_ring))
744                 ;
745
746         /* check that all mbufs are back into mempool by now */
747         for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
748                 if ((i = rte_mempool_avail_count(refcnt_pool)) == n) {
749                         refcnt_lcore[lcore] += tref;
750                         printf("%s(lcore=%u, iter=%u) completed, "
751                             "%u references processed\n",
752                             __func__, lcore, iter, tref);
753                         return;
754                 }
755                 rte_delay_ms(100);
756         }
757
758         rte_panic("(lcore=%u, iter=%u): after %us only "
759                   "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
760 }
761
762 static int
763 test_refcnt_master(void)
764 {
765         unsigned i, lcore;
766
767         lcore = rte_lcore_id();
768         printf("%s started at lcore %u\n", __func__, lcore);
769
770         for (i = 0; i != REFCNT_MAX_ITER; i++)
771                 test_refcnt_iter(lcore, i);
772
773         refcnt_stop_slaves = 1;
774         rte_wmb();
775
776         printf("%s finished at lcore %u\n", __func__, lcore);
777         return 0;
778 }
779
780 #endif
781
782 static int
783 test_refcnt_mbuf(void)
784 {
785 #ifdef RTE_MBUF_REFCNT_ATOMIC
786
787         unsigned lnum, master, slave, tref;
788
789
790         if ((lnum = rte_lcore_count()) == 1) {
791                 printf("skipping %s, number of lcores: %u is not enough\n",
792                     __func__, lnum);
793                 return 0;
794         }
795
796         printf("starting %s, at %u lcores\n", __func__, lnum);
797
798         /* create refcnt pool & ring if they don't exist */
799
800         if (refcnt_pool == NULL &&
801                         (refcnt_pool = rte_pktmbuf_pool_create(
802                                 MAKE_STRING(refcnt_pool),
803                                 REFCNT_MBUF_NUM, 0, 0, 0,
804                                 SOCKET_ID_ANY)) == NULL) {
805                 printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
806                     __func__);
807                 return -1;
808         }
809
810         if (refcnt_mbuf_ring == NULL &&
811                         (refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
812                         REFCNT_RING_SIZE, SOCKET_ID_ANY,
813                         RING_F_SP_ENQ)) == NULL) {
814                 printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
815                     "\n", __func__);
816                 return -1;
817         }
818
819         refcnt_stop_slaves = 0;
820         memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
821
822         rte_eal_mp_remote_launch(test_refcnt_slave, NULL, SKIP_MASTER);
823
824         test_refcnt_master();
825
826         rte_eal_mp_wait_lcore();
827
828         /* check that we porcessed all references */
829         tref = 0;
830         master = rte_get_master_lcore();
831
832         RTE_LCORE_FOREACH_SLAVE(slave)
833                 tref += refcnt_lcore[slave];
834
835         if (tref != refcnt_lcore[master])
836                 rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
837                           tref, refcnt_lcore[master]);
838
839         rte_mempool_dump(stdout, refcnt_pool);
840         rte_ring_dump(stdout, refcnt_mbuf_ring);
841
842 #endif
843         return 0;
844 }
845
846 #include <unistd.h>
847 #include <sys/wait.h>
848
849 /* use fork() to test mbuf errors panic */
850 static int
851 verify_mbuf_check_panics(struct rte_mbuf *buf)
852 {
853         int pid;
854         int status;
855
856         pid = fork();
857
858         if (pid == 0) {
859                 rte_mbuf_sanity_check(buf, 1); /* should panic */
860                 exit(0);  /* return normally if it doesn't panic */
861         } else if (pid < 0){
862                 printf("Fork Failed\n");
863                 return -1;
864         }
865         wait(&status);
866         if(status == 0)
867                 return -1;
868
869         return 0;
870 }
871
872 static int
873 test_failing_mbuf_sanity_check(void)
874 {
875         struct rte_mbuf *buf;
876         struct rte_mbuf badbuf;
877
878         printf("Checking rte_mbuf_sanity_check for failure conditions\n");
879
880         /* get a good mbuf to use to make copies */
881         buf = rte_pktmbuf_alloc(pktmbuf_pool);
882         if (buf == NULL)
883                 return -1;
884         printf("Checking good mbuf initially\n");
885         if (verify_mbuf_check_panics(buf) != -1)
886                 return -1;
887
888         printf("Now checking for error conditions\n");
889
890         if (verify_mbuf_check_panics(NULL)) {
891                 printf("Error with NULL mbuf test\n");
892                 return -1;
893         }
894
895         badbuf = *buf;
896         badbuf.pool = NULL;
897         if (verify_mbuf_check_panics(&badbuf)) {
898                 printf("Error with bad-pool mbuf test\n");
899                 return -1;
900         }
901
902         badbuf = *buf;
903         badbuf.buf_physaddr = 0;
904         if (verify_mbuf_check_panics(&badbuf)) {
905                 printf("Error with bad-physaddr mbuf test\n");
906                 return -1;
907         }
908
909         badbuf = *buf;
910         badbuf.buf_addr = NULL;
911         if (verify_mbuf_check_panics(&badbuf)) {
912                 printf("Error with bad-addr mbuf test\n");
913                 return -1;
914         }
915
916         badbuf = *buf;
917         badbuf.refcnt = 0;
918         if (verify_mbuf_check_panics(&badbuf)) {
919                 printf("Error with bad-refcnt(0) mbuf test\n");
920                 return -1;
921         }
922
923         badbuf = *buf;
924         badbuf.refcnt = UINT16_MAX;
925         if (verify_mbuf_check_panics(&badbuf)) {
926                 printf("Error with bad-refcnt(MAX) mbuf test\n");
927                 return -1;
928         }
929
930         return 0;
931 }
932
933
934 static int
935 test_mbuf(void)
936 {
937         RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
938
939         /* create pktmbuf pool if it does not exist */
940         if (pktmbuf_pool == NULL) {
941                 pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
942                         NB_MBUF, 32, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
943         }
944
945         if (pktmbuf_pool == NULL) {
946                 printf("cannot allocate mbuf pool\n");
947                 return -1;
948         }
949
950         /* create a specific pktmbuf pool with a priv_size != 0 and no data
951          * room size */
952         if (pktmbuf_pool2 == NULL) {
953                 pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
954                         NB_MBUF, 32, MBUF2_PRIV_SIZE, 0, SOCKET_ID_ANY);
955         }
956
957         if (pktmbuf_pool2 == NULL) {
958                 printf("cannot allocate mbuf pool\n");
959                 return -1;
960         }
961
962         /* test multiple mbuf alloc */
963         if (test_pktmbuf_pool() < 0) {
964                 printf("test_mbuf_pool() failed\n");
965                 return -1;
966         }
967
968         /* do it another time to check that all mbufs were freed */
969         if (test_pktmbuf_pool() < 0) {
970                 printf("test_mbuf_pool() failed (2)\n");
971                 return -1;
972         }
973
974         /* test that the pointer to the data on a packet mbuf is set properly */
975         if (test_pktmbuf_pool_ptr() < 0) {
976                 printf("test_pktmbuf_pool_ptr() failed\n");
977                 return -1;
978         }
979
980         /* test data manipulation in mbuf */
981         if (test_one_pktmbuf() < 0) {
982                 printf("test_one_mbuf() failed\n");
983                 return -1;
984         }
985
986
987         /*
988          * do it another time, to check that allocation reinitialize
989          * the mbuf correctly
990          */
991         if (test_one_pktmbuf() < 0) {
992                 printf("test_one_mbuf() failed (2)\n");
993                 return -1;
994         }
995
996         if (test_pktmbuf_with_non_ascii_data() < 0) {
997                 printf("test_pktmbuf_with_non_ascii_data() failed\n");
998                 return -1;
999         }
1000
1001         /* test free pktmbuf segment one by one */
1002         if (test_pktmbuf_free_segment() < 0) {
1003                 printf("test_pktmbuf_free_segment() failed.\n");
1004                 return -1;
1005         }
1006
1007         if (testclone_testupdate_testdetach()<0){
1008                 printf("testclone_and_testupdate() failed \n");
1009                 return -1;
1010         }
1011
1012         if (test_attach_from_different_pool() < 0) {
1013                 printf("test_attach_from_different_pool() failed\n");
1014                 return -1;
1015         }
1016
1017         if (test_refcnt_mbuf()<0){
1018                 printf("test_refcnt_mbuf() failed \n");
1019                 return -1;
1020         }
1021
1022         if (test_failing_mbuf_sanity_check() < 0) {
1023                 printf("test_failing_mbuf_sanity_check() failed\n");
1024                 return -1;
1025         }
1026         return 0;
1027 }
1028
1029 static struct test_command mbuf_cmd = {
1030         .command = "mbuf_autotest",
1031         .callback = test_mbuf,
1032 };
1033 REGISTER_TEST_COMMAND(mbuf_cmd);