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