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