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