tailq: remove unneeded inclusions
[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_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 #define REFCNT_MAX_ITER         64
73 #define REFCNT_MAX_TIMEOUT      10
74 #define REFCNT_MAX_REF          (RTE_MAX_LCORE)
75 #define REFCNT_MBUF_NUM         64
76 #define REFCNT_MBUF_SIZE        (sizeof (struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
77 #define REFCNT_RING_SIZE        (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
78
79 #define MAKE_STRING(x)          # x
80
81 static struct rte_mempool *pktmbuf_pool = NULL;
82
83 #ifdef RTE_MBUF_REFCNT_ATOMIC
84
85 static struct rte_mempool *refcnt_pool = NULL;
86 static struct rte_ring *refcnt_mbuf_ring = NULL;
87 static volatile uint32_t refcnt_stop_slaves;
88 static unsigned refcnt_lcore[RTE_MAX_LCORE];
89
90 #endif
91
92 /*
93  * MBUF
94  * ====
95  *
96  * #. Allocate a mbuf pool.
97  *
98  *    - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
99  *      bytes long.
100  *
101  * #. Test multiple allocations of mbufs from this pool.
102  *
103  *    - Allocate NB_MBUF and store pointers in a table.
104  *    - If an allocation fails, return an error.
105  *    - Free all these mbufs.
106  *    - Repeat the same test to check that mbufs were freed correctly.
107  *
108  * #. Test data manipulation in pktmbuf.
109  *
110  *    - Alloc an mbuf.
111  *    - Append data using rte_pktmbuf_append().
112  *    - Test for error in rte_pktmbuf_append() when len is too large.
113  *    - Trim data at the end of mbuf using rte_pktmbuf_trim().
114  *    - Test for error in rte_pktmbuf_trim() when len is too large.
115  *    - Prepend a header using rte_pktmbuf_prepend().
116  *    - Test for error in rte_pktmbuf_prepend() when len is too large.
117  *    - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
118  *    - Test for error in rte_pktmbuf_adj() when len is too large.
119  *    - Check that appended data is not corrupt.
120  *    - Free the mbuf.
121  *    - Between all these tests, check data_len and pkt_len, and
122  *      that the mbuf is contiguous.
123  *    - Repeat the test to check that allocation operations
124  *      reinitialize the mbuf correctly.
125  *
126  */
127
128 #define GOTO_FAIL(str, ...) do {                                        \
129                 printf("mbuf test FAILED (l.%d): <" str ">\n",          \
130                        __LINE__,  ##__VA_ARGS__);                       \
131                 goto fail;                                              \
132 } while(0)
133
134 /*
135  * test data manipulation in mbuf with non-ascii data
136  */
137 static int
138 test_pktmbuf_with_non_ascii_data(void)
139 {
140         struct rte_mbuf *m = NULL;
141         char *data;
142
143         m = rte_pktmbuf_alloc(pktmbuf_pool);
144         if (m == NULL)
145                 GOTO_FAIL("Cannot allocate mbuf");
146         if (rte_pktmbuf_pkt_len(m) != 0)
147                 GOTO_FAIL("Bad length");
148
149         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
150         if (data == NULL)
151                 GOTO_FAIL("Cannot append data");
152         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
153                 GOTO_FAIL("Bad pkt length");
154         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
155                 GOTO_FAIL("Bad data length");
156         memset(data, 0xff, rte_pktmbuf_pkt_len(m));
157         if (!rte_pktmbuf_is_contiguous(m))
158                 GOTO_FAIL("Buffer should be continuous");
159         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
160
161         rte_pktmbuf_free(m);
162
163         return 0;
164
165 fail:
166         if(m) {
167                 rte_pktmbuf_free(m);
168         }
169         return -1;
170 }
171
172 /*
173  * test data manipulation in mbuf
174  */
175 static int
176 test_one_pktmbuf(void)
177 {
178         struct rte_mbuf *m = NULL;
179         char *data, *data2, *hdr;
180         unsigned i;
181
182         printf("Test pktmbuf API\n");
183
184         /* alloc a mbuf */
185
186         m = rte_pktmbuf_alloc(pktmbuf_pool);
187         if (m == NULL)
188                 GOTO_FAIL("Cannot allocate mbuf");
189         if (rte_pktmbuf_pkt_len(m) != 0)
190                 GOTO_FAIL("Bad length");
191
192         rte_pktmbuf_dump(stdout, m, 0);
193
194         /* append data */
195
196         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
197         if (data == NULL)
198                 GOTO_FAIL("Cannot append data");
199         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
200                 GOTO_FAIL("Bad pkt length");
201         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
202                 GOTO_FAIL("Bad data length");
203         memset(data, 0x66, rte_pktmbuf_pkt_len(m));
204         if (!rte_pktmbuf_is_contiguous(m))
205                 GOTO_FAIL("Buffer should be continuous");
206         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
207         rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
208
209         /* this append should fail */
210
211         data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
212         if (data2 != NULL)
213                 GOTO_FAIL("Append should not succeed");
214
215         /* append some more data */
216
217         data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
218         if (data2 == NULL)
219                 GOTO_FAIL("Cannot append data");
220         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
221                 GOTO_FAIL("Bad pkt length");
222         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
223                 GOTO_FAIL("Bad data length");
224         if (!rte_pktmbuf_is_contiguous(m))
225                 GOTO_FAIL("Buffer should be continuous");
226
227         /* trim data at the end of mbuf */
228
229         if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
230                 GOTO_FAIL("Cannot trim data");
231         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
232                 GOTO_FAIL("Bad pkt length");
233         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
234                 GOTO_FAIL("Bad data length");
235         if (!rte_pktmbuf_is_contiguous(m))
236                 GOTO_FAIL("Buffer should be continuous");
237
238         /* this trim should fail */
239
240         if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
241                 GOTO_FAIL("trim should not succeed");
242
243         /* prepend one header */
244
245         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
246         if (hdr == NULL)
247                 GOTO_FAIL("Cannot prepend");
248         if (data - hdr != MBUF_TEST_HDR1_LEN)
249                 GOTO_FAIL("Prepend failed");
250         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
251                 GOTO_FAIL("Bad pkt length");
252         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
253                 GOTO_FAIL("Bad data length");
254         if (!rte_pktmbuf_is_contiguous(m))
255                 GOTO_FAIL("Buffer should be continuous");
256         memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
257
258         /* prepend another header */
259
260         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
261         if (hdr == NULL)
262                 GOTO_FAIL("Cannot prepend");
263         if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
264                 GOTO_FAIL("Prepend failed");
265         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
266                 GOTO_FAIL("Bad pkt length");
267         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
268                 GOTO_FAIL("Bad data length");
269         if (!rte_pktmbuf_is_contiguous(m))
270                 GOTO_FAIL("Buffer should be continuous");
271         memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
272
273         rte_mbuf_sanity_check(m, 1);
274         rte_mbuf_sanity_check(m, 0);
275         rte_pktmbuf_dump(stdout, m, 0);
276
277         /* this prepend should fail */
278
279         hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
280         if (hdr != NULL)
281                 GOTO_FAIL("prepend should not succeed");
282
283         /* remove data at beginning of mbuf (adj) */
284
285         if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
286                 GOTO_FAIL("rte_pktmbuf_adj failed");
287         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
288                 GOTO_FAIL("Bad pkt length");
289         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
290                 GOTO_FAIL("Bad data length");
291         if (!rte_pktmbuf_is_contiguous(m))
292                 GOTO_FAIL("Buffer should be continuous");
293
294         /* this adj should fail */
295
296         if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
297                 GOTO_FAIL("rte_pktmbuf_adj should not succeed");
298
299         /* check data */
300
301         if (!rte_pktmbuf_is_contiguous(m))
302                 GOTO_FAIL("Buffer should be continuous");
303
304         for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
305                 if (data[i] != 0x66)
306                         GOTO_FAIL("Data corrupted at offset %u", i);
307         }
308
309         /* free mbuf */
310
311         rte_pktmbuf_free(m);
312         m = NULL;
313         return 0;
314
315 fail:
316         if (m)
317                 rte_pktmbuf_free(m);
318         return -1;
319 }
320
321 static int
322 testclone_testupdate_testdetach(void)
323 {
324         struct rte_mbuf *mc = NULL;
325         struct rte_mbuf *clone = NULL;
326
327         /* alloc a mbuf */
328
329         mc = rte_pktmbuf_alloc(pktmbuf_pool);
330         if (mc == NULL)
331                 GOTO_FAIL("ooops not allocating mbuf");
332
333         if (rte_pktmbuf_pkt_len(mc) != 0)
334                 GOTO_FAIL("Bad length");
335
336
337         /* clone the allocated mbuf */
338         clone = rte_pktmbuf_clone(mc, pktmbuf_pool);
339         if (clone == NULL)
340                 GOTO_FAIL("cannot clone data\n");
341         rte_pktmbuf_free(clone);
342
343         mc->next = rte_pktmbuf_alloc(pktmbuf_pool);
344         if(mc->next == NULL)
345                 GOTO_FAIL("Next Pkt Null\n");
346
347         clone = rte_pktmbuf_clone(mc, pktmbuf_pool);
348         if (clone == NULL)
349                 GOTO_FAIL("cannot clone data\n");
350
351         /* free mbuf */
352         rte_pktmbuf_free(mc);
353         rte_pktmbuf_free(clone);
354         mc = NULL;
355         clone = NULL;
356         return 0;
357
358 fail:
359         if (mc)
360                 rte_pktmbuf_free(mc);
361         return -1;
362 }
363 #undef GOTO_FAIL
364
365
366
367 /*
368  * test allocation and free of mbufs
369  */
370 static int
371 test_pktmbuf_pool(void)
372 {
373         unsigned i;
374         struct rte_mbuf *m[NB_MBUF];
375         int ret = 0;
376
377         for (i=0; i<NB_MBUF; i++)
378                 m[i] = NULL;
379
380         /* alloc NB_MBUF mbufs */
381         for (i=0; i<NB_MBUF; i++) {
382                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
383                 if (m[i] == NULL) {
384                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
385                         ret = -1;
386                 }
387         }
388         struct rte_mbuf *extra = NULL;
389         extra = rte_pktmbuf_alloc(pktmbuf_pool);
390         if(extra != NULL) {
391                 printf("Error pool not empty");
392                 ret = -1;
393         }
394         extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
395         if(extra != NULL) {
396                 printf("Error pool not empty");
397                 ret = -1;
398         }
399         /* free them */
400         for (i=0; i<NB_MBUF; i++) {
401                 if (m[i] != NULL)
402                         rte_pktmbuf_free(m[i]);
403         }
404
405         return ret;
406 }
407
408 /*
409  * test that the pointer to the data on a packet mbuf is set properly
410  */
411 static int
412 test_pktmbuf_pool_ptr(void)
413 {
414         unsigned i;
415         struct rte_mbuf *m[NB_MBUF];
416         int ret = 0;
417
418         for (i=0; i<NB_MBUF; i++)
419                 m[i] = NULL;
420
421         /* alloc NB_MBUF mbufs */
422         for (i=0; i<NB_MBUF; i++) {
423                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
424                 if (m[i] == NULL) {
425                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
426                         ret = -1;
427                 }
428                 m[i]->data_off += 64;
429         }
430
431         /* free them */
432         for (i=0; i<NB_MBUF; i++) {
433                 if (m[i] != NULL)
434                         rte_pktmbuf_free(m[i]);
435         }
436
437         for (i=0; i<NB_MBUF; i++)
438                 m[i] = NULL;
439
440         /* alloc NB_MBUF mbufs */
441         for (i=0; i<NB_MBUF; i++) {
442                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
443                 if (m[i] == NULL) {
444                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
445                         ret = -1;
446                 }
447                 if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
448                         printf("invalid data_off\n");
449                         ret = -1;
450                 }
451         }
452
453         /* free them */
454         for (i=0; i<NB_MBUF; i++) {
455                 if (m[i] != NULL)
456                         rte_pktmbuf_free(m[i]);
457         }
458
459         return ret;
460 }
461
462 static int
463 test_pktmbuf_free_segment(void)
464 {
465         unsigned i;
466         struct rte_mbuf *m[NB_MBUF];
467         int ret = 0;
468
469         for (i=0; i<NB_MBUF; i++)
470                 m[i] = NULL;
471
472         /* alloc NB_MBUF mbufs */
473         for (i=0; i<NB_MBUF; i++) {
474                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
475                 if (m[i] == NULL) {
476                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
477                         ret = -1;
478                 }
479         }
480
481         /* free them */
482         for (i=0; i<NB_MBUF; i++) {
483                 if (m[i] != NULL) {
484                         struct rte_mbuf *mb, *mt;
485
486                         mb = m[i];
487                         while(mb != NULL) {
488                                 mt = mb;
489                                 mb = mb->next;
490                                 rte_pktmbuf_free_seg(mt);
491                         }
492                 }
493         }
494
495         return ret;
496 }
497
498 /*
499  * Stress test for rte_mbuf atomic refcnt.
500  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
501  * For more efficency, recomended to run with RTE_LIBRTE_MBUF_DEBUG defined.
502  */
503
504 #ifdef RTE_MBUF_REFCNT_ATOMIC
505
506 static int
507 test_refcnt_slave(__attribute__((unused)) void *arg)
508 {
509         unsigned lcore, free;
510         void *mp = 0;
511
512         lcore = rte_lcore_id();
513         printf("%s started at lcore %u\n", __func__, lcore);
514
515         free = 0;
516         while (refcnt_stop_slaves == 0) {
517                 if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
518                         free++;
519                         rte_pktmbuf_free((struct rte_mbuf *)mp);
520                 }
521         }
522
523         refcnt_lcore[lcore] += free;
524         printf("%s finished at lcore %u, "
525                "number of freed mbufs: %u\n",
526                __func__, lcore, free);
527         return (0);
528 }
529
530 static void
531 test_refcnt_iter(unsigned lcore, unsigned iter)
532 {
533         uint16_t ref;
534         unsigned i, n, tref, wn;
535         struct rte_mbuf *m;
536
537         tref = 0;
538
539         /* For each mbuf in the pool:
540          * - allocate mbuf,
541          * - increment it's reference up to N+1,
542          * - enqueue it N times into the ring for slave cores to free.
543          */
544         for (i = 0, n = rte_mempool_count(refcnt_pool);
545             i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
546             i++) {
547                 ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
548                 tref += ref;
549                 if ((ref & 1) != 0) {
550                         rte_pktmbuf_refcnt_update(m, ref);
551                         while (ref-- != 0)
552                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
553                 } else {
554                         while (ref-- != 0) {
555                                 rte_pktmbuf_refcnt_update(m, 1);
556                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
557                         }
558                 }
559                 rte_pktmbuf_free(m);
560         }
561
562         if (i != n)
563                 rte_panic("(lcore=%u, iter=%u): was able to allocate only "
564                           "%u from %u mbufs\n", lcore, iter, i, n);
565
566         /* wait till slave lcores  will consume all mbufs */
567         while (!rte_ring_empty(refcnt_mbuf_ring))
568                 ;
569
570         /* check that all mbufs are back into mempool by now */
571         for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
572                 if ((i = rte_mempool_count(refcnt_pool)) == n) {
573                         refcnt_lcore[lcore] += tref;
574                         printf("%s(lcore=%u, iter=%u) completed, "
575                             "%u references processed\n",
576                             __func__, lcore, iter, tref);
577                         return;
578                 }
579                 rte_delay_ms(1000);
580         }
581
582         rte_panic("(lcore=%u, iter=%u): after %us only "
583                   "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
584 }
585
586 static int
587 test_refcnt_master(void)
588 {
589         unsigned i, lcore;
590
591         lcore = rte_lcore_id();
592         printf("%s started at lcore %u\n", __func__, lcore);
593
594         for (i = 0; i != REFCNT_MAX_ITER; i++)
595                 test_refcnt_iter(lcore, i);
596
597         refcnt_stop_slaves = 1;
598         rte_wmb();
599
600         printf("%s finished at lcore %u\n", __func__, lcore);
601         return (0);
602 }
603
604 #endif
605
606 static int
607 test_refcnt_mbuf(void)
608 {
609 #ifdef RTE_MBUF_REFCNT_ATOMIC
610
611         unsigned lnum, master, slave, tref;
612
613
614         if ((lnum = rte_lcore_count()) == 1) {
615                 printf("skipping %s, number of lcores: %u is not enough\n",
616                     __func__, lnum);
617                 return (0);
618         }
619
620         printf("starting %s, at %u lcores\n", __func__, lnum);
621
622         /* create refcnt pool & ring if they don't exist */
623
624         if (refcnt_pool == NULL &&
625                         (refcnt_pool = rte_mempool_create(
626                         MAKE_STRING(refcnt_pool),
627                         REFCNT_MBUF_NUM, REFCNT_MBUF_SIZE, 0,
628                         sizeof(struct rte_pktmbuf_pool_private),
629                         rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL,
630                         SOCKET_ID_ANY, 0)) == NULL) {
631                 printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
632                     __func__);
633                 return (-1);
634         }
635
636         if (refcnt_mbuf_ring == NULL &&
637                         (refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
638                         REFCNT_RING_SIZE, SOCKET_ID_ANY,
639                         RING_F_SP_ENQ)) == NULL) {
640                 printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
641                     "\n", __func__);
642                 return (-1);
643         }
644
645         refcnt_stop_slaves = 0;
646         memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
647
648         rte_eal_mp_remote_launch(test_refcnt_slave, NULL, SKIP_MASTER);
649
650         test_refcnt_master();
651
652         rte_eal_mp_wait_lcore();
653
654         /* check that we porcessed all references */
655         tref = 0;
656         master = rte_get_master_lcore();
657
658         RTE_LCORE_FOREACH_SLAVE(slave)
659                 tref += refcnt_lcore[slave];
660
661         if (tref != refcnt_lcore[master])
662                 rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
663                           tref, refcnt_lcore[master]);
664
665         rte_mempool_dump(stdout, refcnt_pool);
666         rte_ring_dump(stdout, refcnt_mbuf_ring);
667
668 #endif
669         return (0);
670 }
671
672 #include <unistd.h>
673 #include <sys/wait.h>
674
675 /* use fork() to test mbuf errors panic */
676 static int
677 verify_mbuf_check_panics(struct rte_mbuf *buf)
678 {
679         int pid;
680         int status;
681
682         pid = fork();
683
684         if (pid == 0) {
685                 rte_mbuf_sanity_check(buf, 1); /* should panic */
686                 exit(0);  /* return normally if it doesn't panic */
687         } else if (pid < 0){
688                 printf("Fork Failed\n");
689                 return -1;
690         }
691         wait(&status);
692         if(status == 0)
693                 return -1;
694
695         return 0;
696 }
697
698 static int
699 test_failing_mbuf_sanity_check(void)
700 {
701         struct rte_mbuf *buf;
702         struct rte_mbuf badbuf;
703
704         printf("Checking rte_mbuf_sanity_check for failure conditions\n");
705
706         /* get a good mbuf to use to make copies */
707         buf = rte_pktmbuf_alloc(pktmbuf_pool);
708         if (buf == NULL)
709                 return -1;
710         printf("Checking good mbuf initially\n");
711         if (verify_mbuf_check_panics(buf) != -1)
712                 return -1;
713
714         printf("Now checking for error conditions\n");
715
716         if (verify_mbuf_check_panics(NULL)) {
717                 printf("Error with NULL mbuf test\n");
718                 return -1;
719         }
720
721         badbuf = *buf;
722         badbuf.pool = NULL;
723         if (verify_mbuf_check_panics(&badbuf)) {
724                 printf("Error with bad-pool mbuf test\n");
725                 return -1;
726         }
727
728         badbuf = *buf;
729         badbuf.buf_physaddr = 0;
730         if (verify_mbuf_check_panics(&badbuf)) {
731                 printf("Error with bad-physaddr mbuf test\n");
732                 return -1;
733         }
734
735         badbuf = *buf;
736         badbuf.buf_addr = NULL;
737         if (verify_mbuf_check_panics(&badbuf)) {
738                 printf("Error with bad-addr mbuf test\n");
739                 return -1;
740         }
741
742         badbuf = *buf;
743         badbuf.refcnt = 0;
744         if (verify_mbuf_check_panics(&badbuf)) {
745                 printf("Error with bad-refcnt(0) mbuf test\n");
746                 return -1;
747         }
748
749         badbuf = *buf;
750         badbuf.refcnt = UINT16_MAX;
751         if (verify_mbuf_check_panics(&badbuf)) {
752                 printf("Error with bad-refcnt(MAX) mbuf test\n");
753                 return -1;
754         }
755
756         return 0;
757 }
758
759
760 static int
761 test_mbuf(void)
762 {
763         RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_SIZE * 2);
764
765         /* create pktmbuf pool if it does not exist */
766         if (pktmbuf_pool == NULL) {
767                 pktmbuf_pool =
768                         rte_mempool_create("test_pktmbuf_pool", NB_MBUF,
769                                            MBUF_SIZE, 32,
770                                            sizeof(struct rte_pktmbuf_pool_private),
771                                            rte_pktmbuf_pool_init, NULL,
772                                            rte_pktmbuf_init, NULL,
773                                            SOCKET_ID_ANY, 0);
774         }
775
776         if (pktmbuf_pool == NULL) {
777                 printf("cannot allocate mbuf pool\n");
778                 return -1;
779         }
780
781         /* test multiple mbuf alloc */
782         if (test_pktmbuf_pool() < 0) {
783                 printf("test_mbuf_pool() failed\n");
784                 return -1;
785         }
786
787         /* do it another time to check that all mbufs were freed */
788         if (test_pktmbuf_pool() < 0) {
789                 printf("test_mbuf_pool() failed (2)\n");
790                 return -1;
791         }
792
793         /* test that the pointer to the data on a packet mbuf is set properly */
794         if (test_pktmbuf_pool_ptr() < 0) {
795                 printf("test_pktmbuf_pool_ptr() failed\n");
796                 return -1;
797         }
798
799         /* test data manipulation in mbuf */
800         if (test_one_pktmbuf() < 0) {
801                 printf("test_one_mbuf() failed\n");
802                 return -1;
803         }
804
805
806         /*
807          * do it another time, to check that allocation reinitialize
808          * the mbuf correctly
809          */
810         if (test_one_pktmbuf() < 0) {
811                 printf("test_one_mbuf() failed (2)\n");
812                 return -1;
813         }
814
815         if (test_pktmbuf_with_non_ascii_data() < 0) {
816                 printf("test_pktmbuf_with_non_ascii_data() failed\n");
817                 return -1;
818         }
819
820         /* test free pktmbuf segment one by one */
821         if (test_pktmbuf_free_segment() < 0) {
822                 printf("test_pktmbuf_free_segment() failed.\n");
823                 return -1;
824         }
825
826         if (testclone_testupdate_testdetach()<0){
827                 printf("testclone_and_testupdate() failed \n");
828                 return -1;
829         }
830
831         if (test_refcnt_mbuf()<0){
832                 printf("test_refcnt_mbuf() failed \n");
833                 return -1;
834         }
835
836         if (test_failing_mbuf_sanity_check() < 0) {
837                 printf("test_failing_mbuf_sanity_check() failed\n");
838                 return -1;
839         }
840         return 0;
841 }
842
843 static struct test_command mbuf_cmd = {
844         .command = "mbuf_autotest",
845         .callback = test_mbuf,
846 };
847 REGISTER_TEST_COMMAND(mbuf_cmd);