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