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