test/mbuf: add unit test cases
[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_errno.h>
16 #include <rte_debug.h>
17 #include <rte_log.h>
18 #include <rte_memory.h>
19 #include <rte_memcpy.h>
20 #include <rte_launch.h>
21 #include <rte_eal.h>
22 #include <rte_per_lcore.h>
23 #include <rte_lcore.h>
24 #include <rte_atomic.h>
25 #include <rte_branch_prediction.h>
26 #include <rte_ring.h>
27 #include <rte_mempool.h>
28 #include <rte_mbuf.h>
29 #include <rte_random.h>
30 #include <rte_cycles.h>
31 #include <rte_malloc.h>
32 #include <rte_ether.h>
33 #include <rte_ip.h>
34 #include <rte_tcp.h>
35
36 #include "test.h"
37
38 #define MEMPOOL_CACHE_SIZE      32
39 #define MBUF_DATA_SIZE          2048
40 #define NB_MBUF                 128
41 #define MBUF_TEST_DATA_LEN      1464
42 #define MBUF_TEST_DATA_LEN2     50
43 #define MBUF_TEST_DATA_LEN3     256
44 #define MBUF_TEST_HDR1_LEN      20
45 #define MBUF_TEST_HDR2_LEN      30
46 #define MBUF_TEST_ALL_HDRS_LEN  (MBUF_TEST_HDR1_LEN+MBUF_TEST_HDR2_LEN)
47 #define MBUF_TEST_SEG_SIZE      64
48 #define MBUF_TEST_BURST         8
49 #define EXT_BUF_TEST_DATA_LEN   1024
50 #define MBUF_MAX_SEG            16
51 #define MBUF_NO_HEADER          0
52 #define MBUF_HEADER             1
53 #define MBUF_NEG_TEST_READ      2
54
55 /* chain length in bulk test */
56 #define CHAIN_LEN 16
57
58 /* size of private data for mbuf in pktmbuf_pool2 */
59 #define MBUF2_PRIV_SIZE         128
60
61 #define REFCNT_MAX_ITER         64
62 #define REFCNT_MAX_TIMEOUT      10
63 #define REFCNT_MAX_REF          (RTE_MAX_LCORE)
64 #define REFCNT_MBUF_NUM         64
65 #define REFCNT_RING_SIZE        (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
66
67 #define MAGIC_DATA              0x42424242
68
69 #define MAKE_STRING(x)          # x
70
71 #ifdef RTE_MBUF_REFCNT_ATOMIC
72
73 static volatile uint32_t refcnt_stop_slaves;
74 static unsigned refcnt_lcore[RTE_MAX_LCORE];
75
76 #endif
77
78 /*
79  * MBUF
80  * ====
81  *
82  * #. Allocate a mbuf pool.
83  *
84  *    - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
85  *      bytes long.
86  *
87  * #. Test multiple allocations of mbufs from this pool.
88  *
89  *    - Allocate NB_MBUF and store pointers in a table.
90  *    - If an allocation fails, return an error.
91  *    - Free all these mbufs.
92  *    - Repeat the same test to check that mbufs were freed correctly.
93  *
94  * #. Test data manipulation in pktmbuf.
95  *
96  *    - Alloc an mbuf.
97  *    - Append data using rte_pktmbuf_append().
98  *    - Test for error in rte_pktmbuf_append() when len is too large.
99  *    - Trim data at the end of mbuf using rte_pktmbuf_trim().
100  *    - Test for error in rte_pktmbuf_trim() when len is too large.
101  *    - Prepend a header using rte_pktmbuf_prepend().
102  *    - Test for error in rte_pktmbuf_prepend() when len is too large.
103  *    - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
104  *    - Test for error in rte_pktmbuf_adj() when len is too large.
105  *    - Check that appended data is not corrupt.
106  *    - Free the mbuf.
107  *    - Between all these tests, check data_len and pkt_len, and
108  *      that the mbuf is contiguous.
109  *    - Repeat the test to check that allocation operations
110  *      reinitialize the mbuf correctly.
111  *
112  * #. Test packet cloning
113  *    - Clone a mbuf and verify the data
114  *    - Clone the cloned mbuf and verify the data
115  *    - Attach a mbuf to another that does not have the same priv_size.
116  */
117
118 #define GOTO_FAIL(str, ...) do {                                        \
119                 printf("mbuf test FAILED (l.%d): <" str ">\n",          \
120                        __LINE__,  ##__VA_ARGS__);                       \
121                 goto fail;                                              \
122 } while(0)
123
124 /*
125  * test data manipulation in mbuf with non-ascii data
126  */
127 static int
128 test_pktmbuf_with_non_ascii_data(struct rte_mempool *pktmbuf_pool)
129 {
130         struct rte_mbuf *m = NULL;
131         char *data;
132
133         m = rte_pktmbuf_alloc(pktmbuf_pool);
134         if (m == NULL)
135                 GOTO_FAIL("Cannot allocate mbuf");
136         if (rte_pktmbuf_pkt_len(m) != 0)
137                 GOTO_FAIL("Bad length");
138
139         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
140         if (data == NULL)
141                 GOTO_FAIL("Cannot append data");
142         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
143                 GOTO_FAIL("Bad pkt length");
144         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
145                 GOTO_FAIL("Bad data length");
146         memset(data, 0xff, rte_pktmbuf_pkt_len(m));
147         if (!rte_pktmbuf_is_contiguous(m))
148                 GOTO_FAIL("Buffer should be continuous");
149         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
150
151         rte_pktmbuf_free(m);
152
153         return 0;
154
155 fail:
156         if(m) {
157                 rte_pktmbuf_free(m);
158         }
159         return -1;
160 }
161
162 /*
163  * test data manipulation in mbuf
164  */
165 static int
166 test_one_pktmbuf(struct rte_mempool *pktmbuf_pool)
167 {
168         struct rte_mbuf *m = NULL;
169         char *data, *data2, *hdr;
170         unsigned i;
171
172         printf("Test pktmbuf API\n");
173
174         /* alloc a mbuf */
175
176         m = rte_pktmbuf_alloc(pktmbuf_pool);
177         if (m == NULL)
178                 GOTO_FAIL("Cannot allocate mbuf");
179         if (rte_pktmbuf_pkt_len(m) != 0)
180                 GOTO_FAIL("Bad length");
181
182         rte_pktmbuf_dump(stdout, m, 0);
183
184         /* append data */
185
186         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
187         if (data == NULL)
188                 GOTO_FAIL("Cannot append data");
189         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
190                 GOTO_FAIL("Bad pkt length");
191         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
192                 GOTO_FAIL("Bad data length");
193         memset(data, 0x66, rte_pktmbuf_pkt_len(m));
194         if (!rte_pktmbuf_is_contiguous(m))
195                 GOTO_FAIL("Buffer should be continuous");
196         rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
197         rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
198
199         /* this append should fail */
200
201         data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
202         if (data2 != NULL)
203                 GOTO_FAIL("Append should not succeed");
204
205         /* append some more data */
206
207         data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
208         if (data2 == NULL)
209                 GOTO_FAIL("Cannot append data");
210         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
211                 GOTO_FAIL("Bad pkt length");
212         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
213                 GOTO_FAIL("Bad data length");
214         if (!rte_pktmbuf_is_contiguous(m))
215                 GOTO_FAIL("Buffer should be continuous");
216
217         /* trim data at the end of mbuf */
218
219         if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
220                 GOTO_FAIL("Cannot trim data");
221         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
222                 GOTO_FAIL("Bad pkt length");
223         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
224                 GOTO_FAIL("Bad data length");
225         if (!rte_pktmbuf_is_contiguous(m))
226                 GOTO_FAIL("Buffer should be continuous");
227
228         /* this trim should fail */
229
230         if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
231                 GOTO_FAIL("trim should not succeed");
232
233         /* prepend one header */
234
235         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
236         if (hdr == NULL)
237                 GOTO_FAIL("Cannot prepend");
238         if (data - hdr != MBUF_TEST_HDR1_LEN)
239                 GOTO_FAIL("Prepend failed");
240         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
241                 GOTO_FAIL("Bad pkt length");
242         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
243                 GOTO_FAIL("Bad data length");
244         if (!rte_pktmbuf_is_contiguous(m))
245                 GOTO_FAIL("Buffer should be continuous");
246         memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
247
248         /* prepend another header */
249
250         hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
251         if (hdr == NULL)
252                 GOTO_FAIL("Cannot prepend");
253         if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
254                 GOTO_FAIL("Prepend failed");
255         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
256                 GOTO_FAIL("Bad pkt length");
257         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
258                 GOTO_FAIL("Bad data length");
259         if (!rte_pktmbuf_is_contiguous(m))
260                 GOTO_FAIL("Buffer should be continuous");
261         memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
262
263         rte_mbuf_sanity_check(m, 1);
264         rte_mbuf_sanity_check(m, 0);
265         rte_pktmbuf_dump(stdout, m, 0);
266
267         /* this prepend should fail */
268
269         hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
270         if (hdr != NULL)
271                 GOTO_FAIL("prepend should not succeed");
272
273         /* remove data at beginning of mbuf (adj) */
274
275         if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
276                 GOTO_FAIL("rte_pktmbuf_adj failed");
277         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
278                 GOTO_FAIL("Bad pkt length");
279         if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
280                 GOTO_FAIL("Bad data length");
281         if (!rte_pktmbuf_is_contiguous(m))
282                 GOTO_FAIL("Buffer should be continuous");
283
284         /* this adj should fail */
285
286         if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
287                 GOTO_FAIL("rte_pktmbuf_adj should not succeed");
288
289         /* check data */
290
291         if (!rte_pktmbuf_is_contiguous(m))
292                 GOTO_FAIL("Buffer should be continuous");
293
294         for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
295                 if (data[i] != 0x66)
296                         GOTO_FAIL("Data corrupted at offset %u", i);
297         }
298
299         /* free mbuf */
300
301         rte_pktmbuf_free(m);
302         m = NULL;
303         return 0;
304
305 fail:
306         if (m)
307                 rte_pktmbuf_free(m);
308         return -1;
309 }
310
311 static int
312 testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool)
313 {
314         struct rte_mbuf *m = NULL;
315         struct rte_mbuf *clone = NULL;
316         struct rte_mbuf *clone2 = NULL;
317         unaligned_uint32_t *data;
318
319         /* alloc a mbuf */
320         m = rte_pktmbuf_alloc(pktmbuf_pool);
321         if (m == NULL)
322                 GOTO_FAIL("ooops not allocating mbuf");
323
324         if (rte_pktmbuf_pkt_len(m) != 0)
325                 GOTO_FAIL("Bad length");
326
327         rte_pktmbuf_append(m, sizeof(uint32_t));
328         data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
329         *data = MAGIC_DATA;
330
331         /* clone the allocated mbuf */
332         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
333         if (clone == NULL)
334                 GOTO_FAIL("cannot clone data\n");
335
336         data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
337         if (*data != MAGIC_DATA)
338                 GOTO_FAIL("invalid data in clone\n");
339
340         if (rte_mbuf_refcnt_read(m) != 2)
341                 GOTO_FAIL("invalid refcnt in m\n");
342
343         /* free the clone */
344         rte_pktmbuf_free(clone);
345         clone = NULL;
346
347         /* same test with a chained mbuf */
348         m->next = rte_pktmbuf_alloc(pktmbuf_pool);
349         if (m->next == NULL)
350                 GOTO_FAIL("Next Pkt Null\n");
351         m->nb_segs = 2;
352
353         rte_pktmbuf_append(m->next, sizeof(uint32_t));
354         m->pkt_len = 2 * sizeof(uint32_t);
355
356         data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
357         *data = MAGIC_DATA;
358
359         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
360         if (clone == NULL)
361                 GOTO_FAIL("cannot clone data\n");
362
363         data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
364         if (*data != MAGIC_DATA)
365                 GOTO_FAIL("invalid data in clone\n");
366
367         data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
368         if (*data != MAGIC_DATA)
369                 GOTO_FAIL("invalid data in clone->next\n");
370
371         if (rte_mbuf_refcnt_read(m) != 2)
372                 GOTO_FAIL("invalid refcnt in m\n");
373
374         if (rte_mbuf_refcnt_read(m->next) != 2)
375                 GOTO_FAIL("invalid refcnt in m->next\n");
376
377         /* try to clone the clone */
378
379         clone2 = rte_pktmbuf_clone(clone, pktmbuf_pool);
380         if (clone2 == NULL)
381                 GOTO_FAIL("cannot clone the clone\n");
382
383         data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
384         if (*data != MAGIC_DATA)
385                 GOTO_FAIL("invalid data in clone2\n");
386
387         data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
388         if (*data != MAGIC_DATA)
389                 GOTO_FAIL("invalid data in clone2->next\n");
390
391         if (rte_mbuf_refcnt_read(m) != 3)
392                 GOTO_FAIL("invalid refcnt in m\n");
393
394         if (rte_mbuf_refcnt_read(m->next) != 3)
395                 GOTO_FAIL("invalid refcnt in m->next\n");
396
397         /* free mbuf */
398         rte_pktmbuf_free(m);
399         rte_pktmbuf_free(clone);
400         rte_pktmbuf_free(clone2);
401
402         m = NULL;
403         clone = NULL;
404         clone2 = NULL;
405         printf("%s ok\n", __func__);
406         return 0;
407
408 fail:
409         if (m)
410                 rte_pktmbuf_free(m);
411         if (clone)
412                 rte_pktmbuf_free(clone);
413         if (clone2)
414                 rte_pktmbuf_free(clone2);
415         return -1;
416 }
417
418 static int
419 test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool)
420 {
421         struct rte_mbuf *m = NULL;
422         struct rte_mbuf *copy = NULL;
423         struct rte_mbuf *copy2 = NULL;
424         struct rte_mbuf *clone = NULL;
425         unaligned_uint32_t *data;
426
427         /* alloc a mbuf */
428         m = rte_pktmbuf_alloc(pktmbuf_pool);
429         if (m == NULL)
430                 GOTO_FAIL("ooops not allocating mbuf");
431
432         if (rte_pktmbuf_pkt_len(m) != 0)
433                 GOTO_FAIL("Bad length");
434
435         rte_pktmbuf_append(m, sizeof(uint32_t));
436         data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
437         *data = MAGIC_DATA;
438
439         /* copy the allocated mbuf */
440         copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
441         if (copy == NULL)
442                 GOTO_FAIL("cannot copy data\n");
443
444         if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
445                 GOTO_FAIL("copy length incorrect\n");
446
447         if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
448                 GOTO_FAIL("copy data length incorrect\n");
449
450         data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
451         if (*data != MAGIC_DATA)
452                 GOTO_FAIL("invalid data in copy\n");
453
454         /* free the copy */
455         rte_pktmbuf_free(copy);
456         copy = NULL;
457
458         /* same test with a cloned mbuf */
459         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
460         if (clone == NULL)
461                 GOTO_FAIL("cannot clone data\n");
462
463         if (!RTE_MBUF_CLONED(clone))
464                 GOTO_FAIL("clone did not give a cloned mbuf\n");
465
466         copy = rte_pktmbuf_copy(clone, pktmbuf_pool, 0, UINT32_MAX);
467         if (copy == NULL)
468                 GOTO_FAIL("cannot copy cloned mbuf\n");
469
470         if (RTE_MBUF_CLONED(copy))
471                 GOTO_FAIL("copy of clone is cloned?\n");
472
473         if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
474                 GOTO_FAIL("copy clone length incorrect\n");
475
476         if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
477                 GOTO_FAIL("copy clone data length incorrect\n");
478
479         data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
480         if (*data != MAGIC_DATA)
481                 GOTO_FAIL("invalid data in clone copy\n");
482         rte_pktmbuf_free(clone);
483         rte_pktmbuf_free(copy);
484         copy = NULL;
485         clone = NULL;
486
487
488         /* same test with a chained mbuf */
489         m->next = rte_pktmbuf_alloc(pktmbuf_pool);
490         if (m->next == NULL)
491                 GOTO_FAIL("Next Pkt Null\n");
492         m->nb_segs = 2;
493
494         rte_pktmbuf_append(m->next, sizeof(uint32_t));
495         m->pkt_len = 2 * sizeof(uint32_t);
496         data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
497         *data = MAGIC_DATA + 1;
498
499         copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
500         if (copy == NULL)
501                 GOTO_FAIL("cannot copy data\n");
502
503         if (rte_pktmbuf_pkt_len(copy) != 2 * sizeof(uint32_t))
504                 GOTO_FAIL("chain copy length incorrect\n");
505
506         if (rte_pktmbuf_data_len(copy) != 2 * sizeof(uint32_t))
507                 GOTO_FAIL("chain copy data length incorrect\n");
508
509         data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
510         if (data[0] != MAGIC_DATA || data[1] != MAGIC_DATA + 1)
511                 GOTO_FAIL("invalid data in copy\n");
512
513         rte_pktmbuf_free(copy2);
514
515         /* test offset copy */
516         copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
517                                  sizeof(uint32_t), UINT32_MAX);
518         if (copy2 == NULL)
519                 GOTO_FAIL("cannot copy the copy\n");
520
521         if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
522                 GOTO_FAIL("copy with offset, length incorrect\n");
523
524         if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
525                 GOTO_FAIL("copy with offset, data length incorrect\n");
526
527         data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
528         if (data[0] != MAGIC_DATA + 1)
529                 GOTO_FAIL("copy with offset, invalid data\n");
530
531         rte_pktmbuf_free(copy2);
532
533         /* test truncation copy */
534         copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
535                                  0, sizeof(uint32_t));
536         if (copy2 == NULL)
537                 GOTO_FAIL("cannot copy the copy\n");
538
539         if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
540                 GOTO_FAIL("copy with truncate, length incorrect\n");
541
542         if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
543                 GOTO_FAIL("copy with truncate, data length incorrect\n");
544
545         data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
546         if (data[0] != MAGIC_DATA)
547                 GOTO_FAIL("copy with truncate, invalid data\n");
548
549         /* free mbuf */
550         rte_pktmbuf_free(m);
551         rte_pktmbuf_free(copy);
552         rte_pktmbuf_free(copy2);
553
554         m = NULL;
555         copy = NULL;
556         copy2 = NULL;
557         printf("%s ok\n", __func__);
558         return 0;
559
560 fail:
561         if (m)
562                 rte_pktmbuf_free(m);
563         if (copy)
564                 rte_pktmbuf_free(copy);
565         if (copy2)
566                 rte_pktmbuf_free(copy2);
567         return -1;
568 }
569
570 static int
571 test_attach_from_different_pool(struct rte_mempool *pktmbuf_pool,
572                                 struct rte_mempool *pktmbuf_pool2)
573 {
574         struct rte_mbuf *m = NULL;
575         struct rte_mbuf *clone = NULL;
576         struct rte_mbuf *clone2 = NULL;
577         char *data, *c_data, *c_data2;
578
579         /* alloc a mbuf */
580         m = rte_pktmbuf_alloc(pktmbuf_pool);
581         if (m == NULL)
582                 GOTO_FAIL("cannot allocate mbuf");
583
584         if (rte_pktmbuf_pkt_len(m) != 0)
585                 GOTO_FAIL("Bad length");
586
587         data = rte_pktmbuf_mtod(m, char *);
588
589         /* allocate a new mbuf from the second pool, and attach it to the first
590          * mbuf */
591         clone = rte_pktmbuf_alloc(pktmbuf_pool2);
592         if (clone == NULL)
593                 GOTO_FAIL("cannot allocate mbuf from second pool\n");
594
595         /* check data room size and priv size, and erase priv */
596         if (rte_pktmbuf_data_room_size(clone->pool) != 0)
597                 GOTO_FAIL("data room size should be 0\n");
598         if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE)
599                 GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
600         memset(clone + 1, 0, MBUF2_PRIV_SIZE);
601
602         /* save data pointer to compare it after detach() */
603         c_data = rte_pktmbuf_mtod(clone, char *);
604         if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE)
605                 GOTO_FAIL("bad data pointer in clone");
606         if (rte_pktmbuf_headroom(clone) != 0)
607                 GOTO_FAIL("bad headroom in clone");
608
609         rte_pktmbuf_attach(clone, m);
610
611         if (rte_pktmbuf_mtod(clone, char *) != data)
612                 GOTO_FAIL("clone was not attached properly\n");
613         if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM)
614                 GOTO_FAIL("bad headroom in clone after attach");
615         if (rte_mbuf_refcnt_read(m) != 2)
616                 GOTO_FAIL("invalid refcnt in m\n");
617
618         /* allocate a new mbuf from the second pool, and attach it to the first
619          * cloned mbuf */
620         clone2 = rte_pktmbuf_alloc(pktmbuf_pool2);
621         if (clone2 == NULL)
622                 GOTO_FAIL("cannot allocate clone2 from second pool\n");
623
624         /* check data room size and priv size, and erase priv */
625         if (rte_pktmbuf_data_room_size(clone2->pool) != 0)
626                 GOTO_FAIL("data room size should be 0\n");
627         if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE)
628                 GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
629         memset(clone2 + 1, 0, MBUF2_PRIV_SIZE);
630
631         /* save data pointer to compare it after detach() */
632         c_data2 = rte_pktmbuf_mtod(clone2, char *);
633         if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE)
634                 GOTO_FAIL("bad data pointer in clone2");
635         if (rte_pktmbuf_headroom(clone2) != 0)
636                 GOTO_FAIL("bad headroom in clone2");
637
638         rte_pktmbuf_attach(clone2, clone);
639
640         if (rte_pktmbuf_mtod(clone2, char *) != data)
641                 GOTO_FAIL("clone2 was not attached properly\n");
642         if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM)
643                 GOTO_FAIL("bad headroom in clone2 after attach");
644         if (rte_mbuf_refcnt_read(m) != 3)
645                 GOTO_FAIL("invalid refcnt in m\n");
646
647         /* detach the clones */
648         rte_pktmbuf_detach(clone);
649         if (c_data != rte_pktmbuf_mtod(clone, char *))
650                 GOTO_FAIL("clone was not detached properly\n");
651         if (rte_mbuf_refcnt_read(m) != 2)
652                 GOTO_FAIL("invalid refcnt in m\n");
653
654         rte_pktmbuf_detach(clone2);
655         if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
656                 GOTO_FAIL("clone2 was not detached properly\n");
657         if (rte_mbuf_refcnt_read(m) != 1)
658                 GOTO_FAIL("invalid refcnt in m\n");
659
660         /* free the clones and the initial mbuf */
661         rte_pktmbuf_free(clone2);
662         rte_pktmbuf_free(clone);
663         rte_pktmbuf_free(m);
664         printf("%s ok\n", __func__);
665         return 0;
666
667 fail:
668         if (m)
669                 rte_pktmbuf_free(m);
670         if (clone)
671                 rte_pktmbuf_free(clone);
672         if (clone2)
673                 rte_pktmbuf_free(clone2);
674         return -1;
675 }
676
677 /*
678  * test allocation and free of mbufs
679  */
680 static int
681 test_pktmbuf_pool(struct rte_mempool *pktmbuf_pool)
682 {
683         unsigned i;
684         struct rte_mbuf *m[NB_MBUF];
685         int ret = 0;
686
687         for (i=0; i<NB_MBUF; i++)
688                 m[i] = NULL;
689
690         /* alloc NB_MBUF mbufs */
691         for (i=0; i<NB_MBUF; i++) {
692                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
693                 if (m[i] == NULL) {
694                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
695                         ret = -1;
696                 }
697         }
698         struct rte_mbuf *extra = NULL;
699         extra = rte_pktmbuf_alloc(pktmbuf_pool);
700         if(extra != NULL) {
701                 printf("Error pool not empty");
702                 ret = -1;
703         }
704         extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
705         if(extra != NULL) {
706                 printf("Error pool not empty");
707                 ret = -1;
708         }
709         /* free them */
710         for (i=0; i<NB_MBUF; i++) {
711                 if (m[i] != NULL)
712                         rte_pktmbuf_free(m[i]);
713         }
714
715         return ret;
716 }
717
718 /*
719  * test bulk allocation and bulk free of mbufs
720  */
721 static int
722 test_pktmbuf_pool_bulk(void)
723 {
724         struct rte_mempool *pool = NULL;
725         struct rte_mempool *pool2 = NULL;
726         unsigned int i;
727         struct rte_mbuf *m;
728         struct rte_mbuf *mbufs[NB_MBUF];
729         int ret = 0;
730
731         /* We cannot use the preallocated mbuf pools because their caches
732          * prevent us from bulk allocating all objects in them.
733          * So we create our own mbuf pools without caches.
734          */
735         printf("Create mbuf pools for bulk allocation.\n");
736         pool = rte_pktmbuf_pool_create("test_pktmbuf_bulk",
737                         NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
738         if (pool == NULL) {
739                 printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
740                        rte_errno);
741                 goto err;
742         }
743         pool2 = rte_pktmbuf_pool_create("test_pktmbuf_bulk2",
744                         NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
745         if (pool2 == NULL) {
746                 printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
747                        rte_errno);
748                 goto err;
749         }
750
751         /* Preconditions: Mempools must be full. */
752         if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
753                 printf("Test precondition failed: mempools not full\n");
754                 goto err;
755         }
756         if (!(rte_mempool_avail_count(pool) == NB_MBUF &&
757                         rte_mempool_avail_count(pool2) == NB_MBUF)) {
758                 printf("Test precondition failed: mempools: %u+%u != %u+%u",
759                        rte_mempool_avail_count(pool),
760                        rte_mempool_avail_count(pool2),
761                        NB_MBUF, NB_MBUF);
762                 goto err;
763         }
764
765         printf("Test single bulk alloc, followed by multiple bulk free.\n");
766
767         /* Bulk allocate all mbufs in the pool, in one go. */
768         ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
769         if (ret != 0) {
770                 printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
771                 goto err;
772         }
773         /* Test that they have been removed from the pool. */
774         if (!rte_mempool_empty(pool)) {
775                 printf("mempool not empty\n");
776                 goto err;
777         }
778         /* Bulk free all mbufs, in four steps. */
779         RTE_BUILD_BUG_ON(NB_MBUF % 4 != 0);
780         for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
781                 rte_pktmbuf_free_bulk(&mbufs[i], NB_MBUF / 4);
782                 /* Test that they have been returned to the pool. */
783                 if (rte_mempool_avail_count(pool) != i + NB_MBUF / 4) {
784                         printf("mempool avail count incorrect\n");
785                         goto err;
786                 }
787         }
788
789         printf("Test multiple bulk alloc, followed by single bulk free.\n");
790
791         /* Bulk allocate all mbufs in the pool, in four steps. */
792         for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
793                 ret = rte_pktmbuf_alloc_bulk(pool, &mbufs[i], NB_MBUF / 4);
794                 if (ret != 0) {
795                         printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
796                         goto err;
797                 }
798         }
799         /* Test that they have been removed from the pool. */
800         if (!rte_mempool_empty(pool)) {
801                 printf("mempool not empty\n");
802                 goto err;
803         }
804         /* Bulk free all mbufs, in one go. */
805         rte_pktmbuf_free_bulk(mbufs, NB_MBUF);
806         /* Test that they have been returned to the pool. */
807         if (!rte_mempool_full(pool)) {
808                 printf("mempool not full\n");
809                 goto err;
810         }
811
812         printf("Test bulk free of single long chain.\n");
813
814         /* Bulk allocate all mbufs in the pool, in one go. */
815         ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
816         if (ret != 0) {
817                 printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
818                 goto err;
819         }
820         /* Create a long mbuf chain. */
821         for (i = 1; i < NB_MBUF; i++) {
822                 ret = rte_pktmbuf_chain(mbufs[0], mbufs[i]);
823                 if (ret != 0) {
824                         printf("rte_pktmbuf_chain() failed: %d\n", ret);
825                         goto err;
826                 }
827                 mbufs[i] = NULL;
828         }
829         /* Free the mbuf chain containing all the mbufs. */
830         rte_pktmbuf_free_bulk(mbufs, 1);
831         /* Test that they have been returned to the pool. */
832         if (!rte_mempool_full(pool)) {
833                 printf("mempool not full\n");
834                 goto err;
835         }
836
837         printf("Test bulk free of multiple chains using multiple pools.\n");
838
839         /* Create mbuf chains containing mbufs from different pools. */
840         RTE_BUILD_BUG_ON(CHAIN_LEN % 2 != 0);
841         RTE_BUILD_BUG_ON(NB_MBUF % (CHAIN_LEN / 2) != 0);
842         for (i = 0; i < NB_MBUF * 2; i++) {
843                 m = rte_pktmbuf_alloc((i & 4) ? pool2 : pool);
844                 if (m == NULL) {
845                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
846                         goto err;
847                 }
848                 if ((i % CHAIN_LEN) == 0)
849                         mbufs[i / CHAIN_LEN] = m;
850                 else
851                         rte_pktmbuf_chain(mbufs[i / CHAIN_LEN], m);
852         }
853         /* Test that both pools have been emptied. */
854         if (!(rte_mempool_empty(pool) && rte_mempool_empty(pool2))) {
855                 printf("mempools not empty\n");
856                 goto err;
857         }
858         /* Free one mbuf chain. */
859         rte_pktmbuf_free_bulk(mbufs, 1);
860         /* Test that the segments have been returned to the pools. */
861         if (!(rte_mempool_avail_count(pool) == CHAIN_LEN / 2 &&
862                         rte_mempool_avail_count(pool2) == CHAIN_LEN / 2)) {
863                 printf("all segments of first mbuf have not been returned\n");
864                 goto err;
865         }
866         /* Free the remaining mbuf chains. */
867         rte_pktmbuf_free_bulk(&mbufs[1], NB_MBUF * 2 / CHAIN_LEN - 1);
868         /* Test that they have been returned to the pools. */
869         if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
870                 printf("mempools not full\n");
871                 goto err;
872         }
873
874         ret = 0;
875         goto done;
876
877 err:
878         ret = -1;
879
880 done:
881         printf("Free mbuf pools for bulk allocation.\n");
882         rte_mempool_free(pool);
883         rte_mempool_free(pool2);
884         return ret;
885 }
886
887 /*
888  * test that the pointer to the data on a packet mbuf is set properly
889  */
890 static int
891 test_pktmbuf_pool_ptr(struct rte_mempool *pktmbuf_pool)
892 {
893         unsigned i;
894         struct rte_mbuf *m[NB_MBUF];
895         int ret = 0;
896
897         for (i=0; i<NB_MBUF; i++)
898                 m[i] = NULL;
899
900         /* alloc NB_MBUF mbufs */
901         for (i=0; i<NB_MBUF; i++) {
902                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
903                 if (m[i] == NULL) {
904                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
905                         ret = -1;
906                         break;
907                 }
908                 m[i]->data_off += 64;
909         }
910
911         /* free them */
912         for (i=0; i<NB_MBUF; i++) {
913                 if (m[i] != NULL)
914                         rte_pktmbuf_free(m[i]);
915         }
916
917         for (i=0; i<NB_MBUF; i++)
918                 m[i] = NULL;
919
920         /* alloc NB_MBUF mbufs */
921         for (i=0; i<NB_MBUF; i++) {
922                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
923                 if (m[i] == NULL) {
924                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
925                         ret = -1;
926                         break;
927                 }
928                 if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
929                         printf("invalid data_off\n");
930                         ret = -1;
931                 }
932         }
933
934         /* free them */
935         for (i=0; i<NB_MBUF; i++) {
936                 if (m[i] != NULL)
937                         rte_pktmbuf_free(m[i]);
938         }
939
940         return ret;
941 }
942
943 static int
944 test_pktmbuf_free_segment(struct rte_mempool *pktmbuf_pool)
945 {
946         unsigned i;
947         struct rte_mbuf *m[NB_MBUF];
948         int ret = 0;
949
950         for (i=0; i<NB_MBUF; i++)
951                 m[i] = NULL;
952
953         /* alloc NB_MBUF mbufs */
954         for (i=0; i<NB_MBUF; i++) {
955                 m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
956                 if (m[i] == NULL) {
957                         printf("rte_pktmbuf_alloc() failed (%u)\n", i);
958                         ret = -1;
959                 }
960         }
961
962         /* free them */
963         for (i=0; i<NB_MBUF; i++) {
964                 if (m[i] != NULL) {
965                         struct rte_mbuf *mb, *mt;
966
967                         mb = m[i];
968                         while(mb != NULL) {
969                                 mt = mb;
970                                 mb = mb->next;
971                                 rte_pktmbuf_free_seg(mt);
972                         }
973                 }
974         }
975
976         return ret;
977 }
978
979 /*
980  * Stress test for rte_mbuf atomic refcnt.
981  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
982  * For more efficiency, recommended to run with RTE_LIBRTE_MBUF_DEBUG defined.
983  */
984
985 #ifdef RTE_MBUF_REFCNT_ATOMIC
986
987 static int
988 test_refcnt_slave(void *arg)
989 {
990         unsigned lcore, free;
991         void *mp = 0;
992         struct rte_ring *refcnt_mbuf_ring = arg;
993
994         lcore = rte_lcore_id();
995         printf("%s started at lcore %u\n", __func__, lcore);
996
997         free = 0;
998         while (refcnt_stop_slaves == 0) {
999                 if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
1000                         free++;
1001                         rte_pktmbuf_free(mp);
1002                 }
1003         }
1004
1005         refcnt_lcore[lcore] += free;
1006         printf("%s finished at lcore %u, "
1007                "number of freed mbufs: %u\n",
1008                __func__, lcore, free);
1009         return 0;
1010 }
1011
1012 static void
1013 test_refcnt_iter(unsigned int lcore, unsigned int iter,
1014                  struct rte_mempool *refcnt_pool,
1015                  struct rte_ring *refcnt_mbuf_ring)
1016 {
1017         uint16_t ref;
1018         unsigned i, n, tref, wn;
1019         struct rte_mbuf *m;
1020
1021         tref = 0;
1022
1023         /* For each mbuf in the pool:
1024          * - allocate mbuf,
1025          * - increment it's reference up to N+1,
1026          * - enqueue it N times into the ring for slave cores to free.
1027          */
1028         for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
1029             i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
1030             i++) {
1031                 ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
1032                 tref += ref;
1033                 if ((ref & 1) != 0) {
1034                         rte_pktmbuf_refcnt_update(m, ref);
1035                         while (ref-- != 0)
1036                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
1037                 } else {
1038                         while (ref-- != 0) {
1039                                 rte_pktmbuf_refcnt_update(m, 1);
1040                                 rte_ring_enqueue(refcnt_mbuf_ring, m);
1041                         }
1042                 }
1043                 rte_pktmbuf_free(m);
1044         }
1045
1046         if (i != n)
1047                 rte_panic("(lcore=%u, iter=%u): was able to allocate only "
1048                           "%u from %u mbufs\n", lcore, iter, i, n);
1049
1050         /* wait till slave lcores  will consume all mbufs */
1051         while (!rte_ring_empty(refcnt_mbuf_ring))
1052                 ;
1053
1054         /* check that all mbufs are back into mempool by now */
1055         for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
1056                 if ((i = rte_mempool_avail_count(refcnt_pool)) == n) {
1057                         refcnt_lcore[lcore] += tref;
1058                         printf("%s(lcore=%u, iter=%u) completed, "
1059                             "%u references processed\n",
1060                             __func__, lcore, iter, tref);
1061                         return;
1062                 }
1063                 rte_delay_ms(100);
1064         }
1065
1066         rte_panic("(lcore=%u, iter=%u): after %us only "
1067                   "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
1068 }
1069
1070 static int
1071 test_refcnt_master(struct rte_mempool *refcnt_pool,
1072                    struct rte_ring *refcnt_mbuf_ring)
1073 {
1074         unsigned i, lcore;
1075
1076         lcore = rte_lcore_id();
1077         printf("%s started at lcore %u\n", __func__, lcore);
1078
1079         for (i = 0; i != REFCNT_MAX_ITER; i++)
1080                 test_refcnt_iter(lcore, i, refcnt_pool, refcnt_mbuf_ring);
1081
1082         refcnt_stop_slaves = 1;
1083         rte_wmb();
1084
1085         printf("%s finished at lcore %u\n", __func__, lcore);
1086         return 0;
1087 }
1088
1089 #endif
1090
1091 static int
1092 test_refcnt_mbuf(void)
1093 {
1094 #ifdef RTE_MBUF_REFCNT_ATOMIC
1095         unsigned int master, slave, tref;
1096         int ret = -1;
1097         struct rte_mempool *refcnt_pool = NULL;
1098         struct rte_ring *refcnt_mbuf_ring = NULL;
1099
1100         if (rte_lcore_count() < 2) {
1101                 printf("Not enough cores for test_refcnt_mbuf, expecting at least 2\n");
1102                 return TEST_SKIPPED;
1103         }
1104
1105         printf("starting %s, at %u lcores\n", __func__, rte_lcore_count());
1106
1107         /* create refcnt pool & ring if they don't exist */
1108
1109         refcnt_pool = rte_pktmbuf_pool_create(MAKE_STRING(refcnt_pool),
1110                                               REFCNT_MBUF_NUM, 0, 0, 0,
1111                                               SOCKET_ID_ANY);
1112         if (refcnt_pool == NULL) {
1113                 printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
1114                     __func__);
1115                 return -1;
1116         }
1117
1118         refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
1119                         rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
1120                                         RING_F_SP_ENQ);
1121         if (refcnt_mbuf_ring == NULL) {
1122                 printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
1123                     "\n", __func__);
1124                 goto err;
1125         }
1126
1127         refcnt_stop_slaves = 0;
1128         memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
1129
1130         rte_eal_mp_remote_launch(test_refcnt_slave, refcnt_mbuf_ring,
1131                                  SKIP_MASTER);
1132
1133         test_refcnt_master(refcnt_pool, refcnt_mbuf_ring);
1134
1135         rte_eal_mp_wait_lcore();
1136
1137         /* check that we porcessed all references */
1138         tref = 0;
1139         master = rte_get_master_lcore();
1140
1141         RTE_LCORE_FOREACH_SLAVE(slave)
1142                 tref += refcnt_lcore[slave];
1143
1144         if (tref != refcnt_lcore[master])
1145                 rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
1146                           tref, refcnt_lcore[master]);
1147
1148         rte_mempool_dump(stdout, refcnt_pool);
1149         rte_ring_dump(stdout, refcnt_mbuf_ring);
1150
1151         ret = 0;
1152
1153 err:
1154         rte_mempool_free(refcnt_pool);
1155         rte_ring_free(refcnt_mbuf_ring);
1156         return ret;
1157 #else
1158         return 0;
1159 #endif
1160 }
1161
1162 #include <unistd.h>
1163 #include <sys/wait.h>
1164
1165 /* use fork() to test mbuf errors panic */
1166 static int
1167 verify_mbuf_check_panics(struct rte_mbuf *buf)
1168 {
1169         int pid;
1170         int status;
1171
1172         pid = fork();
1173
1174         if (pid == 0) {
1175                 rte_mbuf_sanity_check(buf, 1); /* should panic */
1176                 exit(0);  /* return normally if it doesn't panic */
1177         } else if (pid < 0){
1178                 printf("Fork Failed\n");
1179                 return -1;
1180         }
1181         wait(&status);
1182         if(status == 0)
1183                 return -1;
1184
1185         return 0;
1186 }
1187
1188 static int
1189 test_failing_mbuf_sanity_check(struct rte_mempool *pktmbuf_pool)
1190 {
1191         struct rte_mbuf *buf;
1192         struct rte_mbuf badbuf;
1193
1194         printf("Checking rte_mbuf_sanity_check for failure conditions\n");
1195
1196         /* get a good mbuf to use to make copies */
1197         buf = rte_pktmbuf_alloc(pktmbuf_pool);
1198         if (buf == NULL)
1199                 return -1;
1200         printf("Checking good mbuf initially\n");
1201         if (verify_mbuf_check_panics(buf) != -1)
1202                 return -1;
1203
1204         printf("Now checking for error conditions\n");
1205
1206         if (verify_mbuf_check_panics(NULL)) {
1207                 printf("Error with NULL mbuf test\n");
1208                 return -1;
1209         }
1210
1211         badbuf = *buf;
1212         badbuf.pool = NULL;
1213         if (verify_mbuf_check_panics(&badbuf)) {
1214                 printf("Error with bad-pool mbuf test\n");
1215                 return -1;
1216         }
1217
1218         badbuf = *buf;
1219         badbuf.buf_iova = 0;
1220         if (verify_mbuf_check_panics(&badbuf)) {
1221                 printf("Error with bad-physaddr mbuf test\n");
1222                 return -1;
1223         }
1224
1225         badbuf = *buf;
1226         badbuf.buf_addr = NULL;
1227         if (verify_mbuf_check_panics(&badbuf)) {
1228                 printf("Error with bad-addr mbuf test\n");
1229                 return -1;
1230         }
1231
1232         badbuf = *buf;
1233         badbuf.refcnt = 0;
1234         if (verify_mbuf_check_panics(&badbuf)) {
1235                 printf("Error with bad-refcnt(0) mbuf test\n");
1236                 return -1;
1237         }
1238
1239         badbuf = *buf;
1240         badbuf.refcnt = UINT16_MAX;
1241         if (verify_mbuf_check_panics(&badbuf)) {
1242                 printf("Error with bad-refcnt(MAX) mbuf test\n");
1243                 return -1;
1244         }
1245
1246         return 0;
1247 }
1248
1249 static int
1250 test_mbuf_linearize(struct rte_mempool *pktmbuf_pool, int pkt_len,
1251                     int nb_segs)
1252 {
1253
1254         struct rte_mbuf *m = NULL, *mbuf = NULL;
1255         uint8_t *data;
1256         int data_len = 0;
1257         int remain;
1258         int seg, seg_len;
1259         int i;
1260
1261         if (pkt_len < 1) {
1262                 printf("Packet size must be 1 or more (is %d)\n", pkt_len);
1263                 return -1;
1264         }
1265
1266         if (nb_segs < 1) {
1267                 printf("Number of segments must be 1 or more (is %d)\n",
1268                                 nb_segs);
1269                 return -1;
1270         }
1271
1272         seg_len = pkt_len / nb_segs;
1273         if (seg_len == 0)
1274                 seg_len = 1;
1275
1276         remain = pkt_len;
1277
1278         /* Create chained mbuf_src and fill it generated data */
1279         for (seg = 0; remain > 0; seg++) {
1280
1281                 m = rte_pktmbuf_alloc(pktmbuf_pool);
1282                 if (m == NULL) {
1283                         printf("Cannot create segment for source mbuf");
1284                         goto fail;
1285                 }
1286
1287                 /* Make sure if tailroom is zeroed */
1288                 memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
1289                                 rte_pktmbuf_tailroom(m));
1290
1291                 data_len = remain;
1292                 if (data_len > seg_len)
1293                         data_len = seg_len;
1294
1295                 data = (uint8_t *)rte_pktmbuf_append(m, data_len);
1296                 if (data == NULL) {
1297                         printf("Cannot append %d bytes to the mbuf\n",
1298                                         data_len);
1299                         goto fail;
1300                 }
1301
1302                 for (i = 0; i < data_len; i++)
1303                         data[i] = (seg * seg_len + i) % 0x0ff;
1304
1305                 if (seg == 0)
1306                         mbuf = m;
1307                 else
1308                         rte_pktmbuf_chain(mbuf, m);
1309
1310                 remain -= data_len;
1311         }
1312
1313         /* Create destination buffer to store coalesced data */
1314         if (rte_pktmbuf_linearize(mbuf)) {
1315                 printf("Mbuf linearization failed\n");
1316                 goto fail;
1317         }
1318
1319         if (!rte_pktmbuf_is_contiguous(mbuf)) {
1320                 printf("Source buffer should be contiguous after "
1321                                 "linearization\n");
1322                 goto fail;
1323         }
1324
1325         data = rte_pktmbuf_mtod(mbuf, uint8_t *);
1326
1327         for (i = 0; i < pkt_len; i++)
1328                 if (data[i] != (i % 0x0ff)) {
1329                         printf("Incorrect data in linearized mbuf\n");
1330                         goto fail;
1331                 }
1332
1333         rte_pktmbuf_free(mbuf);
1334         return 0;
1335
1336 fail:
1337         if (mbuf)
1338                 rte_pktmbuf_free(mbuf);
1339         return -1;
1340 }
1341
1342 static int
1343 test_mbuf_linearize_check(struct rte_mempool *pktmbuf_pool)
1344 {
1345         struct test_mbuf_array {
1346                 int size;
1347                 int nb_segs;
1348         } mbuf_array[] = {
1349                         { 128, 1 },
1350                         { 64, 64 },
1351                         { 512, 10 },
1352                         { 250, 11 },
1353                         { 123, 8 },
1354         };
1355         unsigned int i;
1356
1357         printf("Test mbuf linearize API\n");
1358
1359         for (i = 0; i < RTE_DIM(mbuf_array); i++)
1360                 if (test_mbuf_linearize(pktmbuf_pool, mbuf_array[i].size,
1361                                 mbuf_array[i].nb_segs)) {
1362                         printf("Test failed for %d, %d\n", mbuf_array[i].size,
1363                                         mbuf_array[i].nb_segs);
1364                         return -1;
1365                 }
1366
1367         return 0;
1368 }
1369
1370 /*
1371  * Helper function for test_tx_ofload
1372  */
1373 static inline void
1374 set_tx_offload(struct rte_mbuf *mb, uint64_t il2, uint64_t il3, uint64_t il4,
1375         uint64_t tso, uint64_t ol3, uint64_t ol2)
1376 {
1377         mb->l2_len = il2;
1378         mb->l3_len = il3;
1379         mb->l4_len = il4;
1380         mb->tso_segsz = tso;
1381         mb->outer_l3_len = ol3;
1382         mb->outer_l2_len = ol2;
1383 }
1384
1385 static int
1386 test_tx_offload(void)
1387 {
1388         struct rte_mbuf *mb;
1389         uint64_t tm, v1, v2;
1390         size_t sz;
1391         uint32_t i;
1392
1393         static volatile struct {
1394                 uint16_t l2;
1395                 uint16_t l3;
1396                 uint16_t l4;
1397                 uint16_t tso;
1398         } txof;
1399
1400         const uint32_t num = 0x10000;
1401
1402         txof.l2 = rte_rand() % (1 <<  RTE_MBUF_L2_LEN_BITS);
1403         txof.l3 = rte_rand() % (1 <<  RTE_MBUF_L3_LEN_BITS);
1404         txof.l4 = rte_rand() % (1 <<  RTE_MBUF_L4_LEN_BITS);
1405         txof.tso = rte_rand() % (1 <<   RTE_MBUF_TSO_SEGSZ_BITS);
1406
1407         printf("%s started, tx_offload = {\n"
1408                 "\tl2_len=%#hx,\n"
1409                 "\tl3_len=%#hx,\n"
1410                 "\tl4_len=%#hx,\n"
1411                 "\ttso_segsz=%#hx,\n"
1412                 "\touter_l3_len=%#x,\n"
1413                 "\touter_l2_len=%#x,\n"
1414                 "};\n",
1415                 __func__,
1416                 txof.l2, txof.l3, txof.l4, txof.tso, txof.l3, txof.l2);
1417
1418         sz = sizeof(*mb) * num;
1419         mb = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
1420         if (mb == NULL) {
1421                 printf("%s failed, out of memory\n", __func__);
1422                 return -ENOMEM;
1423         }
1424
1425         memset(mb, 0, sz);
1426         tm = rte_rdtsc_precise();
1427
1428         for (i = 0; i != num; i++)
1429                 set_tx_offload(mb + i, txof.l2, txof.l3, txof.l4,
1430                         txof.tso, txof.l3, txof.l2);
1431
1432         tm = rte_rdtsc_precise() - tm;
1433         printf("%s set tx_offload by bit-fields: %u iterations, %"
1434                 PRIu64 " cycles, %#Lf cycles/iter\n",
1435                 __func__, num, tm, (long double)tm / num);
1436
1437         v1 = mb[rte_rand() % num].tx_offload;
1438
1439         memset(mb, 0, sz);
1440         tm = rte_rdtsc_precise();
1441
1442         for (i = 0; i != num; i++)
1443                 mb[i].tx_offload = rte_mbuf_tx_offload(txof.l2, txof.l3,
1444                         txof.l4, txof.tso, txof.l3, txof.l2, 0);
1445
1446         tm = rte_rdtsc_precise() - tm;
1447         printf("%s set raw tx_offload: %u iterations, %"
1448                 PRIu64 " cycles, %#Lf cycles/iter\n",
1449                 __func__, num, tm, (long double)tm / num);
1450
1451         v2 = mb[rte_rand() % num].tx_offload;
1452
1453         rte_free(mb);
1454
1455         printf("%s finished\n"
1456                 "expected tx_offload value: 0x%" PRIx64 ";\n"
1457                 "rte_mbuf_tx_offload value: 0x%" PRIx64 ";\n",
1458                 __func__, v1, v2);
1459
1460         return (v1 == v2) ? 0 : -EINVAL;
1461 }
1462
1463 static int
1464 test_mbuf_validate_tx_offload(const char *test_name,
1465                 struct rte_mempool *pktmbuf_pool,
1466                 uint64_t ol_flags,
1467                 uint16_t segsize,
1468                 int expected_retval)
1469 {
1470         struct rte_mbuf *m = NULL;
1471         int ret = 0;
1472
1473         /* alloc a mbuf and do sanity check */
1474         m = rte_pktmbuf_alloc(pktmbuf_pool);
1475         if (m == NULL)
1476                 GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1477         if (rte_pktmbuf_pkt_len(m) != 0)
1478                 GOTO_FAIL("%s: Bad packet length\n", __func__);
1479         rte_mbuf_sanity_check(m, 0);
1480         m->ol_flags = ol_flags;
1481         m->tso_segsz = segsize;
1482         ret = rte_validate_tx_offload(m);
1483         if (ret != expected_retval)
1484                 GOTO_FAIL("%s(%s): expected ret val: %d; received: %d\n",
1485                                 __func__, test_name, expected_retval, ret);
1486         rte_pktmbuf_free(m);
1487         m = NULL;
1488         return 0;
1489 fail:
1490         if (m) {
1491                 rte_pktmbuf_free(m);
1492                 m = NULL;
1493         }
1494         return -1;
1495 }
1496
1497 static int
1498 test_mbuf_validate_tx_offload_one(struct rte_mempool *pktmbuf_pool)
1499 {
1500         /* test to validate tx offload flags */
1501         uint64_t ol_flags = 0;
1502
1503         /* test to validate if IP checksum is counted only for IPV4 packet */
1504         /* set both IP checksum and IPV6 flags */
1505         ol_flags |= PKT_TX_IP_CKSUM;
1506         ol_flags |= PKT_TX_IPV6;
1507         if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_CKSUM_IPV6_SET",
1508                                 pktmbuf_pool,
1509                                 ol_flags, 0, -EINVAL) < 0)
1510                 GOTO_FAIL("%s failed: IP cksum is set incorrect.\n", __func__);
1511         /* resetting ol_flags for next testcase */
1512         ol_flags = 0;
1513
1514         /* test to validate if IP type is set when required */
1515         ol_flags |= PKT_TX_L4_MASK;
1516         if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
1517                                 pktmbuf_pool,
1518                                 ol_flags, 0, -EINVAL) < 0)
1519                 GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
1520
1521         /* test if IP type is set when TCP SEG is on */
1522         ol_flags |= PKT_TX_TCP_SEG;
1523         if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
1524                                 pktmbuf_pool,
1525                                 ol_flags, 0, -EINVAL) < 0)
1526                 GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
1527
1528         ol_flags = 0;
1529         /* test to confirm IP type (IPV4/IPV6) is set */
1530         ol_flags = PKT_TX_L4_MASK;
1531         ol_flags |= PKT_TX_IPV6;
1532         if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_SET",
1533                                 pktmbuf_pool,
1534                                 ol_flags, 0, 0) < 0)
1535                 GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1536
1537         ol_flags = 0;
1538         /* test to check TSO segment size is non-zero */
1539         ol_flags |= PKT_TX_IPV4;
1540         ol_flags |= PKT_TX_TCP_SEG;
1541         /* set 0 tso segment size */
1542         if (test_mbuf_validate_tx_offload("MBUF_TEST_NULL_TSO_SEGSZ",
1543                                 pktmbuf_pool,
1544                                 ol_flags, 0, -EINVAL) < 0)
1545                 GOTO_FAIL("%s failed: tso segment size is null.\n", __func__);
1546
1547         /* retain IPV4 and PKT_TX_TCP_SEG mask */
1548         /* set valid tso segment size but IP CKSUM not set */
1549         if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_NOT_SET",
1550                                 pktmbuf_pool,
1551                                 ol_flags, 512, -EINVAL) < 0)
1552                 GOTO_FAIL("%s failed: IP CKSUM is not set.\n", __func__);
1553
1554         /* test to validate if IP checksum is set for TSO capability */
1555         /* retain IPV4, TCP_SEG, tso_seg size */
1556         ol_flags |= PKT_TX_IP_CKSUM;
1557         if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_SET",
1558                                 pktmbuf_pool,
1559                                 ol_flags, 512, 0) < 0)
1560                 GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1561
1562         /* test to confirm TSO for IPV6 type */
1563         ol_flags = 0;
1564         ol_flags |= PKT_TX_IPV6;
1565         ol_flags |= PKT_TX_TCP_SEG;
1566         if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IPV6_SET",
1567                                 pktmbuf_pool,
1568                                 ol_flags, 512, 0) < 0)
1569                 GOTO_FAIL("%s failed: TSO req not met.\n", __func__);
1570
1571         ol_flags = 0;
1572         /* test if outer IP checksum set for non outer IPv4 packet */
1573         ol_flags |= PKT_TX_IPV6;
1574         ol_flags |= PKT_TX_OUTER_IP_CKSUM;
1575         if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_NOT_SET",
1576                                 pktmbuf_pool,
1577                                 ol_flags, 512, -EINVAL) < 0)
1578                 GOTO_FAIL("%s failed: Outer IP cksum set.\n", __func__);
1579
1580         ol_flags = 0;
1581         /* test to confirm outer IP checksum is set for outer IPV4 packet */
1582         ol_flags |= PKT_TX_OUTER_IP_CKSUM;
1583         ol_flags |= PKT_TX_OUTER_IPV4;
1584         if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_SET",
1585                                 pktmbuf_pool,
1586                                 ol_flags, 512, 0) < 0)
1587                 GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1588
1589         ol_flags = 0;
1590         /* test to confirm if packets with no TX_OFFLOAD_MASK are skipped */
1591         if (test_mbuf_validate_tx_offload("MBUF_TEST_OL_MASK_NOT_SET",
1592                                 pktmbuf_pool,
1593                                 ol_flags, 512, 0) < 0)
1594                 GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1595         return 0;
1596 fail:
1597         return -1;
1598 }
1599
1600 /*
1601  * Test for allocating a bulk of mbufs
1602  * define an array with positive sizes for mbufs allocations.
1603  */
1604 static int
1605 test_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
1606 {
1607         int ret = 0;
1608         unsigned int idx, loop;
1609         unsigned int alloc_counts[] = {
1610                 0,
1611                 MEMPOOL_CACHE_SIZE - 1,
1612                 MEMPOOL_CACHE_SIZE + 1,
1613                 MEMPOOL_CACHE_SIZE * 1.5,
1614                 MEMPOOL_CACHE_SIZE * 2,
1615                 MEMPOOL_CACHE_SIZE * 2 - 1,
1616                 MEMPOOL_CACHE_SIZE * 2 + 1,
1617                 MEMPOOL_CACHE_SIZE,
1618         };
1619
1620         /* allocate a large array of mbuf pointers */
1621         struct rte_mbuf *mbufs[NB_MBUF] = { 0 };
1622         for (idx = 0; idx < RTE_DIM(alloc_counts); idx++) {
1623                 ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
1624                                 alloc_counts[idx]);
1625                 if (ret == 0) {
1626                         for (loop = 0; loop < alloc_counts[idx] &&
1627                                         mbufs[loop] != NULL; loop++)
1628                                 rte_pktmbuf_free(mbufs[loop]);
1629                 } else if (ret != 0) {
1630                         printf("%s: Bulk alloc failed count(%u); ret val(%d)\n",
1631                                         __func__, alloc_counts[idx], ret);
1632                         return -1;
1633                 }
1634         }
1635         return 0;
1636 }
1637
1638 /*
1639  * Negative testing for allocating a bulk of mbufs
1640  */
1641 static int
1642 test_neg_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
1643 {
1644         int ret = 0;
1645         unsigned int idx, loop;
1646         unsigned int neg_alloc_counts[] = {
1647                 MEMPOOL_CACHE_SIZE - NB_MBUF,
1648                 NB_MBUF + 1,
1649                 NB_MBUF * 8,
1650                 UINT_MAX
1651         };
1652         struct rte_mbuf *mbufs[NB_MBUF * 8] = { 0 };
1653
1654         for (idx = 0; idx < RTE_DIM(neg_alloc_counts); idx++) {
1655                 ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
1656                                 neg_alloc_counts[idx]);
1657                 if (ret == 0) {
1658                         printf("%s: Bulk alloc must fail! count(%u); ret(%d)\n",
1659                                         __func__, neg_alloc_counts[idx], ret);
1660                         for (loop = 0; loop < neg_alloc_counts[idx] &&
1661                                         mbufs[loop] != NULL; loop++)
1662                                 rte_pktmbuf_free(mbufs[loop]);
1663                         return -1;
1664                 }
1665         }
1666         return 0;
1667 }
1668
1669 /*
1670  * Test to read mbuf packet using rte_pktmbuf_read
1671  */
1672 static int
1673 test_pktmbuf_read(struct rte_mempool *pktmbuf_pool)
1674 {
1675         struct rte_mbuf *m = NULL;
1676         char *data = NULL;
1677         const char *data_copy = NULL;
1678         int off;
1679
1680         /* alloc a mbuf */
1681         m = rte_pktmbuf_alloc(pktmbuf_pool);
1682         if (m == NULL)
1683                 GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1684         if (rte_pktmbuf_pkt_len(m) != 0)
1685                 GOTO_FAIL("%s: Bad packet length\n", __func__);
1686         rte_mbuf_sanity_check(m, 0);
1687
1688         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
1689         if (data == NULL)
1690                 GOTO_FAIL("%s: Cannot append data\n", __func__);
1691         if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN2)
1692                 GOTO_FAIL("%s: Bad packet length\n", __func__);
1693         memset(data, 0xfe, MBUF_TEST_DATA_LEN2);
1694
1695         /* read the data from mbuf */
1696         data_copy = rte_pktmbuf_read(m, 0, MBUF_TEST_DATA_LEN2, NULL);
1697         if (data_copy == NULL)
1698                 GOTO_FAIL("%s: Error in reading data!\n", __func__);
1699         for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
1700                 if (data_copy[off] != (char)0xfe)
1701                         GOTO_FAIL("Data corrupted at offset %u", off);
1702         }
1703         rte_pktmbuf_free(m);
1704         m = NULL;
1705
1706         return 0;
1707 fail:
1708         if (m) {
1709                 rte_pktmbuf_free(m);
1710                 m = NULL;
1711         }
1712         return -1;
1713 }
1714
1715 /*
1716  * Test to read mbuf packet data from offset
1717  */
1718 static int
1719 test_pktmbuf_read_from_offset(struct rte_mempool *pktmbuf_pool)
1720 {
1721         struct rte_mbuf *m = NULL;
1722         struct ether_hdr *hdr = NULL;
1723         char *data = NULL;
1724         const char *data_copy = NULL;
1725         unsigned int off;
1726         unsigned int hdr_len = sizeof(struct rte_ether_hdr);
1727
1728         /* alloc a mbuf */
1729         m = rte_pktmbuf_alloc(pktmbuf_pool);
1730         if (m == NULL)
1731                 GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1732
1733         if (rte_pktmbuf_pkt_len(m) != 0)
1734                 GOTO_FAIL("%s: Bad packet length\n", __func__);
1735         rte_mbuf_sanity_check(m, 0);
1736
1737         /* prepend an ethernet header */
1738         hdr = (struct ether_hdr *)rte_pktmbuf_prepend(m, hdr_len);
1739         if (hdr == NULL)
1740                 GOTO_FAIL("%s: Cannot prepend header\n", __func__);
1741         if (rte_pktmbuf_pkt_len(m) != hdr_len)
1742                 GOTO_FAIL("%s: Bad pkt length", __func__);
1743         if (rte_pktmbuf_data_len(m) != hdr_len)
1744                 GOTO_FAIL("%s: Bad data length", __func__);
1745         memset(hdr, 0xde, hdr_len);
1746
1747         /* read mbuf header info from 0 offset */
1748         data_copy = rte_pktmbuf_read(m, 0, hdr_len, NULL);
1749         if (data_copy == NULL)
1750                 GOTO_FAIL("%s: Error in reading header!\n", __func__);
1751         for (off = 0; off < hdr_len; off++) {
1752                 if (data_copy[off] != (char)0xde)
1753                         GOTO_FAIL("Header info corrupted at offset %u", off);
1754         }
1755
1756         /* append sample data after ethernet header */
1757         data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
1758         if (data == NULL)
1759                 GOTO_FAIL("%s: Cannot append data\n", __func__);
1760         if (rte_pktmbuf_pkt_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
1761                 GOTO_FAIL("%s: Bad packet length\n", __func__);
1762         if (rte_pktmbuf_data_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
1763                 GOTO_FAIL("%s: Bad data length\n", __func__);
1764         memset(data, 0xcc, MBUF_TEST_DATA_LEN2);
1765
1766         /* read mbuf data after header info */
1767         data_copy = rte_pktmbuf_read(m, hdr_len, MBUF_TEST_DATA_LEN2, NULL);
1768         if (data_copy == NULL)
1769                 GOTO_FAIL("%s: Error in reading header data!\n", __func__);
1770         for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
1771                 if (data_copy[off] != (char)0xcc)
1772                         GOTO_FAIL("Data corrupted at offset %u", off);
1773         }
1774
1775         /* partial reading of mbuf data */
1776         data_copy = rte_pktmbuf_read(m, hdr_len + 5, MBUF_TEST_DATA_LEN2 - 5,
1777                         NULL);
1778         if (data_copy == NULL)
1779                 GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
1780         if (strlen(data_copy) != MBUF_TEST_DATA_LEN2 - 5)
1781                 GOTO_FAIL("%s: Incorrect data length!\n", __func__);
1782         for (off = 0; off < MBUF_TEST_DATA_LEN2 - 5; off++) {
1783                 if (data_copy[off] != (char)0xcc)
1784                         GOTO_FAIL("Data corrupted at offset %u", off);
1785         }
1786
1787         /* read length greater than mbuf data_len */
1788         if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_data_len(m) + 1,
1789                                 NULL) != NULL)
1790                 GOTO_FAIL("%s: Requested len is larger than mbuf data len!\n",
1791                                 __func__);
1792
1793         /* read length greater than mbuf pkt_len */
1794         if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_pkt_len(m) + 1,
1795                                 NULL) != NULL)
1796                 GOTO_FAIL("%s: Requested len is larger than mbuf pkt len!\n",
1797                                 __func__);
1798
1799         /* read data of zero len from valid offset */
1800         data_copy = rte_pktmbuf_read(m, hdr_len, 0, NULL);
1801         if (data_copy == NULL)
1802                 GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
1803         if (strlen(data_copy) != MBUF_TEST_DATA_LEN2)
1804                 GOTO_FAIL("%s: Corrupted data content!\n", __func__);
1805         for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
1806                 if (data_copy[off] != (char)0xcc)
1807                         GOTO_FAIL("Data corrupted at offset %u", off);
1808         }
1809
1810         /* read data of zero length from zero offset */
1811         data_copy = rte_pktmbuf_read(m, 0, 0, NULL);
1812         if (data_copy == NULL)
1813                 GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
1814         /* check if the received address is the beginning of header info */
1815         if (hdr != (const struct ether_hdr *)data_copy)
1816                 GOTO_FAIL("%s: Corrupted data address!\n", __func__);
1817
1818         /* read data of max length from valid offset */
1819         data_copy = rte_pktmbuf_read(m, hdr_len, UINT_MAX, NULL);
1820         if (data_copy == NULL)
1821                 GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
1822         /* check if the received address is the beginning of data segment */
1823         if (data_copy != data)
1824                 GOTO_FAIL("%s: Corrupted data address!\n", __func__);
1825
1826         /* try to read from mbuf with max size offset */
1827         data_copy = rte_pktmbuf_read(m, UINT_MAX, 0, NULL);
1828         if (data_copy != NULL)
1829                 GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
1830
1831         /* try to read from mbuf with max size offset and len */
1832         data_copy = rte_pktmbuf_read(m, UINT_MAX, UINT_MAX, NULL);
1833         if (data_copy != NULL)
1834                 GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
1835
1836         rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
1837
1838         rte_pktmbuf_free(m);
1839         m = NULL;
1840
1841         return 0;
1842 fail:
1843         if (m) {
1844                 rte_pktmbuf_free(m);
1845                 m = NULL;
1846         }
1847         return -1;
1848 }
1849
1850 struct test_case {
1851         unsigned int seg_count;
1852         unsigned int flags;
1853         uint32_t read_off;
1854         uint32_t read_len;
1855         unsigned int seg_lengths[MBUF_MAX_SEG];
1856 };
1857
1858 /* create a mbuf with different sized segments
1859  *  and fill with data [0x00 0x01 0x02 ...]
1860  */
1861 static struct rte_mbuf *
1862 create_packet(struct rte_mempool *pktmbuf_pool,
1863                 struct test_case *test_data)
1864 {
1865         uint16_t i, ret, seg, seg_len = 0;
1866         uint32_t last_index = 0;
1867         unsigned int seg_lengths[MBUF_MAX_SEG];
1868         unsigned int hdr_len;
1869         struct rte_mbuf *pkt = NULL;
1870         struct rte_mbuf *pkt_seg = NULL;
1871         char *hdr = NULL;
1872         char *data = NULL;
1873
1874         memcpy(seg_lengths, test_data->seg_lengths,
1875                         sizeof(unsigned int)*test_data->seg_count);
1876         for (seg = 0; seg < test_data->seg_count; seg++) {
1877                 hdr_len = 0;
1878                 seg_len =  seg_lengths[seg];
1879                 pkt_seg = rte_pktmbuf_alloc(pktmbuf_pool);
1880                 if (pkt_seg == NULL)
1881                         GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1882                 if (rte_pktmbuf_pkt_len(pkt_seg) != 0)
1883                         GOTO_FAIL("%s: Bad packet length\n", __func__);
1884                 rte_mbuf_sanity_check(pkt_seg, 0);
1885                 /* Add header only for the first segment */
1886                 if (test_data->flags == MBUF_HEADER && seg == 0) {
1887                         hdr_len = sizeof(struct rte_ether_hdr);
1888                         /* prepend a header and fill with dummy data */
1889                         hdr = (char *)rte_pktmbuf_prepend(pkt_seg, hdr_len);
1890                         if (hdr == NULL)
1891                                 GOTO_FAIL("%s: Cannot prepend header\n",
1892                                                 __func__);
1893                         if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len)
1894                                 GOTO_FAIL("%s: Bad pkt length", __func__);
1895                         if (rte_pktmbuf_data_len(pkt_seg) != hdr_len)
1896                                 GOTO_FAIL("%s: Bad data length", __func__);
1897                         for (i = 0; i < hdr_len; i++)
1898                                 hdr[i] = (last_index + i) % 0xffff;
1899                         last_index += hdr_len;
1900                 }
1901                 /* skip appending segment with 0 length */
1902                 if (seg_len == 0)
1903                         continue;
1904                 data = rte_pktmbuf_append(pkt_seg, seg_len);
1905                 if (data == NULL)
1906                         GOTO_FAIL("%s: Cannot append data segment\n", __func__);
1907                 if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len + seg_len)
1908                         GOTO_FAIL("%s: Bad packet segment length: %d\n",
1909                                         __func__, rte_pktmbuf_pkt_len(pkt_seg));
1910                 if (rte_pktmbuf_data_len(pkt_seg) != hdr_len + seg_len)
1911                         GOTO_FAIL("%s: Bad data length\n", __func__);
1912                 for (i = 0; i < seg_len; i++)
1913                         data[i] = (last_index + i) % 0xffff;
1914                 /* to fill continuous data from one seg to another */
1915                 last_index += i;
1916                 /* create chained mbufs */
1917                 if (seg == 0)
1918                         pkt = pkt_seg;
1919                 else {
1920                         ret = rte_pktmbuf_chain(pkt, pkt_seg);
1921                         if (ret != 0)
1922                                 GOTO_FAIL("%s:FAIL: Chained mbuf creation %d\n",
1923                                                 __func__, ret);
1924                 }
1925
1926                 pkt_seg = pkt_seg->next;
1927         }
1928         return pkt;
1929 fail:
1930         if (pkt != NULL) {
1931                 rte_pktmbuf_free(pkt);
1932                 pkt = NULL;
1933         }
1934         if (pkt_seg != NULL) {
1935                 rte_pktmbuf_free(pkt_seg);
1936                 pkt_seg = NULL;
1937         }
1938         return NULL;
1939 }
1940
1941 static int
1942 test_pktmbuf_read_from_chain(struct rte_mempool *pktmbuf_pool)
1943 {
1944         struct rte_mbuf *m;
1945         struct test_case test_cases[] = {
1946                 {
1947                         .seg_lengths = { 100, 100, 100 },
1948                         .seg_count = 3,
1949                         .flags = MBUF_NO_HEADER,
1950                         .read_off = 0,
1951                         .read_len = 300
1952                 },
1953                 {
1954                         .seg_lengths = { 100, 125, 150 },
1955                         .seg_count = 3,
1956                         .flags = MBUF_NO_HEADER,
1957                         .read_off = 99,
1958                         .read_len = 201
1959                 },
1960                 {
1961                         .seg_lengths = { 100, 100 },
1962                         .seg_count = 2,
1963                         .flags = MBUF_NO_HEADER,
1964                         .read_off = 0,
1965                         .read_len = 100
1966                 },
1967                 {
1968                         .seg_lengths = { 100, 200 },
1969                         .seg_count = 2,
1970                         .flags = MBUF_HEADER,
1971                         .read_off = sizeof(struct rte_ether_hdr),
1972                         .read_len = 150
1973                 },
1974                 {
1975                         .seg_lengths = { 1000, 100 },
1976                         .seg_count = 2,
1977                         .flags = MBUF_NO_HEADER,
1978                         .read_off = 0,
1979                         .read_len = 1000
1980                 },
1981                 {
1982                         .seg_lengths = { 1024, 0, 100 },
1983                         .seg_count = 3,
1984                         .flags = MBUF_NO_HEADER,
1985                         .read_off = 100,
1986                         .read_len = 1001
1987                 },
1988                 {
1989                         .seg_lengths = { 1000, 1, 1000 },
1990                         .seg_count = 3,
1991                         .flags = MBUF_NO_HEADER,
1992                         .read_off = 1000,
1993                         .read_len = 2
1994                 },
1995                 {
1996                         .seg_lengths = { MBUF_TEST_DATA_LEN,
1997                                         MBUF_TEST_DATA_LEN2,
1998                                         MBUF_TEST_DATA_LEN3, 800, 10 },
1999                         .seg_count = 5,
2000                         .flags = MBUF_NEG_TEST_READ,
2001                         .read_off = 1000,
2002                         .read_len = MBUF_DATA_SIZE
2003                 },
2004         };
2005
2006         uint32_t i, pos;
2007         const char *data_copy = NULL;
2008         char data_buf[MBUF_DATA_SIZE];
2009
2010         memset(data_buf, 0, MBUF_DATA_SIZE);
2011
2012         for (i = 0; i < RTE_DIM(test_cases); i++) {
2013                 m = create_packet(pktmbuf_pool, &test_cases[i]);
2014                 if (m == NULL)
2015                         GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
2016
2017                 data_copy = rte_pktmbuf_read(m, test_cases[i].read_off,
2018                                 test_cases[i].read_len, data_buf);
2019                 if (test_cases[i].flags == MBUF_NEG_TEST_READ) {
2020                         if (data_copy != NULL)
2021                                 GOTO_FAIL("%s: mbuf data read should fail!\n",
2022                                                 __func__);
2023                         else {
2024                                 rte_pktmbuf_free(m);
2025                                 m = NULL;
2026                                 continue;
2027                         }
2028                 }
2029                 if (data_copy == NULL)
2030                         GOTO_FAIL("%s: Error in reading packet data!\n",
2031                                         __func__);
2032                 for (pos = 0; pos < test_cases[i].read_len; pos++) {
2033                         if (data_copy[pos] !=
2034                                         (char)((test_cases[i].read_off + pos)
2035                                                 % 0xffff))
2036                                 GOTO_FAIL("Data corrupted at offset %u is %2X",
2037                                                 pos, data_copy[pos]);
2038                 }
2039                 rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
2040                 rte_pktmbuf_free(m);
2041                 m = NULL;
2042         }
2043         return 0;
2044
2045 fail:
2046         if (m != NULL) {
2047                 rte_pktmbuf_free(m);
2048                 m = NULL;
2049         }
2050         return -1;
2051 }
2052
2053 /* Define a free call back function to be used for external buffer */
2054 static void
2055 ext_buf_free_callback_fn(void *addr __rte_unused, void *opaque)
2056 {
2057         void *ext_buf_addr = opaque;
2058
2059         if (ext_buf_addr == NULL) {
2060                 printf("External buffer address is invalid\n");
2061                 return;
2062         }
2063         rte_free(ext_buf_addr);
2064         ext_buf_addr = NULL;
2065         printf("External buffer freed via callback\n");
2066 }
2067
2068 /*
2069  * Test to initialize shared data in external buffer before attaching to mbuf
2070  *  - Allocate mbuf with no data.
2071  *  - Allocate external buffer with size should be large enough to accommodate
2072  *     rte_mbuf_ext_shared_info.
2073  *  - Invoke pktmbuf_ext_shinfo_init_helper to initialize shared data.
2074  *  - Invoke rte_pktmbuf_attach_extbuf to attach external buffer to the mbuf.
2075  *  - Clone another mbuf and attach the same external buffer to it.
2076  *  - Invoke rte_pktmbuf_detach_extbuf to detach the external buffer from mbuf.
2077  */
2078 static int
2079 test_pktmbuf_ext_shinfo_init_helper(struct rte_mempool *pktmbuf_pool)
2080 {
2081         struct rte_mbuf *m = NULL;
2082         struct rte_mbuf *clone = NULL;
2083         struct rte_mbuf_ext_shared_info *ret_shinfo = NULL;
2084         rte_iova_t buf_iova;
2085         void *ext_buf_addr = NULL;
2086         uint16_t buf_len = EXT_BUF_TEST_DATA_LEN +
2087                                 sizeof(struct rte_mbuf_ext_shared_info);
2088
2089         /* alloc a mbuf */
2090         m = rte_pktmbuf_alloc(pktmbuf_pool);
2091         if (m == NULL)
2092                 GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
2093         if (rte_pktmbuf_pkt_len(m) != 0)
2094                 GOTO_FAIL("%s: Bad packet length\n", __func__);
2095         rte_mbuf_sanity_check(m, 0);
2096
2097         ext_buf_addr = rte_malloc("External buffer", buf_len,
2098                         RTE_CACHE_LINE_SIZE);
2099         if (ext_buf_addr == NULL)
2100                 GOTO_FAIL("%s: External buffer allocation failed\n", __func__);
2101
2102         ret_shinfo = rte_pktmbuf_ext_shinfo_init_helper(ext_buf_addr, &buf_len,
2103                 ext_buf_free_callback_fn, ext_buf_addr);
2104         if (ret_shinfo == NULL)
2105                 GOTO_FAIL("%s: Shared info initialization failed!\n", __func__);
2106
2107         if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
2108                 GOTO_FAIL("%s: External refcount is not 1\n", __func__);
2109
2110         if (rte_mbuf_refcnt_read(m) != 1)
2111                 GOTO_FAIL("%s: Invalid refcnt in mbuf\n", __func__);
2112
2113         buf_iova = rte_mempool_virt2iova(ext_buf_addr);
2114         rte_pktmbuf_attach_extbuf(m, ext_buf_addr, buf_iova, buf_len,
2115                 ret_shinfo);
2116         if (m->ol_flags != EXT_ATTACHED_MBUF)
2117                 GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
2118                                 __func__);
2119
2120         /* allocate one more mbuf */
2121         clone = rte_pktmbuf_clone(m, pktmbuf_pool);
2122         if (clone == NULL)
2123                 GOTO_FAIL("%s: mbuf clone allocation failed!\n", __func__);
2124         if (rte_pktmbuf_pkt_len(clone) != 0)
2125                 GOTO_FAIL("%s: Bad packet length\n", __func__);
2126
2127         /* attach the same external buffer to the cloned mbuf */
2128         rte_pktmbuf_attach_extbuf(clone, ext_buf_addr, buf_iova, buf_len,
2129                         ret_shinfo);
2130         if (clone->ol_flags != EXT_ATTACHED_MBUF)
2131                 GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
2132                                 __func__);
2133
2134         if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
2135                 GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
2136
2137         /* test to manually update ext_buf_ref_cnt from 2 to 3*/
2138         rte_mbuf_ext_refcnt_update(ret_shinfo, 1);
2139         if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 3)
2140                 GOTO_FAIL("%s: Update ext_buf ref_cnt failed\n", __func__);
2141
2142         /* reset the ext_refcnt before freeing the external buffer */
2143         rte_mbuf_ext_refcnt_set(ret_shinfo, 2);
2144         if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
2145                 GOTO_FAIL("%s: set ext_buf ref_cnt failed\n", __func__);
2146
2147         /* detach the external buffer from mbufs */
2148         rte_pktmbuf_detach_extbuf(m);
2149         /* check if ref cnt is decremented */
2150         if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
2151                 GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
2152
2153         rte_pktmbuf_detach_extbuf(clone);
2154         if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 0)
2155                 GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
2156
2157         rte_pktmbuf_free(m);
2158         m = NULL;
2159         rte_pktmbuf_free(clone);
2160         clone = NULL;
2161
2162         return 0;
2163
2164 fail:
2165         if (m) {
2166                 rte_pktmbuf_free(m);
2167                 m = NULL;
2168         }
2169         if (clone) {
2170                 rte_pktmbuf_free(clone);
2171                 clone = NULL;
2172         }
2173         if (ext_buf_addr != NULL) {
2174                 rte_free(ext_buf_addr);
2175                 ext_buf_addr = NULL;
2176         }
2177         return -1;
2178 }
2179
2180 static int
2181 test_mbuf(void)
2182 {
2183         int ret = -1;
2184         struct rte_mempool *pktmbuf_pool = NULL;
2185         struct rte_mempool *pktmbuf_pool2 = NULL;
2186
2187
2188         RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
2189
2190         /* create pktmbuf pool if it does not exist */
2191         pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
2192                         NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
2193                         SOCKET_ID_ANY);
2194
2195         if (pktmbuf_pool == NULL) {
2196                 printf("cannot allocate mbuf pool\n");
2197                 goto err;
2198         }
2199
2200         /* create a specific pktmbuf pool with a priv_size != 0 and no data
2201          * room size */
2202         pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
2203                         NB_MBUF, MEMPOOL_CACHE_SIZE, MBUF2_PRIV_SIZE, 0,
2204                         SOCKET_ID_ANY);
2205
2206         if (pktmbuf_pool2 == NULL) {
2207                 printf("cannot allocate mbuf pool\n");
2208                 goto err;
2209         }
2210
2211         /* test multiple mbuf alloc */
2212         if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
2213                 printf("test_mbuf_pool() failed\n");
2214                 goto err;
2215         }
2216
2217         /* do it another time to check that all mbufs were freed */
2218         if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
2219                 printf("test_mbuf_pool() failed (2)\n");
2220                 goto err;
2221         }
2222
2223         /* test bulk mbuf alloc and free */
2224         if (test_pktmbuf_pool_bulk() < 0) {
2225                 printf("test_pktmbuf_pool_bulk() failed\n");
2226                 goto err;
2227         }
2228
2229         /* test that the pointer to the data on a packet mbuf is set properly */
2230         if (test_pktmbuf_pool_ptr(pktmbuf_pool) < 0) {
2231                 printf("test_pktmbuf_pool_ptr() failed\n");
2232                 goto err;
2233         }
2234
2235         /* test data manipulation in mbuf */
2236         if (test_one_pktmbuf(pktmbuf_pool) < 0) {
2237                 printf("test_one_mbuf() failed\n");
2238                 goto err;
2239         }
2240
2241
2242         /*
2243          * do it another time, to check that allocation reinitialize
2244          * the mbuf correctly
2245          */
2246         if (test_one_pktmbuf(pktmbuf_pool) < 0) {
2247                 printf("test_one_mbuf() failed (2)\n");
2248                 goto err;
2249         }
2250
2251         if (test_pktmbuf_with_non_ascii_data(pktmbuf_pool) < 0) {
2252                 printf("test_pktmbuf_with_non_ascii_data() failed\n");
2253                 goto err;
2254         }
2255
2256         /* test free pktmbuf segment one by one */
2257         if (test_pktmbuf_free_segment(pktmbuf_pool) < 0) {
2258                 printf("test_pktmbuf_free_segment() failed.\n");
2259                 goto err;
2260         }
2261
2262         if (testclone_testupdate_testdetach(pktmbuf_pool) < 0) {
2263                 printf("testclone_and_testupdate() failed \n");
2264                 goto err;
2265         }
2266
2267         if (test_pktmbuf_copy(pktmbuf_pool) < 0) {
2268                 printf("test_pktmbuf_copy() failed\n");
2269                 goto err;
2270         }
2271
2272         if (test_attach_from_different_pool(pktmbuf_pool, pktmbuf_pool2) < 0) {
2273                 printf("test_attach_from_different_pool() failed\n");
2274                 goto err;
2275         }
2276
2277         if (test_refcnt_mbuf() < 0) {
2278                 printf("test_refcnt_mbuf() failed \n");
2279                 goto err;
2280         }
2281
2282         if (test_failing_mbuf_sanity_check(pktmbuf_pool) < 0) {
2283                 printf("test_failing_mbuf_sanity_check() failed\n");
2284                 goto err;
2285         }
2286
2287         if (test_mbuf_linearize_check(pktmbuf_pool) < 0) {
2288                 printf("test_mbuf_linearize_check() failed\n");
2289                 goto err;
2290         }
2291
2292         if (test_tx_offload() < 0) {
2293                 printf("test_tx_offload() failed\n");
2294                 goto err;
2295         }
2296
2297         if (test_mbuf_validate_tx_offload_one(pktmbuf_pool) < 0) {
2298                 printf("test_mbuf_validate_tx_offload_one() failed\n");
2299                 goto err;
2300         }
2301
2302         /* test for allocating a bulk of mbufs with various sizes */
2303         if (test_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
2304                 printf("test_rte_pktmbuf_alloc_bulk() failed\n");
2305                 goto err;
2306         }
2307
2308         /* test for allocating a bulk of mbufs with various sizes */
2309         if (test_neg_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
2310                 printf("test_neg_rte_pktmbuf_alloc_bulk() failed\n");
2311                 goto err;
2312         }
2313
2314         /* test to read mbuf packet */
2315         if (test_pktmbuf_read(pktmbuf_pool) < 0) {
2316                 printf("test_rte_pktmbuf_read() failed\n");
2317                 goto err;
2318         }
2319
2320         /* test to read mbuf packet from offset */
2321         if (test_pktmbuf_read_from_offset(pktmbuf_pool) < 0) {
2322                 printf("test_rte_pktmbuf_read_from_offset() failed\n");
2323                 goto err;
2324         }
2325
2326         /* test to read data from chain of mbufs with data segments */
2327         if (test_pktmbuf_read_from_chain(pktmbuf_pool) < 0) {
2328                 printf("test_rte_pktmbuf_read_from_chain() failed\n");
2329                 goto err;
2330         }
2331
2332         /* test to initialize shared info. at the end of external buffer */
2333         if (test_pktmbuf_ext_shinfo_init_helper(pktmbuf_pool) < 0) {
2334                 printf("test_pktmbuf_ext_shinfo_init_helper() failed\n");
2335                 goto err;
2336         }
2337
2338         ret = 0;
2339 err:
2340         rte_mempool_free(pktmbuf_pool);
2341         rte_mempool_free(pktmbuf_pool2);
2342         return ret;
2343 }
2344 #undef GOTO_FAIL
2345
2346 REGISTER_TEST_COMMAND(mbuf_autotest, test_mbuf);