mbuf: add a copy routine
[dpdk.git] / app / test / test_mbuf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <string.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <inttypes.h>
11 #include <errno.h>
12 #include <sys/queue.h>
13
14 #include <rte_common.h>
15 #include <rte_debug.h>
16 #include <rte_log.h>
17 #include <rte_memory.h>
18 #include <rte_memcpy.h>
19 #include <rte_launch.h>
20 #include <rte_eal.h>
21 #include <rte_per_lcore.h>
22 #include <rte_lcore.h>
23 #include <rte_atomic.h>
24 #include <rte_branch_prediction.h>
25 #include <rte_ring.h>
26 #include <rte_mempool.h>
27 #include <rte_mbuf.h>
28 #include <rte_random.h>
29 #include <rte_cycles.h>
30 #include <rte_malloc.h>
31
32 #include "test.h"
33
34 #define MBUF_DATA_SIZE          2048
35 #define NB_MBUF                 128
36 #define MBUF_TEST_DATA_LEN      1464
37 #define MBUF_TEST_DATA_LEN2     50
38 #define MBUF_TEST_HDR1_LEN      20
39 #define MBUF_TEST_HDR2_LEN      30
40 #define MBUF_TEST_ALL_HDRS_LEN  (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN)
41
42 /* size of private data for mbuf in pktmbuf_pool2 */
43 #define MBUF2_PRIV_SIZE         128
44
45 #define REFCNT_MAX_ITER         64
46 #define REFCNT_MAX_TIMEOUT      10
47 #define REFCNT_MAX_REF          (RTE_MAX_LCORE)
48 #define REFCNT_MBUF_NUM         64
49 #define REFCNT_RING_SIZE        (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
50
51 #define MAGIC_DATA              0x42424242
52
53 #define MAKE_STRING(x)          # x
54
55 #ifdef RTE_MBUF_REFCNT_ATOMIC
56
57 static volatile uint32_t refcnt_stop_slaves;
58 static unsigned refcnt_lcore[RTE_MAX_LCORE];
59
60 #endif
61
62 /*
63  * MBUF
64  * ====
65  *
66  * #. Allocate a mbuf pool.
67  *
68  *    - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
69  *      bytes long.
70  *
71  * #. Test multiple allocations of mbufs from this pool.
72  *
73  *    - Allocate NB_MBUF and store pointers in a table.
74  *    - If an allocation fails, return an error.
75  *    - Free all these mbufs.
76  *    - Repeat the same test to check that mbufs were freed correctly.
77  *
78  * #. Test data manipulation in pktmbuf.
79  *
80  *    - Alloc an mbuf.
81  *    - Append data using rte_pktmbuf_append().
82  *    - Test for error in rte_pktmbuf_append() when len is too large.
83  *    - Trim data at the end of mbuf using rte_pktmbuf_trim().
84  *    - Test for error in rte_pktmbuf_trim() when len is too large.
85  *    - Prepend a header using rte_pktmbuf_prepend().
86  *    - Test for error in rte_pktmbuf_prepend() when len is too large.
87  *    - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
88  *    - Test for error in rte_pktmbuf_adj() when len is too large.
89  *    - Check that appended data is not corrupt.
90  *    - Free the mbuf.
91  *    - Between all these tests, check data_len and pkt_len, and
92  *      that the mbuf is contiguous.
93  *    - Repeat the test to check that allocation operations
94  *      reinitialize the mbuf correctly.
95  *
96  * #. Test packet cloning
97  *    - Clone a mbuf and verify the data
98  *    - Clone the cloned mbuf and verify the data
99  *    - Attach a mbuf to another that does not have the same priv_size.
100  */
101
102 #define GOTO_FAIL(str, ...) do {                                        \
103                 printf("mbuf test FAILED (l.%d): <" str ">\n",          \
104                        __LINE__,  ##__VA_ARGS__);                       \
105                 goto fail;                                              \
106 } while(0)
107
108 /*
109  * test data manipulation in mbuf with non-ascii data
110  */
111 static int
112 test_pktmbuf_with_non_ascii_data(struct rte_mempool *pktmbuf_pool)
113 {
114         struct rte_mbuf *m = NULL;
115         char *data;
116
117         m = rte_pktmbuf_alloc(pktmbuf_pool);
118         if (m == NULL)
119                 GOTO_FAIL("Cannot allocate mbuf");
120         if (rte_pktmbuf_pkt_len(m) != 0)
121                 GOTO_FAIL("Bad length");
122
123         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
124         if (data == NULL)
125                 GOTO_FAIL("Cannot append data");
126         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
127                 GOTO_FAIL("Bad pkt length");
128         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
129                 GOTO_FAIL("Bad data length");
130         memset(data, 0xff, rte_pktmbuf_pkt_len(m));
131         if (!rte_pktmbuf_is_contiguous(m))
132                 GOTO_FAIL("Buffer should be continuous");
133         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
134
135         rte_pktmbuf_free(m);
136
137         return 0;
138
139 fail:
140         if(m) {
141                 rte_pktmbuf_free(m);
142         }
143         return -1;
144 }
145
146 /*
147  * test data manipulation in mbuf
148  */
149 static int
150 test_one_pktmbuf(struct rte_mempool *pktmbuf_pool)
151 {
152         struct rte_mbuf *m = NULL;
153         char *data, *data2, *hdr;
154         unsigned i;
155
156         printf("Test pktmbuf API\n");
157
158         /* alloc a mbuf */
159
160         m = rte_pktmbuf_alloc(pktmbuf_pool);
161         if (m == NULL)
162                 GOTO_FAIL("Cannot allocate mbuf");
163         if (rte_pktmbuf_pkt_len(m) != 0)
164                 GOTO_FAIL("Bad length");
165
166         rte_pktmbuf_dump(stdout, m, 0);
167
168         /* append data */
169
170         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
171         if (data == NULL)
172                 GOTO_FAIL("Cannot append data");
173         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
174                 GOTO_FAIL("Bad pkt length");
175         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
176                 GOTO_FAIL("Bad data length");
177         memset(data, 0x66, rte_pktmbuf_pkt_len(m));
178         if (!rte_pktmbuf_is_contiguous(m))
179                 GOTO_FAIL("Buffer should be continuous");
180         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
181         rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
182
183         /* this append should fail */
184
185         data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
186         if (data2 != NULL)
187                 GOTO_FAIL("Append should not succeed");
188
189         /* append some more data */
190
191         data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
192         if (data2 == NULL)
193                 GOTO_FAIL("Cannot append data");
194         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
195                 GOTO_FAIL("Bad pkt length");
196         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
197                 GOTO_FAIL("Bad data length");
198         if (!rte_pktmbuf_is_contiguous(m))
199                 GOTO_FAIL("Buffer should be continuous");
200
201         /* trim data at the end of mbuf */
202
203         if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
204                 GOTO_FAIL("Cannot trim 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         if (!rte_pktmbuf_is_contiguous(m))
210                 GOTO_FAIL("Buffer should be continuous");
211
212         /* this trim should fail */
213
214         if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
215                 GOTO_FAIL("trim should not succeed");
216
217         /* prepend one header */
218
219         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
220         if (hdr == NULL)
221                 GOTO_FAIL("Cannot prepend");
222         if (data - hdr != MBUF_TEST_HDR1_LEN)
223                 GOTO_FAIL("Prepend failed");
224         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
225                 GOTO_FAIL("Bad pkt length");
226         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
227                 GOTO_FAIL("Bad data length");
228         if (!rte_pktmbuf_is_contiguous(m))
229                 GOTO_FAIL("Buffer should be continuous");
230         memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
231
232         /* prepend another header */
233
234         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
235         if (hdr == NULL)
236                 GOTO_FAIL("Cannot prepend");
237         if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
238                 GOTO_FAIL("Prepend failed");
239         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
240                 GOTO_FAIL("Bad pkt length");
241         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
242                 GOTO_FAIL("Bad data length");
243         if (!rte_pktmbuf_is_contiguous(m))
244                 GOTO_FAIL("Buffer should be continuous");
245         memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
246
247         rte_mbuf_sanity_check(m, 1);
248         rte_mbuf_sanity_check(m, 0);
249         rte_pktmbuf_dump(stdout, m, 0);
250
251         /* this prepend should fail */
252
253         hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
254         if (hdr != NULL)
255                 GOTO_FAIL("prepend should not succeed");
256
257         /* remove data at beginning of mbuf (adj) */
258
259         if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
260                 GOTO_FAIL("rte_pktmbuf_adj failed");
261         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
262                 GOTO_FAIL("Bad pkt length");
263         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
264                 GOTO_FAIL("Bad data length");
265         if (!rte_pktmbuf_is_contiguous(m))
266                 GOTO_FAIL("Buffer should be continuous");
267
268         /* this adj should fail */
269
270         if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
271                 GOTO_FAIL("rte_pktmbuf_adj should not succeed");
272
273         /* check data */
274
275         if (!rte_pktmbuf_is_contiguous(m))
276                 GOTO_FAIL("Buffer should be continuous");
277
278         for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
279                 if (data[i] != 0x66)
280                         GOTO_FAIL("Data corrupted at offset %u", i);
281         }
282
283         /* free mbuf */
284
285         rte_pktmbuf_free(m);
286         m = NULL;
287         return 0;
288
289 fail:
290         if (m)
291                 rte_pktmbuf_free(m);
292         return -1;
293 }
294
295 static int
296 testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool)
297 {
298         struct rte_mbuf *m = NULL;
299         struct rte_mbuf *clone = NULL;
300         struct rte_mbuf *clone2 = NULL;
301         unaligned_uint32_t *data;
302
303         /* alloc a mbuf */
304         m = rte_pktmbuf_alloc(pktmbuf_pool);
305         if (m == NULL)
306                 GOTO_FAIL("ooops not allocating mbuf");
307
308         if (rte_pktmbuf_pkt_len(m) != 0)
309                 GOTO_FAIL("Bad length");
310
311         rte_pktmbuf_append(m, sizeof(uint32_t));
312         data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
313         *data = MAGIC_DATA;
314
315         /* clone the allocated mbuf */
316         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
317         if (clone == NULL)
318                 GOTO_FAIL("cannot clone data\n");
319
320         data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
321         if (*data != MAGIC_DATA)
322                 GOTO_FAIL("invalid data in clone\n");
323
324         if (rte_mbuf_refcnt_read(m) != 2)
325                 GOTO_FAIL("invalid refcnt in m\n");
326
327         /* free the clone */
328         rte_pktmbuf_free(clone);
329         clone = NULL;
330
331         /* same test with a chained mbuf */
332         m->next = rte_pktmbuf_alloc(pktmbuf_pool);
333         if (m->next == NULL)
334                 GOTO_FAIL("Next Pkt Null\n");
335         m->nb_segs = 2;
336
337         rte_pktmbuf_append(m->next, sizeof(uint32_t));
338         m->pkt_len = 2 * sizeof(uint32_t);
339
340         data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
341         *data = MAGIC_DATA;
342
343         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
344         if (clone == NULL)
345                 GOTO_FAIL("cannot clone data\n");
346
347         data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
348         if (*data != MAGIC_DATA)
349                 GOTO_FAIL("invalid data in clone\n");
350
351         data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
352         if (*data != MAGIC_DATA)
353                 GOTO_FAIL("invalid data in clone->next\n");
354
355         if (rte_mbuf_refcnt_read(m) != 2)
356                 GOTO_FAIL("invalid refcnt in m\n");
357
358         if (rte_mbuf_refcnt_read(m->next) != 2)
359                 GOTO_FAIL("invalid refcnt in m->next\n");
360
361         /* try to clone the clone */
362
363         clone2 = rte_pktmbuf_clone(clone, pktmbuf_pool);
364         if (clone2 == NULL)
365                 GOTO_FAIL("cannot clone the clone\n");
366
367         data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
368         if (*data != MAGIC_DATA)
369                 GOTO_FAIL("invalid data in clone2\n");
370
371         data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
372         if (*data != MAGIC_DATA)
373                 GOTO_FAIL("invalid data in clone2->next\n");
374
375         if (rte_mbuf_refcnt_read(m) != 3)
376                 GOTO_FAIL("invalid refcnt in m\n");
377
378         if (rte_mbuf_refcnt_read(m->next) != 3)
379                 GOTO_FAIL("invalid refcnt in m->next\n");
380
381         /* free mbuf */
382         rte_pktmbuf_free(m);
383         rte_pktmbuf_free(clone);
384         rte_pktmbuf_free(clone2);
385
386         m = NULL;
387         clone = NULL;
388         clone2 = NULL;
389         printf("%s ok\n", __func__);
390         return 0;
391
392 fail:
393         if (m)
394                 rte_pktmbuf_free(m);
395         if (clone)
396                 rte_pktmbuf_free(clone);
397         if (clone2)
398                 rte_pktmbuf_free(clone2);
399         return -1;
400 }
401
402 static int
403 test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool)
404 {
405         struct rte_mbuf *m = NULL;
406         struct rte_mbuf *copy = NULL;
407         struct rte_mbuf *copy2 = NULL;
408         struct rte_mbuf *clone = NULL;
409         unaligned_uint32_t *data;
410
411         /* alloc a mbuf */
412         m = rte_pktmbuf_alloc(pktmbuf_pool);
413         if (m == NULL)
414                 GOTO_FAIL("ooops not allocating mbuf");
415
416         if (rte_pktmbuf_pkt_len(m) != 0)
417                 GOTO_FAIL("Bad length");
418
419         rte_pktmbuf_append(m, sizeof(uint32_t));
420         data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
421         *data = MAGIC_DATA;
422
423         /* copy the allocated mbuf */
424         copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
425         if (copy == NULL)
426                 GOTO_FAIL("cannot copy data\n");
427
428         if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
429                 GOTO_FAIL("copy length incorrect\n");
430
431         if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
432                 GOTO_FAIL("copy data length incorrect\n");
433
434         data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
435         if (*data != MAGIC_DATA)
436                 GOTO_FAIL("invalid data in copy\n");
437
438         /* free the copy */
439         rte_pktmbuf_free(copy);
440         copy = NULL;
441
442         /* same test with a cloned mbuf */
443         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
444         if (clone == NULL)
445                 GOTO_FAIL("cannot clone data\n");
446
447         if (!RTE_MBUF_CLONED(clone))
448                 GOTO_FAIL("clone did not give a cloned mbuf\n");
449
450         copy = rte_pktmbuf_copy(clone, pktmbuf_pool, 0, UINT32_MAX);
451         if (copy == NULL)
452                 GOTO_FAIL("cannot copy cloned mbuf\n");
453
454         if (RTE_MBUF_CLONED(copy))
455                 GOTO_FAIL("copy of clone is cloned?\n");
456
457         if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
458                 GOTO_FAIL("copy clone length incorrect\n");
459
460         if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
461                 GOTO_FAIL("copy clone data length incorrect\n");
462
463         data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
464         if (*data != MAGIC_DATA)
465                 GOTO_FAIL("invalid data in clone copy\n");
466         rte_pktmbuf_free(clone);
467         rte_pktmbuf_free(copy);
468         copy = NULL;
469         clone = NULL;
470
471
472         /* same test with a chained mbuf */
473         m->next = rte_pktmbuf_alloc(pktmbuf_pool);
474         if (m->next == NULL)
475                 GOTO_FAIL("Next Pkt Null\n");
476         m->nb_segs = 2;
477
478         rte_pktmbuf_append(m->next, sizeof(uint32_t));
479         m->pkt_len = 2 * sizeof(uint32_t);
480         data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
481         *data = MAGIC_DATA + 1;
482
483         copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
484         if (copy == NULL)
485                 GOTO_FAIL("cannot copy data\n");
486
487         if (rte_pktmbuf_pkt_len(copy) != 2 * sizeof(uint32_t))
488                 GOTO_FAIL("chain copy length incorrect\n");
489
490         if (rte_pktmbuf_data_len(copy) != 2 * sizeof(uint32_t))
491                 GOTO_FAIL("chain copy data length incorrect\n");
492
493         data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
494         if (data[0] != MAGIC_DATA || data[1] != MAGIC_DATA + 1)
495                 GOTO_FAIL("invalid data in copy\n");
496
497         rte_pktmbuf_free(copy2);
498
499         /* test offset copy */
500         copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
501                                  sizeof(uint32_t), UINT32_MAX);
502         if (copy2 == NULL)
503                 GOTO_FAIL("cannot copy the copy\n");
504
505         if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
506                 GOTO_FAIL("copy with offset, length incorrect\n");
507
508         if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
509                 GOTO_FAIL("copy with offset, data length incorrect\n");
510
511         data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
512         if (data[0] != MAGIC_DATA + 1)
513                 GOTO_FAIL("copy with offset, invalid data\n");
514
515         rte_pktmbuf_free(copy2);
516
517         /* test truncation copy */
518         copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
519                                  0, sizeof(uint32_t));
520         if (copy2 == NULL)
521                 GOTO_FAIL("cannot copy the copy\n");
522
523         if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
524                 GOTO_FAIL("copy with truncate, length incorrect\n");
525
526         if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
527                 GOTO_FAIL("copy with truncate, data length incorrect\n");
528
529         data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
530         if (data[0] != MAGIC_DATA)
531                 GOTO_FAIL("copy with truncate, invalid data\n");
532
533         /* free mbuf */
534         rte_pktmbuf_free(m);
535         rte_pktmbuf_free(copy);
536         rte_pktmbuf_free(copy2);
537
538         m = NULL;
539         copy = NULL;
540         copy2 = NULL;
541         printf("%s ok\n", __func__);
542         return 0;
543
544 fail:
545         if (m)
546                 rte_pktmbuf_free(m);
547         if (copy)
548                 rte_pktmbuf_free(copy);
549         if (copy2)
550                 rte_pktmbuf_free(copy2);
551         return -1;
552 }
553
554 static int
555 test_attach_from_different_pool(struct rte_mempool *pktmbuf_pool,
556                                 struct rte_mempool *pktmbuf_pool2)
557 {
558         struct rte_mbuf *m = NULL;
559         struct rte_mbuf *clone = NULL;
560         struct rte_mbuf *clone2 = NULL;
561         char *data, *c_data, *c_data2;
562
563         /* alloc a mbuf */
564         m = rte_pktmbuf_alloc(pktmbuf_pool);
565         if (m == NULL)
566                 GOTO_FAIL("cannot allocate mbuf");
567
568         if (rte_pktmbuf_pkt_len(m) != 0)
569                 GOTO_FAIL("Bad length");
570
571         data = rte_pktmbuf_mtod(m, char *);
572
573         /* allocate a new mbuf from the second pool, and attach it to the first
574          * mbuf */
575         clone = rte_pktmbuf_alloc(pktmbuf_pool2);
576         if (clone == NULL)
577                 GOTO_FAIL("cannot allocate mbuf from second pool\n");
578
579         /* check data room size and priv size, and erase priv */
580         if (rte_pktmbuf_data_room_size(clone->pool) != 0)
581                 GOTO_FAIL("data room size should be 0\n");
582         if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE)
583                 GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
584         memset(clone + 1, 0, MBUF2_PRIV_SIZE);
585
586         /* save data pointer to compare it after detach() */
587         c_data = rte_pktmbuf_mtod(clone, char *);
588         if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE)
589                 GOTO_FAIL("bad data pointer in clone");
590         if (rte_pktmbuf_headroom(clone) != 0)
591                 GOTO_FAIL("bad headroom in clone");
592
593         rte_pktmbuf_attach(clone, m);
594
595         if (rte_pktmbuf_mtod(clone, char *) != data)
596                 GOTO_FAIL("clone was not attached properly\n");
597         if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM)
598                 GOTO_FAIL("bad headroom in clone after attach");
599         if (rte_mbuf_refcnt_read(m) != 2)
600                 GOTO_FAIL("invalid refcnt in m\n");
601
602         /* allocate a new mbuf from the second pool, and attach it to the first
603          * cloned mbuf */
604         clone2 = rte_pktmbuf_alloc(pktmbuf_pool2);
605         if (clone2 == NULL)
606                 GOTO_FAIL("cannot allocate clone2 from second pool\n");
607
608         /* check data room size and priv size, and erase priv */
609         if (rte_pktmbuf_data_room_size(clone2->pool) != 0)
610                 GOTO_FAIL("data room size should be 0\n");
611         if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE)
612                 GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
613         memset(clone2 + 1, 0, MBUF2_PRIV_SIZE);
614
615         /* save data pointer to compare it after detach() */
616         c_data2 = rte_pktmbuf_mtod(clone2, char *);
617         if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE)
618                 GOTO_FAIL("bad data pointer in clone2");
619         if (rte_pktmbuf_headroom(clone2) != 0)
620                 GOTO_FAIL("bad headroom in clone2");
621
622         rte_pktmbuf_attach(clone2, clone);
623
624         if (rte_pktmbuf_mtod(clone2, char *) != data)
625                 GOTO_FAIL("clone2 was not attached properly\n");
626         if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM)
627                 GOTO_FAIL("bad headroom in clone2 after attach");
628         if (rte_mbuf_refcnt_read(m) != 3)
629                 GOTO_FAIL("invalid refcnt in m\n");
630
631         /* detach the clones */
632         rte_pktmbuf_detach(clone);
633         if (c_data != rte_pktmbuf_mtod(clone, char *))
634                 GOTO_FAIL("clone was not detached properly\n");
635         if (rte_mbuf_refcnt_read(m) != 2)
636                 GOTO_FAIL("invalid refcnt in m\n");
637
638         rte_pktmbuf_detach(clone2);
639         if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
640                 GOTO_FAIL("clone2 was not detached properly\n");
641         if (rte_mbuf_refcnt_read(m) != 1)
642                 GOTO_FAIL("invalid refcnt in m\n");
643
644         /* free the clones and the initial mbuf */
645         rte_pktmbuf_free(clone2);
646         rte_pktmbuf_free(clone);
647         rte_pktmbuf_free(m);
648         printf("%s ok\n", __func__);
649         return 0;
650
651 fail:
652         if (m)
653                 rte_pktmbuf_free(m);
654         if (clone)
655                 rte_pktmbuf_free(clone);
656         if (clone2)
657                 rte_pktmbuf_free(clone2);
658         return -1;
659 }
660 #undef GOTO_FAIL
661
662 /*
663  * test allocation and free of mbufs
664  */
665 static int
666 test_pktmbuf_pool(struct rte_mempool *pktmbuf_pool)
667 {
668         unsigned i;
669         struct rte_mbuf *m[NB_MBUF];
670         int ret = 0;
671
672         for (i=0; i<NB_MBUF; i++)
673                 m[i] = NULL;
674
675         /* alloc NB_MBUF mbufs */
676         for (i=0; i<NB_MBUF; i++) {
677                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
678                 if (m[i] == NULL) {
679                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
680                         ret = -1;
681                 }
682         }
683         struct rte_mbuf *extra = NULL;
684         extra = rte_pktmbuf_alloc(pktmbuf_pool);
685         if(extra != NULL) {
686                 printf("Error pool not empty");
687                 ret = -1;
688         }
689         extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
690         if(extra != NULL) {
691                 printf("Error pool not empty");
692                 ret = -1;
693         }
694         /* free them */
695         for (i=0; i<NB_MBUF; i++) {
696                 if (m[i] != NULL)
697                         rte_pktmbuf_free(m[i]);
698         }
699
700         return ret;
701 }
702
703 /*
704  * test that the pointer to the data on a packet mbuf is set properly
705  */
706 static int
707 test_pktmbuf_pool_ptr(struct rte_mempool *pktmbuf_pool)
708 {
709         unsigned i;
710         struct rte_mbuf *m[NB_MBUF];
711         int ret = 0;
712
713         for (i=0; i<NB_MBUF; i++)
714                 m[i] = NULL;
715
716         /* alloc NB_MBUF mbufs */
717         for (i=0; i<NB_MBUF; i++) {
718                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
719                 if (m[i] == NULL) {
720                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
721                         ret = -1;
722                         break;
723                 }
724                 m[i]->data_off += 64;
725         }
726
727         /* free them */
728         for (i=0; i<NB_MBUF; i++) {
729                 if (m[i] != NULL)
730                         rte_pktmbuf_free(m[i]);
731         }
732
733         for (i=0; i<NB_MBUF; i++)
734                 m[i] = NULL;
735
736         /* alloc NB_MBUF mbufs */
737         for (i=0; i<NB_MBUF; i++) {
738                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
739                 if (m[i] == NULL) {
740                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
741                         ret = -1;
742                         break;
743                 }
744                 if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
745                         printf("invalid data_off\n");
746                         ret = -1;
747                 }
748         }
749
750         /* free them */
751         for (i=0; i<NB_MBUF; i++) {
752                 if (m[i] != NULL)
753                         rte_pktmbuf_free(m[i]);
754         }
755
756         return ret;
757 }
758
759 static int
760 test_pktmbuf_free_segment(struct rte_mempool *pktmbuf_pool)
761 {
762         unsigned i;
763         struct rte_mbuf *m[NB_MBUF];
764         int ret = 0;
765
766         for (i=0; i<NB_MBUF; i++)
767                 m[i] = NULL;
768
769         /* alloc NB_MBUF mbufs */
770         for (i=0; i<NB_MBUF; i++) {
771                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
772                 if (m[i] == NULL) {
773                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
774                         ret = -1;
775                 }
776         }
777
778         /* free them */
779         for (i=0; i<NB_MBUF; i++) {
780                 if (m[i] != NULL) {
781                         struct rte_mbuf *mb, *mt;
782
783                         mb = m[i];
784                         while(mb != NULL) {
785                                 mt = mb;
786                                 mb = mb->next;
787                                 rte_pktmbuf_free_seg(mt);
788                         }
789                 }
790         }
791
792         return ret;
793 }
794
795 /*
796  * Stress test for rte_mbuf atomic refcnt.
797  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
798  * For more efficiency, recommended to run with RTE_LIBRTE_MBUF_DEBUG defined.
799  */
800
801 #ifdef RTE_MBUF_REFCNT_ATOMIC
802
803 static int
804 test_refcnt_slave(void *arg)
805 {
806         unsigned lcore, free;
807         void *mp = 0;
808         struct rte_ring *refcnt_mbuf_ring = arg;
809
810         lcore = rte_lcore_id();
811         printf("%s started at lcore %u\n", __func__, lcore);
812
813         free = 0;
814         while (refcnt_stop_slaves == 0) {
815                 if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
816                         free++;
817                         rte_pktmbuf_free(mp);
818                 }
819         }
820
821         refcnt_lcore[lcore] += free;
822         printf("%s finished at lcore %u, "
823                "number of freed mbufs: %u\n",
824                __func__, lcore, free);
825         return 0;
826 }
827
828 static void
829 test_refcnt_iter(unsigned int lcore, unsigned int iter,
830                  struct rte_mempool *refcnt_pool,
831                  struct rte_ring *refcnt_mbuf_ring)
832 {
833         uint16_t ref;
834         unsigned i, n, tref, wn;
835         struct rte_mbuf *m;
836
837         tref = 0;
838
839         /* For each mbuf in the pool:
840          * - allocate mbuf,
841          * - increment it's reference up to N+1,
842          * - enqueue it N times into the ring for slave cores to free.
843          */
844         for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
845             i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
846             i++) {
847                 ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
848                 tref += ref;
849                 if ((ref & 1) != 0) {
850                         rte_pktmbuf_refcnt_update(m, ref);
851                         while (ref-- != 0)
852                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
853                 } else {
854                         while (ref-- != 0) {
855                                 rte_pktmbuf_refcnt_update(m, 1);
856                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
857                         }
858                 }
859                 rte_pktmbuf_free(m);
860         }
861
862         if (i != n)
863                 rte_panic("(lcore=%u, iter=%u): was able to allocate only "
864                           "%u from %u mbufs\n", lcore, iter, i, n);
865
866         /* wait till slave lcores  will consume all mbufs */
867         while (!rte_ring_empty(refcnt_mbuf_ring))
868                 ;
869
870         /* check that all mbufs are back into mempool by now */
871         for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
872                 if ((i = rte_mempool_avail_count(refcnt_pool)) == n) {
873                         refcnt_lcore[lcore] += tref;
874                         printf("%s(lcore=%u, iter=%u) completed, "
875                             "%u references processed\n",
876                             __func__, lcore, iter, tref);
877                         return;
878                 }
879                 rte_delay_ms(100);
880         }
881
882         rte_panic("(lcore=%u, iter=%u): after %us only "
883                   "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
884 }
885
886 static int
887 test_refcnt_master(struct rte_mempool *refcnt_pool,
888                    struct rte_ring *refcnt_mbuf_ring)
889 {
890         unsigned i, lcore;
891
892         lcore = rte_lcore_id();
893         printf("%s started at lcore %u\n", __func__, lcore);
894
895         for (i = 0; i != REFCNT_MAX_ITER; i++)
896                 test_refcnt_iter(lcore, i, refcnt_pool, refcnt_mbuf_ring);
897
898         refcnt_stop_slaves = 1;
899         rte_wmb();
900
901         printf("%s finished at lcore %u\n", __func__, lcore);
902         return 0;
903 }
904
905 #endif
906
907 static int
908 test_refcnt_mbuf(void)
909 {
910 #ifdef RTE_MBUF_REFCNT_ATOMIC
911         unsigned int master, slave, tref;
912         int ret = -1;
913         struct rte_mempool *refcnt_pool = NULL;
914         struct rte_ring *refcnt_mbuf_ring = NULL;
915
916         if (rte_lcore_count() < 2) {
917                 printf("Not enough cores for test_refcnt_mbuf, expecting at least 2\n");
918                 return TEST_SKIPPED;
919         }
920
921         printf("starting %s, at %u lcores\n", __func__, rte_lcore_count());
922
923         /* create refcnt pool & ring if they don't exist */
924
925         refcnt_pool = rte_pktmbuf_pool_create(MAKE_STRING(refcnt_pool),
926                                               REFCNT_MBUF_NUM, 0, 0, 0,
927                                               SOCKET_ID_ANY);
928         if (refcnt_pool == NULL) {
929                 printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
930                     __func__);
931                 return -1;
932         }
933
934         refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
935                         rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
936                                         RING_F_SP_ENQ);
937         if (refcnt_mbuf_ring == NULL) {
938                 printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
939                     "\n", __func__);
940                 goto err;
941         }
942
943         refcnt_stop_slaves = 0;
944         memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
945
946         rte_eal_mp_remote_launch(test_refcnt_slave, refcnt_mbuf_ring,
947                                  SKIP_MASTER);
948
949         test_refcnt_master(refcnt_pool, refcnt_mbuf_ring);
950
951         rte_eal_mp_wait_lcore();
952
953         /* check that we porcessed all references */
954         tref = 0;
955         master = rte_get_master_lcore();
956
957         RTE_LCORE_FOREACH_SLAVE(slave)
958                 tref += refcnt_lcore[slave];
959
960         if (tref != refcnt_lcore[master])
961                 rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
962                           tref, refcnt_lcore[master]);
963
964         rte_mempool_dump(stdout, refcnt_pool);
965         rte_ring_dump(stdout, refcnt_mbuf_ring);
966
967         ret = 0;
968
969 err:
970         rte_mempool_free(refcnt_pool);
971         rte_ring_free(refcnt_mbuf_ring);
972         return ret;
973 #else
974         return 0;
975 #endif
976 }
977
978 #include <unistd.h>
979 #include <sys/wait.h>
980
981 /* use fork() to test mbuf errors panic */
982 static int
983 verify_mbuf_check_panics(struct rte_mbuf *buf)
984 {
985         int pid;
986         int status;
987
988         pid = fork();
989
990         if (pid == 0) {
991                 rte_mbuf_sanity_check(buf, 1); /* should panic */
992                 exit(0);  /* return normally if it doesn't panic */
993         } else if (pid < 0){
994                 printf("Fork Failed\n");
995                 return -1;
996         }
997         wait(&status);
998         if(status == 0)
999                 return -1;
1000
1001         return 0;
1002 }
1003
1004 static int
1005 test_failing_mbuf_sanity_check(struct rte_mempool *pktmbuf_pool)
1006 {
1007         struct rte_mbuf *buf;
1008         struct rte_mbuf badbuf;
1009
1010         printf("Checking rte_mbuf_sanity_check for failure conditions\n");
1011
1012         /* get a good mbuf to use to make copies */
1013         buf = rte_pktmbuf_alloc(pktmbuf_pool);
1014         if (buf == NULL)
1015                 return -1;
1016         printf("Checking good mbuf initially\n");
1017         if (verify_mbuf_check_panics(buf) != -1)
1018                 return -1;
1019
1020         printf("Now checking for error conditions\n");
1021
1022         if (verify_mbuf_check_panics(NULL)) {
1023                 printf("Error with NULL mbuf test\n");
1024                 return -1;
1025         }
1026
1027         badbuf = *buf;
1028         badbuf.pool = NULL;
1029         if (verify_mbuf_check_panics(&badbuf)) {
1030                 printf("Error with bad-pool mbuf test\n");
1031                 return -1;
1032         }
1033
1034         badbuf = *buf;
1035         badbuf.buf_iova = 0;
1036         if (verify_mbuf_check_panics(&badbuf)) {
1037                 printf("Error with bad-physaddr mbuf test\n");
1038                 return -1;
1039         }
1040
1041         badbuf = *buf;
1042         badbuf.buf_addr = NULL;
1043         if (verify_mbuf_check_panics(&badbuf)) {
1044                 printf("Error with bad-addr mbuf test\n");
1045                 return -1;
1046         }
1047
1048         badbuf = *buf;
1049         badbuf.refcnt = 0;
1050         if (verify_mbuf_check_panics(&badbuf)) {
1051                 printf("Error with bad-refcnt(0) mbuf test\n");
1052                 return -1;
1053         }
1054
1055         badbuf = *buf;
1056         badbuf.refcnt = UINT16_MAX;
1057         if (verify_mbuf_check_panics(&badbuf)) {
1058                 printf("Error with bad-refcnt(MAX) mbuf test\n");
1059                 return -1;
1060         }
1061
1062         return 0;
1063 }
1064
1065 static int
1066 test_mbuf_linearize(struct rte_mempool *pktmbuf_pool, int pkt_len,
1067                     int nb_segs)
1068 {
1069
1070         struct rte_mbuf *m = NULL, *mbuf = NULL;
1071         uint8_t *data;
1072         int data_len = 0;
1073         int remain;
1074         int seg, seg_len;
1075         int i;
1076
1077         if (pkt_len < 1) {
1078                 printf("Packet size must be 1 or more (is %d)\n", pkt_len);
1079                 return -1;
1080         }
1081
1082         if (nb_segs < 1) {
1083                 printf("Number of segments must be 1 or more (is %d)\n",
1084                                 nb_segs);
1085                 return -1;
1086         }
1087
1088         seg_len = pkt_len / nb_segs;
1089         if (seg_len == 0)
1090                 seg_len = 1;
1091
1092         remain = pkt_len;
1093
1094         /* Create chained mbuf_src and fill it generated data */
1095         for (seg = 0; remain > 0; seg++) {
1096
1097                 m = rte_pktmbuf_alloc(pktmbuf_pool);
1098                 if (m == NULL) {
1099                         printf("Cannot create segment for source mbuf");
1100                         goto fail;
1101                 }
1102
1103                 /* Make sure if tailroom is zeroed */
1104                 memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
1105                                 rte_pktmbuf_tailroom(m));
1106
1107                 data_len = remain;
1108                 if (data_len > seg_len)
1109                         data_len = seg_len;
1110
1111                 data = (uint8_t *)rte_pktmbuf_append(m, data_len);
1112                 if (data == NULL) {
1113                         printf("Cannot append %d bytes to the mbuf\n",
1114                                         data_len);
1115                         goto fail;
1116                 }
1117
1118                 for (i = 0; i < data_len; i++)
1119                         data[i] = (seg * seg_len + i) % 0x0ff;
1120
1121                 if (seg == 0)
1122                         mbuf = m;
1123                 else
1124                         rte_pktmbuf_chain(mbuf, m);
1125
1126                 remain -= data_len;
1127         }
1128
1129         /* Create destination buffer to store coalesced data */
1130         if (rte_pktmbuf_linearize(mbuf)) {
1131                 printf("Mbuf linearization failed\n");
1132                 goto fail;
1133         }
1134
1135         if (!rte_pktmbuf_is_contiguous(mbuf)) {
1136                 printf("Source buffer should be contiguous after "
1137                                 "linearization\n");
1138                 goto fail;
1139         }
1140
1141         data = rte_pktmbuf_mtod(mbuf, uint8_t *);
1142
1143         for (i = 0; i < pkt_len; i++)
1144                 if (data[i] != (i % 0x0ff)) {
1145                         printf("Incorrect data in linearized mbuf\n");
1146                         goto fail;
1147                 }
1148
1149         rte_pktmbuf_free(mbuf);
1150         return 0;
1151
1152 fail:
1153         if (mbuf)
1154                 rte_pktmbuf_free(mbuf);
1155         return -1;
1156 }
1157
1158 static int
1159 test_mbuf_linearize_check(struct rte_mempool *pktmbuf_pool)
1160 {
1161         struct test_mbuf_array {
1162                 int size;
1163                 int nb_segs;
1164         } mbuf_array[] = {
1165                         { 128, 1 },
1166                         { 64, 64 },
1167                         { 512, 10 },
1168                         { 250, 11 },
1169                         { 123, 8 },
1170         };
1171         unsigned int i;
1172
1173         printf("Test mbuf linearize API\n");
1174
1175         for (i = 0; i < RTE_DIM(mbuf_array); i++)
1176                 if (test_mbuf_linearize(pktmbuf_pool, mbuf_array[i].size,
1177                                 mbuf_array[i].nb_segs)) {
1178                         printf("Test failed for %d, %d\n", mbuf_array[i].size,
1179                                         mbuf_array[i].nb_segs);
1180                         return -1;
1181                 }
1182
1183         return 0;
1184 }
1185
1186 /*
1187  * Helper function for test_tx_ofload
1188  */
1189 static inline void
1190 set_tx_offload(struct rte_mbuf *mb, uint64_t il2, uint64_t il3, uint64_t il4,
1191         uint64_t tso, uint64_t ol3, uint64_t ol2)
1192 {
1193         mb->l2_len = il2;
1194         mb->l3_len = il3;
1195         mb->l4_len = il4;
1196         mb->tso_segsz = tso;
1197         mb->outer_l3_len = ol3;
1198         mb->outer_l2_len = ol2;
1199 }
1200
1201 static int
1202 test_tx_offload(void)
1203 {
1204         struct rte_mbuf *mb;
1205         uint64_t tm, v1, v2;
1206         size_t sz;
1207         uint32_t i;
1208
1209         static volatile struct {
1210                 uint16_t l2;
1211                 uint16_t l3;
1212                 uint16_t l4;
1213                 uint16_t tso;
1214         } txof;
1215
1216         const uint32_t num = 0x10000;
1217
1218         txof.l2 = rte_rand() % (1 <<  RTE_MBUF_L2_LEN_BITS);
1219         txof.l3 = rte_rand() % (1 <<  RTE_MBUF_L3_LEN_BITS);
1220         txof.l4 = rte_rand() % (1 <<  RTE_MBUF_L4_LEN_BITS);
1221         txof.tso = rte_rand() % (1 <<   RTE_MBUF_TSO_SEGSZ_BITS);
1222
1223         printf("%s started, tx_offload = {\n"
1224                 "\tl2_len=%#hx,\n"
1225                 "\tl3_len=%#hx,\n"
1226                 "\tl4_len=%#hx,\n"
1227                 "\ttso_segsz=%#hx,\n"
1228                 "\touter_l3_len=%#x,\n"
1229                 "\touter_l2_len=%#x,\n"
1230                 "};\n",
1231                 __func__,
1232                 txof.l2, txof.l3, txof.l4, txof.tso, txof.l3, txof.l2);
1233
1234         sz = sizeof(*mb) * num;
1235         mb = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
1236         if (mb == NULL) {
1237                 printf("%s failed, out of memory\n", __func__);
1238                 return -ENOMEM;
1239         }
1240
1241         memset(mb, 0, sz);
1242         tm = rte_rdtsc_precise();
1243
1244         for (i = 0; i != num; i++)
1245                 set_tx_offload(mb + i, txof.l2, txof.l3, txof.l4,
1246                         txof.tso, txof.l3, txof.l2);
1247
1248         tm = rte_rdtsc_precise() - tm;
1249         printf("%s set tx_offload by bit-fields: %u iterations, %"
1250                 PRIu64 " cycles, %#Lf cycles/iter\n",
1251                 __func__, num, tm, (long double)tm / num);
1252
1253         v1 = mb[rte_rand() % num].tx_offload;
1254
1255         memset(mb, 0, sz);
1256         tm = rte_rdtsc_precise();
1257
1258         for (i = 0; i != num; i++)
1259                 mb[i].tx_offload = rte_mbuf_tx_offload(txof.l2, txof.l3,
1260                         txof.l4, txof.tso, txof.l3, txof.l2, 0);
1261
1262         tm = rte_rdtsc_precise() - tm;
1263         printf("%s set raw tx_offload: %u iterations, %"
1264                 PRIu64 " cycles, %#Lf cycles/iter\n",
1265                 __func__, num, tm, (long double)tm / num);
1266
1267         v2 = mb[rte_rand() % num].tx_offload;
1268
1269         rte_free(mb);
1270
1271         printf("%s finished\n"
1272                 "expected tx_offload value: 0x%" PRIx64 ";\n"
1273                 "rte_mbuf_tx_offload value: 0x%" PRIx64 ";\n",
1274                 __func__, v1, v2);
1275
1276         return (v1 == v2) ? 0 : -EINVAL;
1277 }
1278
1279 static int
1280 test_mbuf(void)
1281 {
1282         int ret = -1;
1283         struct rte_mempool *pktmbuf_pool = NULL;
1284         struct rte_mempool *pktmbuf_pool2 = NULL;
1285
1286
1287         RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
1288
1289         /* create pktmbuf pool if it does not exist */
1290         pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
1291                         NB_MBUF, 32, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
1292
1293         if (pktmbuf_pool == NULL) {
1294                 printf("cannot allocate mbuf pool\n");
1295                 goto err;
1296         }
1297
1298         /* create a specific pktmbuf pool with a priv_size != 0 and no data
1299          * room size */
1300         pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
1301                         NB_MBUF, 32, MBUF2_PRIV_SIZE, 0, SOCKET_ID_ANY);
1302
1303         if (pktmbuf_pool2 == NULL) {
1304                 printf("cannot allocate mbuf pool\n");
1305                 goto err;
1306         }
1307
1308         /* test multiple mbuf alloc */
1309         if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
1310                 printf("test_mbuf_pool() failed\n");
1311                 goto err;
1312         }
1313
1314         /* do it another time to check that all mbufs were freed */
1315         if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
1316                 printf("test_mbuf_pool() failed (2)\n");
1317                 goto err;
1318         }
1319
1320         /* test that the pointer to the data on a packet mbuf is set properly */
1321         if (test_pktmbuf_pool_ptr(pktmbuf_pool) < 0) {
1322                 printf("test_pktmbuf_pool_ptr() failed\n");
1323                 goto err;
1324         }
1325
1326         /* test data manipulation in mbuf */
1327         if (test_one_pktmbuf(pktmbuf_pool) < 0) {
1328                 printf("test_one_mbuf() failed\n");
1329                 goto err;
1330         }
1331
1332
1333         /*
1334          * do it another time, to check that allocation reinitialize
1335          * the mbuf correctly
1336          */
1337         if (test_one_pktmbuf(pktmbuf_pool) < 0) {
1338                 printf("test_one_mbuf() failed (2)\n");
1339                 goto err;
1340         }
1341
1342         if (test_pktmbuf_with_non_ascii_data(pktmbuf_pool) < 0) {
1343                 printf("test_pktmbuf_with_non_ascii_data() failed\n");
1344                 goto err;
1345         }
1346
1347         /* test free pktmbuf segment one by one */
1348         if (test_pktmbuf_free_segment(pktmbuf_pool) < 0) {
1349                 printf("test_pktmbuf_free_segment() failed.\n");
1350                 goto err;
1351         }
1352
1353         if (testclone_testupdate_testdetach(pktmbuf_pool) < 0) {
1354                 printf("testclone_and_testupdate() failed \n");
1355                 goto err;
1356         }
1357
1358         if (test_pktmbuf_copy(pktmbuf_pool) < 0) {
1359                 printf("test_pktmbuf_copy() failed\n");
1360                 goto err;
1361         }
1362
1363         if (test_attach_from_different_pool(pktmbuf_pool, pktmbuf_pool2) < 0) {
1364                 printf("test_attach_from_different_pool() failed\n");
1365                 goto err;
1366         }
1367
1368         if (test_refcnt_mbuf() < 0) {
1369                 printf("test_refcnt_mbuf() failed \n");
1370                 goto err;
1371         }
1372
1373         if (test_failing_mbuf_sanity_check(pktmbuf_pool) < 0) {
1374                 printf("test_failing_mbuf_sanity_check() failed\n");
1375                 goto err;
1376         }
1377
1378         if (test_mbuf_linearize_check(pktmbuf_pool) < 0) {
1379                 printf("test_mbuf_linearize_check() failed\n");
1380                 goto err;
1381         }
1382
1383         if (test_tx_offload() < 0) {
1384                 printf("test_tx_offload() failed\n");
1385                 goto err;
1386         }
1387
1388         ret = 0;
1389 err:
1390         rte_mempool_free(pktmbuf_pool);
1391         rte_mempool_free(pktmbuf_pool2);
1392         return ret;
1393 }
1394
1395 REGISTER_TEST_COMMAND(mbuf_autotest, test_mbuf);