eal: add and use unaligned integer types
[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
515         rte_pktmbuf_detach(clone2);
516         if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
517                 GOTO_FAIL("clone2 was not detached properly\n");
518
519         /* free the clones and the initial mbuf */
520         rte_pktmbuf_free(clone2);
521         rte_pktmbuf_free(clone);
522         rte_pktmbuf_free(m);
523         printf("%s ok\n", __func__);
524         return 0;
525
526 fail:
527         if (m)
528                 rte_pktmbuf_free(m);
529         if (clone)
530                 rte_pktmbuf_free(clone);
531         if (clone2)
532                 rte_pktmbuf_free(clone2);
533         return -1;
534 }
535 #undef GOTO_FAIL
536
537 /*
538  * test allocation and free of mbufs
539  */
540 static int
541 test_pktmbuf_pool(void)
542 {
543         unsigned i;
544         struct rte_mbuf *m[NB_MBUF];
545         int ret = 0;
546
547         for (i=0; i<NB_MBUF; i++)
548                 m[i] = NULL;
549
550         /* alloc NB_MBUF mbufs */
551         for (i=0; i<NB_MBUF; i++) {
552                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
553                 if (m[i] == NULL) {
554                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
555                         ret = -1;
556                 }
557         }
558         struct rte_mbuf *extra = NULL;
559         extra = rte_pktmbuf_alloc(pktmbuf_pool);
560         if(extra != NULL) {
561                 printf("Error pool not empty");
562                 ret = -1;
563         }
564         extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
565         if(extra != NULL) {
566                 printf("Error pool not empty");
567                 ret = -1;
568         }
569         /* free them */
570         for (i=0; i<NB_MBUF; i++) {
571                 if (m[i] != NULL)
572                         rte_pktmbuf_free(m[i]);
573         }
574
575         return ret;
576 }
577
578 /*
579  * test that the pointer to the data on a packet mbuf is set properly
580  */
581 static int
582 test_pktmbuf_pool_ptr(void)
583 {
584         unsigned i;
585         struct rte_mbuf *m[NB_MBUF];
586         int ret = 0;
587
588         for (i=0; i<NB_MBUF; i++)
589                 m[i] = NULL;
590
591         /* alloc NB_MBUF mbufs */
592         for (i=0; i<NB_MBUF; i++) {
593                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
594                 if (m[i] == NULL) {
595                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
596                         ret = -1;
597                         break;
598                 }
599                 m[i]->data_off += 64;
600         }
601
602         /* free them */
603         for (i=0; i<NB_MBUF; i++) {
604                 if (m[i] != NULL)
605                         rte_pktmbuf_free(m[i]);
606         }
607
608         for (i=0; i<NB_MBUF; i++)
609                 m[i] = NULL;
610
611         /* alloc NB_MBUF mbufs */
612         for (i=0; i<NB_MBUF; i++) {
613                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
614                 if (m[i] == NULL) {
615                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
616                         ret = -1;
617                         break;
618                 }
619                 if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
620                         printf("invalid data_off\n");
621                         ret = -1;
622                 }
623         }
624
625         /* free them */
626         for (i=0; i<NB_MBUF; i++) {
627                 if (m[i] != NULL)
628                         rte_pktmbuf_free(m[i]);
629         }
630
631         return ret;
632 }
633
634 static int
635 test_pktmbuf_free_segment(void)
636 {
637         unsigned i;
638         struct rte_mbuf *m[NB_MBUF];
639         int ret = 0;
640
641         for (i=0; i<NB_MBUF; i++)
642                 m[i] = NULL;
643
644         /* alloc NB_MBUF mbufs */
645         for (i=0; i<NB_MBUF; i++) {
646                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
647                 if (m[i] == NULL) {
648                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
649                         ret = -1;
650                 }
651         }
652
653         /* free them */
654         for (i=0; i<NB_MBUF; i++) {
655                 if (m[i] != NULL) {
656                         struct rte_mbuf *mb, *mt;
657
658                         mb = m[i];
659                         while(mb != NULL) {
660                                 mt = mb;
661                                 mb = mb->next;
662                                 rte_pktmbuf_free_seg(mt);
663                         }
664                 }
665         }
666
667         return ret;
668 }
669
670 /*
671  * Stress test for rte_mbuf atomic refcnt.
672  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
673  * For more efficency, recomended to run with RTE_LIBRTE_MBUF_DEBUG defined.
674  */
675
676 #ifdef RTE_MBUF_REFCNT_ATOMIC
677
678 static int
679 test_refcnt_slave(__attribute__((unused)) void *arg)
680 {
681         unsigned lcore, free;
682         void *mp = 0;
683
684         lcore = rte_lcore_id();
685         printf("%s started at lcore %u\n", __func__, lcore);
686
687         free = 0;
688         while (refcnt_stop_slaves == 0) {
689                 if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
690                         free++;
691                         rte_pktmbuf_free((struct rte_mbuf *)mp);
692                 }
693         }
694
695         refcnt_lcore[lcore] += free;
696         printf("%s finished at lcore %u, "
697                "number of freed mbufs: %u\n",
698                __func__, lcore, free);
699         return (0);
700 }
701
702 static void
703 test_refcnt_iter(unsigned lcore, unsigned iter)
704 {
705         uint16_t ref;
706         unsigned i, n, tref, wn;
707         struct rte_mbuf *m;
708
709         tref = 0;
710
711         /* For each mbuf in the pool:
712          * - allocate mbuf,
713          * - increment it's reference up to N+1,
714          * - enqueue it N times into the ring for slave cores to free.
715          */
716         for (i = 0, n = rte_mempool_count(refcnt_pool);
717             i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
718             i++) {
719                 ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
720                 tref += ref;
721                 if ((ref & 1) != 0) {
722                         rte_pktmbuf_refcnt_update(m, ref);
723                         while (ref-- != 0)
724                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
725                 } else {
726                         while (ref-- != 0) {
727                                 rte_pktmbuf_refcnt_update(m, 1);
728                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
729                         }
730                 }
731                 rte_pktmbuf_free(m);
732         }
733
734         if (i != n)
735                 rte_panic("(lcore=%u, iter=%u): was able to allocate only "
736                           "%u from %u mbufs\n", lcore, iter, i, n);
737
738         /* wait till slave lcores  will consume all mbufs */
739         while (!rte_ring_empty(refcnt_mbuf_ring))
740                 ;
741
742         /* check that all mbufs are back into mempool by now */
743         for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
744                 if ((i = rte_mempool_count(refcnt_pool)) == n) {
745                         refcnt_lcore[lcore] += tref;
746                         printf("%s(lcore=%u, iter=%u) completed, "
747                             "%u references processed\n",
748                             __func__, lcore, iter, tref);
749                         return;
750                 }
751                 rte_delay_ms(1000);
752         }
753
754         rte_panic("(lcore=%u, iter=%u): after %us only "
755                   "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
756 }
757
758 static int
759 test_refcnt_master(void)
760 {
761         unsigned i, lcore;
762
763         lcore = rte_lcore_id();
764         printf("%s started at lcore %u\n", __func__, lcore);
765
766         for (i = 0; i != REFCNT_MAX_ITER; i++)
767                 test_refcnt_iter(lcore, i);
768
769         refcnt_stop_slaves = 1;
770         rte_wmb();
771
772         printf("%s finished at lcore %u\n", __func__, lcore);
773         return (0);
774 }
775
776 #endif
777
778 static int
779 test_refcnt_mbuf(void)
780 {
781 #ifdef RTE_MBUF_REFCNT_ATOMIC
782
783         unsigned lnum, master, slave, tref;
784
785
786         if ((lnum = rte_lcore_count()) == 1) {
787                 printf("skipping %s, number of lcores: %u is not enough\n",
788                     __func__, lnum);
789                 return (0);
790         }
791
792         printf("starting %s, at %u lcores\n", __func__, lnum);
793
794         /* create refcnt pool & ring if they don't exist */
795
796         if (refcnt_pool == NULL &&
797                         (refcnt_pool = rte_pktmbuf_pool_create(
798                                 MAKE_STRING(refcnt_pool),
799                                 REFCNT_MBUF_NUM, 0, 0, 0,
800                                 SOCKET_ID_ANY)) == NULL) {
801                 printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
802                     __func__);
803                 return (-1);
804         }
805
806         if (refcnt_mbuf_ring == NULL &&
807                         (refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
808                         REFCNT_RING_SIZE, SOCKET_ID_ANY,
809                         RING_F_SP_ENQ)) == NULL) {
810                 printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
811                     "\n", __func__);
812                 return (-1);
813         }
814
815         refcnt_stop_slaves = 0;
816         memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
817
818         rte_eal_mp_remote_launch(test_refcnt_slave, NULL, SKIP_MASTER);
819
820         test_refcnt_master();
821
822         rte_eal_mp_wait_lcore();
823
824         /* check that we porcessed all references */
825         tref = 0;
826         master = rte_get_master_lcore();
827
828         RTE_LCORE_FOREACH_SLAVE(slave)
829                 tref += refcnt_lcore[slave];
830
831         if (tref != refcnt_lcore[master])
832                 rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
833                           tref, refcnt_lcore[master]);
834
835         rte_mempool_dump(stdout, refcnt_pool);
836         rte_ring_dump(stdout, refcnt_mbuf_ring);
837
838 #endif
839         return (0);
840 }
841
842 #include <unistd.h>
843 #include <sys/wait.h>
844
845 /* use fork() to test mbuf errors panic */
846 static int
847 verify_mbuf_check_panics(struct rte_mbuf *buf)
848 {
849         int pid;
850         int status;
851
852         pid = fork();
853
854         if (pid == 0) {
855                 rte_mbuf_sanity_check(buf, 1); /* should panic */
856                 exit(0);  /* return normally if it doesn't panic */
857         } else if (pid < 0){
858                 printf("Fork Failed\n");
859                 return -1;
860         }
861         wait(&status);
862         if(status == 0)
863                 return -1;
864
865         return 0;
866 }
867
868 static int
869 test_failing_mbuf_sanity_check(void)
870 {
871         struct rte_mbuf *buf;
872         struct rte_mbuf badbuf;
873
874         printf("Checking rte_mbuf_sanity_check for failure conditions\n");
875
876         /* get a good mbuf to use to make copies */
877         buf = rte_pktmbuf_alloc(pktmbuf_pool);
878         if (buf == NULL)
879                 return -1;
880         printf("Checking good mbuf initially\n");
881         if (verify_mbuf_check_panics(buf) != -1)
882                 return -1;
883
884         printf("Now checking for error conditions\n");
885
886         if (verify_mbuf_check_panics(NULL)) {
887                 printf("Error with NULL mbuf test\n");
888                 return -1;
889         }
890
891         badbuf = *buf;
892         badbuf.pool = NULL;
893         if (verify_mbuf_check_panics(&badbuf)) {
894                 printf("Error with bad-pool mbuf test\n");
895                 return -1;
896         }
897
898         badbuf = *buf;
899         badbuf.buf_physaddr = 0;
900         if (verify_mbuf_check_panics(&badbuf)) {
901                 printf("Error with bad-physaddr mbuf test\n");
902                 return -1;
903         }
904
905         badbuf = *buf;
906         badbuf.buf_addr = NULL;
907         if (verify_mbuf_check_panics(&badbuf)) {
908                 printf("Error with bad-addr mbuf test\n");
909                 return -1;
910         }
911
912         badbuf = *buf;
913         badbuf.refcnt = 0;
914         if (verify_mbuf_check_panics(&badbuf)) {
915                 printf("Error with bad-refcnt(0) mbuf test\n");
916                 return -1;
917         }
918
919         badbuf = *buf;
920         badbuf.refcnt = UINT16_MAX;
921         if (verify_mbuf_check_panics(&badbuf)) {
922                 printf("Error with bad-refcnt(MAX) mbuf test\n");
923                 return -1;
924         }
925
926         return 0;
927 }
928
929
930 static int
931 test_mbuf(void)
932 {
933         RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_SIZE * 2);
934
935         /* create pktmbuf pool if it does not exist */
936         if (pktmbuf_pool == NULL) {
937                 pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
938                         NB_MBUF, 32, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
939         }
940
941         if (pktmbuf_pool == NULL) {
942                 printf("cannot allocate mbuf pool\n");
943                 return -1;
944         }
945
946         /* create a specific pktmbuf pool with a priv_size != 0 and no data
947          * room size */
948         if (pktmbuf_pool2 == NULL) {
949                 pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
950                         NB_MBUF, 32, MBUF2_PRIV_SIZE, 0, SOCKET_ID_ANY);
951         }
952
953         if (pktmbuf_pool2 == NULL) {
954                 printf("cannot allocate mbuf pool\n");
955                 return -1;
956         }
957
958         /* test multiple mbuf alloc */
959         if (test_pktmbuf_pool() < 0) {
960                 printf("test_mbuf_pool() failed\n");
961                 return -1;
962         }
963
964         /* do it another time to check that all mbufs were freed */
965         if (test_pktmbuf_pool() < 0) {
966                 printf("test_mbuf_pool() failed (2)\n");
967                 return -1;
968         }
969
970         /* test that the pointer to the data on a packet mbuf is set properly */
971         if (test_pktmbuf_pool_ptr() < 0) {
972                 printf("test_pktmbuf_pool_ptr() failed\n");
973                 return -1;
974         }
975
976         /* test data manipulation in mbuf */
977         if (test_one_pktmbuf() < 0) {
978                 printf("test_one_mbuf() failed\n");
979                 return -1;
980         }
981
982
983         /*
984          * do it another time, to check that allocation reinitialize
985          * the mbuf correctly
986          */
987         if (test_one_pktmbuf() < 0) {
988                 printf("test_one_mbuf() failed (2)\n");
989                 return -1;
990         }
991
992         if (test_pktmbuf_with_non_ascii_data() < 0) {
993                 printf("test_pktmbuf_with_non_ascii_data() failed\n");
994                 return -1;
995         }
996
997         /* test free pktmbuf segment one by one */
998         if (test_pktmbuf_free_segment() < 0) {
999                 printf("test_pktmbuf_free_segment() failed.\n");
1000                 return -1;
1001         }
1002
1003         if (testclone_testupdate_testdetach()<0){
1004                 printf("testclone_and_testupdate() failed \n");
1005                 return -1;
1006         }
1007
1008         if (test_attach_from_different_pool() < 0) {
1009                 printf("test_attach_from_different_pool() failed\n");
1010                 return -1;
1011         }
1012
1013         if (test_refcnt_mbuf()<0){
1014                 printf("test_refcnt_mbuf() failed \n");
1015                 return -1;
1016         }
1017
1018         if (test_failing_mbuf_sanity_check() < 0) {
1019                 printf("test_failing_mbuf_sanity_check() failed\n");
1020                 return -1;
1021         }
1022         return 0;
1023 }
1024
1025 static struct test_command mbuf_cmd = {
1026         .command = "mbuf_autotest",
1027         .callback = test_mbuf,
1028 };
1029 REGISTER_TEST_COMMAND(mbuf_cmd);