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