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