1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 6 #include <stdio.h> 7 #include <inttypes.h> 8 #include <signal.h> 9 #include <unistd.h> 10 #include <rte_cycles.h> 11 #include <rte_ethdev.h> 12 #include <rte_byteorder.h> 13 #include <rte_atomic.h> 14 #include <rte_malloc.h> 15 #include "packet_burst_generator.h" 16 #include "test.h" 17 18 #define NB_ETHPORTS_USED (1) 19 #define NB_SOCKETS (2) 20 #define MEMPOOL_CACHE_SIZE 250 21 #define MAX_PKT_BURST (32) 22 #define RTE_TEST_RX_DESC_DEFAULT (1024) 23 #define RTE_TEST_TX_DESC_DEFAULT (1024) 24 #define RTE_PORT_ALL (~(uint16_t)0x0) 25 26 /* how long test would take at full line rate */ 27 #define RTE_TEST_DURATION (2) 28 29 /* 30 * RX and TX Prefetch, Host, and Write-back threshold values should be 31 * carefully set for optimal performance. Consult the network 32 * controller's datasheet and supporting DPDK documentation for guidance 33 * on how these parameters should be set. 34 */ 35 #define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */ 36 #define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */ 37 #define RX_WTHRESH 0 /**< Default values of RX write-back threshold reg. */ 38 39 /* 40 * These default values are optimized for use with the Intel(R) 82599 10 GbE 41 * Controller and the DPDK ixgbe PMD. Consider using other values for other 42 * network controllers and/or network drivers. 43 */ 44 #define TX_PTHRESH 32 /**< Default values of TX prefetch threshold reg. */ 45 #define TX_HTHRESH 0 /**< Default values of TX host threshold reg. */ 46 #define TX_WTHRESH 0 /**< Default values of TX write-back threshold reg. */ 47 48 #define MAX_TRAFFIC_BURST 2048 49 50 #define NB_MBUF RTE_MAX( \ 51 (unsigned)(nb_ports*nb_rx_queue*nb_rxd + \ 52 nb_ports*nb_lcores*MAX_PKT_BURST + \ 53 nb_ports*nb_tx_queue*nb_txd + \ 54 nb_lcores*MEMPOOL_CACHE_SIZE + \ 55 nb_ports*MAX_TRAFFIC_BURST), \ 56 (unsigned)8192) 57 58 59 static struct rte_mempool *mbufpool[NB_SOCKETS]; 60 /* ethernet addresses of ports */ 61 static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 62 63 static struct rte_eth_conf port_conf = { 64 .rxmode = { 65 .mq_mode = ETH_MQ_RX_NONE, 66 .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 67 .split_hdr_size = 0, 68 }, 69 .txmode = { 70 .mq_mode = ETH_MQ_TX_NONE, 71 }, 72 .lpbk_mode = 1, /* enable loopback */ 73 }; 74 75 static struct rte_eth_rxconf rx_conf = { 76 .rx_thresh = { 77 .pthresh = RX_PTHRESH, 78 .hthresh = RX_HTHRESH, 79 .wthresh = RX_WTHRESH, 80 }, 81 .rx_free_thresh = 32, 82 }; 83 84 static struct rte_eth_txconf tx_conf = { 85 .tx_thresh = { 86 .pthresh = TX_PTHRESH, 87 .hthresh = TX_HTHRESH, 88 .wthresh = TX_WTHRESH, 89 }, 90 .tx_free_thresh = 32, /* Use PMD default values */ 91 .tx_rs_thresh = 32, /* Use PMD default values */ 92 }; 93 94 enum { 95 LCORE_INVALID = 0, 96 LCORE_AVAIL, 97 LCORE_USED, 98 }; 99 100 struct lcore_conf { 101 uint8_t status; 102 uint8_t socketid; 103 uint16_t nb_ports; 104 uint16_t portlist[RTE_MAX_ETHPORTS]; 105 } __rte_cache_aligned; 106 107 struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 108 109 static uint64_t link_mbps; 110 111 enum { 112 SC_CONTINUOUS = 0, 113 SC_BURST_POLL_FIRST, 114 SC_BURST_XMIT_FIRST, 115 }; 116 117 static uint32_t sc_flag; 118 119 /* Check the link status of all ports in up to 3s, and print them finally */ 120 static void 121 check_all_ports_link_status(uint16_t port_num, uint32_t port_mask) 122 { 123 #define CHECK_INTERVAL 100 /* 100ms */ 124 #define MAX_CHECK_TIME 30 /* 3s (30 * 100ms) in total */ 125 uint16_t portid; 126 uint8_t count, all_ports_up, print_flag = 0; 127 struct rte_eth_link link; 128 129 printf("Checking link statuses...\n"); 130 fflush(stdout); 131 for (count = 0; count <= MAX_CHECK_TIME; count++) { 132 all_ports_up = 1; 133 for (portid = 0; portid < port_num; portid++) { 134 if ((port_mask & (1 << portid)) == 0) 135 continue; 136 memset(&link, 0, sizeof(link)); 137 rte_eth_link_get_nowait(portid, &link); 138 /* print link status if flag set */ 139 if (print_flag == 1) { 140 if (link.link_status) { 141 printf( 142 "Port%d Link Up. Speed %u Mbps - %s\n", 143 portid, link.link_speed, 144 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 145 ("full-duplex") : ("half-duplex\n")); 146 if (link_mbps == 0) 147 link_mbps = link.link_speed; 148 } else 149 printf("Port %d Link Down\n", portid); 150 continue; 151 } 152 /* clear all_ports_up flag if any link down */ 153 if (link.link_status == ETH_LINK_DOWN) { 154 all_ports_up = 0; 155 break; 156 } 157 } 158 /* after finally printing all link status, get out */ 159 if (print_flag == 1) 160 break; 161 162 if (all_ports_up == 0) { 163 fflush(stdout); 164 rte_delay_ms(CHECK_INTERVAL); 165 } 166 167 /* set the print_flag if all ports up or timeout */ 168 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) 169 print_flag = 1; 170 } 171 } 172 173 static void 174 print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 175 { 176 char buf[RTE_ETHER_ADDR_FMT_SIZE]; 177 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 178 printf("%s%s", name, buf); 179 } 180 181 static int 182 init_traffic(struct rte_mempool *mp, 183 struct rte_mbuf **pkts_burst, uint32_t burst_size) 184 { 185 struct rte_ether_hdr pkt_eth_hdr; 186 struct rte_ipv4_hdr pkt_ipv4_hdr; 187 struct rte_udp_hdr pkt_udp_hdr; 188 uint32_t pktlen; 189 static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF }; 190 static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA }; 191 192 193 initialize_eth_header(&pkt_eth_hdr, 194 (struct rte_ether_addr *)src_mac, 195 (struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPv4, 0, 0); 196 197 pktlen = initialize_ipv4_header(&pkt_ipv4_hdr, 198 IPV4_ADDR(10, 0, 0, 1), 199 IPV4_ADDR(10, 0, 0, 2), 26); 200 printf("IPv4 pktlen %u\n", pktlen); 201 202 pktlen = initialize_udp_header(&pkt_udp_hdr, 0, 0, 18); 203 204 printf("UDP pktlen %u\n", pktlen); 205 206 return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr, 207 0, &pkt_ipv4_hdr, 1, 208 &pkt_udp_hdr, burst_size, 209 PACKET_BURST_GEN_PKT_LEN, 1); 210 } 211 212 static int 213 init_lcores(void) 214 { 215 unsigned lcore_id; 216 217 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 218 lcore_conf[lcore_id].socketid = 219 rte_lcore_to_socket_id(lcore_id); 220 if (rte_lcore_is_enabled(lcore_id) == 0) { 221 lcore_conf[lcore_id].status = LCORE_INVALID; 222 continue; 223 } else 224 lcore_conf[lcore_id].status = LCORE_AVAIL; 225 } 226 return 0; 227 } 228 229 static int 230 init_mbufpool(unsigned nb_mbuf) 231 { 232 int socketid; 233 unsigned lcore_id; 234 char s[64]; 235 236 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 237 if (rte_lcore_is_enabled(lcore_id) == 0) 238 continue; 239 240 socketid = rte_lcore_to_socket_id(lcore_id); 241 if (socketid >= NB_SOCKETS) { 242 rte_exit(EXIT_FAILURE, 243 "Socket %d of lcore %u is out of range %d\n", 244 socketid, lcore_id, NB_SOCKETS); 245 } 246 if (mbufpool[socketid] == NULL) { 247 snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); 248 mbufpool[socketid] = 249 rte_pktmbuf_pool_create(s, nb_mbuf, 250 MEMPOOL_CACHE_SIZE, 0, 251 RTE_MBUF_DEFAULT_BUF_SIZE, socketid); 252 if (mbufpool[socketid] == NULL) 253 rte_exit(EXIT_FAILURE, 254 "Cannot init mbuf pool on socket %d\n", 255 socketid); 256 else 257 printf("Allocated mbuf pool on socket %d\n", 258 socketid); 259 } 260 } 261 return 0; 262 } 263 264 static uint16_t 265 alloc_lcore(uint16_t socketid) 266 { 267 unsigned lcore_id; 268 269 for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 270 if (LCORE_AVAIL != lcore_conf[lcore_id].status || 271 lcore_conf[lcore_id].socketid != socketid || 272 lcore_id == rte_get_master_lcore()) 273 continue; 274 lcore_conf[lcore_id].status = LCORE_USED; 275 lcore_conf[lcore_id].nb_ports = 0; 276 return lcore_id; 277 } 278 279 return (uint16_t)-1; 280 } 281 282 static volatile uint64_t stop; 283 static uint64_t count; 284 static uint64_t drop; 285 static uint64_t idle; 286 287 static void 288 reset_count(void) 289 { 290 count = 0; 291 drop = 0; 292 idle = 0; 293 } 294 295 static void 296 stats_display(uint16_t port_id) 297 { 298 struct rte_eth_stats stats; 299 rte_eth_stats_get(port_id, &stats); 300 301 printf(" RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: " 302 "%-"PRIu64"\n", 303 stats.ipackets, stats.imissed, stats.ibytes); 304 printf(" RX-errors: %-10"PRIu64" RX-nombuf: %-10"PRIu64"\n", 305 stats.ierrors, stats.rx_nombuf); 306 printf(" TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: " 307 "%-"PRIu64"\n", 308 stats.opackets, stats.oerrors, stats.obytes); 309 } 310 311 static void 312 signal_handler(int signum) 313 { 314 /* USR1 signal, stop testing */ 315 if (signum == SIGUSR1) { 316 printf("Force Stop!\n"); 317 stop = 1; 318 } 319 320 /* USR2 signal, print stats */ 321 if (signum == SIGUSR2) 322 stats_display(0); 323 } 324 325 struct rte_mbuf **tx_burst; 326 327 uint64_t (*do_measure)(struct lcore_conf *conf, 328 struct rte_mbuf *pkts_burst[], 329 uint64_t total_pkts); 330 331 static uint64_t 332 measure_rxtx(struct lcore_conf *conf, 333 struct rte_mbuf *pkts_burst[], 334 uint64_t total_pkts) 335 { 336 unsigned i, portid, nb_rx, nb_tx; 337 uint64_t prev_tsc, cur_tsc; 338 339 prev_tsc = rte_rdtsc(); 340 341 while (likely(!stop)) { 342 for (i = 0; i < conf->nb_ports; i++) { 343 portid = conf->portlist[i]; 344 nb_rx = rte_eth_rx_burst(portid, 0, 345 pkts_burst, MAX_PKT_BURST); 346 if (unlikely(nb_rx == 0)) { 347 idle++; 348 continue; 349 } 350 351 count += nb_rx; 352 nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx); 353 if (unlikely(nb_tx < nb_rx)) { 354 drop += (nb_rx - nb_tx); 355 do { 356 rte_pktmbuf_free(pkts_burst[nb_tx]); 357 } while (++nb_tx < nb_rx); 358 } 359 } 360 if (unlikely(count >= total_pkts)) 361 break; 362 } 363 364 cur_tsc = rte_rdtsc(); 365 366 return cur_tsc - prev_tsc; 367 } 368 369 static uint64_t 370 measure_rxonly(struct lcore_conf *conf, 371 struct rte_mbuf *pkts_burst[], 372 uint64_t total_pkts) 373 { 374 unsigned i, portid, nb_rx, nb_tx; 375 uint64_t diff_tsc, cur_tsc; 376 377 diff_tsc = 0; 378 while (likely(!stop)) { 379 for (i = 0; i < conf->nb_ports; i++) { 380 portid = conf->portlist[i]; 381 382 cur_tsc = rte_rdtsc(); 383 nb_rx = rte_eth_rx_burst(portid, 0, 384 pkts_burst, MAX_PKT_BURST); 385 if (unlikely(nb_rx == 0)) { 386 idle++; 387 continue; 388 } 389 diff_tsc += rte_rdtsc() - cur_tsc; 390 391 count += nb_rx; 392 nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx); 393 if (unlikely(nb_tx < nb_rx)) { 394 drop += (nb_rx - nb_tx); 395 do { 396 rte_pktmbuf_free(pkts_burst[nb_tx]); 397 } while (++nb_tx < nb_rx); 398 } 399 } 400 if (unlikely(count >= total_pkts)) 401 break; 402 } 403 404 return diff_tsc; 405 } 406 407 static uint64_t 408 measure_txonly(struct lcore_conf *conf, 409 struct rte_mbuf *pkts_burst[], 410 uint64_t total_pkts) 411 { 412 unsigned i, portid, nb_rx, nb_tx; 413 uint64_t diff_tsc, cur_tsc; 414 415 printf("do tx measure\n"); 416 diff_tsc = 0; 417 while (likely(!stop)) { 418 for (i = 0; i < conf->nb_ports; i++) { 419 portid = conf->portlist[i]; 420 nb_rx = rte_eth_rx_burst(portid, 0, 421 pkts_burst, MAX_PKT_BURST); 422 if (unlikely(nb_rx == 0)) { 423 idle++; 424 continue; 425 } 426 427 count += nb_rx; 428 429 cur_tsc = rte_rdtsc(); 430 nb_tx = rte_eth_tx_burst(portid, 0, pkts_burst, nb_rx); 431 if (unlikely(nb_tx < nb_rx)) { 432 drop += (nb_rx - nb_tx); 433 do { 434 rte_pktmbuf_free(pkts_burst[nb_tx]); 435 } while (++nb_tx < nb_rx); 436 } 437 diff_tsc += rte_rdtsc() - cur_tsc; 438 } 439 if (unlikely(count >= total_pkts)) 440 break; 441 } 442 443 return diff_tsc; 444 } 445 446 /* main processing loop */ 447 static int 448 main_loop(__rte_unused void *args) 449 { 450 #define PACKET_SIZE 64 451 #define FRAME_GAP 12 452 #define MAC_PREAMBLE 8 453 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 454 unsigned lcore_id; 455 unsigned i, portid, nb_rx = 0, nb_tx = 0; 456 struct lcore_conf *conf; 457 int pkt_per_port; 458 uint64_t diff_tsc; 459 uint64_t packets_per_second, total_packets; 460 461 lcore_id = rte_lcore_id(); 462 conf = &lcore_conf[lcore_id]; 463 if (conf->status != LCORE_USED) 464 return 0; 465 466 pkt_per_port = MAX_TRAFFIC_BURST; 467 468 int idx = 0; 469 for (i = 0; i < conf->nb_ports; i++) { 470 int num = pkt_per_port; 471 portid = conf->portlist[i]; 472 printf("inject %d packet to port %d\n", num, portid); 473 while (num) { 474 nb_tx = RTE_MIN(MAX_PKT_BURST, num); 475 nb_tx = rte_eth_tx_burst(portid, 0, 476 &tx_burst[idx], nb_tx); 477 num -= nb_tx; 478 idx += nb_tx; 479 } 480 } 481 printf("Total packets inject to prime ports = %u\n", idx); 482 483 packets_per_second = (link_mbps * 1000 * 1000) / 484 ((PACKET_SIZE + FRAME_GAP + MAC_PREAMBLE) * CHAR_BIT); 485 printf("Each port will do %"PRIu64" packets per second\n", 486 packets_per_second); 487 488 total_packets = RTE_TEST_DURATION * conf->nb_ports * packets_per_second; 489 printf("Test will stop after at least %"PRIu64" packets received\n", 490 + total_packets); 491 492 diff_tsc = do_measure(conf, pkts_burst, total_packets); 493 494 for (i = 0; i < conf->nb_ports; i++) { 495 portid = conf->portlist[i]; 496 int nb_free = 0; 497 uint64_t timeout = 10000; 498 do { /* dry out */ 499 nb_rx = rte_eth_rx_burst(portid, 0, 500 pkts_burst, MAX_PKT_BURST); 501 nb_tx = 0; 502 while (nb_tx < nb_rx) 503 rte_pktmbuf_free(pkts_burst[nb_tx++]); 504 nb_free += nb_rx; 505 506 if (unlikely(nb_rx == 0)) 507 timeout--; 508 } while (nb_free != pkt_per_port && timeout != 0); 509 printf("free %d (expected %d) mbuf left in port %u\n", nb_free, 510 pkt_per_port, portid); 511 } 512 513 if (count == 0) 514 return -1; 515 516 printf("%"PRIu64" packet, %"PRIu64" drop, %"PRIu64" idle\n", 517 count, drop, idle); 518 printf("Result: %"PRIu64" cycles per packet\n", diff_tsc / count); 519 520 return 0; 521 } 522 523 static rte_atomic64_t start; 524 525 static inline int 526 poll_burst(void *args) 527 { 528 #define MAX_IDLE (10000) 529 unsigned lcore_id; 530 struct rte_mbuf **pkts_burst; 531 uint64_t diff_tsc, cur_tsc; 532 uint16_t next[RTE_MAX_ETHPORTS]; 533 struct lcore_conf *conf; 534 uint32_t pkt_per_port = *((uint32_t *)args); 535 unsigned i, portid, nb_rx = 0; 536 uint64_t total; 537 uint64_t timeout = MAX_IDLE; 538 int num[RTE_MAX_ETHPORTS]; 539 540 lcore_id = rte_lcore_id(); 541 conf = &lcore_conf[lcore_id]; 542 if (conf->status != LCORE_USED) 543 return 0; 544 545 total = pkt_per_port * conf->nb_ports; 546 printf("start to receive total expect %"PRIu64"\n", total); 547 548 pkts_burst = (struct rte_mbuf **) 549 rte_calloc_socket("poll_burst", 550 total, sizeof(void *), 551 RTE_CACHE_LINE_SIZE, conf->socketid); 552 if (!pkts_burst) 553 return -1; 554 555 for (i = 0; i < conf->nb_ports; i++) { 556 portid = conf->portlist[i]; 557 next[portid] = i * pkt_per_port; 558 num[portid] = pkt_per_port; 559 } 560 561 while (!rte_atomic64_read(&start)) 562 ; 563 564 cur_tsc = rte_rdtsc(); 565 while (total) { 566 for (i = 0; i < conf->nb_ports; i++) { 567 portid = conf->portlist[i]; 568 nb_rx = rte_eth_rx_burst(portid, 0, 569 &pkts_burst[next[portid]], 570 RTE_MIN(MAX_PKT_BURST, num[portid])); 571 if (unlikely(nb_rx == 0)) { 572 timeout--; 573 if (unlikely(timeout == 0)) 574 goto timeout; 575 continue; 576 } 577 next[portid] += nb_rx; 578 num[portid] -= nb_rx; 579 total -= nb_rx; 580 } 581 } 582 timeout: 583 diff_tsc = rte_rdtsc() - cur_tsc; 584 585 printf("%"PRIu64" packets lost, IDLE %"PRIu64" times\n", 586 total, MAX_IDLE - timeout); 587 /* clean up */ 588 total = pkt_per_port * conf->nb_ports - total; 589 for (i = 0; i < total; i++) 590 rte_pktmbuf_free(pkts_burst[i]); 591 592 rte_free(pkts_burst); 593 594 if (total > 0) 595 return diff_tsc / total; 596 else 597 return -1; 598 } 599 600 static int 601 exec_burst(uint32_t flags, int lcore) 602 { 603 unsigned i, portid, nb_tx = 0; 604 struct lcore_conf *conf; 605 uint32_t pkt_per_port; 606 int num, idx = 0; 607 int diff_tsc; 608 609 conf = &lcore_conf[lcore]; 610 611 pkt_per_port = MAX_TRAFFIC_BURST; 612 num = pkt_per_port * conf->nb_ports; 613 614 rte_atomic64_init(&start); 615 616 /* start polling thread, but not actually poll yet */ 617 rte_eal_remote_launch(poll_burst, 618 (void *)&pkt_per_port, lcore); 619 620 /* Only when polling first */ 621 if (flags == SC_BURST_POLL_FIRST) 622 rte_atomic64_set(&start, 1); 623 624 /* start xmit */ 625 while (num) { 626 nb_tx = RTE_MIN(MAX_PKT_BURST, num); 627 for (i = 0; i < conf->nb_ports; i++) { 628 portid = conf->portlist[i]; 629 nb_tx = rte_eth_tx_burst(portid, 0, 630 &tx_burst[idx], nb_tx); 631 idx += nb_tx; 632 num -= nb_tx; 633 } 634 635 } 636 637 sleep(5); 638 639 /* only when polling second */ 640 if (flags == SC_BURST_XMIT_FIRST) 641 rte_atomic64_set(&start, 1); 642 643 /* wait for polling finished */ 644 diff_tsc = rte_eal_wait_lcore(lcore); 645 if (diff_tsc < 0) { 646 printf("exec_burst: Failed to measure cycles per packet\n"); 647 return -1; 648 } 649 650 printf("Result: %d cycles per packet\n", diff_tsc); 651 652 return 0; 653 } 654 655 static int 656 test_pmd_perf(void) 657 { 658 uint16_t nb_ports, num, nb_lcores, slave_id = (uint16_t)-1; 659 uint16_t nb_rxd = MAX_TRAFFIC_BURST; 660 uint16_t nb_txd = MAX_TRAFFIC_BURST; 661 uint16_t portid; 662 uint16_t nb_rx_queue = 1, nb_tx_queue = 1; 663 int socketid = -1; 664 int ret; 665 666 printf("Start PMD RXTX cycles cost test.\n"); 667 668 signal(SIGUSR1, signal_handler); 669 signal(SIGUSR2, signal_handler); 670 671 nb_ports = rte_eth_dev_count_avail(); 672 if (nb_ports < NB_ETHPORTS_USED) { 673 printf("At least %u port(s) used for perf. test\n", 674 NB_ETHPORTS_USED); 675 return -1; 676 } 677 678 nb_lcores = rte_lcore_count(); 679 680 memset(lcore_conf, 0, sizeof(lcore_conf)); 681 init_lcores(); 682 683 init_mbufpool(NB_MBUF); 684 685 if (sc_flag == SC_CONTINUOUS) { 686 nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 687 nb_txd = RTE_TEST_TX_DESC_DEFAULT; 688 } 689 printf("CONFIG RXD=%d TXD=%d\n", nb_rxd, nb_txd); 690 691 reset_count(); 692 num = 0; 693 RTE_ETH_FOREACH_DEV(portid) { 694 if (socketid == -1) { 695 socketid = rte_eth_dev_socket_id(portid); 696 slave_id = alloc_lcore(socketid); 697 if (slave_id == (uint16_t)-1) { 698 printf("No avail lcore to run test\n"); 699 return -1; 700 } 701 printf("Performance test runs on lcore %u socket %u\n", 702 slave_id, socketid); 703 } 704 705 if (socketid != rte_eth_dev_socket_id(portid)) { 706 printf("Skip port %d\n", portid); 707 continue; 708 } 709 710 /* port configure */ 711 ret = rte_eth_dev_configure(portid, nb_rx_queue, 712 nb_tx_queue, &port_conf); 713 if (ret < 0) 714 rte_exit(EXIT_FAILURE, 715 "Cannot configure device: err=%d, port=%d\n", 716 ret, portid); 717 718 rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 719 printf("Port %u ", portid); 720 print_ethaddr("Address:", &ports_eth_addr[portid]); 721 printf("\n"); 722 723 /* tx queue setup */ 724 ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, 725 socketid, &tx_conf); 726 if (ret < 0) 727 rte_exit(EXIT_FAILURE, 728 "rte_eth_tx_queue_setup: err=%d, " 729 "port=%d\n", ret, portid); 730 731 /* rx queue steup */ 732 ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, 733 socketid, &rx_conf, 734 mbufpool[socketid]); 735 if (ret < 0) 736 rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup: err=%d," 737 "port=%d\n", ret, portid); 738 739 /* Start device */ 740 stop = 0; 741 ret = rte_eth_dev_start(portid); 742 if (ret < 0) 743 rte_exit(EXIT_FAILURE, 744 "rte_eth_dev_start: err=%d, port=%d\n", 745 ret, portid); 746 747 /* always eanble promiscuous */ 748 rte_eth_promiscuous_enable(portid); 749 750 lcore_conf[slave_id].portlist[num++] = portid; 751 lcore_conf[slave_id].nb_ports++; 752 } 753 check_all_ports_link_status(nb_ports, RTE_PORT_ALL); 754 755 if (tx_burst == NULL) { 756 tx_burst = (struct rte_mbuf **) 757 rte_calloc_socket("tx_buff", 758 MAX_TRAFFIC_BURST * nb_ports, 759 sizeof(void *), 760 RTE_CACHE_LINE_SIZE, socketid); 761 if (!tx_burst) 762 return -1; 763 } 764 765 init_traffic(mbufpool[socketid], 766 tx_burst, MAX_TRAFFIC_BURST * nb_ports); 767 768 printf("Generate %d packets @socket %d\n", 769 MAX_TRAFFIC_BURST * nb_ports, socketid); 770 771 if (sc_flag == SC_CONTINUOUS) { 772 /* do both rxtx by default */ 773 if (NULL == do_measure) 774 do_measure = measure_rxtx; 775 776 rte_eal_remote_launch(main_loop, NULL, slave_id); 777 778 if (rte_eal_wait_lcore(slave_id) < 0) 779 return -1; 780 } else if (sc_flag == SC_BURST_POLL_FIRST || 781 sc_flag == SC_BURST_XMIT_FIRST) 782 if (exec_burst(sc_flag, slave_id) < 0) 783 return -1; 784 785 /* port tear down */ 786 RTE_ETH_FOREACH_DEV(portid) { 787 if (socketid != rte_eth_dev_socket_id(portid)) 788 continue; 789 790 rte_eth_dev_stop(portid); 791 } 792 793 return 0; 794 } 795 796 int 797 test_set_rxtx_conf(cmdline_fixed_string_t mode) 798 { 799 printf("mode switch to %s\n", mode); 800 801 if (!strcmp(mode, "vector")) { 802 /* vector rx, tx */ 803 tx_conf.tx_rs_thresh = 32; 804 tx_conf.tx_free_thresh = 32; 805 return 0; 806 } else if (!strcmp(mode, "scalar")) { 807 /* bulk alloc rx, full-featured tx */ 808 tx_conf.tx_rs_thresh = 32; 809 tx_conf.tx_free_thresh = 32; 810 port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM; 811 return 0; 812 } else if (!strcmp(mode, "hybrid")) { 813 /* bulk alloc rx, vector tx 814 * when vec macro not define, 815 * using the same rx/tx as scalar 816 */ 817 tx_conf.tx_rs_thresh = 32; 818 tx_conf.tx_free_thresh = 32; 819 port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_CHECKSUM; 820 return 0; 821 } else if (!strcmp(mode, "full")) { 822 /* full feature rx,tx pair */ 823 tx_conf.tx_rs_thresh = 32; 824 tx_conf.tx_free_thresh = 32; 825 port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_SCATTER; 826 return 0; 827 } 828 829 return -1; 830 } 831 832 int 833 test_set_rxtx_anchor(cmdline_fixed_string_t type) 834 { 835 printf("type switch to %s\n", type); 836 837 if (!strcmp(type, "rxtx")) { 838 do_measure = measure_rxtx; 839 return 0; 840 } else if (!strcmp(type, "rxonly")) { 841 do_measure = measure_rxonly; 842 return 0; 843 } else if (!strcmp(type, "txonly")) { 844 do_measure = measure_txonly; 845 return 0; 846 } 847 848 return -1; 849 } 850 851 int 852 test_set_rxtx_sc(cmdline_fixed_string_t type) 853 { 854 printf("stream control switch to %s\n", type); 855 856 if (!strcmp(type, "continuous")) { 857 sc_flag = SC_CONTINUOUS; 858 return 0; 859 } else if (!strcmp(type, "poll_before_xmit")) { 860 sc_flag = SC_BURST_POLL_FIRST; 861 return 0; 862 } else if (!strcmp(type, "poll_after_xmit")) { 863 sc_flag = SC_BURST_XMIT_FIRST; 864 return 0; 865 } 866 867 return -1; 868 } 869 870 REGISTER_TEST_COMMAND(pmd_perf_autotest, test_pmd_perf); 871