1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2017 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 #include <stdarg.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <signal.h> 38 #include <string.h> 39 #include <time.h> 40 #include <fcntl.h> 41 #include <sys/mman.h> 42 #include <sys/types.h> 43 #include <errno.h> 44 45 #include <sys/queue.h> 46 #include <sys/stat.h> 47 48 #include <stdint.h> 49 #include <unistd.h> 50 #include <inttypes.h> 51 52 #include <rte_common.h> 53 #include <rte_errno.h> 54 #include <rte_byteorder.h> 55 #include <rte_log.h> 56 #include <rte_debug.h> 57 #include <rte_cycles.h> 58 #include <rte_memory.h> 59 #include <rte_memcpy.h> 60 #include <rte_memzone.h> 61 #include <rte_launch.h> 62 #include <rte_eal.h> 63 #include <rte_alarm.h> 64 #include <rte_per_lcore.h> 65 #include <rte_lcore.h> 66 #include <rte_atomic.h> 67 #include <rte_branch_prediction.h> 68 #include <rte_mempool.h> 69 #include <rte_malloc.h> 70 #include <rte_mbuf.h> 71 #include <rte_interrupts.h> 72 #include <rte_pci.h> 73 #include <rte_ether.h> 74 #include <rte_ethdev.h> 75 #include <rte_dev.h> 76 #include <rte_string_fns.h> 77 #ifdef RTE_LIBRTE_IXGBE_PMD 78 #include <rte_pmd_ixgbe.h> 79 #endif 80 #ifdef RTE_LIBRTE_PDUMP 81 #include <rte_pdump.h> 82 #endif 83 #include <rte_flow.h> 84 #include <rte_metrics.h> 85 #ifdef RTE_LIBRTE_BITRATE 86 #include <rte_bitrate.h> 87 #endif 88 #ifdef RTE_LIBRTE_LATENCY_STATS 89 #include <rte_latencystats.h> 90 #endif 91 92 #include "testpmd.h" 93 94 uint16_t verbose_level = 0; /**< Silent by default. */ 95 96 /* use master core for command line ? */ 97 uint8_t interactive = 0; 98 uint8_t auto_start = 0; 99 uint8_t tx_first; 100 char cmdline_filename[PATH_MAX] = {0}; 101 102 /* 103 * NUMA support configuration. 104 * When set, the NUMA support attempts to dispatch the allocation of the 105 * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the 106 * probed ports among the CPU sockets 0 and 1. 107 * Otherwise, all memory is allocated from CPU socket 0. 108 */ 109 uint8_t numa_support = 1; /**< numa enabled by default */ 110 111 /* 112 * In UMA mode,all memory is allocated from socket 0 if --socket-num is 113 * not configured. 114 */ 115 uint8_t socket_num = UMA_NO_CONFIG; 116 117 /* 118 * Use ANONYMOUS mapped memory (might be not physically continuous) for mbufs. 119 */ 120 uint8_t mp_anon = 0; 121 122 /* 123 * Record the Ethernet address of peer target ports to which packets are 124 * forwarded. 125 * Must be instantiated with the ethernet addresses of peer traffic generator 126 * ports. 127 */ 128 struct ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS]; 129 portid_t nb_peer_eth_addrs = 0; 130 131 /* 132 * Probed Target Environment. 133 */ 134 struct rte_port *ports; /**< For all probed ethernet ports. */ 135 portid_t nb_ports; /**< Number of probed ethernet ports. */ 136 struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */ 137 lcoreid_t nb_lcores; /**< Number of probed logical cores. */ 138 139 /* 140 * Test Forwarding Configuration. 141 * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores 142 * nb_fwd_ports <= nb_cfg_ports <= nb_ports 143 */ 144 lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */ 145 lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */ 146 portid_t nb_cfg_ports; /**< Number of configured ports. */ 147 portid_t nb_fwd_ports; /**< Number of forwarding ports. */ 148 149 unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */ 150 portid_t fwd_ports_ids[RTE_MAX_ETHPORTS]; /**< Port ids configuration. */ 151 152 struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */ 153 streamid_t nb_fwd_streams; /**< Is equal to (nb_ports * nb_rxq). */ 154 155 /* 156 * Forwarding engines. 157 */ 158 struct fwd_engine * fwd_engines[] = { 159 &io_fwd_engine, 160 &mac_fwd_engine, 161 &mac_swap_engine, 162 &flow_gen_engine, 163 &rx_only_engine, 164 &tx_only_engine, 165 &csum_fwd_engine, 166 &icmp_echo_engine, 167 #ifdef RTE_LIBRTE_IEEE1588 168 &ieee1588_fwd_engine, 169 #endif 170 NULL, 171 }; 172 173 struct fwd_config cur_fwd_config; 174 struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */ 175 uint32_t retry_enabled; 176 uint32_t burst_tx_delay_time = BURST_TX_WAIT_US; 177 uint32_t burst_tx_retry_num = BURST_TX_RETRIES; 178 179 uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */ 180 uint32_t param_total_num_mbufs = 0; /**< number of mbufs in all pools - if 181 * specified on command-line. */ 182 uint16_t stats_period; /**< Period to show statistics (disabled by default) */ 183 184 /* 185 * In container, it cannot terminate the process which running with 'stats-period' 186 * option. Set flag to exit stats period loop after received SIGINT/SIGTERM. 187 */ 188 uint8_t f_quit; 189 190 /* 191 * Configuration of packet segments used by the "txonly" processing engine. 192 */ 193 uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */ 194 uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = { 195 TXONLY_DEF_PACKET_LEN, 196 }; 197 uint8_t tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */ 198 199 enum tx_pkt_split tx_pkt_split = TX_PKT_SPLIT_OFF; 200 /**< Split policy for packets to TX. */ 201 202 uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */ 203 uint16_t mb_mempool_cache = DEF_MBUF_CACHE; /**< Size of mbuf mempool cache. */ 204 205 /* current configuration is in DCB or not,0 means it is not in DCB mode */ 206 uint8_t dcb_config = 0; 207 208 /* Whether the dcb is in testing status */ 209 uint8_t dcb_test = 0; 210 211 /* 212 * Configurable number of RX/TX queues. 213 */ 214 queueid_t nb_rxq = 1; /**< Number of RX queues per port. */ 215 queueid_t nb_txq = 1; /**< Number of TX queues per port. */ 216 217 /* 218 * Configurable number of RX/TX ring descriptors. 219 */ 220 #define RTE_TEST_RX_DESC_DEFAULT 128 221 #define RTE_TEST_TX_DESC_DEFAULT 512 222 uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */ 223 uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */ 224 225 #define RTE_PMD_PARAM_UNSET -1 226 /* 227 * Configurable values of RX and TX ring threshold registers. 228 */ 229 230 int8_t rx_pthresh = RTE_PMD_PARAM_UNSET; 231 int8_t rx_hthresh = RTE_PMD_PARAM_UNSET; 232 int8_t rx_wthresh = RTE_PMD_PARAM_UNSET; 233 234 int8_t tx_pthresh = RTE_PMD_PARAM_UNSET; 235 int8_t tx_hthresh = RTE_PMD_PARAM_UNSET; 236 int8_t tx_wthresh = RTE_PMD_PARAM_UNSET; 237 238 /* 239 * Configurable value of RX free threshold. 240 */ 241 int16_t rx_free_thresh = RTE_PMD_PARAM_UNSET; 242 243 /* 244 * Configurable value of RX drop enable. 245 */ 246 int8_t rx_drop_en = RTE_PMD_PARAM_UNSET; 247 248 /* 249 * Configurable value of TX free threshold. 250 */ 251 int16_t tx_free_thresh = RTE_PMD_PARAM_UNSET; 252 253 /* 254 * Configurable value of TX RS bit threshold. 255 */ 256 int16_t tx_rs_thresh = RTE_PMD_PARAM_UNSET; 257 258 /* 259 * Configurable value of TX queue flags. 260 */ 261 int32_t txq_flags = RTE_PMD_PARAM_UNSET; 262 263 /* 264 * Receive Side Scaling (RSS) configuration. 265 */ 266 uint64_t rss_hf = ETH_RSS_IP; /* RSS IP by default. */ 267 268 /* 269 * Port topology configuration 270 */ 271 uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */ 272 273 /* 274 * Avoids to flush all the RX streams before starts forwarding. 275 */ 276 uint8_t no_flush_rx = 0; /* flush by default */ 277 278 /* 279 * Flow API isolated mode. 280 */ 281 uint8_t flow_isolate_all; 282 283 /* 284 * Avoids to check link status when starting/stopping a port. 285 */ 286 uint8_t no_link_check = 0; /* check by default */ 287 288 /* 289 * Enable link status change notification 290 */ 291 uint8_t lsc_interrupt = 1; /* enabled by default */ 292 293 /* 294 * Enable device removal notification. 295 */ 296 uint8_t rmv_interrupt = 1; /* enabled by default */ 297 298 /* 299 * Display or mask ether events 300 * Default to all events except VF_MBOX 301 */ 302 uint32_t event_print_mask = (UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN) | 303 (UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC) | 304 (UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE) | 305 (UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET) | 306 (UINT32_C(1) << RTE_ETH_EVENT_MACSEC) | 307 (UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV); 308 309 /* 310 * NIC bypass mode configuration options. 311 */ 312 313 #if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS 314 /* The NIC bypass watchdog timeout. */ 315 uint32_t bypass_timeout = RTE_PMD_IXGBE_BYPASS_TMT_OFF; 316 #endif 317 318 319 #ifdef RTE_LIBRTE_LATENCY_STATS 320 321 /* 322 * Set when latency stats is enabled in the commandline 323 */ 324 uint8_t latencystats_enabled; 325 326 /* 327 * Lcore ID to serive latency statistics. 328 */ 329 lcoreid_t latencystats_lcore_id = -1; 330 331 #endif 332 333 /* 334 * Ethernet device configuration. 335 */ 336 struct rte_eth_rxmode rx_mode = { 337 .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */ 338 .split_hdr_size = 0, 339 .header_split = 0, /**< Header Split disabled. */ 340 .hw_ip_checksum = 0, /**< IP checksum offload disabled. */ 341 .hw_vlan_filter = 1, /**< VLAN filtering enabled. */ 342 .hw_vlan_strip = 1, /**< VLAN strip enabled. */ 343 .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ 344 .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */ 345 .hw_strip_crc = 1, /**< CRC stripping by hardware enabled. */ 346 }; 347 348 struct rte_fdir_conf fdir_conf = { 349 .mode = RTE_FDIR_MODE_NONE, 350 .pballoc = RTE_FDIR_PBALLOC_64K, 351 .status = RTE_FDIR_REPORT_STATUS, 352 .mask = { 353 .vlan_tci_mask = 0x0, 354 .ipv4_mask = { 355 .src_ip = 0xFFFFFFFF, 356 .dst_ip = 0xFFFFFFFF, 357 }, 358 .ipv6_mask = { 359 .src_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 360 .dst_ip = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, 361 }, 362 .src_port_mask = 0xFFFF, 363 .dst_port_mask = 0xFFFF, 364 .mac_addr_byte_mask = 0xFF, 365 .tunnel_type_mask = 1, 366 .tunnel_id_mask = 0xFFFFFFFF, 367 }, 368 .drop_queue = 127, 369 }; 370 371 volatile int test_done = 1; /* stop packet forwarding when set to 1. */ 372 373 struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS]; 374 struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS]; 375 376 struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array; 377 struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array; 378 379 uint16_t nb_tx_queue_stats_mappings = 0; 380 uint16_t nb_rx_queue_stats_mappings = 0; 381 382 unsigned int num_sockets = 0; 383 unsigned int socket_ids[RTE_MAX_NUMA_NODES]; 384 385 #ifdef RTE_LIBRTE_BITRATE 386 /* Bitrate statistics */ 387 struct rte_stats_bitrates *bitrate_data; 388 lcoreid_t bitrate_lcore_id; 389 uint8_t bitrate_enabled; 390 #endif 391 392 struct gro_status gro_ports[RTE_MAX_ETHPORTS]; 393 uint8_t gro_flush_cycles = GRO_DEFAULT_FLUSH_CYCLES; 394 395 /* Forward function declarations */ 396 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); 397 static void check_all_ports_link_status(uint32_t port_mask); 398 static int eth_event_callback(portid_t port_id, 399 enum rte_eth_event_type type, 400 void *param, void *ret_param); 401 402 /* 403 * Check if all the ports are started. 404 * If yes, return positive value. If not, return zero. 405 */ 406 static int all_ports_started(void); 407 408 struct gso_status gso_ports[RTE_MAX_ETHPORTS]; 409 uint16_t gso_max_segment_size = ETHER_MAX_LEN - ETHER_CRC_LEN; 410 411 /* 412 * Helper function to check if socket is already discovered. 413 * If yes, return positive value. If not, return zero. 414 */ 415 int 416 new_socket_id(unsigned int socket_id) 417 { 418 unsigned int i; 419 420 for (i = 0; i < num_sockets; i++) { 421 if (socket_ids[i] == socket_id) 422 return 0; 423 } 424 return 1; 425 } 426 427 /* 428 * Setup default configuration. 429 */ 430 static void 431 set_default_fwd_lcores_config(void) 432 { 433 unsigned int i; 434 unsigned int nb_lc; 435 unsigned int sock_num; 436 437 nb_lc = 0; 438 for (i = 0; i < RTE_MAX_LCORE; i++) { 439 sock_num = rte_lcore_to_socket_id(i); 440 if (new_socket_id(sock_num)) { 441 if (num_sockets >= RTE_MAX_NUMA_NODES) { 442 rte_exit(EXIT_FAILURE, 443 "Total sockets greater than %u\n", 444 RTE_MAX_NUMA_NODES); 445 } 446 socket_ids[num_sockets++] = sock_num; 447 } 448 if (!rte_lcore_is_enabled(i)) 449 continue; 450 if (i == rte_get_master_lcore()) 451 continue; 452 fwd_lcores_cpuids[nb_lc++] = i; 453 } 454 nb_lcores = (lcoreid_t) nb_lc; 455 nb_cfg_lcores = nb_lcores; 456 nb_fwd_lcores = 1; 457 } 458 459 static void 460 set_def_peer_eth_addrs(void) 461 { 462 portid_t i; 463 464 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 465 peer_eth_addrs[i].addr_bytes[0] = ETHER_LOCAL_ADMIN_ADDR; 466 peer_eth_addrs[i].addr_bytes[5] = i; 467 } 468 } 469 470 static void 471 set_default_fwd_ports_config(void) 472 { 473 portid_t pt_id; 474 int i = 0; 475 476 RTE_ETH_FOREACH_DEV(pt_id) 477 fwd_ports_ids[i++] = pt_id; 478 479 nb_cfg_ports = nb_ports; 480 nb_fwd_ports = nb_ports; 481 } 482 483 void 484 set_def_fwd_config(void) 485 { 486 set_default_fwd_lcores_config(); 487 set_def_peer_eth_addrs(); 488 set_default_fwd_ports_config(); 489 } 490 491 /* 492 * Configuration initialisation done once at init time. 493 */ 494 static void 495 mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf, 496 unsigned int socket_id) 497 { 498 char pool_name[RTE_MEMPOOL_NAMESIZE]; 499 struct rte_mempool *rte_mp = NULL; 500 uint32_t mb_size; 501 502 mb_size = sizeof(struct rte_mbuf) + mbuf_seg_size; 503 mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name)); 504 505 RTE_LOG(INFO, USER1, 506 "create a new mbuf pool <%s>: n=%u, size=%u, socket=%u\n", 507 pool_name, nb_mbuf, mbuf_seg_size, socket_id); 508 509 if (mp_anon != 0) { 510 rte_mp = rte_mempool_create_empty(pool_name, nb_mbuf, 511 mb_size, (unsigned) mb_mempool_cache, 512 sizeof(struct rte_pktmbuf_pool_private), 513 socket_id, 0); 514 if (rte_mp == NULL) 515 goto err; 516 517 if (rte_mempool_populate_anon(rte_mp) == 0) { 518 rte_mempool_free(rte_mp); 519 rte_mp = NULL; 520 goto err; 521 } 522 rte_pktmbuf_pool_init(rte_mp, NULL); 523 rte_mempool_obj_iter(rte_mp, rte_pktmbuf_init, NULL); 524 } else { 525 /* wrapper to rte_mempool_create() */ 526 rte_mp = rte_pktmbuf_pool_create(pool_name, nb_mbuf, 527 mb_mempool_cache, 0, mbuf_seg_size, socket_id); 528 } 529 530 err: 531 if (rte_mp == NULL) { 532 rte_exit(EXIT_FAILURE, 533 "Creation of mbuf pool for socket %u failed: %s\n", 534 socket_id, rte_strerror(rte_errno)); 535 } else if (verbose_level > 0) { 536 rte_mempool_dump(stdout, rte_mp); 537 } 538 } 539 540 /* 541 * Check given socket id is valid or not with NUMA mode, 542 * if valid, return 0, else return -1 543 */ 544 static int 545 check_socket_id(const unsigned int socket_id) 546 { 547 static int warning_once = 0; 548 549 if (new_socket_id(socket_id)) { 550 if (!warning_once && numa_support) 551 printf("Warning: NUMA should be configured manually by" 552 " using --port-numa-config and" 553 " --ring-numa-config parameters along with" 554 " --numa.\n"); 555 warning_once = 1; 556 return -1; 557 } 558 return 0; 559 } 560 561 static void 562 init_config(void) 563 { 564 portid_t pid; 565 struct rte_port *port; 566 struct rte_mempool *mbp; 567 unsigned int nb_mbuf_per_pool; 568 lcoreid_t lc_id; 569 uint8_t port_per_socket[RTE_MAX_NUMA_NODES]; 570 struct rte_gro_param gro_param; 571 uint32_t gso_types; 572 573 memset(port_per_socket,0,RTE_MAX_NUMA_NODES); 574 575 if (numa_support) { 576 memset(port_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); 577 memset(rxring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); 578 memset(txring_numa, NUMA_NO_CONFIG, RTE_MAX_ETHPORTS); 579 } 580 581 /* Configuration of logical cores. */ 582 fwd_lcores = rte_zmalloc("testpmd: fwd_lcores", 583 sizeof(struct fwd_lcore *) * nb_lcores, 584 RTE_CACHE_LINE_SIZE); 585 if (fwd_lcores == NULL) { 586 rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) " 587 "failed\n", nb_lcores); 588 } 589 for (lc_id = 0; lc_id < nb_lcores; lc_id++) { 590 fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore", 591 sizeof(struct fwd_lcore), 592 RTE_CACHE_LINE_SIZE); 593 if (fwd_lcores[lc_id] == NULL) { 594 rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) " 595 "failed\n"); 596 } 597 fwd_lcores[lc_id]->cpuid_idx = lc_id; 598 } 599 600 RTE_ETH_FOREACH_DEV(pid) { 601 port = &ports[pid]; 602 rte_eth_dev_info_get(pid, &port->dev_info); 603 604 if (numa_support) { 605 if (port_numa[pid] != NUMA_NO_CONFIG) 606 port_per_socket[port_numa[pid]]++; 607 else { 608 uint32_t socket_id = rte_eth_dev_socket_id(pid); 609 610 /* if socket_id is invalid, set to 0 */ 611 if (check_socket_id(socket_id) < 0) 612 socket_id = 0; 613 port_per_socket[socket_id]++; 614 } 615 } 616 617 /* set flag to initialize port/queue */ 618 port->need_reconfig = 1; 619 port->need_reconfig_queues = 1; 620 } 621 622 /* 623 * Create pools of mbuf. 624 * If NUMA support is disabled, create a single pool of mbuf in 625 * socket 0 memory by default. 626 * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1. 627 * 628 * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and 629 * nb_txd can be configured at run time. 630 */ 631 if (param_total_num_mbufs) 632 nb_mbuf_per_pool = param_total_num_mbufs; 633 else { 634 nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + 635 (nb_lcores * mb_mempool_cache) + 636 RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST; 637 nb_mbuf_per_pool *= RTE_MAX_ETHPORTS; 638 } 639 640 if (numa_support) { 641 uint8_t i; 642 643 for (i = 0; i < num_sockets; i++) 644 mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 645 socket_ids[i]); 646 } else { 647 if (socket_num == UMA_NO_CONFIG) 648 mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0); 649 else 650 mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 651 socket_num); 652 } 653 654 init_port_config(); 655 656 gso_types = DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_VXLAN_TNL_TSO | 657 DEV_TX_OFFLOAD_GRE_TNL_TSO; 658 /* 659 * Records which Mbuf pool to use by each logical core, if needed. 660 */ 661 for (lc_id = 0; lc_id < nb_lcores; lc_id++) { 662 mbp = mbuf_pool_find( 663 rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id])); 664 665 if (mbp == NULL) 666 mbp = mbuf_pool_find(0); 667 fwd_lcores[lc_id]->mbp = mbp; 668 /* initialize GSO context */ 669 fwd_lcores[lc_id]->gso_ctx.direct_pool = mbp; 670 fwd_lcores[lc_id]->gso_ctx.indirect_pool = mbp; 671 fwd_lcores[lc_id]->gso_ctx.gso_types = gso_types; 672 fwd_lcores[lc_id]->gso_ctx.gso_size = ETHER_MAX_LEN - 673 ETHER_CRC_LEN; 674 fwd_lcores[lc_id]->gso_ctx.flag = 0; 675 } 676 677 /* Configuration of packet forwarding streams. */ 678 if (init_fwd_streams() < 0) 679 rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n"); 680 681 fwd_config_setup(); 682 683 /* create a gro context for each lcore */ 684 gro_param.gro_types = RTE_GRO_TCP_IPV4; 685 gro_param.max_flow_num = GRO_MAX_FLUSH_CYCLES; 686 gro_param.max_item_per_flow = MAX_PKT_BURST; 687 for (lc_id = 0; lc_id < nb_lcores; lc_id++) { 688 gro_param.socket_id = rte_lcore_to_socket_id( 689 fwd_lcores_cpuids[lc_id]); 690 fwd_lcores[lc_id]->gro_ctx = rte_gro_ctx_create(&gro_param); 691 if (fwd_lcores[lc_id]->gro_ctx == NULL) { 692 rte_exit(EXIT_FAILURE, 693 "rte_gro_ctx_create() failed\n"); 694 } 695 } 696 } 697 698 699 void 700 reconfig(portid_t new_port_id, unsigned socket_id) 701 { 702 struct rte_port *port; 703 704 /* Reconfiguration of Ethernet ports. */ 705 port = &ports[new_port_id]; 706 rte_eth_dev_info_get(new_port_id, &port->dev_info); 707 708 /* set flag to initialize port/queue */ 709 port->need_reconfig = 1; 710 port->need_reconfig_queues = 1; 711 port->socket_id = socket_id; 712 713 init_port_config(); 714 } 715 716 717 int 718 init_fwd_streams(void) 719 { 720 portid_t pid; 721 struct rte_port *port; 722 streamid_t sm_id, nb_fwd_streams_new; 723 queueid_t q; 724 725 /* set socket id according to numa or not */ 726 RTE_ETH_FOREACH_DEV(pid) { 727 port = &ports[pid]; 728 if (nb_rxq > port->dev_info.max_rx_queues) { 729 printf("Fail: nb_rxq(%d) is greater than " 730 "max_rx_queues(%d)\n", nb_rxq, 731 port->dev_info.max_rx_queues); 732 return -1; 733 } 734 if (nb_txq > port->dev_info.max_tx_queues) { 735 printf("Fail: nb_txq(%d) is greater than " 736 "max_tx_queues(%d)\n", nb_txq, 737 port->dev_info.max_tx_queues); 738 return -1; 739 } 740 if (numa_support) { 741 if (port_numa[pid] != NUMA_NO_CONFIG) 742 port->socket_id = port_numa[pid]; 743 else { 744 port->socket_id = rte_eth_dev_socket_id(pid); 745 746 /* if socket_id is invalid, set to 0 */ 747 if (check_socket_id(port->socket_id) < 0) 748 port->socket_id = 0; 749 } 750 } 751 else { 752 if (socket_num == UMA_NO_CONFIG) 753 port->socket_id = 0; 754 else 755 port->socket_id = socket_num; 756 } 757 } 758 759 q = RTE_MAX(nb_rxq, nb_txq); 760 if (q == 0) { 761 printf("Fail: Cannot allocate fwd streams as number of queues is 0\n"); 762 return -1; 763 } 764 nb_fwd_streams_new = (streamid_t)(nb_ports * q); 765 if (nb_fwd_streams_new == nb_fwd_streams) 766 return 0; 767 /* clear the old */ 768 if (fwd_streams != NULL) { 769 for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { 770 if (fwd_streams[sm_id] == NULL) 771 continue; 772 rte_free(fwd_streams[sm_id]); 773 fwd_streams[sm_id] = NULL; 774 } 775 rte_free(fwd_streams); 776 fwd_streams = NULL; 777 } 778 779 /* init new */ 780 nb_fwd_streams = nb_fwd_streams_new; 781 fwd_streams = rte_zmalloc("testpmd: fwd_streams", 782 sizeof(struct fwd_stream *) * nb_fwd_streams, RTE_CACHE_LINE_SIZE); 783 if (fwd_streams == NULL) 784 rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) " 785 "failed\n", nb_fwd_streams); 786 787 for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { 788 fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream", 789 sizeof(struct fwd_stream), RTE_CACHE_LINE_SIZE); 790 if (fwd_streams[sm_id] == NULL) 791 rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)" 792 " failed\n"); 793 } 794 795 return 0; 796 } 797 798 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 799 static void 800 pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs) 801 { 802 unsigned int total_burst; 803 unsigned int nb_burst; 804 unsigned int burst_stats[3]; 805 uint16_t pktnb_stats[3]; 806 uint16_t nb_pkt; 807 int burst_percent[3]; 808 809 /* 810 * First compute the total number of packet bursts and the 811 * two highest numbers of bursts of the same number of packets. 812 */ 813 total_burst = 0; 814 burst_stats[0] = burst_stats[1] = burst_stats[2] = 0; 815 pktnb_stats[0] = pktnb_stats[1] = pktnb_stats[2] = 0; 816 for (nb_pkt = 0; nb_pkt < MAX_PKT_BURST; nb_pkt++) { 817 nb_burst = pbs->pkt_burst_spread[nb_pkt]; 818 if (nb_burst == 0) 819 continue; 820 total_burst += nb_burst; 821 if (nb_burst > burst_stats[0]) { 822 burst_stats[1] = burst_stats[0]; 823 pktnb_stats[1] = pktnb_stats[0]; 824 burst_stats[0] = nb_burst; 825 pktnb_stats[0] = nb_pkt; 826 } 827 } 828 if (total_burst == 0) 829 return; 830 burst_percent[0] = (burst_stats[0] * 100) / total_burst; 831 printf(" %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst, 832 burst_percent[0], (int) pktnb_stats[0]); 833 if (burst_stats[0] == total_burst) { 834 printf("]\n"); 835 return; 836 } 837 if (burst_stats[0] + burst_stats[1] == total_burst) { 838 printf(" + %d%% of %d pkts]\n", 839 100 - burst_percent[0], pktnb_stats[1]); 840 return; 841 } 842 burst_percent[1] = (burst_stats[1] * 100) / total_burst; 843 burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]); 844 if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) { 845 printf(" + %d%% of others]\n", 100 - burst_percent[0]); 846 return; 847 } 848 printf(" + %d%% of %d pkts + %d%% of others]\n", 849 burst_percent[1], (int) pktnb_stats[1], burst_percent[2]); 850 } 851 #endif /* RTE_TEST_PMD_RECORD_BURST_STATS */ 852 853 static void 854 fwd_port_stats_display(portid_t port_id, struct rte_eth_stats *stats) 855 { 856 struct rte_port *port; 857 uint8_t i; 858 859 static const char *fwd_stats_border = "----------------------"; 860 861 port = &ports[port_id]; 862 printf("\n %s Forward statistics for port %-2d %s\n", 863 fwd_stats_border, port_id, fwd_stats_border); 864 865 if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { 866 printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " 867 "%-"PRIu64"\n", 868 stats->ipackets, stats->imissed, 869 (uint64_t) (stats->ipackets + stats->imissed)); 870 871 if (cur_fwd_eng == &csum_fwd_engine) 872 printf(" Bad-ipcsum: %-14"PRIu64" Bad-l4csum: %-14"PRIu64" \n", 873 port->rx_bad_ip_csum, port->rx_bad_l4_csum); 874 if ((stats->ierrors + stats->rx_nombuf) > 0) { 875 printf(" RX-error: %-"PRIu64"\n", stats->ierrors); 876 printf(" RX-nombufs: %-14"PRIu64"\n", stats->rx_nombuf); 877 } 878 879 printf(" TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " 880 "%-"PRIu64"\n", 881 stats->opackets, port->tx_dropped, 882 (uint64_t) (stats->opackets + port->tx_dropped)); 883 } 884 else { 885 printf(" RX-packets: %14"PRIu64" RX-dropped:%14"PRIu64" RX-total:" 886 "%14"PRIu64"\n", 887 stats->ipackets, stats->imissed, 888 (uint64_t) (stats->ipackets + stats->imissed)); 889 890 if (cur_fwd_eng == &csum_fwd_engine) 891 printf(" Bad-ipcsum:%14"PRIu64" Bad-l4csum:%14"PRIu64"\n", 892 port->rx_bad_ip_csum, port->rx_bad_l4_csum); 893 if ((stats->ierrors + stats->rx_nombuf) > 0) { 894 printf(" RX-error:%"PRIu64"\n", stats->ierrors); 895 printf(" RX-nombufs: %14"PRIu64"\n", 896 stats->rx_nombuf); 897 } 898 899 printf(" TX-packets: %14"PRIu64" TX-dropped:%14"PRIu64" TX-total:" 900 "%14"PRIu64"\n", 901 stats->opackets, port->tx_dropped, 902 (uint64_t) (stats->opackets + port->tx_dropped)); 903 } 904 905 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 906 if (port->rx_stream) 907 pkt_burst_stats_display("RX", 908 &port->rx_stream->rx_burst_stats); 909 if (port->tx_stream) 910 pkt_burst_stats_display("TX", 911 &port->tx_stream->tx_burst_stats); 912 #endif 913 914 if (port->rx_queue_stats_mapping_enabled) { 915 printf("\n"); 916 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 917 printf(" Stats reg %2d RX-packets:%14"PRIu64 918 " RX-errors:%14"PRIu64 919 " RX-bytes:%14"PRIu64"\n", 920 i, stats->q_ipackets[i], stats->q_errors[i], stats->q_ibytes[i]); 921 } 922 printf("\n"); 923 } 924 if (port->tx_queue_stats_mapping_enabled) { 925 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 926 printf(" Stats reg %2d TX-packets:%14"PRIu64 927 " TX-bytes:%14"PRIu64"\n", 928 i, stats->q_opackets[i], stats->q_obytes[i]); 929 } 930 } 931 932 printf(" %s--------------------------------%s\n", 933 fwd_stats_border, fwd_stats_border); 934 } 935 936 static void 937 fwd_stream_stats_display(streamid_t stream_id) 938 { 939 struct fwd_stream *fs; 940 static const char *fwd_top_stats_border = "-------"; 941 942 fs = fwd_streams[stream_id]; 943 if ((fs->rx_packets == 0) && (fs->tx_packets == 0) && 944 (fs->fwd_dropped == 0)) 945 return; 946 printf("\n %s Forward Stats for RX Port=%2d/Queue=%2d -> " 947 "TX Port=%2d/Queue=%2d %s\n", 948 fwd_top_stats_border, fs->rx_port, fs->rx_queue, 949 fs->tx_port, fs->tx_queue, fwd_top_stats_border); 950 printf(" RX-packets: %-14u TX-packets: %-14u TX-dropped: %-14u", 951 fs->rx_packets, fs->tx_packets, fs->fwd_dropped); 952 953 /* if checksum mode */ 954 if (cur_fwd_eng == &csum_fwd_engine) { 955 printf(" RX- bad IP checksum: %-14u Rx- bad L4 checksum: " 956 "%-14u\n", fs->rx_bad_ip_csum, fs->rx_bad_l4_csum); 957 } 958 959 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 960 pkt_burst_stats_display("RX", &fs->rx_burst_stats); 961 pkt_burst_stats_display("TX", &fs->tx_burst_stats); 962 #endif 963 } 964 965 static void 966 flush_fwd_rx_queues(void) 967 { 968 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 969 portid_t rxp; 970 portid_t port_id; 971 queueid_t rxq; 972 uint16_t nb_rx; 973 uint16_t i; 974 uint8_t j; 975 uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0; 976 uint64_t timer_period; 977 978 /* convert to number of cycles */ 979 timer_period = rte_get_timer_hz(); /* 1 second timeout */ 980 981 for (j = 0; j < 2; j++) { 982 for (rxp = 0; rxp < cur_fwd_config.nb_fwd_ports; rxp++) { 983 for (rxq = 0; rxq < nb_rxq; rxq++) { 984 port_id = fwd_ports_ids[rxp]; 985 /** 986 * testpmd can stuck in the below do while loop 987 * if rte_eth_rx_burst() always returns nonzero 988 * packets. So timer is added to exit this loop 989 * after 1sec timer expiry. 990 */ 991 prev_tsc = rte_rdtsc(); 992 do { 993 nb_rx = rte_eth_rx_burst(port_id, rxq, 994 pkts_burst, MAX_PKT_BURST); 995 for (i = 0; i < nb_rx; i++) 996 rte_pktmbuf_free(pkts_burst[i]); 997 998 cur_tsc = rte_rdtsc(); 999 diff_tsc = cur_tsc - prev_tsc; 1000 timer_tsc += diff_tsc; 1001 } while ((nb_rx > 0) && 1002 (timer_tsc < timer_period)); 1003 timer_tsc = 0; 1004 } 1005 } 1006 rte_delay_ms(10); /* wait 10 milli-seconds before retrying */ 1007 } 1008 } 1009 1010 static void 1011 run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) 1012 { 1013 struct fwd_stream **fsm; 1014 streamid_t nb_fs; 1015 streamid_t sm_id; 1016 #ifdef RTE_LIBRTE_BITRATE 1017 uint64_t tics_per_1sec; 1018 uint64_t tics_datum; 1019 uint64_t tics_current; 1020 uint8_t idx_port, cnt_ports; 1021 1022 cnt_ports = rte_eth_dev_count(); 1023 tics_datum = rte_rdtsc(); 1024 tics_per_1sec = rte_get_timer_hz(); 1025 #endif 1026 fsm = &fwd_streams[fc->stream_idx]; 1027 nb_fs = fc->stream_nb; 1028 do { 1029 for (sm_id = 0; sm_id < nb_fs; sm_id++) 1030 (*pkt_fwd)(fsm[sm_id]); 1031 #ifdef RTE_LIBRTE_BITRATE 1032 if (bitrate_enabled != 0 && 1033 bitrate_lcore_id == rte_lcore_id()) { 1034 tics_current = rte_rdtsc(); 1035 if (tics_current - tics_datum >= tics_per_1sec) { 1036 /* Periodic bitrate calculation */ 1037 for (idx_port = 0; 1038 idx_port < cnt_ports; 1039 idx_port++) 1040 rte_stats_bitrate_calc(bitrate_data, 1041 idx_port); 1042 tics_datum = tics_current; 1043 } 1044 } 1045 #endif 1046 #ifdef RTE_LIBRTE_LATENCY_STATS 1047 if (latencystats_enabled != 0 && 1048 latencystats_lcore_id == rte_lcore_id()) 1049 rte_latencystats_update(); 1050 #endif 1051 1052 } while (! fc->stopped); 1053 } 1054 1055 static int 1056 start_pkt_forward_on_core(void *fwd_arg) 1057 { 1058 run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg, 1059 cur_fwd_config.fwd_eng->packet_fwd); 1060 return 0; 1061 } 1062 1063 /* 1064 * Run the TXONLY packet forwarding engine to send a single burst of packets. 1065 * Used to start communication flows in network loopback test configurations. 1066 */ 1067 static int 1068 run_one_txonly_burst_on_core(void *fwd_arg) 1069 { 1070 struct fwd_lcore *fwd_lc; 1071 struct fwd_lcore tmp_lcore; 1072 1073 fwd_lc = (struct fwd_lcore *) fwd_arg; 1074 tmp_lcore = *fwd_lc; 1075 tmp_lcore.stopped = 1; 1076 run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd); 1077 return 0; 1078 } 1079 1080 /* 1081 * Launch packet forwarding: 1082 * - Setup per-port forwarding context. 1083 * - launch logical cores with their forwarding configuration. 1084 */ 1085 static void 1086 launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore) 1087 { 1088 port_fwd_begin_t port_fwd_begin; 1089 unsigned int i; 1090 unsigned int lc_id; 1091 int diag; 1092 1093 port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin; 1094 if (port_fwd_begin != NULL) { 1095 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 1096 (*port_fwd_begin)(fwd_ports_ids[i]); 1097 } 1098 for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) { 1099 lc_id = fwd_lcores_cpuids[i]; 1100 if ((interactive == 0) || (lc_id != rte_lcore_id())) { 1101 fwd_lcores[i]->stopped = 0; 1102 diag = rte_eal_remote_launch(pkt_fwd_on_lcore, 1103 fwd_lcores[i], lc_id); 1104 if (diag != 0) 1105 printf("launch lcore %u failed - diag=%d\n", 1106 lc_id, diag); 1107 } 1108 } 1109 } 1110 1111 /* 1112 * Launch packet forwarding configuration. 1113 */ 1114 void 1115 start_packet_forwarding(int with_tx_first) 1116 { 1117 port_fwd_begin_t port_fwd_begin; 1118 port_fwd_end_t port_fwd_end; 1119 struct rte_port *port; 1120 unsigned int i; 1121 portid_t pt_id; 1122 streamid_t sm_id; 1123 1124 if (strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") == 0 && !nb_rxq) 1125 rte_exit(EXIT_FAILURE, "rxq are 0, cannot use rxonly fwd mode\n"); 1126 1127 if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 && !nb_txq) 1128 rte_exit(EXIT_FAILURE, "txq are 0, cannot use txonly fwd mode\n"); 1129 1130 if ((strcmp(cur_fwd_eng->fwd_mode_name, "rxonly") != 0 && 1131 strcmp(cur_fwd_eng->fwd_mode_name, "txonly") != 0) && 1132 (!nb_rxq || !nb_txq)) 1133 rte_exit(EXIT_FAILURE, 1134 "Either rxq or txq are 0, cannot use %s fwd mode\n", 1135 cur_fwd_eng->fwd_mode_name); 1136 1137 if (all_ports_started() == 0) { 1138 printf("Not all ports were started\n"); 1139 return; 1140 } 1141 if (test_done == 0) { 1142 printf("Packet forwarding already started\n"); 1143 return; 1144 } 1145 1146 if (init_fwd_streams() < 0) { 1147 printf("Fail from init_fwd_streams()\n"); 1148 return; 1149 } 1150 1151 if(dcb_test) { 1152 for (i = 0; i < nb_fwd_ports; i++) { 1153 pt_id = fwd_ports_ids[i]; 1154 port = &ports[pt_id]; 1155 if (!port->dcb_flag) { 1156 printf("In DCB mode, all forwarding ports must " 1157 "be configured in this mode.\n"); 1158 return; 1159 } 1160 } 1161 if (nb_fwd_lcores == 1) { 1162 printf("In DCB mode,the nb forwarding cores " 1163 "should be larger than 1.\n"); 1164 return; 1165 } 1166 } 1167 test_done = 0; 1168 1169 if(!no_flush_rx) 1170 flush_fwd_rx_queues(); 1171 1172 fwd_config_setup(); 1173 pkt_fwd_config_display(&cur_fwd_config); 1174 rxtx_config_display(); 1175 1176 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 1177 pt_id = fwd_ports_ids[i]; 1178 port = &ports[pt_id]; 1179 rte_eth_stats_get(pt_id, &port->stats); 1180 port->tx_dropped = 0; 1181 1182 map_port_queue_stats_mapping_registers(pt_id, port); 1183 } 1184 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 1185 fwd_streams[sm_id]->rx_packets = 0; 1186 fwd_streams[sm_id]->tx_packets = 0; 1187 fwd_streams[sm_id]->fwd_dropped = 0; 1188 fwd_streams[sm_id]->rx_bad_ip_csum = 0; 1189 fwd_streams[sm_id]->rx_bad_l4_csum = 0; 1190 1191 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 1192 memset(&fwd_streams[sm_id]->rx_burst_stats, 0, 1193 sizeof(fwd_streams[sm_id]->rx_burst_stats)); 1194 memset(&fwd_streams[sm_id]->tx_burst_stats, 0, 1195 sizeof(fwd_streams[sm_id]->tx_burst_stats)); 1196 #endif 1197 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 1198 fwd_streams[sm_id]->core_cycles = 0; 1199 #endif 1200 } 1201 if (with_tx_first) { 1202 port_fwd_begin = tx_only_engine.port_fwd_begin; 1203 if (port_fwd_begin != NULL) { 1204 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 1205 (*port_fwd_begin)(fwd_ports_ids[i]); 1206 } 1207 while (with_tx_first--) { 1208 launch_packet_forwarding( 1209 run_one_txonly_burst_on_core); 1210 rte_eal_mp_wait_lcore(); 1211 } 1212 port_fwd_end = tx_only_engine.port_fwd_end; 1213 if (port_fwd_end != NULL) { 1214 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 1215 (*port_fwd_end)(fwd_ports_ids[i]); 1216 } 1217 } 1218 launch_packet_forwarding(start_pkt_forward_on_core); 1219 } 1220 1221 void 1222 stop_packet_forwarding(void) 1223 { 1224 struct rte_eth_stats stats; 1225 struct rte_port *port; 1226 port_fwd_end_t port_fwd_end; 1227 int i; 1228 portid_t pt_id; 1229 streamid_t sm_id; 1230 lcoreid_t lc_id; 1231 uint64_t total_recv; 1232 uint64_t total_xmit; 1233 uint64_t total_rx_dropped; 1234 uint64_t total_tx_dropped; 1235 uint64_t total_rx_nombuf; 1236 uint64_t tx_dropped; 1237 uint64_t rx_bad_ip_csum; 1238 uint64_t rx_bad_l4_csum; 1239 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 1240 uint64_t fwd_cycles; 1241 #endif 1242 1243 static const char *acc_stats_border = "+++++++++++++++"; 1244 1245 if (test_done) { 1246 printf("Packet forwarding not started\n"); 1247 return; 1248 } 1249 printf("Telling cores to stop..."); 1250 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) 1251 fwd_lcores[lc_id]->stopped = 1; 1252 printf("\nWaiting for lcores to finish...\n"); 1253 rte_eal_mp_wait_lcore(); 1254 port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end; 1255 if (port_fwd_end != NULL) { 1256 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 1257 pt_id = fwd_ports_ids[i]; 1258 (*port_fwd_end)(pt_id); 1259 } 1260 } 1261 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 1262 fwd_cycles = 0; 1263 #endif 1264 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 1265 if (cur_fwd_config.nb_fwd_streams > 1266 cur_fwd_config.nb_fwd_ports) { 1267 fwd_stream_stats_display(sm_id); 1268 ports[fwd_streams[sm_id]->tx_port].tx_stream = NULL; 1269 ports[fwd_streams[sm_id]->rx_port].rx_stream = NULL; 1270 } else { 1271 ports[fwd_streams[sm_id]->tx_port].tx_stream = 1272 fwd_streams[sm_id]; 1273 ports[fwd_streams[sm_id]->rx_port].rx_stream = 1274 fwd_streams[sm_id]; 1275 } 1276 tx_dropped = ports[fwd_streams[sm_id]->tx_port].tx_dropped; 1277 tx_dropped = (uint64_t) (tx_dropped + 1278 fwd_streams[sm_id]->fwd_dropped); 1279 ports[fwd_streams[sm_id]->tx_port].tx_dropped = tx_dropped; 1280 1281 rx_bad_ip_csum = 1282 ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum; 1283 rx_bad_ip_csum = (uint64_t) (rx_bad_ip_csum + 1284 fwd_streams[sm_id]->rx_bad_ip_csum); 1285 ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum = 1286 rx_bad_ip_csum; 1287 1288 rx_bad_l4_csum = 1289 ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum; 1290 rx_bad_l4_csum = (uint64_t) (rx_bad_l4_csum + 1291 fwd_streams[sm_id]->rx_bad_l4_csum); 1292 ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum = 1293 rx_bad_l4_csum; 1294 1295 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 1296 fwd_cycles = (uint64_t) (fwd_cycles + 1297 fwd_streams[sm_id]->core_cycles); 1298 #endif 1299 } 1300 total_recv = 0; 1301 total_xmit = 0; 1302 total_rx_dropped = 0; 1303 total_tx_dropped = 0; 1304 total_rx_nombuf = 0; 1305 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 1306 pt_id = fwd_ports_ids[i]; 1307 1308 port = &ports[pt_id]; 1309 rte_eth_stats_get(pt_id, &stats); 1310 stats.ipackets -= port->stats.ipackets; 1311 port->stats.ipackets = 0; 1312 stats.opackets -= port->stats.opackets; 1313 port->stats.opackets = 0; 1314 stats.ibytes -= port->stats.ibytes; 1315 port->stats.ibytes = 0; 1316 stats.obytes -= port->stats.obytes; 1317 port->stats.obytes = 0; 1318 stats.imissed -= port->stats.imissed; 1319 port->stats.imissed = 0; 1320 stats.oerrors -= port->stats.oerrors; 1321 port->stats.oerrors = 0; 1322 stats.rx_nombuf -= port->stats.rx_nombuf; 1323 port->stats.rx_nombuf = 0; 1324 1325 total_recv += stats.ipackets; 1326 total_xmit += stats.opackets; 1327 total_rx_dropped += stats.imissed; 1328 total_tx_dropped += port->tx_dropped; 1329 total_rx_nombuf += stats.rx_nombuf; 1330 1331 fwd_port_stats_display(pt_id, &stats); 1332 } 1333 1334 printf("\n %s Accumulated forward statistics for all ports" 1335 "%s\n", 1336 acc_stats_border, acc_stats_border); 1337 printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " 1338 "%-"PRIu64"\n" 1339 " TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " 1340 "%-"PRIu64"\n", 1341 total_recv, total_rx_dropped, total_recv + total_rx_dropped, 1342 total_xmit, total_tx_dropped, total_xmit + total_tx_dropped); 1343 if (total_rx_nombuf > 0) 1344 printf(" RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf); 1345 printf(" %s++++++++++++++++++++++++++++++++++++++++++++++" 1346 "%s\n", 1347 acc_stats_border, acc_stats_border); 1348 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 1349 if (total_recv > 0) 1350 printf("\n CPU cycles/packet=%u (total cycles=" 1351 "%"PRIu64" / total RX packets=%"PRIu64")\n", 1352 (unsigned int)(fwd_cycles / total_recv), 1353 fwd_cycles, total_recv); 1354 #endif 1355 printf("\nDone.\n"); 1356 test_done = 1; 1357 } 1358 1359 void 1360 dev_set_link_up(portid_t pid) 1361 { 1362 if (rte_eth_dev_set_link_up((uint8_t)pid) < 0) 1363 printf("\nSet link up fail.\n"); 1364 } 1365 1366 void 1367 dev_set_link_down(portid_t pid) 1368 { 1369 if (rte_eth_dev_set_link_down((uint8_t)pid) < 0) 1370 printf("\nSet link down fail.\n"); 1371 } 1372 1373 static int 1374 all_ports_started(void) 1375 { 1376 portid_t pi; 1377 struct rte_port *port; 1378 1379 RTE_ETH_FOREACH_DEV(pi) { 1380 port = &ports[pi]; 1381 /* Check if there is a port which is not started */ 1382 if ((port->port_status != RTE_PORT_STARTED) && 1383 (port->slave_flag == 0)) 1384 return 0; 1385 } 1386 1387 /* No port is not started */ 1388 return 1; 1389 } 1390 1391 int 1392 all_ports_stopped(void) 1393 { 1394 portid_t pi; 1395 struct rte_port *port; 1396 1397 RTE_ETH_FOREACH_DEV(pi) { 1398 port = &ports[pi]; 1399 if ((port->port_status != RTE_PORT_STOPPED) && 1400 (port->slave_flag == 0)) 1401 return 0; 1402 } 1403 1404 return 1; 1405 } 1406 1407 int 1408 port_is_started(portid_t port_id) 1409 { 1410 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1411 return 0; 1412 1413 if (ports[port_id].port_status != RTE_PORT_STARTED) 1414 return 0; 1415 1416 return 1; 1417 } 1418 1419 static int 1420 port_is_closed(portid_t port_id) 1421 { 1422 if (port_id_is_invalid(port_id, ENABLED_WARN)) 1423 return 0; 1424 1425 if (ports[port_id].port_status != RTE_PORT_CLOSED) 1426 return 0; 1427 1428 return 1; 1429 } 1430 1431 int 1432 start_port(portid_t pid) 1433 { 1434 int diag, need_check_link_status = -1; 1435 portid_t pi; 1436 queueid_t qi; 1437 struct rte_port *port; 1438 struct ether_addr mac_addr; 1439 enum rte_eth_event_type event_type; 1440 1441 if (port_id_is_invalid(pid, ENABLED_WARN)) 1442 return 0; 1443 1444 if(dcb_config) 1445 dcb_test = 1; 1446 RTE_ETH_FOREACH_DEV(pi) { 1447 if (pid != pi && pid != (portid_t)RTE_PORT_ALL) 1448 continue; 1449 1450 need_check_link_status = 0; 1451 port = &ports[pi]; 1452 if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED, 1453 RTE_PORT_HANDLING) == 0) { 1454 printf("Port %d is now not stopped\n", pi); 1455 continue; 1456 } 1457 1458 if (port->need_reconfig > 0) { 1459 port->need_reconfig = 0; 1460 1461 if (flow_isolate_all) { 1462 int ret = port_flow_isolate(pi, 1); 1463 if (ret) { 1464 printf("Failed to apply isolated" 1465 " mode on port %d\n", pi); 1466 return -1; 1467 } 1468 } 1469 1470 printf("Configuring Port %d (socket %u)\n", pi, 1471 port->socket_id); 1472 /* configure port */ 1473 diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, 1474 &(port->dev_conf)); 1475 if (diag != 0) { 1476 if (rte_atomic16_cmpset(&(port->port_status), 1477 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1478 printf("Port %d can not be set back " 1479 "to stopped\n", pi); 1480 printf("Fail to configure port %d\n", pi); 1481 /* try to reconfigure port next time */ 1482 port->need_reconfig = 1; 1483 return -1; 1484 } 1485 } 1486 if (port->need_reconfig_queues > 0) { 1487 port->need_reconfig_queues = 0; 1488 /* setup tx queues */ 1489 for (qi = 0; qi < nb_txq; qi++) { 1490 if ((numa_support) && 1491 (txring_numa[pi] != NUMA_NO_CONFIG)) 1492 diag = rte_eth_tx_queue_setup(pi, qi, 1493 nb_txd,txring_numa[pi], 1494 &(port->tx_conf)); 1495 else 1496 diag = rte_eth_tx_queue_setup(pi, qi, 1497 nb_txd,port->socket_id, 1498 &(port->tx_conf)); 1499 1500 if (diag == 0) 1501 continue; 1502 1503 /* Fail to setup tx queue, return */ 1504 if (rte_atomic16_cmpset(&(port->port_status), 1505 RTE_PORT_HANDLING, 1506 RTE_PORT_STOPPED) == 0) 1507 printf("Port %d can not be set back " 1508 "to stopped\n", pi); 1509 printf("Fail to configure port %d tx queues\n", pi); 1510 /* try to reconfigure queues next time */ 1511 port->need_reconfig_queues = 1; 1512 return -1; 1513 } 1514 /* setup rx queues */ 1515 for (qi = 0; qi < nb_rxq; qi++) { 1516 if ((numa_support) && 1517 (rxring_numa[pi] != NUMA_NO_CONFIG)) { 1518 struct rte_mempool * mp = 1519 mbuf_pool_find(rxring_numa[pi]); 1520 if (mp == NULL) { 1521 printf("Failed to setup RX queue:" 1522 "No mempool allocation" 1523 " on the socket %d\n", 1524 rxring_numa[pi]); 1525 return -1; 1526 } 1527 1528 diag = rte_eth_rx_queue_setup(pi, qi, 1529 nb_rxd,rxring_numa[pi], 1530 &(port->rx_conf),mp); 1531 } else { 1532 struct rte_mempool *mp = 1533 mbuf_pool_find(port->socket_id); 1534 if (mp == NULL) { 1535 printf("Failed to setup RX queue:" 1536 "No mempool allocation" 1537 " on the socket %d\n", 1538 port->socket_id); 1539 return -1; 1540 } 1541 diag = rte_eth_rx_queue_setup(pi, qi, 1542 nb_rxd,port->socket_id, 1543 &(port->rx_conf), mp); 1544 } 1545 if (diag == 0) 1546 continue; 1547 1548 /* Fail to setup rx queue, return */ 1549 if (rte_atomic16_cmpset(&(port->port_status), 1550 RTE_PORT_HANDLING, 1551 RTE_PORT_STOPPED) == 0) 1552 printf("Port %d can not be set back " 1553 "to stopped\n", pi); 1554 printf("Fail to configure port %d rx queues\n", pi); 1555 /* try to reconfigure queues next time */ 1556 port->need_reconfig_queues = 1; 1557 return -1; 1558 } 1559 } 1560 1561 for (event_type = RTE_ETH_EVENT_UNKNOWN; 1562 event_type < RTE_ETH_EVENT_MAX; 1563 event_type++) { 1564 diag = rte_eth_dev_callback_register(pi, 1565 event_type, 1566 eth_event_callback, 1567 NULL); 1568 if (diag) { 1569 printf("Failed to setup even callback for event %d\n", 1570 event_type); 1571 return -1; 1572 } 1573 } 1574 1575 /* start port */ 1576 if (rte_eth_dev_start(pi) < 0) { 1577 printf("Fail to start port %d\n", pi); 1578 1579 /* Fail to setup rx queue, return */ 1580 if (rte_atomic16_cmpset(&(port->port_status), 1581 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1582 printf("Port %d can not be set back to " 1583 "stopped\n", pi); 1584 continue; 1585 } 1586 1587 if (rte_atomic16_cmpset(&(port->port_status), 1588 RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0) 1589 printf("Port %d can not be set into started\n", pi); 1590 1591 rte_eth_macaddr_get(pi, &mac_addr); 1592 printf("Port %d: %02X:%02X:%02X:%02X:%02X:%02X\n", pi, 1593 mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], 1594 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], 1595 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5]); 1596 1597 /* at least one port started, need checking link status */ 1598 need_check_link_status = 1; 1599 } 1600 1601 if (need_check_link_status == 1 && !no_link_check) 1602 check_all_ports_link_status(RTE_PORT_ALL); 1603 else if (need_check_link_status == 0) 1604 printf("Please stop the ports first\n"); 1605 1606 printf("Done\n"); 1607 return 0; 1608 } 1609 1610 void 1611 stop_port(portid_t pid) 1612 { 1613 portid_t pi; 1614 struct rte_port *port; 1615 int need_check_link_status = 0; 1616 1617 if (dcb_test) { 1618 dcb_test = 0; 1619 dcb_config = 0; 1620 } 1621 1622 if (port_id_is_invalid(pid, ENABLED_WARN)) 1623 return; 1624 1625 printf("Stopping ports...\n"); 1626 1627 RTE_ETH_FOREACH_DEV(pi) { 1628 if (pid != pi && pid != (portid_t)RTE_PORT_ALL) 1629 continue; 1630 1631 if (port_is_forwarding(pi) != 0 && test_done == 0) { 1632 printf("Please remove port %d from forwarding configuration.\n", pi); 1633 continue; 1634 } 1635 1636 if (port_is_bonding_slave(pi)) { 1637 printf("Please remove port %d from bonded device.\n", pi); 1638 continue; 1639 } 1640 1641 port = &ports[pi]; 1642 if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED, 1643 RTE_PORT_HANDLING) == 0) 1644 continue; 1645 1646 rte_eth_dev_stop(pi); 1647 1648 if (rte_atomic16_cmpset(&(port->port_status), 1649 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1650 printf("Port %d can not be set into stopped\n", pi); 1651 need_check_link_status = 1; 1652 } 1653 if (need_check_link_status && !no_link_check) 1654 check_all_ports_link_status(RTE_PORT_ALL); 1655 1656 printf("Done\n"); 1657 } 1658 1659 void 1660 close_port(portid_t pid) 1661 { 1662 portid_t pi; 1663 struct rte_port *port; 1664 1665 if (port_id_is_invalid(pid, ENABLED_WARN)) 1666 return; 1667 1668 printf("Closing ports...\n"); 1669 1670 RTE_ETH_FOREACH_DEV(pi) { 1671 if (pid != pi && pid != (portid_t)RTE_PORT_ALL) 1672 continue; 1673 1674 if (port_is_forwarding(pi) != 0 && test_done == 0) { 1675 printf("Please remove port %d from forwarding configuration.\n", pi); 1676 continue; 1677 } 1678 1679 if (port_is_bonding_slave(pi)) { 1680 printf("Please remove port %d from bonded device.\n", pi); 1681 continue; 1682 } 1683 1684 port = &ports[pi]; 1685 if (rte_atomic16_cmpset(&(port->port_status), 1686 RTE_PORT_CLOSED, RTE_PORT_CLOSED) == 1) { 1687 printf("Port %d is already closed\n", pi); 1688 continue; 1689 } 1690 1691 if (rte_atomic16_cmpset(&(port->port_status), 1692 RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) { 1693 printf("Port %d is now not stopped\n", pi); 1694 continue; 1695 } 1696 1697 if (port->flow_list) 1698 port_flow_flush(pi); 1699 rte_eth_dev_close(pi); 1700 1701 if (rte_atomic16_cmpset(&(port->port_status), 1702 RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0) 1703 printf("Port %d cannot be set to closed\n", pi); 1704 } 1705 1706 printf("Done\n"); 1707 } 1708 1709 void 1710 reset_port(portid_t pid) 1711 { 1712 int diag; 1713 portid_t pi; 1714 struct rte_port *port; 1715 1716 if (port_id_is_invalid(pid, ENABLED_WARN)) 1717 return; 1718 1719 printf("Resetting ports...\n"); 1720 1721 RTE_ETH_FOREACH_DEV(pi) { 1722 if (pid != pi && pid != (portid_t)RTE_PORT_ALL) 1723 continue; 1724 1725 if (port_is_forwarding(pi) != 0 && test_done == 0) { 1726 printf("Please remove port %d from forwarding " 1727 "configuration.\n", pi); 1728 continue; 1729 } 1730 1731 if (port_is_bonding_slave(pi)) { 1732 printf("Please remove port %d from bonded device.\n", 1733 pi); 1734 continue; 1735 } 1736 1737 diag = rte_eth_dev_reset(pi); 1738 if (diag == 0) { 1739 port = &ports[pi]; 1740 port->need_reconfig = 1; 1741 port->need_reconfig_queues = 1; 1742 } else { 1743 printf("Failed to reset port %d. diag=%d\n", pi, diag); 1744 } 1745 } 1746 1747 printf("Done\n"); 1748 } 1749 1750 void 1751 attach_port(char *identifier) 1752 { 1753 portid_t pi = 0; 1754 unsigned int socket_id; 1755 1756 printf("Attaching a new port...\n"); 1757 1758 if (identifier == NULL) { 1759 printf("Invalid parameters are specified\n"); 1760 return; 1761 } 1762 1763 if (rte_eth_dev_attach(identifier, &pi)) 1764 return; 1765 1766 socket_id = (unsigned)rte_eth_dev_socket_id(pi); 1767 /* if socket_id is invalid, set to 0 */ 1768 if (check_socket_id(socket_id) < 0) 1769 socket_id = 0; 1770 reconfig(pi, socket_id); 1771 rte_eth_promiscuous_enable(pi); 1772 1773 nb_ports = rte_eth_dev_count(); 1774 1775 ports[pi].port_status = RTE_PORT_STOPPED; 1776 1777 printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports); 1778 printf("Done\n"); 1779 } 1780 1781 void 1782 detach_port(uint8_t port_id) 1783 { 1784 char name[RTE_ETH_NAME_MAX_LEN]; 1785 1786 printf("Detaching a port...\n"); 1787 1788 if (!port_is_closed(port_id)) { 1789 printf("Please close port first\n"); 1790 return; 1791 } 1792 1793 if (ports[port_id].flow_list) 1794 port_flow_flush(port_id); 1795 1796 if (rte_eth_dev_detach(port_id, name)) { 1797 RTE_LOG(ERR, USER1, "Failed to detach port '%s'\n", name); 1798 return; 1799 } 1800 1801 nb_ports = rte_eth_dev_count(); 1802 1803 printf("Port '%s' is detached. Now total ports is %d\n", 1804 name, nb_ports); 1805 printf("Done\n"); 1806 return; 1807 } 1808 1809 void 1810 pmd_test_exit(void) 1811 { 1812 portid_t pt_id; 1813 1814 if (test_done == 0) 1815 stop_packet_forwarding(); 1816 1817 if (ports != NULL) { 1818 no_link_check = 1; 1819 RTE_ETH_FOREACH_DEV(pt_id) { 1820 printf("\nShutting down port %d...\n", pt_id); 1821 fflush(stdout); 1822 stop_port(pt_id); 1823 close_port(pt_id); 1824 } 1825 } 1826 printf("\nBye...\n"); 1827 } 1828 1829 typedef void (*cmd_func_t)(void); 1830 struct pmd_test_command { 1831 const char *cmd_name; 1832 cmd_func_t cmd_func; 1833 }; 1834 1835 #define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0])) 1836 1837 /* Check the link status of all ports in up to 9s, and print them finally */ 1838 static void 1839 check_all_ports_link_status(uint32_t port_mask) 1840 { 1841 #define CHECK_INTERVAL 100 /* 100ms */ 1842 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1843 portid_t portid; 1844 uint8_t count, all_ports_up, print_flag = 0; 1845 struct rte_eth_link link; 1846 1847 printf("Checking link statuses...\n"); 1848 fflush(stdout); 1849 for (count = 0; count <= MAX_CHECK_TIME; count++) { 1850 all_ports_up = 1; 1851 RTE_ETH_FOREACH_DEV(portid) { 1852 if ((port_mask & (1 << portid)) == 0) 1853 continue; 1854 memset(&link, 0, sizeof(link)); 1855 rte_eth_link_get_nowait(portid, &link); 1856 /* print link status if flag set */ 1857 if (print_flag == 1) { 1858 if (link.link_status) 1859 printf( 1860 "Port%d Link Up. speed %u Mbps- %s\n", 1861 portid, link.link_speed, 1862 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 1863 ("full-duplex") : ("half-duplex\n")); 1864 else 1865 printf("Port %d Link Down\n", portid); 1866 continue; 1867 } 1868 /* clear all_ports_up flag if any link down */ 1869 if (link.link_status == ETH_LINK_DOWN) { 1870 all_ports_up = 0; 1871 break; 1872 } 1873 } 1874 /* after finally printing all link status, get out */ 1875 if (print_flag == 1) 1876 break; 1877 1878 if (all_ports_up == 0) { 1879 fflush(stdout); 1880 rte_delay_ms(CHECK_INTERVAL); 1881 } 1882 1883 /* set the print_flag if all ports up or timeout */ 1884 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1885 print_flag = 1; 1886 } 1887 1888 if (lsc_interrupt) 1889 break; 1890 } 1891 } 1892 1893 static void 1894 rmv_event_callback(void *arg) 1895 { 1896 struct rte_eth_dev *dev; 1897 uint8_t port_id = (intptr_t)arg; 1898 1899 RTE_ETH_VALID_PORTID_OR_RET(port_id); 1900 dev = &rte_eth_devices[port_id]; 1901 1902 stop_port(port_id); 1903 close_port(port_id); 1904 printf("removing device %s\n", dev->device->name); 1905 if (rte_eal_dev_detach(dev->device)) 1906 RTE_LOG(ERR, USER1, "Failed to detach device %s\n", 1907 dev->device->name); 1908 } 1909 1910 /* This function is used by the interrupt thread */ 1911 static int 1912 eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param, 1913 void *ret_param) 1914 { 1915 static const char * const event_desc[] = { 1916 [RTE_ETH_EVENT_UNKNOWN] = "Unknown", 1917 [RTE_ETH_EVENT_INTR_LSC] = "LSC", 1918 [RTE_ETH_EVENT_QUEUE_STATE] = "Queue state", 1919 [RTE_ETH_EVENT_INTR_RESET] = "Interrupt reset", 1920 [RTE_ETH_EVENT_VF_MBOX] = "VF Mbox", 1921 [RTE_ETH_EVENT_MACSEC] = "MACsec", 1922 [RTE_ETH_EVENT_INTR_RMV] = "device removal", 1923 [RTE_ETH_EVENT_MAX] = NULL, 1924 }; 1925 1926 RTE_SET_USED(param); 1927 RTE_SET_USED(ret_param); 1928 1929 if (type >= RTE_ETH_EVENT_MAX) { 1930 fprintf(stderr, "\nPort %" PRIu8 ": %s called upon invalid event %d\n", 1931 port_id, __func__, type); 1932 fflush(stderr); 1933 } else if (event_print_mask & (UINT32_C(1) << type)) { 1934 printf("\nPort %" PRIu8 ": %s event\n", port_id, 1935 event_desc[type]); 1936 fflush(stdout); 1937 } 1938 1939 switch (type) { 1940 case RTE_ETH_EVENT_INTR_RMV: 1941 if (rte_eal_alarm_set(100000, 1942 rmv_event_callback, (void *)(intptr_t)port_id)) 1943 fprintf(stderr, "Could not set up deferred device removal\n"); 1944 break; 1945 default: 1946 break; 1947 } 1948 return 0; 1949 } 1950 1951 static int 1952 set_tx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port) 1953 { 1954 uint16_t i; 1955 int diag; 1956 uint8_t mapping_found = 0; 1957 1958 for (i = 0; i < nb_tx_queue_stats_mappings; i++) { 1959 if ((tx_queue_stats_mappings[i].port_id == port_id) && 1960 (tx_queue_stats_mappings[i].queue_id < nb_txq )) { 1961 diag = rte_eth_dev_set_tx_queue_stats_mapping(port_id, 1962 tx_queue_stats_mappings[i].queue_id, 1963 tx_queue_stats_mappings[i].stats_counter_id); 1964 if (diag != 0) 1965 return diag; 1966 mapping_found = 1; 1967 } 1968 } 1969 if (mapping_found) 1970 port->tx_queue_stats_mapping_enabled = 1; 1971 return 0; 1972 } 1973 1974 static int 1975 set_rx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port) 1976 { 1977 uint16_t i; 1978 int diag; 1979 uint8_t mapping_found = 0; 1980 1981 for (i = 0; i < nb_rx_queue_stats_mappings; i++) { 1982 if ((rx_queue_stats_mappings[i].port_id == port_id) && 1983 (rx_queue_stats_mappings[i].queue_id < nb_rxq )) { 1984 diag = rte_eth_dev_set_rx_queue_stats_mapping(port_id, 1985 rx_queue_stats_mappings[i].queue_id, 1986 rx_queue_stats_mappings[i].stats_counter_id); 1987 if (diag != 0) 1988 return diag; 1989 mapping_found = 1; 1990 } 1991 } 1992 if (mapping_found) 1993 port->rx_queue_stats_mapping_enabled = 1; 1994 return 0; 1995 } 1996 1997 static void 1998 map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port) 1999 { 2000 int diag = 0; 2001 2002 diag = set_tx_queue_stats_mapping_registers(pi, port); 2003 if (diag != 0) { 2004 if (diag == -ENOTSUP) { 2005 port->tx_queue_stats_mapping_enabled = 0; 2006 printf("TX queue stats mapping not supported port id=%d\n", pi); 2007 } 2008 else 2009 rte_exit(EXIT_FAILURE, 2010 "set_tx_queue_stats_mapping_registers " 2011 "failed for port id=%d diag=%d\n", 2012 pi, diag); 2013 } 2014 2015 diag = set_rx_queue_stats_mapping_registers(pi, port); 2016 if (diag != 0) { 2017 if (diag == -ENOTSUP) { 2018 port->rx_queue_stats_mapping_enabled = 0; 2019 printf("RX queue stats mapping not supported port id=%d\n", pi); 2020 } 2021 else 2022 rte_exit(EXIT_FAILURE, 2023 "set_rx_queue_stats_mapping_registers " 2024 "failed for port id=%d diag=%d\n", 2025 pi, diag); 2026 } 2027 } 2028 2029 static void 2030 rxtx_port_config(struct rte_port *port) 2031 { 2032 port->rx_conf = port->dev_info.default_rxconf; 2033 port->tx_conf = port->dev_info.default_txconf; 2034 2035 /* Check if any RX/TX parameters have been passed */ 2036 if (rx_pthresh != RTE_PMD_PARAM_UNSET) 2037 port->rx_conf.rx_thresh.pthresh = rx_pthresh; 2038 2039 if (rx_hthresh != RTE_PMD_PARAM_UNSET) 2040 port->rx_conf.rx_thresh.hthresh = rx_hthresh; 2041 2042 if (rx_wthresh != RTE_PMD_PARAM_UNSET) 2043 port->rx_conf.rx_thresh.wthresh = rx_wthresh; 2044 2045 if (rx_free_thresh != RTE_PMD_PARAM_UNSET) 2046 port->rx_conf.rx_free_thresh = rx_free_thresh; 2047 2048 if (rx_drop_en != RTE_PMD_PARAM_UNSET) 2049 port->rx_conf.rx_drop_en = rx_drop_en; 2050 2051 if (tx_pthresh != RTE_PMD_PARAM_UNSET) 2052 port->tx_conf.tx_thresh.pthresh = tx_pthresh; 2053 2054 if (tx_hthresh != RTE_PMD_PARAM_UNSET) 2055 port->tx_conf.tx_thresh.hthresh = tx_hthresh; 2056 2057 if (tx_wthresh != RTE_PMD_PARAM_UNSET) 2058 port->tx_conf.tx_thresh.wthresh = tx_wthresh; 2059 2060 if (tx_rs_thresh != RTE_PMD_PARAM_UNSET) 2061 port->tx_conf.tx_rs_thresh = tx_rs_thresh; 2062 2063 if (tx_free_thresh != RTE_PMD_PARAM_UNSET) 2064 port->tx_conf.tx_free_thresh = tx_free_thresh; 2065 2066 if (txq_flags != RTE_PMD_PARAM_UNSET) 2067 port->tx_conf.txq_flags = txq_flags; 2068 } 2069 2070 void 2071 init_port_config(void) 2072 { 2073 portid_t pid; 2074 struct rte_port *port; 2075 2076 RTE_ETH_FOREACH_DEV(pid) { 2077 port = &ports[pid]; 2078 port->dev_conf.rxmode = rx_mode; 2079 port->dev_conf.fdir_conf = fdir_conf; 2080 if (nb_rxq > 1) { 2081 port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL; 2082 port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf; 2083 } else { 2084 port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL; 2085 port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0; 2086 } 2087 2088 if (port->dcb_flag == 0) { 2089 if( port->dev_conf.rx_adv_conf.rss_conf.rss_hf != 0) 2090 port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; 2091 else 2092 port->dev_conf.rxmode.mq_mode = ETH_MQ_RX_NONE; 2093 } 2094 2095 rxtx_port_config(port); 2096 2097 rte_eth_macaddr_get(pid, &port->eth_addr); 2098 2099 map_port_queue_stats_mapping_registers(pid, port); 2100 #if defined RTE_LIBRTE_IXGBE_PMD && defined RTE_LIBRTE_IXGBE_BYPASS 2101 rte_pmd_ixgbe_bypass_init(pid); 2102 #endif 2103 2104 if (lsc_interrupt && 2105 (rte_eth_devices[pid].data->dev_flags & 2106 RTE_ETH_DEV_INTR_LSC)) 2107 port->dev_conf.intr_conf.lsc = 1; 2108 if (rmv_interrupt && 2109 (rte_eth_devices[pid].data->dev_flags & 2110 RTE_ETH_DEV_INTR_RMV)) 2111 port->dev_conf.intr_conf.rmv = 1; 2112 } 2113 } 2114 2115 void set_port_slave_flag(portid_t slave_pid) 2116 { 2117 struct rte_port *port; 2118 2119 port = &ports[slave_pid]; 2120 port->slave_flag = 1; 2121 } 2122 2123 void clear_port_slave_flag(portid_t slave_pid) 2124 { 2125 struct rte_port *port; 2126 2127 port = &ports[slave_pid]; 2128 port->slave_flag = 0; 2129 } 2130 2131 uint8_t port_is_bonding_slave(portid_t slave_pid) 2132 { 2133 struct rte_port *port; 2134 2135 port = &ports[slave_pid]; 2136 return port->slave_flag; 2137 } 2138 2139 const uint16_t vlan_tags[] = { 2140 0, 1, 2, 3, 4, 5, 6, 7, 2141 8, 9, 10, 11, 12, 13, 14, 15, 2142 16, 17, 18, 19, 20, 21, 22, 23, 2143 24, 25, 26, 27, 28, 29, 30, 31 2144 }; 2145 2146 static int 2147 get_eth_dcb_conf(struct rte_eth_conf *eth_conf, 2148 enum dcb_mode_enable dcb_mode, 2149 enum rte_eth_nb_tcs num_tcs, 2150 uint8_t pfc_en) 2151 { 2152 uint8_t i; 2153 2154 /* 2155 * Builds up the correct configuration for dcb+vt based on the vlan tags array 2156 * given above, and the number of traffic classes available for use. 2157 */ 2158 if (dcb_mode == DCB_VT_ENABLED) { 2159 struct rte_eth_vmdq_dcb_conf *vmdq_rx_conf = 2160 ð_conf->rx_adv_conf.vmdq_dcb_conf; 2161 struct rte_eth_vmdq_dcb_tx_conf *vmdq_tx_conf = 2162 ð_conf->tx_adv_conf.vmdq_dcb_tx_conf; 2163 2164 /* VMDQ+DCB RX and TX configurations */ 2165 vmdq_rx_conf->enable_default_pool = 0; 2166 vmdq_rx_conf->default_pool = 0; 2167 vmdq_rx_conf->nb_queue_pools = 2168 (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); 2169 vmdq_tx_conf->nb_queue_pools = 2170 (num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); 2171 2172 vmdq_rx_conf->nb_pool_maps = vmdq_rx_conf->nb_queue_pools; 2173 for (i = 0; i < vmdq_rx_conf->nb_pool_maps; i++) { 2174 vmdq_rx_conf->pool_map[i].vlan_id = vlan_tags[i]; 2175 vmdq_rx_conf->pool_map[i].pools = 2176 1 << (i % vmdq_rx_conf->nb_queue_pools); 2177 } 2178 for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { 2179 vmdq_rx_conf->dcb_tc[i] = i; 2180 vmdq_tx_conf->dcb_tc[i] = i; 2181 } 2182 2183 /* set DCB mode of RX and TX of multiple queues */ 2184 eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_DCB; 2185 eth_conf->txmode.mq_mode = ETH_MQ_TX_VMDQ_DCB; 2186 } else { 2187 struct rte_eth_dcb_rx_conf *rx_conf = 2188 ð_conf->rx_adv_conf.dcb_rx_conf; 2189 struct rte_eth_dcb_tx_conf *tx_conf = 2190 ð_conf->tx_adv_conf.dcb_tx_conf; 2191 2192 rx_conf->nb_tcs = num_tcs; 2193 tx_conf->nb_tcs = num_tcs; 2194 2195 for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { 2196 rx_conf->dcb_tc[i] = i % num_tcs; 2197 tx_conf->dcb_tc[i] = i % num_tcs; 2198 } 2199 eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB_RSS; 2200 eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf; 2201 eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB; 2202 } 2203 2204 if (pfc_en) 2205 eth_conf->dcb_capability_en = 2206 ETH_DCB_PG_SUPPORT | ETH_DCB_PFC_SUPPORT; 2207 else 2208 eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT; 2209 2210 return 0; 2211 } 2212 2213 int 2214 init_port_dcb_config(portid_t pid, 2215 enum dcb_mode_enable dcb_mode, 2216 enum rte_eth_nb_tcs num_tcs, 2217 uint8_t pfc_en) 2218 { 2219 struct rte_eth_conf port_conf; 2220 struct rte_port *rte_port; 2221 int retval; 2222 uint16_t i; 2223 2224 rte_port = &ports[pid]; 2225 2226 memset(&port_conf, 0, sizeof(struct rte_eth_conf)); 2227 /* Enter DCB configuration status */ 2228 dcb_config = 1; 2229 2230 /*set configuration of DCB in vt mode and DCB in non-vt mode*/ 2231 retval = get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en); 2232 if (retval < 0) 2233 return retval; 2234 port_conf.rxmode.hw_vlan_filter = 1; 2235 2236 /** 2237 * Write the configuration into the device. 2238 * Set the numbers of RX & TX queues to 0, so 2239 * the RX & TX queues will not be setup. 2240 */ 2241 rte_eth_dev_configure(pid, 0, 0, &port_conf); 2242 2243 rte_eth_dev_info_get(pid, &rte_port->dev_info); 2244 2245 /* If dev_info.vmdq_pool_base is greater than 0, 2246 * the queue id of vmdq pools is started after pf queues. 2247 */ 2248 if (dcb_mode == DCB_VT_ENABLED && 2249 rte_port->dev_info.vmdq_pool_base > 0) { 2250 printf("VMDQ_DCB multi-queue mode is nonsensical" 2251 " for port %d.", pid); 2252 return -1; 2253 } 2254 2255 /* Assume the ports in testpmd have the same dcb capability 2256 * and has the same number of rxq and txq in dcb mode 2257 */ 2258 if (dcb_mode == DCB_VT_ENABLED) { 2259 if (rte_port->dev_info.max_vfs > 0) { 2260 nb_rxq = rte_port->dev_info.nb_rx_queues; 2261 nb_txq = rte_port->dev_info.nb_tx_queues; 2262 } else { 2263 nb_rxq = rte_port->dev_info.max_rx_queues; 2264 nb_txq = rte_port->dev_info.max_tx_queues; 2265 } 2266 } else { 2267 /*if vt is disabled, use all pf queues */ 2268 if (rte_port->dev_info.vmdq_pool_base == 0) { 2269 nb_rxq = rte_port->dev_info.max_rx_queues; 2270 nb_txq = rte_port->dev_info.max_tx_queues; 2271 } else { 2272 nb_rxq = (queueid_t)num_tcs; 2273 nb_txq = (queueid_t)num_tcs; 2274 2275 } 2276 } 2277 rx_free_thresh = 64; 2278 2279 memcpy(&rte_port->dev_conf, &port_conf, sizeof(struct rte_eth_conf)); 2280 2281 rxtx_port_config(rte_port); 2282 /* VLAN filter */ 2283 rte_port->dev_conf.rxmode.hw_vlan_filter = 1; 2284 for (i = 0; i < RTE_DIM(vlan_tags); i++) 2285 rx_vft_set(pid, vlan_tags[i], 1); 2286 2287 rte_eth_macaddr_get(pid, &rte_port->eth_addr); 2288 map_port_queue_stats_mapping_registers(pid, rte_port); 2289 2290 rte_port->dcb_flag = 1; 2291 2292 return 0; 2293 } 2294 2295 static void 2296 init_port(void) 2297 { 2298 /* Configuration of Ethernet ports. */ 2299 ports = rte_zmalloc("testpmd: ports", 2300 sizeof(struct rte_port) * RTE_MAX_ETHPORTS, 2301 RTE_CACHE_LINE_SIZE); 2302 if (ports == NULL) { 2303 rte_exit(EXIT_FAILURE, 2304 "rte_zmalloc(%d struct rte_port) failed\n", 2305 RTE_MAX_ETHPORTS); 2306 } 2307 } 2308 2309 static void 2310 force_quit(void) 2311 { 2312 pmd_test_exit(); 2313 prompt_exit(); 2314 } 2315 2316 static void 2317 print_stats(void) 2318 { 2319 uint8_t i; 2320 const char clr[] = { 27, '[', '2', 'J', '\0' }; 2321 const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' }; 2322 2323 /* Clear screen and move to top left */ 2324 printf("%s%s", clr, top_left); 2325 2326 printf("\nPort statistics ===================================="); 2327 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 2328 nic_stats_display(fwd_ports_ids[i]); 2329 } 2330 2331 static void 2332 signal_handler(int signum) 2333 { 2334 if (signum == SIGINT || signum == SIGTERM) { 2335 printf("\nSignal %d received, preparing to exit...\n", 2336 signum); 2337 #ifdef RTE_LIBRTE_PDUMP 2338 /* uninitialize packet capture framework */ 2339 rte_pdump_uninit(); 2340 #endif 2341 #ifdef RTE_LIBRTE_LATENCY_STATS 2342 rte_latencystats_uninit(); 2343 #endif 2344 force_quit(); 2345 /* Set flag to indicate the force termination. */ 2346 f_quit = 1; 2347 /* exit with the expected status */ 2348 signal(signum, SIG_DFL); 2349 kill(getpid(), signum); 2350 } 2351 } 2352 2353 int 2354 main(int argc, char** argv) 2355 { 2356 int diag; 2357 portid_t port_id; 2358 2359 signal(SIGINT, signal_handler); 2360 signal(SIGTERM, signal_handler); 2361 2362 diag = rte_eal_init(argc, argv); 2363 if (diag < 0) 2364 rte_panic("Cannot init EAL\n"); 2365 2366 if (mlockall(MCL_CURRENT | MCL_FUTURE)) { 2367 RTE_LOG(NOTICE, USER1, "mlockall() failed with error \"%s\"\n", 2368 strerror(errno)); 2369 } 2370 2371 #ifdef RTE_LIBRTE_PDUMP 2372 /* initialize packet capture framework */ 2373 rte_pdump_init(NULL); 2374 #endif 2375 2376 nb_ports = (portid_t) rte_eth_dev_count(); 2377 if (nb_ports == 0) 2378 RTE_LOG(WARNING, EAL, "No probed ethernet devices\n"); 2379 2380 /* allocate port structures, and init them */ 2381 init_port(); 2382 2383 set_def_fwd_config(); 2384 if (nb_lcores == 0) 2385 rte_panic("Empty set of forwarding logical cores - check the " 2386 "core mask supplied in the command parameters\n"); 2387 2388 /* Bitrate/latency stats disabled by default */ 2389 #ifdef RTE_LIBRTE_BITRATE 2390 bitrate_enabled = 0; 2391 #endif 2392 #ifdef RTE_LIBRTE_LATENCY_STATS 2393 latencystats_enabled = 0; 2394 #endif 2395 2396 argc -= diag; 2397 argv += diag; 2398 if (argc > 1) 2399 launch_args_parse(argc, argv); 2400 2401 if (tx_first && interactive) 2402 rte_exit(EXIT_FAILURE, "--tx-first cannot be used on " 2403 "interactive mode.\n"); 2404 2405 if (tx_first && lsc_interrupt) { 2406 printf("Warning: lsc_interrupt needs to be off when " 2407 " using tx_first. Disabling.\n"); 2408 lsc_interrupt = 0; 2409 } 2410 2411 if (!nb_rxq && !nb_txq) 2412 printf("Warning: Either rx or tx queues should be non-zero\n"); 2413 2414 if (nb_rxq > 1 && nb_rxq > nb_txq) 2415 printf("Warning: nb_rxq=%d enables RSS configuration, " 2416 "but nb_txq=%d will prevent to fully test it.\n", 2417 nb_rxq, nb_txq); 2418 2419 init_config(); 2420 if (start_port(RTE_PORT_ALL) != 0) 2421 rte_exit(EXIT_FAILURE, "Start ports failed\n"); 2422 2423 /* set all ports to promiscuous mode by default */ 2424 RTE_ETH_FOREACH_DEV(port_id) 2425 rte_eth_promiscuous_enable(port_id); 2426 2427 /* Init metrics library */ 2428 rte_metrics_init(rte_socket_id()); 2429 2430 #ifdef RTE_LIBRTE_LATENCY_STATS 2431 if (latencystats_enabled != 0) { 2432 int ret = rte_latencystats_init(1, NULL); 2433 if (ret) 2434 printf("Warning: latencystats init()" 2435 " returned error %d\n", ret); 2436 printf("Latencystats running on lcore %d\n", 2437 latencystats_lcore_id); 2438 } 2439 #endif 2440 2441 /* Setup bitrate stats */ 2442 #ifdef RTE_LIBRTE_BITRATE 2443 if (bitrate_enabled != 0) { 2444 bitrate_data = rte_stats_bitrate_create(); 2445 if (bitrate_data == NULL) 2446 rte_exit(EXIT_FAILURE, 2447 "Could not allocate bitrate data.\n"); 2448 rte_stats_bitrate_reg(bitrate_data); 2449 } 2450 #endif 2451 2452 #ifdef RTE_LIBRTE_CMDLINE 2453 if (strlen(cmdline_filename) != 0) 2454 cmdline_read_from_file(cmdline_filename); 2455 2456 if (interactive == 1) { 2457 if (auto_start) { 2458 printf("Start automatic packet forwarding\n"); 2459 start_packet_forwarding(0); 2460 } 2461 prompt(); 2462 pmd_test_exit(); 2463 } else 2464 #endif 2465 { 2466 char c; 2467 int rc; 2468 2469 f_quit = 0; 2470 2471 printf("No commandline core given, start packet forwarding\n"); 2472 start_packet_forwarding(tx_first); 2473 if (stats_period != 0) { 2474 uint64_t prev_time = 0, cur_time, diff_time = 0; 2475 uint64_t timer_period; 2476 2477 /* Convert to number of cycles */ 2478 timer_period = stats_period * rte_get_timer_hz(); 2479 2480 while (f_quit == 0) { 2481 cur_time = rte_get_timer_cycles(); 2482 diff_time += cur_time - prev_time; 2483 2484 if (diff_time >= timer_period) { 2485 print_stats(); 2486 /* Reset the timer */ 2487 diff_time = 0; 2488 } 2489 /* Sleep to avoid unnecessary checks */ 2490 prev_time = cur_time; 2491 sleep(1); 2492 } 2493 } 2494 2495 printf("Press enter to exit\n"); 2496 rc = read(0, &c, 1); 2497 pmd_test_exit(); 2498 if (rc < 0) 2499 return 1; 2500 } 2501 2502 return 0; 2503 } 2504