xref: /dpdk/app/test/test_mbuf.c (revision fa4dfda5)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4 
5 #include "test.h"
6 
7 #include <string.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <inttypes.h>
13 #include <errno.h>
14 #include <sys/queue.h>
15 
16 #include <rte_common.h>
17 #include <rte_errno.h>
18 #include <rte_debug.h>
19 #include <rte_log.h>
20 #include <rte_memory.h>
21 #include <rte_memcpy.h>
22 #include <rte_launch.h>
23 #include <rte_eal.h>
24 #include <rte_per_lcore.h>
25 #include <rte_lcore.h>
26 #include <rte_branch_prediction.h>
27 #include <rte_ring.h>
28 #include <rte_mempool.h>
29 #include <rte_mbuf.h>
30 #include <rte_random.h>
31 #include <rte_cycles.h>
32 #include <rte_malloc.h>
33 #include <rte_ether.h>
34 #include <rte_ip.h>
35 #include <rte_tcp.h>
36 #include <rte_mbuf_dyn.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 #define VAL_NAME(flag)          { flag, #flag }
55 
56 /* chain length in bulk test */
57 #define CHAIN_LEN 16
58 
59 /* size of private data for mbuf in pktmbuf_pool2 */
60 #define MBUF2_PRIV_SIZE         128
61 
62 #define REFCNT_MAX_ITER         64
63 #define REFCNT_MAX_TIMEOUT      10
64 #define REFCNT_MAX_REF          (RTE_MAX_LCORE)
65 #define REFCNT_MBUF_NUM         64
66 #define REFCNT_RING_SIZE        (REFCNT_MBUF_NUM * REFCNT_MAX_REF)
67 
68 #define MAGIC_DATA              0x42424242
69 
70 #define MAKE_STRING(x)          # x
71 
72 #ifdef RTE_MBUF_REFCNT_ATOMIC
73 
74 static volatile uint32_t refcnt_stop_workers;
75 static unsigned refcnt_lcore[RTE_MAX_LCORE];
76 
77 #endif
78 
79 /*
80  * MBUF
81  * ====
82  *
83  * #. Allocate a mbuf pool.
84  *
85  *    - The pool contains NB_MBUF elements, where each mbuf is MBUF_SIZE
86  *      bytes long.
87  *
88  * #. Test multiple allocations of mbufs from this pool.
89  *
90  *    - Allocate NB_MBUF and store pointers in a table.
91  *    - If an allocation fails, return an error.
92  *    - Free all these mbufs.
93  *    - Repeat the same test to check that mbufs were freed correctly.
94  *
95  * #. Test data manipulation in pktmbuf.
96  *
97  *    - Alloc an mbuf.
98  *    - Append data using rte_pktmbuf_append().
99  *    - Test for error in rte_pktmbuf_append() when len is too large.
100  *    - Trim data at the end of mbuf using rte_pktmbuf_trim().
101  *    - Test for error in rte_pktmbuf_trim() when len is too large.
102  *    - Prepend a header using rte_pktmbuf_prepend().
103  *    - Test for error in rte_pktmbuf_prepend() when len is too large.
104  *    - Remove data at the beginning of mbuf using rte_pktmbuf_adj().
105  *    - Test for error in rte_pktmbuf_adj() when len is too large.
106  *    - Check that appended data is not corrupt.
107  *    - Free the mbuf.
108  *    - Between all these tests, check data_len and pkt_len, and
109  *      that the mbuf is contiguous.
110  *    - Repeat the test to check that allocation operations
111  *      reinitialize the mbuf correctly.
112  *
113  * #. Test packet cloning
114  *    - Clone a mbuf and verify the data
115  *    - Clone the cloned mbuf and verify the data
116  *    - Attach a mbuf to another that does not have the same priv_size.
117  */
118 
119 #define GOTO_FAIL(str, ...) do {					\
120 		printf("mbuf test FAILED (l.%d): <" str ">\n",		\
121 		       __LINE__,  ##__VA_ARGS__);			\
122 		goto fail;						\
123 } while(0)
124 
125 /*
126  * test data manipulation in mbuf with non-ascii data
127  */
128 static int
129 test_pktmbuf_with_non_ascii_data(struct rte_mempool *pktmbuf_pool)
130 {
131 	struct rte_mbuf *m = NULL;
132 	char *data;
133 
134 	m = rte_pktmbuf_alloc(pktmbuf_pool);
135 	if (m == NULL)
136 		GOTO_FAIL("Cannot allocate mbuf");
137 	if (rte_pktmbuf_pkt_len(m) != 0)
138 		GOTO_FAIL("Bad length");
139 
140 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
141 	if (data == NULL)
142 		GOTO_FAIL("Cannot append data");
143 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
144 		GOTO_FAIL("Bad pkt length");
145 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
146 		GOTO_FAIL("Bad data length");
147 	memset(data, 0xff, rte_pktmbuf_pkt_len(m));
148 	if (!rte_pktmbuf_is_contiguous(m))
149 		GOTO_FAIL("Buffer should be continuous");
150 	rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
151 
152 	rte_pktmbuf_free(m);
153 
154 	return 0;
155 
156 fail:
157 	if(m) {
158 		rte_pktmbuf_free(m);
159 	}
160 	return -1;
161 }
162 
163 /*
164  * test data manipulation in mbuf
165  */
166 static int
167 test_one_pktmbuf(struct rte_mempool *pktmbuf_pool)
168 {
169 	struct rte_mbuf *m = NULL;
170 	char *data, *data2, *hdr;
171 	unsigned i;
172 
173 	printf("Test pktmbuf API\n");
174 
175 	/* alloc a mbuf */
176 
177 	m = rte_pktmbuf_alloc(pktmbuf_pool);
178 	if (m == NULL)
179 		GOTO_FAIL("Cannot allocate mbuf");
180 	if (rte_pktmbuf_pkt_len(m) != 0)
181 		GOTO_FAIL("Bad length");
182 
183 	rte_pktmbuf_dump(stdout, m, 0);
184 
185 	/* append data */
186 
187 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN);
188 	if (data == NULL)
189 		GOTO_FAIL("Cannot append data");
190 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
191 		GOTO_FAIL("Bad pkt length");
192 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
193 		GOTO_FAIL("Bad data length");
194 	memset(data, 0x66, rte_pktmbuf_pkt_len(m));
195 	if (!rte_pktmbuf_is_contiguous(m))
196 		GOTO_FAIL("Buffer should be continuous");
197 	rte_pktmbuf_dump(stdout, m, MBUF_TEST_DATA_LEN);
198 	rte_pktmbuf_dump(stdout, m, 2*MBUF_TEST_DATA_LEN);
199 
200 	/* this append should fail */
201 
202 	data2 = rte_pktmbuf_append(m, (uint16_t)(rte_pktmbuf_tailroom(m) + 1));
203 	if (data2 != NULL)
204 		GOTO_FAIL("Append should not succeed");
205 
206 	/* append some more data */
207 
208 	data2 = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
209 	if (data2 == NULL)
210 		GOTO_FAIL("Cannot append data");
211 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
212 		GOTO_FAIL("Bad pkt length");
213 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_DATA_LEN2)
214 		GOTO_FAIL("Bad data length");
215 	if (!rte_pktmbuf_is_contiguous(m))
216 		GOTO_FAIL("Buffer should be continuous");
217 
218 	/* trim data at the end of mbuf */
219 
220 	if (rte_pktmbuf_trim(m, MBUF_TEST_DATA_LEN2) < 0)
221 		GOTO_FAIL("Cannot trim data");
222 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
223 		GOTO_FAIL("Bad pkt length");
224 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
225 		GOTO_FAIL("Bad data length");
226 	if (!rte_pktmbuf_is_contiguous(m))
227 		GOTO_FAIL("Buffer should be continuous");
228 
229 	/* this trim should fail */
230 
231 	if (rte_pktmbuf_trim(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) == 0)
232 		GOTO_FAIL("trim should not succeed");
233 
234 	/* prepend one header */
235 
236 	hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR1_LEN);
237 	if (hdr == NULL)
238 		GOTO_FAIL("Cannot prepend");
239 	if (data - hdr != MBUF_TEST_HDR1_LEN)
240 		GOTO_FAIL("Prepend failed");
241 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
242 		GOTO_FAIL("Bad pkt length");
243 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_HDR1_LEN)
244 		GOTO_FAIL("Bad data length");
245 	if (!rte_pktmbuf_is_contiguous(m))
246 		GOTO_FAIL("Buffer should be continuous");
247 	memset(hdr, 0x55, MBUF_TEST_HDR1_LEN);
248 
249 	/* prepend another header */
250 
251 	hdr = rte_pktmbuf_prepend(m, MBUF_TEST_HDR2_LEN);
252 	if (hdr == NULL)
253 		GOTO_FAIL("Cannot prepend");
254 	if (data - hdr != MBUF_TEST_ALL_HDRS_LEN)
255 		GOTO_FAIL("Prepend failed");
256 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
257 		GOTO_FAIL("Bad pkt length");
258 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN + MBUF_TEST_ALL_HDRS_LEN)
259 		GOTO_FAIL("Bad data length");
260 	if (!rte_pktmbuf_is_contiguous(m))
261 		GOTO_FAIL("Buffer should be continuous");
262 	memset(hdr, 0x55, MBUF_TEST_HDR2_LEN);
263 
264 	rte_mbuf_sanity_check(m, 1);
265 	rte_mbuf_sanity_check(m, 0);
266 	rte_pktmbuf_dump(stdout, m, 0);
267 
268 	/* this prepend should fail */
269 
270 	hdr = rte_pktmbuf_prepend(m, (uint16_t)(rte_pktmbuf_headroom(m) + 1));
271 	if (hdr != NULL)
272 		GOTO_FAIL("prepend should not succeed");
273 
274 	/* remove data at beginning of mbuf (adj) */
275 
276 	if (data != rte_pktmbuf_adj(m, MBUF_TEST_ALL_HDRS_LEN))
277 		GOTO_FAIL("rte_pktmbuf_adj failed");
278 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN)
279 		GOTO_FAIL("Bad pkt length");
280 	if (rte_pktmbuf_data_len(m) != MBUF_TEST_DATA_LEN)
281 		GOTO_FAIL("Bad data length");
282 	if (!rte_pktmbuf_is_contiguous(m))
283 		GOTO_FAIL("Buffer should be continuous");
284 
285 	/* this adj should fail */
286 
287 	if (rte_pktmbuf_adj(m, (uint16_t)(rte_pktmbuf_data_len(m) + 1)) != NULL)
288 		GOTO_FAIL("rte_pktmbuf_adj should not succeed");
289 
290 	/* check data */
291 
292 	if (!rte_pktmbuf_is_contiguous(m))
293 		GOTO_FAIL("Buffer should be continuous");
294 
295 	for (i=0; i<MBUF_TEST_DATA_LEN; i++) {
296 		if (data[i] != 0x66)
297 			GOTO_FAIL("Data corrupted at offset %u", i);
298 	}
299 
300 	/* free mbuf */
301 
302 	rte_pktmbuf_free(m);
303 	m = NULL;
304 	return 0;
305 
306 fail:
307 	if (m)
308 		rte_pktmbuf_free(m);
309 	return -1;
310 }
311 
312 static uint16_t
313 testclone_refcnt_read(struct rte_mbuf *m)
314 {
315 	return RTE_MBUF_HAS_PINNED_EXTBUF(m) ?
316 	       rte_mbuf_ext_refcnt_read(m->shinfo) :
317 	       rte_mbuf_refcnt_read(m);
318 }
319 
320 static int
321 testclone_testupdate_testdetach(struct rte_mempool *pktmbuf_pool,
322 				struct rte_mempool *clone_pool)
323 {
324 	struct rte_mbuf *m = NULL;
325 	struct rte_mbuf *clone = NULL;
326 	struct rte_mbuf *clone2 = NULL;
327 	unaligned_uint32_t *data;
328 
329 	/* alloc a mbuf */
330 	m = rte_pktmbuf_alloc(pktmbuf_pool);
331 	if (m == NULL)
332 		GOTO_FAIL("ooops not allocating mbuf");
333 
334 	if (rte_pktmbuf_pkt_len(m) != 0)
335 		GOTO_FAIL("Bad length");
336 
337 	rte_pktmbuf_append(m, sizeof(uint32_t));
338 	data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
339 	*data = MAGIC_DATA;
340 
341 	/* clone the allocated mbuf */
342 	clone = rte_pktmbuf_clone(m, clone_pool);
343 	if (clone == NULL)
344 		GOTO_FAIL("cannot clone data\n");
345 
346 	data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
347 	if (*data != MAGIC_DATA)
348 		GOTO_FAIL("invalid data in clone\n");
349 
350 	if (testclone_refcnt_read(m) != 2)
351 		GOTO_FAIL("invalid refcnt in m\n");
352 
353 	/* free the clone */
354 	rte_pktmbuf_free(clone);
355 	clone = NULL;
356 
357 	/* same test with a chained mbuf */
358 	m->next = rte_pktmbuf_alloc(pktmbuf_pool);
359 	if (m->next == NULL)
360 		GOTO_FAIL("Next Pkt Null\n");
361 	m->nb_segs = 2;
362 
363 	rte_pktmbuf_append(m->next, sizeof(uint32_t));
364 	m->pkt_len = 2 * sizeof(uint32_t);
365 
366 	data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
367 	*data = MAGIC_DATA;
368 
369 	clone = rte_pktmbuf_clone(m, clone_pool);
370 	if (clone == NULL)
371 		GOTO_FAIL("cannot clone data\n");
372 
373 	data = rte_pktmbuf_mtod(clone, unaligned_uint32_t *);
374 	if (*data != MAGIC_DATA)
375 		GOTO_FAIL("invalid data in clone\n");
376 
377 	data = rte_pktmbuf_mtod(clone->next, unaligned_uint32_t *);
378 	if (*data != MAGIC_DATA)
379 		GOTO_FAIL("invalid data in clone->next\n");
380 
381 	if (testclone_refcnt_read(m) != 2)
382 		GOTO_FAIL("invalid refcnt in m\n");
383 
384 	if (testclone_refcnt_read(m->next) != 2)
385 		GOTO_FAIL("invalid refcnt in m->next\n");
386 
387 	/* try to clone the clone */
388 
389 	clone2 = rte_pktmbuf_clone(clone, clone_pool);
390 	if (clone2 == NULL)
391 		GOTO_FAIL("cannot clone the clone\n");
392 
393 	data = rte_pktmbuf_mtod(clone2, unaligned_uint32_t *);
394 	if (*data != MAGIC_DATA)
395 		GOTO_FAIL("invalid data in clone2\n");
396 
397 	data = rte_pktmbuf_mtod(clone2->next, unaligned_uint32_t *);
398 	if (*data != MAGIC_DATA)
399 		GOTO_FAIL("invalid data in clone2->next\n");
400 
401 	if (testclone_refcnt_read(m) != 3)
402 		GOTO_FAIL("invalid refcnt in m\n");
403 
404 	if (testclone_refcnt_read(m->next) != 3)
405 		GOTO_FAIL("invalid refcnt in m->next\n");
406 
407 	/* free mbuf */
408 	rte_pktmbuf_free(m);
409 	rte_pktmbuf_free(clone);
410 	rte_pktmbuf_free(clone2);
411 
412 	m = NULL;
413 	clone = NULL;
414 	clone2 = NULL;
415 	printf("%s ok\n", __func__);
416 	return 0;
417 
418 fail:
419 	if (m)
420 		rte_pktmbuf_free(m);
421 	if (clone)
422 		rte_pktmbuf_free(clone);
423 	if (clone2)
424 		rte_pktmbuf_free(clone2);
425 	return -1;
426 }
427 
428 static int
429 test_pktmbuf_copy(struct rte_mempool *pktmbuf_pool,
430 		  struct rte_mempool *clone_pool)
431 {
432 	struct rte_mbuf *m = NULL;
433 	struct rte_mbuf *copy = NULL;
434 	struct rte_mbuf *copy2 = NULL;
435 	struct rte_mbuf *clone = NULL;
436 	unaligned_uint32_t *data;
437 
438 	/* alloc a mbuf */
439 	m = rte_pktmbuf_alloc(pktmbuf_pool);
440 	if (m == NULL)
441 		GOTO_FAIL("ooops not allocating mbuf");
442 
443 	if (rte_pktmbuf_pkt_len(m) != 0)
444 		GOTO_FAIL("Bad length");
445 
446 	rte_pktmbuf_append(m, sizeof(uint32_t));
447 	data = rte_pktmbuf_mtod(m, unaligned_uint32_t *);
448 	*data = MAGIC_DATA;
449 
450 	/* copy the allocated mbuf */
451 	copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
452 	if (copy == NULL)
453 		GOTO_FAIL("cannot copy data\n");
454 
455 	if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
456 		GOTO_FAIL("copy length incorrect\n");
457 
458 	if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
459 		GOTO_FAIL("copy data length incorrect\n");
460 
461 	data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
462 	if (*data != MAGIC_DATA)
463 		GOTO_FAIL("invalid data in copy\n");
464 
465 	/* free the copy */
466 	rte_pktmbuf_free(copy);
467 	copy = NULL;
468 
469 	/* same test with a cloned mbuf */
470 	clone = rte_pktmbuf_clone(m, clone_pool);
471 	if (clone == NULL)
472 		GOTO_FAIL("cannot clone data\n");
473 
474 	if ((!RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
475 	     !RTE_MBUF_CLONED(clone)) ||
476 	    (RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
477 	     !RTE_MBUF_HAS_EXTBUF(clone)))
478 		GOTO_FAIL("clone did not give a cloned mbuf\n");
479 
480 	copy = rte_pktmbuf_copy(clone, pktmbuf_pool, 0, UINT32_MAX);
481 	if (copy == NULL)
482 		GOTO_FAIL("cannot copy cloned mbuf\n");
483 
484 	if (RTE_MBUF_CLONED(copy))
485 		GOTO_FAIL("copy of clone is cloned?\n");
486 
487 	if (rte_pktmbuf_pkt_len(copy) != sizeof(uint32_t))
488 		GOTO_FAIL("copy clone length incorrect\n");
489 
490 	if (rte_pktmbuf_data_len(copy) != sizeof(uint32_t))
491 		GOTO_FAIL("copy clone data length incorrect\n");
492 
493 	data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
494 	if (*data != MAGIC_DATA)
495 		GOTO_FAIL("invalid data in clone copy\n");
496 	rte_pktmbuf_free(clone);
497 	rte_pktmbuf_free(copy);
498 	copy = NULL;
499 	clone = NULL;
500 
501 
502 	/* same test with a chained mbuf */
503 	m->next = rte_pktmbuf_alloc(pktmbuf_pool);
504 	if (m->next == NULL)
505 		GOTO_FAIL("Next Pkt Null\n");
506 	m->nb_segs = 2;
507 
508 	rte_pktmbuf_append(m->next, sizeof(uint32_t));
509 	m->pkt_len = 2 * sizeof(uint32_t);
510 	data = rte_pktmbuf_mtod(m->next, unaligned_uint32_t *);
511 	*data = MAGIC_DATA + 1;
512 
513 	copy = rte_pktmbuf_copy(m, pktmbuf_pool, 0, UINT32_MAX);
514 	if (copy == NULL)
515 		GOTO_FAIL("cannot copy data\n");
516 
517 	if (rte_pktmbuf_pkt_len(copy) != 2 * sizeof(uint32_t))
518 		GOTO_FAIL("chain copy length incorrect\n");
519 
520 	if (rte_pktmbuf_data_len(copy) != 2 * sizeof(uint32_t))
521 		GOTO_FAIL("chain copy data length incorrect\n");
522 
523 	data = rte_pktmbuf_mtod(copy, unaligned_uint32_t *);
524 	if (data[0] != MAGIC_DATA || data[1] != MAGIC_DATA + 1)
525 		GOTO_FAIL("invalid data in copy\n");
526 
527 	rte_pktmbuf_free(copy2);
528 
529 	/* test offset copy */
530 	copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
531 				 sizeof(uint32_t), UINT32_MAX);
532 	if (copy2 == NULL)
533 		GOTO_FAIL("cannot copy the copy\n");
534 
535 	if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
536 		GOTO_FAIL("copy with offset, length incorrect\n");
537 
538 	if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
539 		GOTO_FAIL("copy with offset, data length incorrect\n");
540 
541 	data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
542 	if (data[0] != MAGIC_DATA + 1)
543 		GOTO_FAIL("copy with offset, invalid data\n");
544 
545 	rte_pktmbuf_free(copy2);
546 
547 	/* test truncation copy */
548 	copy2 = rte_pktmbuf_copy(copy, pktmbuf_pool,
549 				 0, sizeof(uint32_t));
550 	if (copy2 == NULL)
551 		GOTO_FAIL("cannot copy the copy\n");
552 
553 	if (rte_pktmbuf_pkt_len(copy2) != sizeof(uint32_t))
554 		GOTO_FAIL("copy with truncate, length incorrect\n");
555 
556 	if (rte_pktmbuf_data_len(copy2) != sizeof(uint32_t))
557 		GOTO_FAIL("copy with truncate, data length incorrect\n");
558 
559 	data = rte_pktmbuf_mtod(copy2, unaligned_uint32_t *);
560 	if (data[0] != MAGIC_DATA)
561 		GOTO_FAIL("copy with truncate, invalid data\n");
562 
563 	/* free mbuf */
564 	rte_pktmbuf_free(m);
565 	rte_pktmbuf_free(copy);
566 	rte_pktmbuf_free(copy2);
567 
568 	m = NULL;
569 	copy = NULL;
570 	copy2 = NULL;
571 	printf("%s ok\n", __func__);
572 	return 0;
573 
574 fail:
575 	if (m)
576 		rte_pktmbuf_free(m);
577 	if (copy)
578 		rte_pktmbuf_free(copy);
579 	if (copy2)
580 		rte_pktmbuf_free(copy2);
581 	return -1;
582 }
583 
584 static int
585 test_attach_from_different_pool(struct rte_mempool *pktmbuf_pool,
586 				struct rte_mempool *pktmbuf_pool2)
587 {
588 	struct rte_mbuf *m = NULL;
589 	struct rte_mbuf *clone = NULL;
590 	struct rte_mbuf *clone2 = NULL;
591 	char *data, *c_data, *c_data2;
592 
593 	/* alloc a mbuf */
594 	m = rte_pktmbuf_alloc(pktmbuf_pool);
595 	if (m == NULL)
596 		GOTO_FAIL("cannot allocate mbuf");
597 
598 	if (rte_pktmbuf_pkt_len(m) != 0)
599 		GOTO_FAIL("Bad length");
600 
601 	data = rte_pktmbuf_mtod(m, char *);
602 
603 	/* allocate a new mbuf from the second pool, and attach it to the first
604 	 * mbuf */
605 	clone = rte_pktmbuf_alloc(pktmbuf_pool2);
606 	if (clone == NULL)
607 		GOTO_FAIL("cannot allocate mbuf from second pool\n");
608 
609 	/* check data room size and priv size, and erase priv */
610 	if (rte_pktmbuf_data_room_size(clone->pool) != 0)
611 		GOTO_FAIL("data room size should be 0\n");
612 	if (rte_pktmbuf_priv_size(clone->pool) != MBUF2_PRIV_SIZE)
613 		GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
614 	memset(clone + 1, 0, MBUF2_PRIV_SIZE);
615 
616 	/* save data pointer to compare it after detach() */
617 	c_data = rte_pktmbuf_mtod(clone, char *);
618 	if (c_data != (char *)clone + sizeof(*clone) + MBUF2_PRIV_SIZE)
619 		GOTO_FAIL("bad data pointer in clone");
620 	if (rte_pktmbuf_headroom(clone) != 0)
621 		GOTO_FAIL("bad headroom in clone");
622 
623 	rte_pktmbuf_attach(clone, m);
624 
625 	if (rte_pktmbuf_mtod(clone, char *) != data)
626 		GOTO_FAIL("clone was not attached properly\n");
627 	if (rte_pktmbuf_headroom(clone) != RTE_PKTMBUF_HEADROOM)
628 		GOTO_FAIL("bad headroom in clone after attach");
629 	if (rte_mbuf_refcnt_read(m) != 2)
630 		GOTO_FAIL("invalid refcnt in m\n");
631 
632 	/* allocate a new mbuf from the second pool, and attach it to the first
633 	 * cloned mbuf */
634 	clone2 = rte_pktmbuf_alloc(pktmbuf_pool2);
635 	if (clone2 == NULL)
636 		GOTO_FAIL("cannot allocate clone2 from second pool\n");
637 
638 	/* check data room size and priv size, and erase priv */
639 	if (rte_pktmbuf_data_room_size(clone2->pool) != 0)
640 		GOTO_FAIL("data room size should be 0\n");
641 	if (rte_pktmbuf_priv_size(clone2->pool) != MBUF2_PRIV_SIZE)
642 		GOTO_FAIL("data room size should be %d\n", MBUF2_PRIV_SIZE);
643 	memset(clone2 + 1, 0, MBUF2_PRIV_SIZE);
644 
645 	/* save data pointer to compare it after detach() */
646 	c_data2 = rte_pktmbuf_mtod(clone2, char *);
647 	if (c_data2 != (char *)clone2 + sizeof(*clone2) + MBUF2_PRIV_SIZE)
648 		GOTO_FAIL("bad data pointer in clone2");
649 	if (rte_pktmbuf_headroom(clone2) != 0)
650 		GOTO_FAIL("bad headroom in clone2");
651 
652 	rte_pktmbuf_attach(clone2, clone);
653 
654 	if (rte_pktmbuf_mtod(clone2, char *) != data)
655 		GOTO_FAIL("clone2 was not attached properly\n");
656 	if (rte_pktmbuf_headroom(clone2) != RTE_PKTMBUF_HEADROOM)
657 		GOTO_FAIL("bad headroom in clone2 after attach");
658 	if (rte_mbuf_refcnt_read(m) != 3)
659 		GOTO_FAIL("invalid refcnt in m\n");
660 
661 	/* detach the clones */
662 	rte_pktmbuf_detach(clone);
663 	if (c_data != rte_pktmbuf_mtod(clone, char *))
664 		GOTO_FAIL("clone was not detached properly\n");
665 	if (rte_mbuf_refcnt_read(m) != 2)
666 		GOTO_FAIL("invalid refcnt in m\n");
667 
668 	rte_pktmbuf_detach(clone2);
669 	if (c_data2 != rte_pktmbuf_mtod(clone2, char *))
670 		GOTO_FAIL("clone2 was not detached properly\n");
671 	if (rte_mbuf_refcnt_read(m) != 1)
672 		GOTO_FAIL("invalid refcnt in m\n");
673 
674 	/* free the clones and the initial mbuf */
675 	rte_pktmbuf_free(clone2);
676 	rte_pktmbuf_free(clone);
677 	rte_pktmbuf_free(m);
678 	printf("%s ok\n", __func__);
679 	return 0;
680 
681 fail:
682 	if (m)
683 		rte_pktmbuf_free(m);
684 	if (clone)
685 		rte_pktmbuf_free(clone);
686 	if (clone2)
687 		rte_pktmbuf_free(clone2);
688 	return -1;
689 }
690 
691 /*
692  * test allocation and free of mbufs
693  */
694 static int
695 test_pktmbuf_pool(struct rte_mempool *pktmbuf_pool)
696 {
697 	unsigned i;
698 	struct rte_mbuf *m[NB_MBUF];
699 	int ret = 0;
700 
701 	for (i=0; i<NB_MBUF; i++)
702 		m[i] = NULL;
703 
704 	/* alloc NB_MBUF mbufs */
705 	for (i=0; i<NB_MBUF; i++) {
706 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
707 		if (m[i] == NULL) {
708 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
709 			ret = -1;
710 		}
711 	}
712 	struct rte_mbuf *extra = NULL;
713 	extra = rte_pktmbuf_alloc(pktmbuf_pool);
714 	if(extra != NULL) {
715 		printf("Error pool not empty");
716 		ret = -1;
717 	}
718 	extra = rte_pktmbuf_clone(m[0], pktmbuf_pool);
719 	if(extra != NULL) {
720 		printf("Error pool not empty");
721 		ret = -1;
722 	}
723 	/* free them */
724 	for (i=0; i<NB_MBUF; i++) {
725 		if (m[i] != NULL)
726 			rte_pktmbuf_free(m[i]);
727 	}
728 
729 	return ret;
730 }
731 
732 /*
733  * test bulk allocation and bulk free of mbufs
734  */
735 static int
736 test_pktmbuf_pool_bulk(void)
737 {
738 	struct rte_mempool *pool = NULL;
739 	struct rte_mempool *pool2 = NULL;
740 	unsigned int i;
741 	struct rte_mbuf *m;
742 	struct rte_mbuf *mbufs[NB_MBUF];
743 	int ret = 0;
744 
745 	/* We cannot use the preallocated mbuf pools because their caches
746 	 * prevent us from bulk allocating all objects in them.
747 	 * So we create our own mbuf pools without caches.
748 	 */
749 	printf("Create mbuf pools for bulk allocation.\n");
750 	pool = rte_pktmbuf_pool_create("test_pktmbuf_bulk",
751 			NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
752 	if (pool == NULL) {
753 		printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
754 		       rte_errno);
755 		goto err;
756 	}
757 	pool2 = rte_pktmbuf_pool_create("test_pktmbuf_bulk2",
758 			NB_MBUF, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
759 	if (pool2 == NULL) {
760 		printf("rte_pktmbuf_pool_create() failed. rte_errno %d\n",
761 		       rte_errno);
762 		goto err;
763 	}
764 
765 	/* Preconditions: Mempools must be full. */
766 	if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
767 		printf("Test precondition failed: mempools not full\n");
768 		goto err;
769 	}
770 	if (!(rte_mempool_avail_count(pool) == NB_MBUF &&
771 			rte_mempool_avail_count(pool2) == NB_MBUF)) {
772 		printf("Test precondition failed: mempools: %u+%u != %u+%u",
773 		       rte_mempool_avail_count(pool),
774 		       rte_mempool_avail_count(pool2),
775 		       NB_MBUF, NB_MBUF);
776 		goto err;
777 	}
778 
779 	printf("Test single bulk alloc, followed by multiple bulk free.\n");
780 
781 	/* Bulk allocate all mbufs in the pool, in one go. */
782 	ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
783 	if (ret != 0) {
784 		printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
785 		goto err;
786 	}
787 	/* Test that they have been removed from the pool. */
788 	if (!rte_mempool_empty(pool)) {
789 		printf("mempool not empty\n");
790 		goto err;
791 	}
792 	/* Bulk free all mbufs, in four steps. */
793 	RTE_BUILD_BUG_ON(NB_MBUF % 4 != 0);
794 	for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
795 		rte_pktmbuf_free_bulk(&mbufs[i], NB_MBUF / 4);
796 		/* Test that they have been returned to the pool. */
797 		if (rte_mempool_avail_count(pool) != i + NB_MBUF / 4) {
798 			printf("mempool avail count incorrect\n");
799 			goto err;
800 		}
801 	}
802 
803 	printf("Test multiple bulk alloc, followed by single bulk free.\n");
804 
805 	/* Bulk allocate all mbufs in the pool, in four steps. */
806 	for (i = 0; i < NB_MBUF; i += NB_MBUF / 4) {
807 		ret = rte_pktmbuf_alloc_bulk(pool, &mbufs[i], NB_MBUF / 4);
808 		if (ret != 0) {
809 			printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
810 			goto err;
811 		}
812 	}
813 	/* Test that they have been removed from the pool. */
814 	if (!rte_mempool_empty(pool)) {
815 		printf("mempool not empty\n");
816 		goto err;
817 	}
818 	/* Bulk free all mbufs, in one go. */
819 	rte_pktmbuf_free_bulk(mbufs, NB_MBUF);
820 	/* Test that they have been returned to the pool. */
821 	if (!rte_mempool_full(pool)) {
822 		printf("mempool not full\n");
823 		goto err;
824 	}
825 
826 	printf("Test bulk free of single long chain.\n");
827 
828 	/* Bulk allocate all mbufs in the pool, in one go. */
829 	ret = rte_pktmbuf_alloc_bulk(pool, mbufs, NB_MBUF);
830 	if (ret != 0) {
831 		printf("rte_pktmbuf_alloc_bulk() failed: %d\n", ret);
832 		goto err;
833 	}
834 	/* Create a long mbuf chain. */
835 	for (i = 1; i < NB_MBUF; i++) {
836 		ret = rte_pktmbuf_chain(mbufs[0], mbufs[i]);
837 		if (ret != 0) {
838 			printf("rte_pktmbuf_chain() failed: %d\n", ret);
839 			goto err;
840 		}
841 		mbufs[i] = NULL;
842 	}
843 	/* Free the mbuf chain containing all the mbufs. */
844 	rte_pktmbuf_free_bulk(mbufs, 1);
845 	/* Test that they have been returned to the pool. */
846 	if (!rte_mempool_full(pool)) {
847 		printf("mempool not full\n");
848 		goto err;
849 	}
850 
851 	printf("Test bulk free of multiple chains using multiple pools.\n");
852 
853 	/* Create mbuf chains containing mbufs from different pools. */
854 	RTE_BUILD_BUG_ON(CHAIN_LEN % 2 != 0);
855 	RTE_BUILD_BUG_ON(NB_MBUF % (CHAIN_LEN / 2) != 0);
856 	for (i = 0; i < NB_MBUF * 2; i++) {
857 		m = rte_pktmbuf_alloc((i & 4) ? pool2 : pool);
858 		if (m == NULL) {
859 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
860 			goto err;
861 		}
862 		if ((i % CHAIN_LEN) == 0)
863 			mbufs[i / CHAIN_LEN] = m;
864 		else
865 			rte_pktmbuf_chain(mbufs[i / CHAIN_LEN], m);
866 	}
867 	/* Test that both pools have been emptied. */
868 	if (!(rte_mempool_empty(pool) && rte_mempool_empty(pool2))) {
869 		printf("mempools not empty\n");
870 		goto err;
871 	}
872 	/* Free one mbuf chain. */
873 	rte_pktmbuf_free_bulk(mbufs, 1);
874 	/* Test that the segments have been returned to the pools. */
875 	if (!(rte_mempool_avail_count(pool) == CHAIN_LEN / 2 &&
876 			rte_mempool_avail_count(pool2) == CHAIN_LEN / 2)) {
877 		printf("all segments of first mbuf have not been returned\n");
878 		goto err;
879 	}
880 	/* Free the remaining mbuf chains. */
881 	rte_pktmbuf_free_bulk(&mbufs[1], NB_MBUF * 2 / CHAIN_LEN - 1);
882 	/* Test that they have been returned to the pools. */
883 	if (!(rte_mempool_full(pool) && rte_mempool_full(pool2))) {
884 		printf("mempools not full\n");
885 		goto err;
886 	}
887 
888 	ret = 0;
889 	goto done;
890 
891 err:
892 	ret = -1;
893 
894 done:
895 	printf("Free mbuf pools for bulk allocation.\n");
896 	rte_mempool_free(pool);
897 	rte_mempool_free(pool2);
898 	return ret;
899 }
900 
901 /*
902  * test that the pointer to the data on a packet mbuf is set properly
903  */
904 static int
905 test_pktmbuf_pool_ptr(struct rte_mempool *pktmbuf_pool)
906 {
907 	unsigned i;
908 	struct rte_mbuf *m[NB_MBUF];
909 	int ret = 0;
910 
911 	for (i=0; i<NB_MBUF; i++)
912 		m[i] = NULL;
913 
914 	/* alloc NB_MBUF mbufs */
915 	for (i=0; i<NB_MBUF; i++) {
916 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
917 		if (m[i] == NULL) {
918 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
919 			ret = -1;
920 			break;
921 		}
922 		m[i]->data_off += 64;
923 	}
924 
925 	/* free them */
926 	for (i=0; i<NB_MBUF; i++) {
927 		if (m[i] != NULL)
928 			rte_pktmbuf_free(m[i]);
929 	}
930 
931 	for (i=0; i<NB_MBUF; i++)
932 		m[i] = NULL;
933 
934 	/* alloc NB_MBUF mbufs */
935 	for (i=0; i<NB_MBUF; i++) {
936 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
937 		if (m[i] == NULL) {
938 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
939 			ret = -1;
940 			break;
941 		}
942 		if (m[i]->data_off != RTE_PKTMBUF_HEADROOM) {
943 			printf("invalid data_off\n");
944 			ret = -1;
945 		}
946 	}
947 
948 	/* free them */
949 	for (i=0; i<NB_MBUF; i++) {
950 		if (m[i] != NULL)
951 			rte_pktmbuf_free(m[i]);
952 	}
953 
954 	return ret;
955 }
956 
957 static int
958 test_pktmbuf_free_segment(struct rte_mempool *pktmbuf_pool)
959 {
960 	unsigned i;
961 	struct rte_mbuf *m[NB_MBUF];
962 	int ret = 0;
963 
964 	for (i=0; i<NB_MBUF; i++)
965 		m[i] = NULL;
966 
967 	/* alloc NB_MBUF mbufs */
968 	for (i=0; i<NB_MBUF; i++) {
969 		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
970 		if (m[i] == NULL) {
971 			printf("rte_pktmbuf_alloc() failed (%u)\n", i);
972 			ret = -1;
973 		}
974 	}
975 
976 	/* free them */
977 	for (i=0; i<NB_MBUF; i++) {
978 		if (m[i] != NULL) {
979 			struct rte_mbuf *mb, *mt;
980 
981 			mb = m[i];
982 			while(mb != NULL) {
983 				mt = mb;
984 				mb = mb->next;
985 				rte_pktmbuf_free_seg(mt);
986 			}
987 		}
988 	}
989 
990 	return ret;
991 }
992 
993 /*
994  * Stress test for rte_mbuf atomic refcnt.
995  * Implies that RTE_MBUF_REFCNT_ATOMIC is defined.
996  * For more efficiency, recommended to run with RTE_LIBRTE_MBUF_DEBUG defined.
997  */
998 
999 #ifdef RTE_MBUF_REFCNT_ATOMIC
1000 
1001 static int
1002 test_refcnt_worker(void *arg)
1003 {
1004 	unsigned lcore, free;
1005 	void *mp = 0;
1006 	struct rte_ring *refcnt_mbuf_ring = arg;
1007 
1008 	lcore = rte_lcore_id();
1009 	printf("%s started at lcore %u\n", __func__, lcore);
1010 
1011 	free = 0;
1012 	while (refcnt_stop_workers == 0) {
1013 		if (rte_ring_dequeue(refcnt_mbuf_ring, &mp) == 0) {
1014 			free++;
1015 			rte_pktmbuf_free(mp);
1016 		}
1017 	}
1018 
1019 	refcnt_lcore[lcore] += free;
1020 	printf("%s finished at lcore %u, "
1021 	       "number of freed mbufs: %u\n",
1022 	       __func__, lcore, free);
1023 	return 0;
1024 }
1025 
1026 static void
1027 test_refcnt_iter(unsigned int lcore, unsigned int iter,
1028 		 struct rte_mempool *refcnt_pool,
1029 		 struct rte_ring *refcnt_mbuf_ring)
1030 {
1031 	uint16_t ref;
1032 	unsigned i, n, tref, wn;
1033 	struct rte_mbuf *m;
1034 
1035 	tref = 0;
1036 
1037 	/* For each mbuf in the pool:
1038 	 * - allocate mbuf,
1039 	 * - increment it's reference up to N+1,
1040 	 * - enqueue it N times into the ring for worker cores to free.
1041 	 */
1042 	for (i = 0, n = rte_mempool_avail_count(refcnt_pool);
1043 	    i != n && (m = rte_pktmbuf_alloc(refcnt_pool)) != NULL;
1044 	    i++) {
1045 		ref = RTE_MAX(rte_rand() % REFCNT_MAX_REF, 1UL);
1046 		tref += ref;
1047 		if ((ref & 1) != 0) {
1048 			rte_pktmbuf_refcnt_update(m, ref);
1049 			while (ref-- != 0)
1050 				rte_ring_enqueue(refcnt_mbuf_ring, m);
1051 		} else {
1052 			while (ref-- != 0) {
1053 				rte_pktmbuf_refcnt_update(m, 1);
1054 				rte_ring_enqueue(refcnt_mbuf_ring, m);
1055 			}
1056 		}
1057 		rte_pktmbuf_free(m);
1058 	}
1059 
1060 	if (i != n)
1061 		rte_panic("(lcore=%u, iter=%u): was able to allocate only "
1062 		          "%u from %u mbufs\n", lcore, iter, i, n);
1063 
1064 	/* wait till worker lcores  will consume all mbufs */
1065 	while (!rte_ring_empty(refcnt_mbuf_ring))
1066 		;
1067 
1068 	/* check that all mbufs are back into mempool by now */
1069 	for (wn = 0; wn != REFCNT_MAX_TIMEOUT; wn++) {
1070 		if ((i = rte_mempool_avail_count(refcnt_pool)) == n) {
1071 			refcnt_lcore[lcore] += tref;
1072 			printf("%s(lcore=%u, iter=%u) completed, "
1073 			    "%u references processed\n",
1074 			    __func__, lcore, iter, tref);
1075 			return;
1076 		}
1077 		rte_delay_ms(100);
1078 	}
1079 
1080 	rte_panic("(lcore=%u, iter=%u): after %us only "
1081 	          "%u of %u mbufs left free\n", lcore, iter, wn, i, n);
1082 }
1083 
1084 static int
1085 test_refcnt_main(struct rte_mempool *refcnt_pool,
1086 		   struct rte_ring *refcnt_mbuf_ring)
1087 {
1088 	unsigned i, lcore;
1089 
1090 	lcore = rte_lcore_id();
1091 	printf("%s started at lcore %u\n", __func__, lcore);
1092 
1093 	for (i = 0; i != REFCNT_MAX_ITER; i++)
1094 		test_refcnt_iter(lcore, i, refcnt_pool, refcnt_mbuf_ring);
1095 
1096 	refcnt_stop_workers = 1;
1097 	rte_wmb();
1098 
1099 	printf("%s finished at lcore %u\n", __func__, lcore);
1100 	return 0;
1101 }
1102 
1103 #endif
1104 
1105 static int
1106 test_refcnt_mbuf(void)
1107 {
1108 #ifdef RTE_MBUF_REFCNT_ATOMIC
1109 	unsigned int main_lcore, worker, tref;
1110 	int ret = -1;
1111 	struct rte_mempool *refcnt_pool = NULL;
1112 	struct rte_ring *refcnt_mbuf_ring = NULL;
1113 
1114 	if (rte_lcore_count() < 2) {
1115 		printf("Not enough cores for test_refcnt_mbuf, expecting at least 2\n");
1116 		return TEST_SKIPPED;
1117 	}
1118 
1119 	printf("starting %s, at %u lcores\n", __func__, rte_lcore_count());
1120 
1121 	/* create refcnt pool & ring if they don't exist */
1122 
1123 	refcnt_pool = rte_pktmbuf_pool_create(MAKE_STRING(refcnt_pool),
1124 					      REFCNT_MBUF_NUM, 0, 0, 0,
1125 					      SOCKET_ID_ANY);
1126 	if (refcnt_pool == NULL) {
1127 		printf("%s: cannot allocate " MAKE_STRING(refcnt_pool) "\n",
1128 		       __func__);
1129 		return -1;
1130 	}
1131 
1132 	refcnt_mbuf_ring = rte_ring_create("refcnt_mbuf_ring",
1133 					   rte_align32pow2(REFCNT_RING_SIZE), SOCKET_ID_ANY,
1134 					   RING_F_SP_ENQ);
1135 	if (refcnt_mbuf_ring == NULL) {
1136 		printf("%s: cannot allocate " MAKE_STRING(refcnt_mbuf_ring)
1137 		       "\n", __func__);
1138 		goto err;
1139 	}
1140 
1141 	refcnt_stop_workers = 0;
1142 	memset(refcnt_lcore, 0, sizeof (refcnt_lcore));
1143 
1144 	rte_eal_mp_remote_launch(test_refcnt_worker, refcnt_mbuf_ring, SKIP_MAIN);
1145 
1146 	test_refcnt_main(refcnt_pool, refcnt_mbuf_ring);
1147 
1148 	rte_eal_mp_wait_lcore();
1149 
1150 	/* check that we processed all references */
1151 	tref = 0;
1152 	main_lcore = rte_get_main_lcore();
1153 
1154 	RTE_LCORE_FOREACH_WORKER(worker)
1155 		tref += refcnt_lcore[worker];
1156 
1157 	if (tref != refcnt_lcore[main_lcore])
1158 		rte_panic("referenced mbufs: %u, freed mbufs: %u\n",
1159 			  tref, refcnt_lcore[main_lcore]);
1160 
1161 	rte_mempool_dump(stdout, refcnt_pool);
1162 	rte_ring_dump(stdout, refcnt_mbuf_ring);
1163 
1164 	ret = 0;
1165 
1166 err:
1167 	rte_mempool_free(refcnt_pool);
1168 	rte_ring_free(refcnt_mbuf_ring);
1169 	return ret;
1170 #else
1171 	return 0;
1172 #endif
1173 }
1174 
1175 #ifdef RTE_EXEC_ENV_WINDOWS
1176 static int
1177 test_failing_mbuf_sanity_check(struct rte_mempool *pktmbuf_pool)
1178 {
1179 	RTE_SET_USED(pktmbuf_pool);
1180 	return TEST_SKIPPED;
1181 }
1182 #else
1183 
1184 #include <unistd.h>
1185 #include <sys/resource.h>
1186 #include <sys/time.h>
1187 #include <sys/wait.h>
1188 
1189 /* use fork() to test mbuf errors panic */
1190 static int
1191 verify_mbuf_check_panics(struct rte_mbuf *buf)
1192 {
1193 	int pid;
1194 	int status;
1195 
1196 	pid = fork();
1197 
1198 	if (pid == 0) {
1199 		struct rlimit rl;
1200 
1201 		/* No need to generate a coredump when panicking. */
1202 		rl.rlim_cur = rl.rlim_max = 0;
1203 		setrlimit(RLIMIT_CORE, &rl);
1204 		rte_mbuf_sanity_check(buf, 1); /* should panic */
1205 		exit(0);  /* return normally if it doesn't panic */
1206 	} else if (pid < 0) {
1207 		printf("Fork Failed\n");
1208 		return -1;
1209 	}
1210 	wait(&status);
1211 	if(status == 0)
1212 		return -1;
1213 
1214 	return 0;
1215 }
1216 
1217 static int
1218 test_failing_mbuf_sanity_check(struct rte_mempool *pktmbuf_pool)
1219 {
1220 	struct rte_mbuf *buf;
1221 	struct rte_mbuf badbuf;
1222 
1223 	printf("Checking rte_mbuf_sanity_check for failure conditions\n");
1224 
1225 	/* get a good mbuf to use to make copies */
1226 	buf = rte_pktmbuf_alloc(pktmbuf_pool);
1227 	if (buf == NULL)
1228 		return -1;
1229 
1230 	printf("Checking good mbuf initially\n");
1231 	if (verify_mbuf_check_panics(buf) != -1)
1232 		return -1;
1233 
1234 	printf("Now checking for error conditions\n");
1235 
1236 	if (verify_mbuf_check_panics(NULL)) {
1237 		printf("Error with NULL mbuf test\n");
1238 		return -1;
1239 	}
1240 
1241 	badbuf = *buf;
1242 	badbuf.pool = NULL;
1243 	if (verify_mbuf_check_panics(&badbuf)) {
1244 		printf("Error with bad-pool mbuf test\n");
1245 		return -1;
1246 	}
1247 
1248 	badbuf = *buf;
1249 	badbuf.buf_iova = 0;
1250 	if (verify_mbuf_check_panics(&badbuf)) {
1251 		printf("Error with bad-physaddr mbuf test\n");
1252 		return -1;
1253 	}
1254 
1255 	badbuf = *buf;
1256 	badbuf.buf_addr = NULL;
1257 	if (verify_mbuf_check_panics(&badbuf)) {
1258 		printf("Error with bad-addr mbuf test\n");
1259 		return -1;
1260 	}
1261 
1262 	badbuf = *buf;
1263 	badbuf.refcnt = 0;
1264 	if (verify_mbuf_check_panics(&badbuf)) {
1265 		printf("Error with bad-refcnt(0) mbuf test\n");
1266 		return -1;
1267 	}
1268 
1269 	badbuf = *buf;
1270 	badbuf.refcnt = UINT16_MAX;
1271 	if (verify_mbuf_check_panics(&badbuf)) {
1272 		printf("Error with bad-refcnt(MAX) mbuf test\n");
1273 		return -1;
1274 	}
1275 
1276 	return 0;
1277 }
1278 
1279 #endif /* !RTE_EXEC_ENV_WINDOWS */
1280 
1281 static int
1282 test_mbuf_linearize(struct rte_mempool *pktmbuf_pool, int pkt_len,
1283 		    int nb_segs)
1284 {
1285 
1286 	struct rte_mbuf *m = NULL, *mbuf = NULL;
1287 	uint8_t *data;
1288 	int data_len = 0;
1289 	int remain;
1290 	int seg, seg_len;
1291 	int i;
1292 
1293 	if (pkt_len < 1) {
1294 		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
1295 		return -1;
1296 	}
1297 
1298 	if (nb_segs < 1) {
1299 		printf("Number of segments must be 1 or more (is %d)\n",
1300 				nb_segs);
1301 		return -1;
1302 	}
1303 
1304 	seg_len = pkt_len / nb_segs;
1305 	if (seg_len == 0)
1306 		seg_len = 1;
1307 
1308 	remain = pkt_len;
1309 
1310 	/* Create chained mbuf_src and fill it generated data */
1311 	for (seg = 0; remain > 0; seg++) {
1312 
1313 		m = rte_pktmbuf_alloc(pktmbuf_pool);
1314 		if (m == NULL) {
1315 			printf("Cannot create segment for source mbuf");
1316 			goto fail;
1317 		}
1318 
1319 		/* Make sure if tailroom is zeroed */
1320 		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
1321 				rte_pktmbuf_tailroom(m));
1322 
1323 		data_len = remain;
1324 		if (data_len > seg_len)
1325 			data_len = seg_len;
1326 
1327 		data = (uint8_t *)rte_pktmbuf_append(m, data_len);
1328 		if (data == NULL) {
1329 			printf("Cannot append %d bytes to the mbuf\n",
1330 					data_len);
1331 			goto fail;
1332 		}
1333 
1334 		for (i = 0; i < data_len; i++)
1335 			data[i] = (seg * seg_len + i) % 0x0ff;
1336 
1337 		if (seg == 0)
1338 			mbuf = m;
1339 		else
1340 			rte_pktmbuf_chain(mbuf, m);
1341 
1342 		remain -= data_len;
1343 	}
1344 
1345 	/* Create destination buffer to store coalesced data */
1346 	if (rte_pktmbuf_linearize(mbuf)) {
1347 		printf("Mbuf linearization failed\n");
1348 		goto fail;
1349 	}
1350 
1351 	if (!rte_pktmbuf_is_contiguous(mbuf)) {
1352 		printf("Source buffer should be contiguous after "
1353 				"linearization\n");
1354 		goto fail;
1355 	}
1356 
1357 	data = rte_pktmbuf_mtod(mbuf, uint8_t *);
1358 
1359 	for (i = 0; i < pkt_len; i++)
1360 		if (data[i] != (i % 0x0ff)) {
1361 			printf("Incorrect data in linearized mbuf\n");
1362 			goto fail;
1363 		}
1364 
1365 	rte_pktmbuf_free(mbuf);
1366 	return 0;
1367 
1368 fail:
1369 	if (mbuf)
1370 		rte_pktmbuf_free(mbuf);
1371 	return -1;
1372 }
1373 
1374 static int
1375 test_mbuf_linearize_check(struct rte_mempool *pktmbuf_pool)
1376 {
1377 	struct test_mbuf_array {
1378 		int size;
1379 		int nb_segs;
1380 	} mbuf_array[] = {
1381 			{ 128, 1 },
1382 			{ 64, 64 },
1383 			{ 512, 10 },
1384 			{ 250, 11 },
1385 			{ 123, 8 },
1386 	};
1387 	unsigned int i;
1388 
1389 	printf("Test mbuf linearize API\n");
1390 
1391 	for (i = 0; i < RTE_DIM(mbuf_array); i++)
1392 		if (test_mbuf_linearize(pktmbuf_pool, mbuf_array[i].size,
1393 				mbuf_array[i].nb_segs)) {
1394 			printf("Test failed for %d, %d\n", mbuf_array[i].size,
1395 					mbuf_array[i].nb_segs);
1396 			return -1;
1397 		}
1398 
1399 	return 0;
1400 }
1401 
1402 /*
1403  * Helper function for test_tx_ofload
1404  */
1405 static inline void
1406 set_tx_offload(struct rte_mbuf *mb, uint64_t il2, uint64_t il3, uint64_t il4,
1407 	uint64_t tso, uint64_t ol3, uint64_t ol2)
1408 {
1409 	mb->l2_len = il2;
1410 	mb->l3_len = il3;
1411 	mb->l4_len = il4;
1412 	mb->tso_segsz = tso;
1413 	mb->outer_l3_len = ol3;
1414 	mb->outer_l2_len = ol2;
1415 }
1416 
1417 static int
1418 test_tx_offload(void)
1419 {
1420 	struct rte_mbuf *mb;
1421 	uint64_t tm, v1, v2;
1422 	size_t sz;
1423 	uint32_t i;
1424 
1425 	static volatile struct {
1426 		uint16_t l2;
1427 		uint16_t l3;
1428 		uint16_t l4;
1429 		uint16_t tso;
1430 	} txof;
1431 
1432 	const uint32_t num = 0x10000;
1433 
1434 	txof.l2 = rte_rand() % (1 <<  RTE_MBUF_L2_LEN_BITS);
1435 	txof.l3 = rte_rand() % (1 <<  RTE_MBUF_L3_LEN_BITS);
1436 	txof.l4 = rte_rand() % (1 <<  RTE_MBUF_L4_LEN_BITS);
1437 	txof.tso = rte_rand() % (1 <<   RTE_MBUF_TSO_SEGSZ_BITS);
1438 
1439 	printf("%s started, tx_offload = {\n"
1440 		"\tl2_len=%#hx,\n"
1441 		"\tl3_len=%#hx,\n"
1442 		"\tl4_len=%#hx,\n"
1443 		"\ttso_segsz=%#hx,\n"
1444 		"\touter_l3_len=%#x,\n"
1445 		"\touter_l2_len=%#x,\n"
1446 		"};\n",
1447 		__func__,
1448 		txof.l2, txof.l3, txof.l4, txof.tso, txof.l3, txof.l2);
1449 
1450 	sz = sizeof(*mb) * num;
1451 	mb = rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);
1452 	if (mb == NULL) {
1453 		printf("%s failed, out of memory\n", __func__);
1454 		return -ENOMEM;
1455 	}
1456 
1457 	memset(mb, 0, sz);
1458 	tm = rte_rdtsc_precise();
1459 
1460 	for (i = 0; i != num; i++)
1461 		set_tx_offload(mb + i, txof.l2, txof.l3, txof.l4,
1462 			txof.tso, txof.l3, txof.l2);
1463 
1464 	tm = rte_rdtsc_precise() - tm;
1465 	printf("%s set tx_offload by bit-fields: %u iterations, %"
1466 		PRIu64 " cycles, %#Lf cycles/iter\n",
1467 		__func__, num, tm, (long double)tm / num);
1468 
1469 	v1 = mb[rte_rand() % num].tx_offload;
1470 
1471 	memset(mb, 0, sz);
1472 	tm = rte_rdtsc_precise();
1473 
1474 	for (i = 0; i != num; i++)
1475 		mb[i].tx_offload = rte_mbuf_tx_offload(txof.l2, txof.l3,
1476 			txof.l4, txof.tso, txof.l3, txof.l2, 0);
1477 
1478 	tm = rte_rdtsc_precise() - tm;
1479 	printf("%s set raw tx_offload: %u iterations, %"
1480 		PRIu64 " cycles, %#Lf cycles/iter\n",
1481 		__func__, num, tm, (long double)tm / num);
1482 
1483 	v2 = mb[rte_rand() % num].tx_offload;
1484 
1485 	rte_free(mb);
1486 
1487 	printf("%s finished\n"
1488 		"expected tx_offload value: 0x%" PRIx64 ";\n"
1489 		"rte_mbuf_tx_offload value: 0x%" PRIx64 ";\n",
1490 		__func__, v1, v2);
1491 
1492 	return (v1 == v2) ? 0 : -EINVAL;
1493 }
1494 
1495 static int
1496 test_get_rx_ol_flag_list(void)
1497 {
1498 	int len = 6, ret = 0;
1499 	char buf[256] = "";
1500 	int buflen = 0;
1501 
1502 	/* Test case to check with null buffer */
1503 	ret = rte_get_rx_ol_flag_list(0, NULL, 0);
1504 	if (ret != -1)
1505 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
1506 
1507 	/* Test case to check with zero buffer len */
1508 	ret = rte_get_rx_ol_flag_list(RTE_MBUF_F_RX_L4_CKSUM_MASK, buf, 0);
1509 	if (ret != -1)
1510 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
1511 
1512 	buflen = strlen(buf);
1513 	if (buflen != 0)
1514 		GOTO_FAIL("%s buffer should be empty, received = %d\n",
1515 				__func__, buflen);
1516 
1517 	/* Test case to check with reduced buffer len */
1518 	ret = rte_get_rx_ol_flag_list(0, buf, len);
1519 	if (ret != -1)
1520 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
1521 
1522 	buflen = strlen(buf);
1523 	if (buflen != (len - 1))
1524 		GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
1525 				"received = %d\n", __func__,
1526 				(len - 1), buflen);
1527 
1528 	/* Test case to check with zero mask value */
1529 	ret = rte_get_rx_ol_flag_list(0, buf, sizeof(buf));
1530 	if (ret != 0)
1531 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
1532 
1533 	buflen = strlen(buf);
1534 	if (buflen == 0)
1535 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
1536 				"non-zero, buffer should not be empty");
1537 
1538 	/* Test case to check with valid mask value */
1539 	ret = rte_get_rx_ol_flag_list(RTE_MBUF_F_RX_SEC_OFFLOAD, buf,
1540 				      sizeof(buf));
1541 	if (ret != 0)
1542 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
1543 
1544 	buflen = strlen(buf);
1545 	if (buflen == 0)
1546 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
1547 				"non-zero, buffer should not be empty");
1548 
1549 	return 0;
1550 fail:
1551 	return -1;
1552 }
1553 
1554 static int
1555 test_get_tx_ol_flag_list(void)
1556 {
1557 	int len = 6, ret = 0;
1558 	char buf[256] = "";
1559 	int buflen = 0;
1560 
1561 	/* Test case to check with null buffer */
1562 	ret = rte_get_tx_ol_flag_list(0, NULL, 0);
1563 	if (ret != -1)
1564 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
1565 
1566 	/* Test case to check with zero buffer len */
1567 	ret = rte_get_tx_ol_flag_list(RTE_MBUF_F_TX_IP_CKSUM, buf, 0);
1568 	if (ret != -1)
1569 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
1570 
1571 	buflen = strlen(buf);
1572 	if (buflen != 0) {
1573 		GOTO_FAIL("%s buffer should be empty, received = %d\n",
1574 				__func__, buflen);
1575 	}
1576 
1577 	/* Test case to check with reduced buffer len */
1578 	ret = rte_get_tx_ol_flag_list(0, buf, len);
1579 	if (ret != -1)
1580 		GOTO_FAIL("%s expected: -1, received = %d\n", __func__, ret);
1581 
1582 	buflen = strlen(buf);
1583 	if (buflen != (len - 1))
1584 		GOTO_FAIL("%s invalid buffer length retrieved, expected: %d,"
1585 				"received = %d\n", __func__,
1586 				(len - 1), buflen);
1587 
1588 	/* Test case to check with zero mask value */
1589 	ret = rte_get_tx_ol_flag_list(0, buf, sizeof(buf));
1590 	if (ret != 0)
1591 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
1592 
1593 	buflen = strlen(buf);
1594 	if (buflen == 0)
1595 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
1596 				"non-zero, buffer should not be empty");
1597 
1598 	/* Test case to check with valid mask value */
1599 	ret = rte_get_tx_ol_flag_list(RTE_MBUF_F_TX_UDP_CKSUM, buf,
1600 				      sizeof(buf));
1601 	if (ret != 0)
1602 		GOTO_FAIL("%s expected: 0, received = %d\n", __func__, ret);
1603 
1604 	buflen = strlen(buf);
1605 	if (buflen == 0)
1606 		GOTO_FAIL("%s expected: %s, received length = 0\n", __func__,
1607 				"non-zero, buffer should not be empty");
1608 
1609 	return 0;
1610 fail:
1611 	return -1;
1612 
1613 }
1614 
1615 struct flag_name {
1616 	uint64_t flag;
1617 	const char *name;
1618 };
1619 
1620 static int
1621 test_get_rx_ol_flag_name(void)
1622 {
1623 	uint16_t i;
1624 	const char *flag_str = NULL;
1625 	const struct flag_name rx_flags[] = {
1626 		VAL_NAME(RTE_MBUF_F_RX_VLAN),
1627 		VAL_NAME(RTE_MBUF_F_RX_RSS_HASH),
1628 		VAL_NAME(RTE_MBUF_F_RX_FDIR),
1629 		VAL_NAME(RTE_MBUF_F_RX_L4_CKSUM_BAD),
1630 		VAL_NAME(RTE_MBUF_F_RX_L4_CKSUM_GOOD),
1631 		VAL_NAME(RTE_MBUF_F_RX_L4_CKSUM_NONE),
1632 		VAL_NAME(RTE_MBUF_F_RX_IP_CKSUM_BAD),
1633 		VAL_NAME(RTE_MBUF_F_RX_IP_CKSUM_GOOD),
1634 		VAL_NAME(RTE_MBUF_F_RX_IP_CKSUM_NONE),
1635 		VAL_NAME(RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD),
1636 		VAL_NAME(RTE_MBUF_F_RX_VLAN_STRIPPED),
1637 		VAL_NAME(RTE_MBUF_F_RX_IEEE1588_PTP),
1638 		VAL_NAME(RTE_MBUF_F_RX_IEEE1588_TMST),
1639 		VAL_NAME(RTE_MBUF_F_RX_FDIR_ID),
1640 		VAL_NAME(RTE_MBUF_F_RX_FDIR_FLX),
1641 		VAL_NAME(RTE_MBUF_F_RX_QINQ_STRIPPED),
1642 		VAL_NAME(RTE_MBUF_F_RX_LRO),
1643 		VAL_NAME(RTE_MBUF_F_RX_SEC_OFFLOAD),
1644 		VAL_NAME(RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED),
1645 		VAL_NAME(RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD),
1646 		VAL_NAME(RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD),
1647 		VAL_NAME(RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID),
1648 	};
1649 
1650 	/* Test case to check with valid flag */
1651 	for (i = 0; i < RTE_DIM(rx_flags); i++) {
1652 		flag_str = rte_get_rx_ol_flag_name(rx_flags[i].flag);
1653 		if (flag_str == NULL)
1654 			GOTO_FAIL("%s: Expected flagname = %s; received null\n",
1655 					__func__, rx_flags[i].name);
1656 		if (strcmp(flag_str, rx_flags[i].name) != 0)
1657 			GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
1658 				__func__, rx_flags[i].name, flag_str);
1659 	}
1660 	/* Test case to check with invalid flag */
1661 	flag_str = rte_get_rx_ol_flag_name(0);
1662 	if (flag_str != NULL) {
1663 		GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
1664 				__func__, flag_str);
1665 	}
1666 
1667 	return 0;
1668 fail:
1669 	return -1;
1670 }
1671 
1672 static int
1673 test_get_tx_ol_flag_name(void)
1674 {
1675 	uint16_t i;
1676 	const char *flag_str = NULL;
1677 	const struct flag_name tx_flags[] = {
1678 		VAL_NAME(RTE_MBUF_F_TX_VLAN),
1679 		VAL_NAME(RTE_MBUF_F_TX_IP_CKSUM),
1680 		VAL_NAME(RTE_MBUF_F_TX_TCP_CKSUM),
1681 		VAL_NAME(RTE_MBUF_F_TX_SCTP_CKSUM),
1682 		VAL_NAME(RTE_MBUF_F_TX_UDP_CKSUM),
1683 		VAL_NAME(RTE_MBUF_F_TX_IEEE1588_TMST),
1684 		VAL_NAME(RTE_MBUF_F_TX_TCP_SEG),
1685 		VAL_NAME(RTE_MBUF_F_TX_IPV4),
1686 		VAL_NAME(RTE_MBUF_F_TX_IPV6),
1687 		VAL_NAME(RTE_MBUF_F_TX_OUTER_IP_CKSUM),
1688 		VAL_NAME(RTE_MBUF_F_TX_OUTER_IPV4),
1689 		VAL_NAME(RTE_MBUF_F_TX_OUTER_IPV6),
1690 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_VXLAN),
1691 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_GRE),
1692 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_IPIP),
1693 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_GENEVE),
1694 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_MPLSINUDP),
1695 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE),
1696 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_IP),
1697 		VAL_NAME(RTE_MBUF_F_TX_TUNNEL_UDP),
1698 		VAL_NAME(RTE_MBUF_F_TX_QINQ),
1699 		VAL_NAME(RTE_MBUF_F_TX_MACSEC),
1700 		VAL_NAME(RTE_MBUF_F_TX_SEC_OFFLOAD),
1701 		VAL_NAME(RTE_MBUF_F_TX_UDP_SEG),
1702 		VAL_NAME(RTE_MBUF_F_TX_OUTER_UDP_CKSUM),
1703 	};
1704 
1705 	/* Test case to check with valid flag */
1706 	for (i = 0; i < RTE_DIM(tx_flags); i++) {
1707 		flag_str = rte_get_tx_ol_flag_name(tx_flags[i].flag);
1708 		if (flag_str == NULL)
1709 			GOTO_FAIL("%s: Expected flagname = %s; received null\n",
1710 				__func__, tx_flags[i].name);
1711 		if (strcmp(flag_str, tx_flags[i].name) != 0)
1712 			GOTO_FAIL("%s: Expected flagname = %s; received = %s\n",
1713 				__func__, tx_flags[i].name, flag_str);
1714 	}
1715 	/* Test case to check with invalid flag */
1716 	flag_str = rte_get_tx_ol_flag_name(0);
1717 	if (flag_str != NULL) {
1718 		GOTO_FAIL("%s: Expected flag name = null; received = %s\n",
1719 				__func__, flag_str);
1720 	}
1721 
1722 	return 0;
1723 fail:
1724 	return -1;
1725 
1726 }
1727 
1728 static int
1729 test_mbuf_validate_tx_offload(const char *test_name,
1730 		struct rte_mempool *pktmbuf_pool,
1731 		uint64_t ol_flags,
1732 		uint16_t segsize,
1733 		int expected_retval)
1734 {
1735 	struct rte_mbuf *m = NULL;
1736 	int ret = 0;
1737 
1738 	/* alloc a mbuf and do sanity check */
1739 	m = rte_pktmbuf_alloc(pktmbuf_pool);
1740 	if (m == NULL)
1741 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1742 	if (rte_pktmbuf_pkt_len(m) != 0)
1743 		GOTO_FAIL("%s: Bad packet length\n", __func__);
1744 	rte_mbuf_sanity_check(m, 0);
1745 	m->ol_flags = ol_flags;
1746 	m->tso_segsz = segsize;
1747 	ret = rte_validate_tx_offload(m);
1748 	if (ret != expected_retval)
1749 		GOTO_FAIL("%s(%s): expected ret val: %d; received: %d\n",
1750 				__func__, test_name, expected_retval, ret);
1751 	rte_pktmbuf_free(m);
1752 	m = NULL;
1753 	return 0;
1754 fail:
1755 	if (m) {
1756 		rte_pktmbuf_free(m);
1757 		m = NULL;
1758 	}
1759 	return -1;
1760 }
1761 
1762 static int
1763 test_mbuf_validate_tx_offload_one(struct rte_mempool *pktmbuf_pool)
1764 {
1765 	/* test to validate tx offload flags */
1766 	uint64_t ol_flags = 0;
1767 
1768 	/* test to validate if IP checksum is counted only for IPV4 packet */
1769 	/* set both IP checksum and IPV6 flags */
1770 	ol_flags |= RTE_MBUF_F_TX_IP_CKSUM;
1771 	ol_flags |= RTE_MBUF_F_TX_IPV6;
1772 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_CKSUM_IPV6_SET",
1773 				pktmbuf_pool,
1774 				ol_flags, 0, -EINVAL) < 0)
1775 		GOTO_FAIL("%s failed: IP cksum is set incorrect.\n", __func__);
1776 	/* resetting ol_flags for next testcase */
1777 	ol_flags = 0;
1778 
1779 	/* test to validate if IP type is set when required */
1780 	ol_flags |= RTE_MBUF_F_TX_L4_MASK;
1781 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
1782 				pktmbuf_pool,
1783 				ol_flags, 0, -EINVAL) < 0)
1784 		GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
1785 
1786 	/* test if IP type is set when TCP SEG is on */
1787 	ol_flags |= RTE_MBUF_F_TX_TCP_SEG;
1788 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_NOT_SET",
1789 				pktmbuf_pool,
1790 				ol_flags, 0, -EINVAL) < 0)
1791 		GOTO_FAIL("%s failed: IP type is not set.\n", __func__);
1792 
1793 	ol_flags = 0;
1794 	/* test to confirm IP type (IPV4/IPV6) is set */
1795 	ol_flags = RTE_MBUF_F_TX_L4_MASK;
1796 	ol_flags |= RTE_MBUF_F_TX_IPV6;
1797 	if (test_mbuf_validate_tx_offload("MBUF_TEST_IP_TYPE_SET",
1798 				pktmbuf_pool,
1799 				ol_flags, 0, 0) < 0)
1800 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1801 
1802 	ol_flags = 0;
1803 	/* test to check TSO segment size is non-zero */
1804 	ol_flags |= RTE_MBUF_F_TX_IPV4;
1805 	ol_flags |= RTE_MBUF_F_TX_TCP_SEG;
1806 	/* set 0 tso segment size */
1807 	if (test_mbuf_validate_tx_offload("MBUF_TEST_NULL_TSO_SEGSZ",
1808 				pktmbuf_pool,
1809 				ol_flags, 0, -EINVAL) < 0)
1810 		GOTO_FAIL("%s failed: tso segment size is null.\n", __func__);
1811 
1812 	/* retain IPV4 and RTE_MBUF_F_TX_TCP_SEG mask */
1813 	/* set valid tso segment size but IP CKSUM not set */
1814 	if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_NOT_SET",
1815 				pktmbuf_pool,
1816 				ol_flags, 512, -EINVAL) < 0)
1817 		GOTO_FAIL("%s failed: IP CKSUM is not set.\n", __func__);
1818 
1819 	/* test to validate if IP checksum is set for TSO capability */
1820 	/* retain IPV4, TCP_SEG, tso_seg size */
1821 	ol_flags |= RTE_MBUF_F_TX_IP_CKSUM;
1822 	if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IP_CKSUM_SET",
1823 				pktmbuf_pool,
1824 				ol_flags, 512, 0) < 0)
1825 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1826 
1827 	/* test to confirm TSO for IPV6 type */
1828 	ol_flags = 0;
1829 	ol_flags |= RTE_MBUF_F_TX_IPV6;
1830 	ol_flags |= RTE_MBUF_F_TX_TCP_SEG;
1831 	if (test_mbuf_validate_tx_offload("MBUF_TEST_TSO_IPV6_SET",
1832 				pktmbuf_pool,
1833 				ol_flags, 512, 0) < 0)
1834 		GOTO_FAIL("%s failed: TSO req not met.\n", __func__);
1835 
1836 	ol_flags = 0;
1837 	/* test if outer IP checksum set for non outer IPv4 packet */
1838 	ol_flags |= RTE_MBUF_F_TX_IPV6;
1839 	ol_flags |= RTE_MBUF_F_TX_OUTER_IP_CKSUM;
1840 	if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_NOT_SET",
1841 				pktmbuf_pool,
1842 				ol_flags, 512, -EINVAL) < 0)
1843 		GOTO_FAIL("%s failed: Outer IP cksum set.\n", __func__);
1844 
1845 	ol_flags = 0;
1846 	/* test to confirm outer IP checksum is set for outer IPV4 packet */
1847 	ol_flags |= RTE_MBUF_F_TX_OUTER_IP_CKSUM;
1848 	ol_flags |= RTE_MBUF_F_TX_OUTER_IPV4;
1849 	if (test_mbuf_validate_tx_offload("MBUF_TEST_OUTER_IPV4_SET",
1850 				pktmbuf_pool,
1851 				ol_flags, 512, 0) < 0)
1852 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1853 
1854 	ol_flags = 0;
1855 	/* test to confirm if packets with no TX_OFFLOAD_MASK are skipped */
1856 	if (test_mbuf_validate_tx_offload("MBUF_TEST_OL_MASK_NOT_SET",
1857 				pktmbuf_pool,
1858 				ol_flags, 512, 0) < 0)
1859 		GOTO_FAIL("%s failed: tx offload flag error.\n", __func__);
1860 	return 0;
1861 fail:
1862 	return -1;
1863 }
1864 
1865 /*
1866  * Test for allocating a bulk of mbufs
1867  * define an array with positive sizes for mbufs allocations.
1868  */
1869 static int
1870 test_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
1871 {
1872 	int ret = 0;
1873 	unsigned int idx, loop;
1874 	unsigned int alloc_counts[] = {
1875 		0,
1876 		MEMPOOL_CACHE_SIZE - 1,
1877 		MEMPOOL_CACHE_SIZE + 1,
1878 		MEMPOOL_CACHE_SIZE * 1.5,
1879 		MEMPOOL_CACHE_SIZE * 2,
1880 		MEMPOOL_CACHE_SIZE * 2 - 1,
1881 		MEMPOOL_CACHE_SIZE * 2 + 1,
1882 		MEMPOOL_CACHE_SIZE,
1883 	};
1884 
1885 	/* allocate a large array of mbuf pointers */
1886 	struct rte_mbuf *mbufs[NB_MBUF] = { 0 };
1887 	for (idx = 0; idx < RTE_DIM(alloc_counts); idx++) {
1888 		ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
1889 				alloc_counts[idx]);
1890 		if (ret == 0) {
1891 			for (loop = 0; loop < alloc_counts[idx] &&
1892 					mbufs[loop] != NULL; loop++)
1893 				rte_pktmbuf_free(mbufs[loop]);
1894 		} else if (ret != 0) {
1895 			printf("%s: Bulk alloc failed count(%u); ret val(%d)\n",
1896 					__func__, alloc_counts[idx], ret);
1897 			return -1;
1898 		}
1899 	}
1900 	return 0;
1901 }
1902 
1903 /*
1904  * Negative testing for allocating a bulk of mbufs
1905  */
1906 static int
1907 test_neg_pktmbuf_alloc_bulk(struct rte_mempool *pktmbuf_pool)
1908 {
1909 	int ret = 0;
1910 	unsigned int idx, loop;
1911 	unsigned int neg_alloc_counts[] = {
1912 		MEMPOOL_CACHE_SIZE - NB_MBUF,
1913 		NB_MBUF + 1,
1914 		NB_MBUF * 8,
1915 		UINT_MAX
1916 	};
1917 	struct rte_mbuf *mbufs[NB_MBUF * 8] = { 0 };
1918 
1919 	for (idx = 0; idx < RTE_DIM(neg_alloc_counts); idx++) {
1920 		ret = rte_pktmbuf_alloc_bulk(pktmbuf_pool, mbufs,
1921 				neg_alloc_counts[idx]);
1922 		if (ret == 0) {
1923 			printf("%s: Bulk alloc must fail! count(%u); ret(%d)\n",
1924 					__func__, neg_alloc_counts[idx], ret);
1925 			for (loop = 0; loop < neg_alloc_counts[idx] &&
1926 					mbufs[loop] != NULL; loop++)
1927 				rte_pktmbuf_free(mbufs[loop]);
1928 			return -1;
1929 		}
1930 	}
1931 	return 0;
1932 }
1933 
1934 /*
1935  * Test to read mbuf packet using rte_pktmbuf_read
1936  */
1937 static int
1938 test_pktmbuf_read(struct rte_mempool *pktmbuf_pool)
1939 {
1940 	struct rte_mbuf *m = NULL;
1941 	char *data = NULL;
1942 	const char *data_copy = NULL;
1943 	int off;
1944 
1945 	/* alloc a mbuf */
1946 	m = rte_pktmbuf_alloc(pktmbuf_pool);
1947 	if (m == NULL)
1948 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1949 	if (rte_pktmbuf_pkt_len(m) != 0)
1950 		GOTO_FAIL("%s: Bad packet length\n", __func__);
1951 	rte_mbuf_sanity_check(m, 0);
1952 
1953 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
1954 	if (data == NULL)
1955 		GOTO_FAIL("%s: Cannot append data\n", __func__);
1956 	if (rte_pktmbuf_pkt_len(m) != MBUF_TEST_DATA_LEN2)
1957 		GOTO_FAIL("%s: Bad packet length\n", __func__);
1958 	memset(data, 0xfe, MBUF_TEST_DATA_LEN2);
1959 
1960 	/* read the data from mbuf */
1961 	data_copy = rte_pktmbuf_read(m, 0, MBUF_TEST_DATA_LEN2, NULL);
1962 	if (data_copy == NULL)
1963 		GOTO_FAIL("%s: Error in reading data!\n", __func__);
1964 	for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
1965 		if (data_copy[off] != (char)0xfe)
1966 			GOTO_FAIL("Data corrupted at offset %u", off);
1967 	}
1968 	rte_pktmbuf_free(m);
1969 	m = NULL;
1970 
1971 	return 0;
1972 fail:
1973 	if (m) {
1974 		rte_pktmbuf_free(m);
1975 		m = NULL;
1976 	}
1977 	return -1;
1978 }
1979 
1980 /*
1981  * Test to read mbuf packet data from offset
1982  */
1983 static int
1984 test_pktmbuf_read_from_offset(struct rte_mempool *pktmbuf_pool)
1985 {
1986 	struct rte_mbuf *m = NULL;
1987 	struct ether_hdr *hdr = NULL;
1988 	char *data = NULL;
1989 	const char *data_copy = NULL;
1990 	unsigned int off;
1991 	unsigned int hdr_len = sizeof(struct rte_ether_hdr);
1992 
1993 	/* alloc a mbuf */
1994 	m = rte_pktmbuf_alloc(pktmbuf_pool);
1995 	if (m == NULL)
1996 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
1997 
1998 	if (rte_pktmbuf_pkt_len(m) != 0)
1999 		GOTO_FAIL("%s: Bad packet length\n", __func__);
2000 	rte_mbuf_sanity_check(m, 0);
2001 
2002 	/* prepend an ethernet header */
2003 	hdr = (struct ether_hdr *)rte_pktmbuf_prepend(m, hdr_len);
2004 	if (hdr == NULL)
2005 		GOTO_FAIL("%s: Cannot prepend header\n", __func__);
2006 	if (rte_pktmbuf_pkt_len(m) != hdr_len)
2007 		GOTO_FAIL("%s: Bad pkt length", __func__);
2008 	if (rte_pktmbuf_data_len(m) != hdr_len)
2009 		GOTO_FAIL("%s: Bad data length", __func__);
2010 	memset(hdr, 0xde, hdr_len);
2011 
2012 	/* read mbuf header info from 0 offset */
2013 	data_copy = rte_pktmbuf_read(m, 0, hdr_len, NULL);
2014 	if (data_copy == NULL)
2015 		GOTO_FAIL("%s: Error in reading header!\n", __func__);
2016 	for (off = 0; off < hdr_len; off++) {
2017 		if (data_copy[off] != (char)0xde)
2018 			GOTO_FAIL("Header info corrupted at offset %u", off);
2019 	}
2020 
2021 	/* append sample data after ethernet header */
2022 	data = rte_pktmbuf_append(m, MBUF_TEST_DATA_LEN2);
2023 	if (data == NULL)
2024 		GOTO_FAIL("%s: Cannot append data\n", __func__);
2025 	if (rte_pktmbuf_pkt_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
2026 		GOTO_FAIL("%s: Bad packet length\n", __func__);
2027 	if (rte_pktmbuf_data_len(m) != hdr_len + MBUF_TEST_DATA_LEN2)
2028 		GOTO_FAIL("%s: Bad data length\n", __func__);
2029 	memset(data, 0xcc, MBUF_TEST_DATA_LEN2);
2030 
2031 	/* read mbuf data after header info */
2032 	data_copy = rte_pktmbuf_read(m, hdr_len, MBUF_TEST_DATA_LEN2, NULL);
2033 	if (data_copy == NULL)
2034 		GOTO_FAIL("%s: Error in reading header data!\n", __func__);
2035 	for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
2036 		if (data_copy[off] != (char)0xcc)
2037 			GOTO_FAIL("Data corrupted at offset %u", off);
2038 	}
2039 
2040 	/* partial reading of mbuf data */
2041 	data_copy = rte_pktmbuf_read(m, hdr_len + 5, MBUF_TEST_DATA_LEN2 - 5,
2042 			NULL);
2043 	if (data_copy == NULL)
2044 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
2045 	if (strlen(data_copy) != MBUF_TEST_DATA_LEN2 - 5)
2046 		GOTO_FAIL("%s: Incorrect data length!\n", __func__);
2047 	for (off = 0; off < MBUF_TEST_DATA_LEN2 - 5; off++) {
2048 		if (data_copy[off] != (char)0xcc)
2049 			GOTO_FAIL("Data corrupted at offset %u", off);
2050 	}
2051 
2052 	/* read length greater than mbuf data_len */
2053 	if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_data_len(m) + 1,
2054 				NULL) != NULL)
2055 		GOTO_FAIL("%s: Requested len is larger than mbuf data len!\n",
2056 				__func__);
2057 
2058 	/* read length greater than mbuf pkt_len */
2059 	if (rte_pktmbuf_read(m, hdr_len, rte_pktmbuf_pkt_len(m) + 1,
2060 				NULL) != NULL)
2061 		GOTO_FAIL("%s: Requested len is larger than mbuf pkt len!\n",
2062 				__func__);
2063 
2064 	/* read data of zero len from valid offset */
2065 	data_copy = rte_pktmbuf_read(m, hdr_len, 0, NULL);
2066 	if (data_copy == NULL)
2067 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
2068 	if (strlen(data_copy) != MBUF_TEST_DATA_LEN2)
2069 		GOTO_FAIL("%s: Corrupted data content!\n", __func__);
2070 	for (off = 0; off < MBUF_TEST_DATA_LEN2; off++) {
2071 		if (data_copy[off] != (char)0xcc)
2072 			GOTO_FAIL("Data corrupted at offset %u", off);
2073 	}
2074 
2075 	/* read data of zero length from zero offset */
2076 	data_copy = rte_pktmbuf_read(m, 0, 0, NULL);
2077 	if (data_copy == NULL)
2078 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
2079 	/* check if the received address is the beginning of header info */
2080 	if (hdr != (const struct ether_hdr *)data_copy)
2081 		GOTO_FAIL("%s: Corrupted data address!\n", __func__);
2082 
2083 	/* read data of max length from valid offset */
2084 	data_copy = rte_pktmbuf_read(m, hdr_len, UINT_MAX, NULL);
2085 	if (data_copy == NULL)
2086 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
2087 	/* check if the received address is the beginning of data segment */
2088 	if (data_copy != data)
2089 		GOTO_FAIL("%s: Corrupted data address!\n", __func__);
2090 
2091 	/* try to read from mbuf with max size offset */
2092 	data_copy = rte_pktmbuf_read(m, UINT_MAX, 0, NULL);
2093 	if (data_copy != NULL)
2094 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
2095 
2096 	/* try to read from mbuf with max size offset and len */
2097 	data_copy = rte_pktmbuf_read(m, UINT_MAX, UINT_MAX, NULL);
2098 	if (data_copy != NULL)
2099 		GOTO_FAIL("%s: Error in reading packet data!\n", __func__);
2100 
2101 	rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
2102 
2103 	rte_pktmbuf_free(m);
2104 	m = NULL;
2105 
2106 	return 0;
2107 fail:
2108 	if (m) {
2109 		rte_pktmbuf_free(m);
2110 		m = NULL;
2111 	}
2112 	return -1;
2113 }
2114 
2115 struct test_case {
2116 	unsigned int seg_count;
2117 	unsigned int flags;
2118 	uint32_t read_off;
2119 	uint32_t read_len;
2120 	unsigned int seg_lengths[MBUF_MAX_SEG];
2121 };
2122 
2123 /* create a mbuf with different sized segments
2124  *  and fill with data [0x00 0x01 0x02 ...]
2125  */
2126 static struct rte_mbuf *
2127 create_packet(struct rte_mempool *pktmbuf_pool,
2128 		struct test_case *test_data)
2129 {
2130 	uint16_t i, ret, seg, seg_len = 0;
2131 	uint32_t last_index = 0;
2132 	unsigned int seg_lengths[MBUF_MAX_SEG];
2133 	unsigned int hdr_len;
2134 	struct rte_mbuf *pkt = NULL;
2135 	struct rte_mbuf	*pkt_seg = NULL;
2136 	char *hdr = NULL;
2137 	char *data = NULL;
2138 
2139 	memcpy(seg_lengths, test_data->seg_lengths,
2140 			sizeof(unsigned int)*test_data->seg_count);
2141 	for (seg = 0; seg < test_data->seg_count; seg++) {
2142 		hdr_len = 0;
2143 		seg_len =  seg_lengths[seg];
2144 		pkt_seg = rte_pktmbuf_alloc(pktmbuf_pool);
2145 		if (pkt_seg == NULL)
2146 			GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
2147 		if (rte_pktmbuf_pkt_len(pkt_seg) != 0)
2148 			GOTO_FAIL("%s: Bad packet length\n", __func__);
2149 		rte_mbuf_sanity_check(pkt_seg, 0);
2150 		/* Add header only for the first segment */
2151 		if (test_data->flags == MBUF_HEADER && seg == 0) {
2152 			hdr_len = sizeof(struct rte_ether_hdr);
2153 			/* prepend a header and fill with dummy data */
2154 			hdr = (char *)rte_pktmbuf_prepend(pkt_seg, hdr_len);
2155 			if (hdr == NULL)
2156 				GOTO_FAIL("%s: Cannot prepend header\n",
2157 						__func__);
2158 			if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len)
2159 				GOTO_FAIL("%s: Bad pkt length", __func__);
2160 			if (rte_pktmbuf_data_len(pkt_seg) != hdr_len)
2161 				GOTO_FAIL("%s: Bad data length", __func__);
2162 			for (i = 0; i < hdr_len; i++)
2163 				hdr[i] = (last_index + i) % 0xffff;
2164 			last_index += hdr_len;
2165 		}
2166 		/* skip appending segment with 0 length */
2167 		if (seg_len == 0)
2168 			continue;
2169 		data = rte_pktmbuf_append(pkt_seg, seg_len);
2170 		if (data == NULL)
2171 			GOTO_FAIL("%s: Cannot append data segment\n", __func__);
2172 		if (rte_pktmbuf_pkt_len(pkt_seg) != hdr_len + seg_len)
2173 			GOTO_FAIL("%s: Bad packet segment length: %d\n",
2174 					__func__, rte_pktmbuf_pkt_len(pkt_seg));
2175 		if (rte_pktmbuf_data_len(pkt_seg) != hdr_len + seg_len)
2176 			GOTO_FAIL("%s: Bad data length\n", __func__);
2177 		for (i = 0; i < seg_len; i++)
2178 			data[i] = (last_index + i) % 0xffff;
2179 		/* to fill continuous data from one seg to another */
2180 		last_index += i;
2181 		/* create chained mbufs */
2182 		if (seg == 0)
2183 			pkt = pkt_seg;
2184 		else {
2185 			ret = rte_pktmbuf_chain(pkt, pkt_seg);
2186 			if (ret != 0)
2187 				GOTO_FAIL("%s:FAIL: Chained mbuf creation %d\n",
2188 						__func__, ret);
2189 		}
2190 
2191 		pkt_seg = pkt_seg->next;
2192 	}
2193 	return pkt;
2194 fail:
2195 	if (pkt != NULL) {
2196 		rte_pktmbuf_free(pkt);
2197 		pkt = NULL;
2198 	}
2199 	if (pkt_seg != NULL) {
2200 		rte_pktmbuf_free(pkt_seg);
2201 		pkt_seg = NULL;
2202 	}
2203 	return NULL;
2204 }
2205 
2206 static int
2207 test_pktmbuf_read_from_chain(struct rte_mempool *pktmbuf_pool)
2208 {
2209 	struct rte_mbuf *m;
2210 	struct test_case test_cases[] = {
2211 		{
2212 			.seg_lengths = { 100, 100, 100 },
2213 			.seg_count = 3,
2214 			.flags = MBUF_NO_HEADER,
2215 			.read_off = 0,
2216 			.read_len = 300
2217 		},
2218 		{
2219 			.seg_lengths = { 100, 125, 150 },
2220 			.seg_count = 3,
2221 			.flags = MBUF_NO_HEADER,
2222 			.read_off = 99,
2223 			.read_len = 201
2224 		},
2225 		{
2226 			.seg_lengths = { 100, 100 },
2227 			.seg_count = 2,
2228 			.flags = MBUF_NO_HEADER,
2229 			.read_off = 0,
2230 			.read_len = 100
2231 		},
2232 		{
2233 			.seg_lengths = { 100, 200 },
2234 			.seg_count = 2,
2235 			.flags = MBUF_HEADER,
2236 			.read_off = sizeof(struct rte_ether_hdr),
2237 			.read_len = 150
2238 		},
2239 		{
2240 			.seg_lengths = { 1000, 100 },
2241 			.seg_count = 2,
2242 			.flags = MBUF_NO_HEADER,
2243 			.read_off = 0,
2244 			.read_len = 1000
2245 		},
2246 		{
2247 			.seg_lengths = { 1024, 0, 100 },
2248 			.seg_count = 3,
2249 			.flags = MBUF_NO_HEADER,
2250 			.read_off = 100,
2251 			.read_len = 1001
2252 		},
2253 		{
2254 			.seg_lengths = { 1000, 1, 1000 },
2255 			.seg_count = 3,
2256 			.flags = MBUF_NO_HEADER,
2257 			.read_off = 1000,
2258 			.read_len = 2
2259 		},
2260 		{
2261 			.seg_lengths = { MBUF_TEST_DATA_LEN,
2262 					MBUF_TEST_DATA_LEN2,
2263 					MBUF_TEST_DATA_LEN3, 800, 10 },
2264 			.seg_count = 5,
2265 			.flags = MBUF_NEG_TEST_READ,
2266 			.read_off = 1000,
2267 			.read_len = MBUF_DATA_SIZE
2268 		},
2269 	};
2270 
2271 	uint32_t i, pos;
2272 	const char *data_copy = NULL;
2273 	char data_buf[MBUF_DATA_SIZE];
2274 
2275 	memset(data_buf, 0, MBUF_DATA_SIZE);
2276 
2277 	for (i = 0; i < RTE_DIM(test_cases); i++) {
2278 		m = create_packet(pktmbuf_pool, &test_cases[i]);
2279 		if (m == NULL)
2280 			GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
2281 
2282 		data_copy = rte_pktmbuf_read(m, test_cases[i].read_off,
2283 				test_cases[i].read_len, data_buf);
2284 		if (test_cases[i].flags == MBUF_NEG_TEST_READ) {
2285 			if (data_copy != NULL)
2286 				GOTO_FAIL("%s: mbuf data read should fail!\n",
2287 						__func__);
2288 			else {
2289 				rte_pktmbuf_free(m);
2290 				m = NULL;
2291 				continue;
2292 			}
2293 		}
2294 		if (data_copy == NULL)
2295 			GOTO_FAIL("%s: Error in reading packet data!\n",
2296 					__func__);
2297 		for (pos = 0; pos < test_cases[i].read_len; pos++) {
2298 			if (data_copy[pos] !=
2299 					(char)((test_cases[i].read_off + pos)
2300 						% 0xffff))
2301 				GOTO_FAIL("Data corrupted at offset %u is %2X",
2302 						pos, data_copy[pos]);
2303 		}
2304 		rte_pktmbuf_dump(stdout, m, rte_pktmbuf_pkt_len(m));
2305 		rte_pktmbuf_free(m);
2306 		m = NULL;
2307 	}
2308 	return 0;
2309 
2310 fail:
2311 	if (m != NULL) {
2312 		rte_pktmbuf_free(m);
2313 		m = NULL;
2314 	}
2315 	return -1;
2316 }
2317 
2318 /* Define a free call back function to be used for external buffer */
2319 static void
2320 ext_buf_free_callback_fn(void *addr, void *opaque)
2321 {
2322 	bool *freed = opaque;
2323 
2324 	if (addr == NULL) {
2325 		printf("External buffer address is invalid\n");
2326 		return;
2327 	}
2328 	rte_free(addr);
2329 	*freed = true;
2330 	printf("External buffer freed via callback\n");
2331 }
2332 
2333 /*
2334  * Test to initialize shared data in external buffer before attaching to mbuf
2335  *  - Allocate mbuf with no data.
2336  *  - Allocate external buffer with size should be large enough to accommodate
2337  *     rte_mbuf_ext_shared_info.
2338  *  - Invoke pktmbuf_ext_shinfo_init_helper to initialize shared data.
2339  *  - Invoke rte_pktmbuf_attach_extbuf to attach external buffer to the mbuf.
2340  *  - Clone another mbuf and attach the same external buffer to it.
2341  *  - Invoke rte_pktmbuf_detach_extbuf to detach the external buffer from mbuf.
2342  */
2343 static int
2344 test_pktmbuf_ext_shinfo_init_helper(struct rte_mempool *pktmbuf_pool)
2345 {
2346 	struct rte_mbuf *m = NULL;
2347 	struct rte_mbuf *clone = NULL;
2348 	struct rte_mbuf_ext_shared_info *ret_shinfo = NULL;
2349 	rte_iova_t buf_iova;
2350 	void *ext_buf_addr = NULL;
2351 	uint16_t buf_len = EXT_BUF_TEST_DATA_LEN +
2352 				sizeof(struct rte_mbuf_ext_shared_info);
2353 	bool freed = false;
2354 
2355 	/* alloc a mbuf */
2356 	m = rte_pktmbuf_alloc(pktmbuf_pool);
2357 	if (m == NULL)
2358 		GOTO_FAIL("%s: mbuf allocation failed!\n", __func__);
2359 	if (rte_pktmbuf_pkt_len(m) != 0)
2360 		GOTO_FAIL("%s: Bad packet length\n", __func__);
2361 	rte_mbuf_sanity_check(m, 0);
2362 
2363 	ext_buf_addr = rte_malloc("External buffer", buf_len,
2364 			RTE_CACHE_LINE_SIZE);
2365 	if (ext_buf_addr == NULL)
2366 		GOTO_FAIL("%s: External buffer allocation failed\n", __func__);
2367 
2368 	ret_shinfo = rte_pktmbuf_ext_shinfo_init_helper(ext_buf_addr, &buf_len,
2369 		ext_buf_free_callback_fn, &freed);
2370 	if (ret_shinfo == NULL)
2371 		GOTO_FAIL("%s: Shared info initialization failed!\n", __func__);
2372 
2373 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
2374 		GOTO_FAIL("%s: External refcount is not 1\n", __func__);
2375 
2376 	if (rte_mbuf_refcnt_read(m) != 1)
2377 		GOTO_FAIL("%s: Invalid refcnt in mbuf\n", __func__);
2378 
2379 	buf_iova = rte_mem_virt2iova(ext_buf_addr);
2380 	rte_pktmbuf_attach_extbuf(m, ext_buf_addr, buf_iova, buf_len,
2381 		ret_shinfo);
2382 	if (m->ol_flags != RTE_MBUF_F_EXTERNAL)
2383 		GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
2384 				__func__);
2385 
2386 	/* allocate one more mbuf */
2387 	clone = rte_pktmbuf_clone(m, pktmbuf_pool);
2388 	if (clone == NULL)
2389 		GOTO_FAIL("%s: mbuf clone allocation failed!\n", __func__);
2390 	if (rte_pktmbuf_pkt_len(clone) != 0)
2391 		GOTO_FAIL("%s: Bad packet length\n", __func__);
2392 
2393 	/* attach the same external buffer to the cloned mbuf */
2394 	rte_pktmbuf_attach_extbuf(clone, ext_buf_addr, buf_iova, buf_len,
2395 			ret_shinfo);
2396 	if (clone->ol_flags != RTE_MBUF_F_EXTERNAL)
2397 		GOTO_FAIL("%s: External buffer is not attached to mbuf\n",
2398 				__func__);
2399 
2400 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
2401 		GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
2402 	if (freed)
2403 		GOTO_FAIL("%s: extbuf should not be freed\n", __func__);
2404 
2405 	/* test to manually update ext_buf_ref_cnt from 2 to 3*/
2406 	rte_mbuf_ext_refcnt_update(ret_shinfo, 1);
2407 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 3)
2408 		GOTO_FAIL("%s: Update ext_buf ref_cnt failed\n", __func__);
2409 	if (freed)
2410 		GOTO_FAIL("%s: extbuf should not be freed\n", __func__);
2411 
2412 	/* reset the ext_refcnt before freeing the external buffer */
2413 	rte_mbuf_ext_refcnt_set(ret_shinfo, 2);
2414 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 2)
2415 		GOTO_FAIL("%s: set ext_buf ref_cnt failed\n", __func__);
2416 	if (freed)
2417 		GOTO_FAIL("%s: extbuf should not be freed\n", __func__);
2418 
2419 	/* detach the external buffer from mbufs */
2420 	rte_pktmbuf_detach_extbuf(m);
2421 	/* check if ref cnt is decremented */
2422 	if (rte_mbuf_ext_refcnt_read(ret_shinfo) != 1)
2423 		GOTO_FAIL("%s: Invalid ext_buf ref_cnt\n", __func__);
2424 	if (freed)
2425 		GOTO_FAIL("%s: extbuf should not be freed\n", __func__);
2426 
2427 	rte_pktmbuf_detach_extbuf(clone);
2428 	if (!freed)
2429 		GOTO_FAIL("%s: extbuf should be freed\n", __func__);
2430 	freed = false;
2431 
2432 	rte_pktmbuf_free(m);
2433 	m = NULL;
2434 	rte_pktmbuf_free(clone);
2435 	clone = NULL;
2436 
2437 	return 0;
2438 
2439 fail:
2440 	if (m) {
2441 		rte_pktmbuf_free(m);
2442 		m = NULL;
2443 	}
2444 	if (clone) {
2445 		rte_pktmbuf_free(clone);
2446 		clone = NULL;
2447 	}
2448 	if (ext_buf_addr != NULL) {
2449 		rte_free(ext_buf_addr);
2450 		ext_buf_addr = NULL;
2451 	}
2452 	return -1;
2453 }
2454 
2455 /*
2456  * Test the mbuf pool with pinned external data buffers
2457  *  - Allocate memory zone for external buffer
2458  *  - Create the mbuf pool with pinned external buffer
2459  *  - Check the created pool with relevant mbuf pool unit tests
2460  */
2461 static int
2462 test_pktmbuf_ext_pinned_buffer(struct rte_mempool *std_pool)
2463 {
2464 
2465 	struct rte_pktmbuf_extmem ext_mem;
2466 	struct rte_mempool *pinned_pool = NULL;
2467 	const struct rte_memzone *mz = NULL;
2468 
2469 	printf("Test mbuf pool with external pinned data buffers\n");
2470 
2471 	/* Allocate memzone for the external data buffer */
2472 	mz = rte_memzone_reserve("pinned_pool",
2473 				 NB_MBUF * MBUF_DATA_SIZE,
2474 				 SOCKET_ID_ANY,
2475 				 RTE_MEMZONE_2MB | RTE_MEMZONE_SIZE_HINT_ONLY);
2476 	if (mz == NULL)
2477 		GOTO_FAIL("%s: Memzone allocation failed\n", __func__);
2478 
2479 	/* Create the mbuf pool with pinned external data buffer */
2480 	ext_mem.buf_ptr = mz->addr;
2481 	ext_mem.buf_iova = mz->iova;
2482 	ext_mem.buf_len = mz->len;
2483 	ext_mem.elt_size = MBUF_DATA_SIZE;
2484 
2485 	pinned_pool = rte_pktmbuf_pool_create_extbuf("test_pinned_pool",
2486 				NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
2487 				MBUF_DATA_SIZE,	SOCKET_ID_ANY,
2488 				&ext_mem, 1);
2489 	if (pinned_pool == NULL)
2490 		GOTO_FAIL("%s: Mbuf pool with pinned external"
2491 			  " buffer creation failed\n", __func__);
2492 	/* test multiple mbuf alloc */
2493 	if (test_pktmbuf_pool(pinned_pool) < 0)
2494 		GOTO_FAIL("%s: test_mbuf_pool(pinned) failed\n",
2495 			  __func__);
2496 
2497 	/* do it another time to check that all mbufs were freed */
2498 	if (test_pktmbuf_pool(pinned_pool) < 0)
2499 		GOTO_FAIL("%s: test_mbuf_pool(pinned) failed (2)\n",
2500 			  __func__);
2501 
2502 	/* test that the data pointer on a packet mbuf is set properly */
2503 	if (test_pktmbuf_pool_ptr(pinned_pool) < 0)
2504 		GOTO_FAIL("%s: test_pktmbuf_pool_ptr(pinned) failed\n",
2505 			  __func__);
2506 
2507 	/* test data manipulation in mbuf with non-ascii data */
2508 	if (test_pktmbuf_with_non_ascii_data(pinned_pool) < 0)
2509 		GOTO_FAIL("%s: test_pktmbuf_with_non_ascii_data(pinned)"
2510 			  " failed\n", __func__);
2511 
2512 	/* test free pktmbuf segment one by one */
2513 	if (test_pktmbuf_free_segment(pinned_pool) < 0)
2514 		GOTO_FAIL("%s: test_pktmbuf_free_segment(pinned) failed\n",
2515 			  __func__);
2516 
2517 	if (testclone_testupdate_testdetach(pinned_pool, std_pool) < 0)
2518 		GOTO_FAIL("%s: testclone_and_testupdate(pinned) failed\n",
2519 			  __func__);
2520 
2521 	if (test_pktmbuf_copy(pinned_pool, std_pool) < 0)
2522 		GOTO_FAIL("%s: test_pktmbuf_copy(pinned) failed\n",
2523 			  __func__);
2524 
2525 	if (test_failing_mbuf_sanity_check(pinned_pool) < 0)
2526 		GOTO_FAIL("%s: test_failing_mbuf_sanity_check(pinned)"
2527 			  " failed\n", __func__);
2528 
2529 	if (test_mbuf_linearize_check(pinned_pool) < 0)
2530 		GOTO_FAIL("%s: test_mbuf_linearize_check(pinned) failed\n",
2531 			  __func__);
2532 
2533 	/* test for allocating a bulk of mbufs with various sizes */
2534 	if (test_pktmbuf_alloc_bulk(pinned_pool) < 0)
2535 		GOTO_FAIL("%s: test_rte_pktmbuf_alloc_bulk(pinned) failed\n",
2536 			  __func__);
2537 
2538 	/* test for allocating a bulk of mbufs with various sizes */
2539 	if (test_neg_pktmbuf_alloc_bulk(pinned_pool) < 0)
2540 		GOTO_FAIL("%s: test_neg_rte_pktmbuf_alloc_bulk(pinned)"
2541 			  " failed\n", __func__);
2542 
2543 	/* test to read mbuf packet */
2544 	if (test_pktmbuf_read(pinned_pool) < 0)
2545 		GOTO_FAIL("%s: test_rte_pktmbuf_read(pinned) failed\n",
2546 			  __func__);
2547 
2548 	/* test to read mbuf packet from offset */
2549 	if (test_pktmbuf_read_from_offset(pinned_pool) < 0)
2550 		GOTO_FAIL("%s: test_rte_pktmbuf_read_from_offset(pinned)"
2551 			  " failed\n", __func__);
2552 
2553 	/* test to read data from chain of mbufs with data segments */
2554 	if (test_pktmbuf_read_from_chain(pinned_pool) < 0)
2555 		GOTO_FAIL("%s: test_rte_pktmbuf_read_from_chain(pinned)"
2556 			  " failed\n", __func__);
2557 
2558 	RTE_SET_USED(std_pool);
2559 	rte_mempool_free(pinned_pool);
2560 	rte_memzone_free(mz);
2561 	return 0;
2562 
2563 fail:
2564 	rte_mempool_free(pinned_pool);
2565 	rte_memzone_free(mz);
2566 	return -1;
2567 }
2568 
2569 static int
2570 test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
2571 {
2572 	const struct rte_mbuf_dynfield dynfield = {
2573 		.name = "test-dynfield",
2574 		.size = sizeof(uint8_t),
2575 		.align = __alignof__(uint8_t),
2576 		.flags = 0,
2577 	};
2578 	const struct rte_mbuf_dynfield dynfield2 = {
2579 		.name = "test-dynfield2",
2580 		.size = sizeof(uint16_t),
2581 		.align = __alignof__(uint16_t),
2582 		.flags = 0,
2583 	};
2584 	const struct rte_mbuf_dynfield dynfield3 = {
2585 		.name = "test-dynfield3",
2586 		.size = sizeof(uint8_t),
2587 		.align = __alignof__(uint8_t),
2588 		.flags = 0,
2589 	};
2590 	const struct rte_mbuf_dynfield dynfield_fail_big = {
2591 		.name = "test-dynfield-fail-big",
2592 		.size = 256,
2593 		.align = 1,
2594 		.flags = 0,
2595 	};
2596 	const struct rte_mbuf_dynfield dynfield_fail_align = {
2597 		.name = "test-dynfield-fail-align",
2598 		.size = 1,
2599 		.align = 3,
2600 		.flags = 0,
2601 	};
2602 	const struct rte_mbuf_dynfield dynfield_fail_flag = {
2603 		.name = "test-dynfield",
2604 		.size = sizeof(uint8_t),
2605 		.align = __alignof__(uint8_t),
2606 		.flags = 1,
2607 	};
2608 	const struct rte_mbuf_dynflag dynflag_fail_flag = {
2609 		.name = "test-dynflag",
2610 		.flags = 1,
2611 	};
2612 	const struct rte_mbuf_dynflag dynflag = {
2613 		.name = "test-dynflag",
2614 		.flags = 0,
2615 	};
2616 	const struct rte_mbuf_dynflag dynflag2 = {
2617 		.name = "test-dynflag2",
2618 		.flags = 0,
2619 	};
2620 	const struct rte_mbuf_dynflag dynflag3 = {
2621 		.name = "test-dynflag3",
2622 		.flags = 0,
2623 	};
2624 	struct rte_mbuf *m = NULL;
2625 	int offset, offset2, offset3;
2626 	int flag, flag2, flag3;
2627 	int ret;
2628 
2629 	printf("Test mbuf dynamic fields and flags\n");
2630 	rte_mbuf_dyn_dump(stdout);
2631 
2632 	offset = rte_mbuf_dynfield_register(&dynfield);
2633 	if (offset == -1)
2634 		GOTO_FAIL("failed to register dynamic field, offset=%d: %s",
2635 			offset, strerror(errno));
2636 
2637 	ret = rte_mbuf_dynfield_register(&dynfield);
2638 	if (ret != offset)
2639 		GOTO_FAIL("failed to lookup dynamic field, ret=%d: %s",
2640 			ret, strerror(errno));
2641 
2642 	offset2 = rte_mbuf_dynfield_register(&dynfield2);
2643 	if (offset2 == -1 || offset2 == offset || (offset2 & 1))
2644 		GOTO_FAIL("failed to register dynamic field 2, offset2=%d: %s",
2645 			offset2, strerror(errno));
2646 
2647 	offset3 = rte_mbuf_dynfield_register_offset(&dynfield3,
2648 				offsetof(struct rte_mbuf, dynfield1[1]));
2649 	if (offset3 != offsetof(struct rte_mbuf, dynfield1[1])) {
2650 		if (rte_errno == EBUSY)
2651 			printf("mbuf test error skipped: dynfield is busy\n");
2652 		else
2653 			GOTO_FAIL("failed to register dynamic field 3, offset="
2654 				"%d: %s", offset3, strerror(errno));
2655 	}
2656 
2657 	printf("dynfield: offset=%d, offset2=%d, offset3=%d\n",
2658 		offset, offset2, offset3);
2659 
2660 	ret = rte_mbuf_dynfield_register(&dynfield_fail_big);
2661 	if (ret != -1)
2662 		GOTO_FAIL("dynamic field creation should fail (too big)");
2663 
2664 	ret = rte_mbuf_dynfield_register(&dynfield_fail_align);
2665 	if (ret != -1)
2666 		GOTO_FAIL("dynamic field creation should fail (bad alignment)");
2667 
2668 	ret = rte_mbuf_dynfield_register_offset(&dynfield_fail_align,
2669 				offsetof(struct rte_mbuf, ol_flags));
2670 	if (ret != -1)
2671 		GOTO_FAIL("dynamic field creation should fail (not avail)");
2672 
2673 	ret = rte_mbuf_dynfield_register(&dynfield_fail_flag);
2674 	if (ret != -1)
2675 		GOTO_FAIL("dynamic field creation should fail (invalid flag)");
2676 
2677 	ret = rte_mbuf_dynflag_register(&dynflag_fail_flag);
2678 	if (ret != -1)
2679 		GOTO_FAIL("dynamic flag creation should fail (invalid flag)");
2680 
2681 	flag = rte_mbuf_dynflag_register(&dynflag);
2682 	if (flag == -1)
2683 		GOTO_FAIL("failed to register dynamic flag, flag=%d: %s",
2684 			flag, strerror(errno));
2685 
2686 	ret = rte_mbuf_dynflag_register(&dynflag);
2687 	if (ret != flag)
2688 		GOTO_FAIL("failed to lookup dynamic flag, ret=%d: %s",
2689 			ret, strerror(errno));
2690 
2691 	flag2 = rte_mbuf_dynflag_register(&dynflag2);
2692 	if (flag2 == -1 || flag2 == flag)
2693 		GOTO_FAIL("failed to register dynamic flag 2, flag2=%d: %s",
2694 			flag2, strerror(errno));
2695 
2696 	flag3 = rte_mbuf_dynflag_register_bitnum(&dynflag3,
2697 						rte_bsf64(RTE_MBUF_F_LAST_FREE));
2698 	if (flag3 != rte_bsf64(RTE_MBUF_F_LAST_FREE))
2699 		GOTO_FAIL("failed to register dynamic flag 3, flag3=%d: %s",
2700 			flag3, strerror(errno));
2701 
2702 	printf("dynflag: flag=%d, flag2=%d, flag3=%d\n", flag, flag2, flag3);
2703 
2704 	/* set, get dynamic field */
2705 	m = rte_pktmbuf_alloc(pktmbuf_pool);
2706 	if (m == NULL)
2707 		GOTO_FAIL("Cannot allocate mbuf");
2708 
2709 	*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) = 1;
2710 	if (*RTE_MBUF_DYNFIELD(m, offset, uint8_t *) != 1)
2711 		GOTO_FAIL("failed to read dynamic field");
2712 	*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) = 1000;
2713 	if (*RTE_MBUF_DYNFIELD(m, offset2, uint16_t *) != 1000)
2714 		GOTO_FAIL("failed to read dynamic field");
2715 
2716 	/* set a dynamic flag */
2717 	m->ol_flags |= (1ULL << flag);
2718 
2719 	rte_mbuf_dyn_dump(stdout);
2720 	rte_pktmbuf_free(m);
2721 	return 0;
2722 fail:
2723 	rte_pktmbuf_free(m);
2724 	return -1;
2725 }
2726 
2727 /* check that m->nb_segs and m->next are reset on mbuf free */
2728 static int
2729 test_nb_segs_and_next_reset(void)
2730 {
2731 	struct rte_mbuf *m0 = NULL, *m1 = NULL, *m2 = NULL;
2732 	struct rte_mempool *pool = NULL;
2733 
2734 	pool = rte_pktmbuf_pool_create("test_mbuf_reset",
2735 			3, 0, 0, MBUF_DATA_SIZE, SOCKET_ID_ANY);
2736 	if (pool == NULL)
2737 		GOTO_FAIL("Failed to create mbuf pool");
2738 
2739 	/* alloc mbufs */
2740 	m0 = rte_pktmbuf_alloc(pool);
2741 	m1 = rte_pktmbuf_alloc(pool);
2742 	m2 = rte_pktmbuf_alloc(pool);
2743 	if (m0 == NULL || m1 == NULL || m2 == NULL)
2744 		GOTO_FAIL("Failed to allocate mbuf");
2745 
2746 	/* append data in all of them */
2747 	if (rte_pktmbuf_append(m0, 500) == NULL ||
2748 			rte_pktmbuf_append(m1, 500) == NULL ||
2749 			rte_pktmbuf_append(m2, 500) == NULL)
2750 		GOTO_FAIL("Failed to append data in mbuf");
2751 
2752 	/* chain them in one mbuf m0 */
2753 	rte_pktmbuf_chain(m1, m2);
2754 	rte_pktmbuf_chain(m0, m1);
2755 	if (m0->nb_segs != 3 || m0->next != m1 || m1->next != m2 ||
2756 			m2->next != NULL) {
2757 		m1 = m2 = NULL;
2758 		GOTO_FAIL("Failed to chain mbufs");
2759 	}
2760 
2761 	/* split m0 chain in two, between m1 and m2 */
2762 	m0->nb_segs = 2;
2763 	m1->next = NULL;
2764 	m2->nb_segs = 1;
2765 
2766 	/* free the 2 mbuf chains m0 and m2  */
2767 	rte_pktmbuf_free(m0);
2768 	rte_pktmbuf_free(m2);
2769 
2770 	/* realloc the 3 mbufs */
2771 	m0 = rte_mbuf_raw_alloc(pool);
2772 	m1 = rte_mbuf_raw_alloc(pool);
2773 	m2 = rte_mbuf_raw_alloc(pool);
2774 	if (m0 == NULL || m1 == NULL || m2 == NULL)
2775 		GOTO_FAIL("Failed to reallocate mbuf");
2776 
2777 	/* ensure that m->next and m->nb_segs are reset allocated mbufs */
2778 	if (m0->nb_segs != 1 || m0->next != NULL ||
2779 			m1->nb_segs != 1 || m1->next != NULL ||
2780 			m2->nb_segs != 1 || m2->next != NULL)
2781 		GOTO_FAIL("nb_segs or next was not reset properly");
2782 
2783 	return 0;
2784 
2785 fail:
2786 	if (pool != NULL)
2787 		rte_mempool_free(pool);
2788 	return -1;
2789 }
2790 
2791 static int
2792 test_mbuf(void)
2793 {
2794 	int ret = -1;
2795 	struct rte_mempool *pktmbuf_pool = NULL;
2796 	struct rte_mempool *pktmbuf_pool2 = NULL;
2797 
2798 
2799 	RTE_BUILD_BUG_ON(sizeof(struct rte_mbuf) != RTE_CACHE_LINE_MIN_SIZE * 2);
2800 
2801 	/* create pktmbuf pool if it does not exist */
2802 	pktmbuf_pool = rte_pktmbuf_pool_create("test_pktmbuf_pool",
2803 			NB_MBUF, MEMPOOL_CACHE_SIZE, 0, MBUF_DATA_SIZE,
2804 			SOCKET_ID_ANY);
2805 
2806 	if (pktmbuf_pool == NULL) {
2807 		printf("cannot allocate mbuf pool\n");
2808 		goto err;
2809 	}
2810 
2811 	/* test registration of dynamic fields and flags */
2812 	if (test_mbuf_dyn(pktmbuf_pool) < 0) {
2813 		printf("mbuf dynflag test failed\n");
2814 		goto err;
2815 	}
2816 
2817 	/* create a specific pktmbuf pool with a priv_size != 0 and no data
2818 	 * room size */
2819 	pktmbuf_pool2 = rte_pktmbuf_pool_create("test_pktmbuf_pool2",
2820 			NB_MBUF, MEMPOOL_CACHE_SIZE, MBUF2_PRIV_SIZE, 0,
2821 			SOCKET_ID_ANY);
2822 
2823 	if (pktmbuf_pool2 == NULL) {
2824 		printf("cannot allocate mbuf pool\n");
2825 		goto err;
2826 	}
2827 
2828 	/* test multiple mbuf alloc */
2829 	if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
2830 		printf("test_mbuf_pool() failed\n");
2831 		goto err;
2832 	}
2833 
2834 	/* do it another time to check that all mbufs were freed */
2835 	if (test_pktmbuf_pool(pktmbuf_pool) < 0) {
2836 		printf("test_mbuf_pool() failed (2)\n");
2837 		goto err;
2838 	}
2839 
2840 	/* test bulk mbuf alloc and free */
2841 	if (test_pktmbuf_pool_bulk() < 0) {
2842 		printf("test_pktmbuf_pool_bulk() failed\n");
2843 		goto err;
2844 	}
2845 
2846 	/* test that the pointer to the data on a packet mbuf is set properly */
2847 	if (test_pktmbuf_pool_ptr(pktmbuf_pool) < 0) {
2848 		printf("test_pktmbuf_pool_ptr() failed\n");
2849 		goto err;
2850 	}
2851 
2852 	/* test data manipulation in mbuf */
2853 	if (test_one_pktmbuf(pktmbuf_pool) < 0) {
2854 		printf("test_one_mbuf() failed\n");
2855 		goto err;
2856 	}
2857 
2858 
2859 	/*
2860 	 * do it another time, to check that allocation reinitialize
2861 	 * the mbuf correctly
2862 	 */
2863 	if (test_one_pktmbuf(pktmbuf_pool) < 0) {
2864 		printf("test_one_mbuf() failed (2)\n");
2865 		goto err;
2866 	}
2867 
2868 	if (test_pktmbuf_with_non_ascii_data(pktmbuf_pool) < 0) {
2869 		printf("test_pktmbuf_with_non_ascii_data() failed\n");
2870 		goto err;
2871 	}
2872 
2873 	/* test free pktmbuf segment one by one */
2874 	if (test_pktmbuf_free_segment(pktmbuf_pool) < 0) {
2875 		printf("test_pktmbuf_free_segment() failed.\n");
2876 		goto err;
2877 	}
2878 
2879 	if (testclone_testupdate_testdetach(pktmbuf_pool, pktmbuf_pool) < 0) {
2880 		printf("testclone_and_testupdate() failed \n");
2881 		goto err;
2882 	}
2883 
2884 	if (test_pktmbuf_copy(pktmbuf_pool, pktmbuf_pool) < 0) {
2885 		printf("test_pktmbuf_copy() failed\n");
2886 		goto err;
2887 	}
2888 
2889 	if (test_attach_from_different_pool(pktmbuf_pool, pktmbuf_pool2) < 0) {
2890 		printf("test_attach_from_different_pool() failed\n");
2891 		goto err;
2892 	}
2893 
2894 	if (test_refcnt_mbuf() < 0) {
2895 		printf("test_refcnt_mbuf() failed \n");
2896 		goto err;
2897 	}
2898 
2899 	if (test_failing_mbuf_sanity_check(pktmbuf_pool) < 0) {
2900 		printf("test_failing_mbuf_sanity_check() failed\n");
2901 		goto err;
2902 	}
2903 
2904 	if (test_mbuf_linearize_check(pktmbuf_pool) < 0) {
2905 		printf("test_mbuf_linearize_check() failed\n");
2906 		goto err;
2907 	}
2908 
2909 	if (test_tx_offload() < 0) {
2910 		printf("test_tx_offload() failed\n");
2911 		goto err;
2912 	}
2913 
2914 	if (test_get_rx_ol_flag_list() < 0) {
2915 		printf("test_rte_get_rx_ol_flag_list() failed\n");
2916 		goto err;
2917 	}
2918 
2919 	if (test_get_tx_ol_flag_list() < 0) {
2920 		printf("test_rte_get_tx_ol_flag_list() failed\n");
2921 		goto err;
2922 	}
2923 
2924 	if (test_get_rx_ol_flag_name() < 0) {
2925 		printf("test_rte_get_rx_ol_flag_name() failed\n");
2926 		goto err;
2927 	}
2928 
2929 	if (test_get_tx_ol_flag_name() < 0) {
2930 		printf("test_rte_get_tx_ol_flag_name() failed\n");
2931 		goto err;
2932 	}
2933 
2934 	if (test_mbuf_validate_tx_offload_one(pktmbuf_pool) < 0) {
2935 		printf("test_mbuf_validate_tx_offload_one() failed\n");
2936 		goto err;
2937 	}
2938 
2939 	/* test for allocating a bulk of mbufs with various sizes */
2940 	if (test_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
2941 		printf("test_rte_pktmbuf_alloc_bulk() failed\n");
2942 		goto err;
2943 	}
2944 
2945 	/* test for allocating a bulk of mbufs with various sizes */
2946 	if (test_neg_pktmbuf_alloc_bulk(pktmbuf_pool) < 0) {
2947 		printf("test_neg_rte_pktmbuf_alloc_bulk() failed\n");
2948 		goto err;
2949 	}
2950 
2951 	/* test to read mbuf packet */
2952 	if (test_pktmbuf_read(pktmbuf_pool) < 0) {
2953 		printf("test_rte_pktmbuf_read() failed\n");
2954 		goto err;
2955 	}
2956 
2957 	/* test to read mbuf packet from offset */
2958 	if (test_pktmbuf_read_from_offset(pktmbuf_pool) < 0) {
2959 		printf("test_rte_pktmbuf_read_from_offset() failed\n");
2960 		goto err;
2961 	}
2962 
2963 	/* test to read data from chain of mbufs with data segments */
2964 	if (test_pktmbuf_read_from_chain(pktmbuf_pool) < 0) {
2965 		printf("test_rte_pktmbuf_read_from_chain() failed\n");
2966 		goto err;
2967 	}
2968 
2969 	/* test to initialize shared info. at the end of external buffer */
2970 	if (test_pktmbuf_ext_shinfo_init_helper(pktmbuf_pool) < 0) {
2971 		printf("test_pktmbuf_ext_shinfo_init_helper() failed\n");
2972 		goto err;
2973 	}
2974 
2975 	/* test the mbuf pool with pinned external data buffers */
2976 	if (test_pktmbuf_ext_pinned_buffer(pktmbuf_pool) < 0) {
2977 		printf("test_pktmbuf_ext_pinned_buffer() failed\n");
2978 		goto err;
2979 	}
2980 
2981 	/* test reset of m->nb_segs and m->next on mbuf free */
2982 	if (test_nb_segs_and_next_reset() < 0) {
2983 		printf("test_nb_segs_and_next_reset() failed\n");
2984 		goto err;
2985 	}
2986 
2987 	ret = 0;
2988 err:
2989 	rte_mempool_free(pktmbuf_pool);
2990 	rte_mempool_free(pktmbuf_pool2);
2991 	return ret;
2992 }
2993 #undef GOTO_FAIL
2994 
2995 REGISTER_TEST_COMMAND(mbuf_autotest, test_mbuf);
2996