1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2012 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 <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <signal.h> 39 #include <string.h> 40 #include <time.h> 41 #include <fcntl.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_byteorder.h> 54 #include <rte_log.h> 55 #include <rte_debug.h> 56 #include <rte_cycles.h> 57 #include <rte_memory.h> 58 #include <rte_memcpy.h> 59 #include <rte_memzone.h> 60 #include <rte_launch.h> 61 #include <rte_tailq.h> 62 #include <rte_eal.h> 63 #include <rte_per_lcore.h> 64 #include <rte_lcore.h> 65 #include <rte_atomic.h> 66 #include <rte_branch_prediction.h> 67 #include <rte_ring.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_string_fns.h> 76 77 #include "testpmd.h" 78 79 uint16_t verbose_level = 0; /**< Silent by default. */ 80 81 /* use master core for command line ? */ 82 uint8_t interactive = 0; 83 84 /* 85 * NUMA support configuration. 86 * When set, the NUMA support attempts to dispatch the allocation of the 87 * RX and TX memory rings, and of the DMA memory buffers (mbufs) for the 88 * probed ports among the CPU sockets 0 and 1. 89 * Otherwise, all memory is allocated from CPU socket 0. 90 */ 91 uint8_t numa_support = 0; /**< No numa support by default */ 92 93 /* 94 * Record the Ethernet address of peer target ports to which packets are 95 * forwarded. 96 * Must be instanciated with the ethernet addresses of peer traffic generator 97 * ports. 98 */ 99 struct ether_addr peer_eth_addrs[RTE_MAX_ETHPORTS]; 100 portid_t nb_peer_eth_addrs = 0; 101 102 /* 103 * Probed Target Environment. 104 */ 105 struct rte_port *ports; /**< For all probed ethernet ports. */ 106 portid_t nb_ports; /**< Number of probed ethernet ports. */ 107 struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */ 108 lcoreid_t nb_lcores; /**< Number of probed logical cores. */ 109 110 /* 111 * Test Forwarding Configuration. 112 * nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores 113 * nb_fwd_ports <= nb_cfg_ports <= nb_ports 114 */ 115 lcoreid_t nb_cfg_lcores; /**< Number of configured logical cores. */ 116 lcoreid_t nb_fwd_lcores; /**< Number of forwarding logical cores. */ 117 portid_t nb_cfg_ports; /**< Number of configured ports. */ 118 portid_t nb_fwd_ports; /**< Number of forwarding ports. */ 119 120 unsigned int fwd_lcores_cpuids[RTE_MAX_LCORE]; /**< CPU ids configuration. */ 121 portid_t fwd_ports_ids[RTE_MAX_ETHPORTS]; /**< Port ids configuration. */ 122 123 struct fwd_stream **fwd_streams; /**< For each RX queue of each port. */ 124 streamid_t nb_fwd_streams; /**< Is equal to (nb_ports * nb_rxq). */ 125 126 /* 127 * Forwarding engines. 128 */ 129 struct fwd_engine * fwd_engines[] = { 130 &io_fwd_engine, 131 &mac_fwd_engine, 132 &rx_only_engine, 133 &tx_only_engine, 134 &csum_fwd_engine, 135 #ifdef RTE_LIBRTE_IEEE1588 136 &ieee1588_fwd_engine, 137 #endif 138 NULL, 139 }; 140 141 struct fwd_config cur_fwd_config; 142 struct fwd_engine *cur_fwd_eng = &io_fwd_engine; /**< IO mode by default. */ 143 144 uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */ 145 uint32_t param_total_num_mbufs = 0; /**< number of mbufs in all pools - if 146 * specified on command-line. */ 147 148 /* 149 * Configuration of packet segments used by the "txonly" processing engine. 150 */ 151 uint16_t tx_pkt_length = TXONLY_DEF_PACKET_LEN; /**< TXONLY packet length. */ 152 uint16_t tx_pkt_seg_lengths[RTE_MAX_SEGS_PER_PKT] = { 153 TXONLY_DEF_PACKET_LEN, 154 }; 155 uint8_t tx_pkt_nb_segs = 1; /**< Number of segments in TXONLY packets */ 156 157 uint16_t nb_pkt_per_burst = DEF_PKT_BURST; /**< Number of packets per burst. */ 158 uint16_t mb_mempool_cache = DEF_PKT_BURST; /**< Size of mbuf mempool cache. */ 159 160 /* current configuration is in DCB or not,0 means it is not in DCB mode */ 161 uint8_t dcb_config = 0; 162 163 /* Whether the dcb is in testing status */ 164 uint8_t dcb_test = 0; 165 166 /* DCB on and VT on mapping is default */ 167 enum dcb_queue_mapping_mode dcb_q_mapping = DCB_VT_Q_MAPPING; 168 169 /* 170 * Configurable number of RX/TX queues. 171 */ 172 queueid_t nb_rxq = 1; /**< Number of RX queues per port. */ 173 queueid_t nb_txq = 1; /**< Number of TX queues per port. */ 174 175 /* 176 * Configurable number of RX/TX ring descriptors. 177 */ 178 #define RTE_TEST_RX_DESC_DEFAULT 128 179 #define RTE_TEST_TX_DESC_DEFAULT 512 180 uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */ 181 uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */ 182 183 /* 184 * Configurable values of RX and TX ring threshold registers. 185 */ 186 #define RX_PTHRESH 8 /**< Default value of RX prefetch threshold register. */ 187 #define RX_HTHRESH 8 /**< Default value of RX host threshold register. */ 188 #define RX_WTHRESH 4 /**< Default value of RX write-back threshold register. */ 189 190 #define TX_PTHRESH 36 /**< Default value of TX prefetch threshold register. */ 191 #define TX_HTHRESH 0 /**< Default value of TX host threshold register. */ 192 #define TX_WTHRESH 0 /**< Default value of TX write-back threshold register. */ 193 194 struct rte_eth_thresh rx_thresh = { 195 .pthresh = RX_PTHRESH, 196 .hthresh = RX_HTHRESH, 197 .wthresh = RX_WTHRESH, 198 }; 199 200 struct rte_eth_thresh tx_thresh = { 201 .pthresh = TX_PTHRESH, 202 .hthresh = TX_HTHRESH, 203 .wthresh = TX_WTHRESH, 204 }; 205 206 /* 207 * Configurable value of RX free threshold. 208 */ 209 uint16_t rx_free_thresh = 0; /* Immediately free RX descriptors by default. */ 210 211 /* 212 * Configurable value of RX drop enable. 213 */ 214 uint8_t rx_drop_en = 0; /* Drop packets when no descriptors for queue. */ 215 216 /* 217 * Configurable value of TX free threshold. 218 */ 219 uint16_t tx_free_thresh = 0; /* Use default values. */ 220 221 /* 222 * Configurable value of TX RS bit threshold. 223 */ 224 uint16_t tx_rs_thresh = 0; /* Use default values. */ 225 226 /* 227 * Configurable value of TX queue flags. 228 */ 229 uint32_t txq_flags = 0; /* No flags set. */ 230 231 /* 232 * Receive Side Scaling (RSS) configuration. 233 */ 234 uint16_t rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6; /* RSS IP by default. */ 235 236 /* 237 * Port topology configuration 238 */ 239 uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */ 240 241 /* 242 * Ethernet device configuration. 243 */ 244 struct rte_eth_rxmode rx_mode = { 245 .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */ 246 .split_hdr_size = 0, 247 .header_split = 0, /**< Header Split disabled. */ 248 .hw_ip_checksum = 0, /**< IP checksum offload disabled. */ 249 .hw_vlan_filter = 1, /**< VLAN filtering enabled. */ 250 .hw_vlan_strip = 1, /**< VLAN strip enabled. */ 251 .hw_vlan_extend = 0, /**< Extended VLAN disabled. */ 252 .jumbo_frame = 0, /**< Jumbo Frame Support disabled. */ 253 .hw_strip_crc = 0, /**< CRC stripping by hardware disabled. */ 254 }; 255 256 struct rte_fdir_conf fdir_conf = { 257 .mode = RTE_FDIR_MODE_NONE, 258 .pballoc = RTE_FDIR_PBALLOC_64K, 259 .status = RTE_FDIR_REPORT_STATUS, 260 .flexbytes_offset = 0x6, 261 .drop_queue = 127, 262 }; 263 264 static volatile int test_done = 1; /* stop packet forwarding when set to 1. */ 265 266 struct queue_stats_mappings tx_queue_stats_mappings_array[MAX_TX_QUEUE_STATS_MAPPINGS]; 267 struct queue_stats_mappings rx_queue_stats_mappings_array[MAX_RX_QUEUE_STATS_MAPPINGS]; 268 269 struct queue_stats_mappings *tx_queue_stats_mappings = tx_queue_stats_mappings_array; 270 struct queue_stats_mappings *rx_queue_stats_mappings = rx_queue_stats_mappings_array; 271 272 uint16_t nb_tx_queue_stats_mappings = 0; 273 uint16_t nb_rx_queue_stats_mappings = 0; 274 275 /* Forward function declarations */ 276 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); 277 static void check_all_ports_link_status(uint8_t port_num, uint32_t port_mask); 278 279 /* 280 * Check if all the ports are started. 281 * If yes, return positive value. If not, return zero. 282 */ 283 static int all_ports_started(void); 284 285 /* 286 * Setup default configuration. 287 */ 288 static void 289 set_default_fwd_lcores_config(void) 290 { 291 unsigned int i; 292 unsigned int nb_lc; 293 294 nb_lc = 0; 295 for (i = 0; i < RTE_MAX_LCORE; i++) { 296 if (! rte_lcore_is_enabled(i)) 297 continue; 298 if (i == rte_get_master_lcore()) 299 continue; 300 fwd_lcores_cpuids[nb_lc++] = i; 301 } 302 nb_lcores = (lcoreid_t) nb_lc; 303 nb_cfg_lcores = nb_lcores; 304 nb_fwd_lcores = 1; 305 } 306 307 static void 308 set_def_peer_eth_addrs(void) 309 { 310 portid_t i; 311 312 for (i = 0; i < RTE_MAX_ETHPORTS; i++) { 313 peer_eth_addrs[i].addr_bytes[0] = ETHER_LOCAL_ADMIN_ADDR; 314 peer_eth_addrs[i].addr_bytes[5] = i; 315 } 316 } 317 318 static void 319 set_default_fwd_ports_config(void) 320 { 321 portid_t pt_id; 322 323 for (pt_id = 0; pt_id < nb_ports; pt_id++) 324 fwd_ports_ids[pt_id] = pt_id; 325 326 nb_cfg_ports = nb_ports; 327 nb_fwd_ports = nb_ports; 328 } 329 330 void 331 set_def_fwd_config(void) 332 { 333 set_default_fwd_lcores_config(); 334 set_def_peer_eth_addrs(); 335 set_default_fwd_ports_config(); 336 } 337 338 /* 339 * Configuration initialisation done once at init time. 340 */ 341 struct mbuf_ctor_arg { 342 uint16_t seg_buf_offset; /**< offset of data in data segment of mbuf. */ 343 uint16_t seg_buf_size; /**< size of data segment in mbuf. */ 344 }; 345 346 struct mbuf_pool_ctor_arg { 347 uint16_t seg_buf_size; /**< size of data segment in mbuf. */ 348 }; 349 350 static void 351 testpmd_mbuf_ctor(struct rte_mempool *mp, 352 void *opaque_arg, 353 void *raw_mbuf, 354 __attribute__((unused)) unsigned i) 355 { 356 struct mbuf_ctor_arg *mb_ctor_arg; 357 struct rte_mbuf *mb; 358 359 mb_ctor_arg = (struct mbuf_ctor_arg *) opaque_arg; 360 mb = (struct rte_mbuf *) raw_mbuf; 361 362 mb->pool = mp; 363 mb->buf_addr = (void *) ((char *)mb + mb_ctor_arg->seg_buf_offset); 364 mb->buf_physaddr = (uint64_t) (rte_mempool_virt2phy(mp, mb) + 365 mb_ctor_arg->seg_buf_offset); 366 mb->buf_len = mb_ctor_arg->seg_buf_size; 367 mb->type = RTE_MBUF_PKT; 368 mb->ol_flags = 0; 369 mb->pkt.data = (char *) mb->buf_addr + RTE_PKTMBUF_HEADROOM; 370 mb->pkt.nb_segs = 1; 371 mb->pkt.vlan_macip.data = 0; 372 mb->pkt.hash.rss = 0; 373 } 374 375 static void 376 testpmd_mbuf_pool_ctor(struct rte_mempool *mp, 377 void *opaque_arg) 378 { 379 struct mbuf_pool_ctor_arg *mbp_ctor_arg; 380 struct rte_pktmbuf_pool_private *mbp_priv; 381 382 if (mp->private_data_size < sizeof(struct rte_pktmbuf_pool_private)) { 383 printf("%s(%s) private_data_size %d < %d\n", 384 __func__, mp->name, (int) mp->private_data_size, 385 (int) sizeof(struct rte_pktmbuf_pool_private)); 386 return; 387 } 388 mbp_ctor_arg = (struct mbuf_pool_ctor_arg *) opaque_arg; 389 mbp_priv = (struct rte_pktmbuf_pool_private *) 390 ((char *)mp + sizeof(struct rte_mempool)); 391 mbp_priv->mbuf_data_room_size = mbp_ctor_arg->seg_buf_size; 392 } 393 394 static void 395 mbuf_pool_create(uint16_t mbuf_seg_size, unsigned nb_mbuf, 396 unsigned int socket_id) 397 { 398 char pool_name[RTE_MEMPOOL_NAMESIZE]; 399 struct rte_mempool *rte_mp; 400 struct mbuf_pool_ctor_arg mbp_ctor_arg; 401 struct mbuf_ctor_arg mb_ctor_arg; 402 uint32_t mb_size; 403 404 mbp_ctor_arg.seg_buf_size = (uint16_t) (RTE_PKTMBUF_HEADROOM + 405 mbuf_seg_size); 406 mb_ctor_arg.seg_buf_offset = 407 (uint16_t) CACHE_LINE_ROUNDUP(sizeof(struct rte_mbuf)); 408 mb_ctor_arg.seg_buf_size = mbp_ctor_arg.seg_buf_size; 409 mb_size = mb_ctor_arg.seg_buf_offset + mb_ctor_arg.seg_buf_size; 410 mbuf_poolname_build(socket_id, pool_name, sizeof(pool_name)); 411 rte_mp = rte_mempool_create(pool_name, nb_mbuf, (unsigned) mb_size, 412 (unsigned) mb_mempool_cache, 413 sizeof(struct rte_pktmbuf_pool_private), 414 testpmd_mbuf_pool_ctor, &mbp_ctor_arg, 415 testpmd_mbuf_ctor, &mb_ctor_arg, 416 socket_id, 0); 417 if (rte_mp == NULL) { 418 rte_exit(EXIT_FAILURE, "Creation of mbuf pool for socket %u " 419 "failed\n", socket_id); 420 } 421 } 422 423 static void 424 init_config(void) 425 { 426 portid_t pid; 427 struct rte_port *port; 428 struct rte_mempool *mbp; 429 unsigned int nb_mbuf_per_pool; 430 lcoreid_t lc_id; 431 432 /* Configuration of logical cores. */ 433 fwd_lcores = rte_zmalloc("testpmd: fwd_lcores", 434 sizeof(struct fwd_lcore *) * nb_lcores, 435 CACHE_LINE_SIZE); 436 if (fwd_lcores == NULL) { 437 rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_lcore *)) " 438 "failed\n", nb_lcores); 439 } 440 for (lc_id = 0; lc_id < nb_lcores; lc_id++) { 441 fwd_lcores[lc_id] = rte_zmalloc("testpmd: struct fwd_lcore", 442 sizeof(struct fwd_lcore), 443 CACHE_LINE_SIZE); 444 if (fwd_lcores[lc_id] == NULL) { 445 rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_lcore) " 446 "failed\n"); 447 } 448 fwd_lcores[lc_id]->cpuid_idx = lc_id; 449 } 450 451 /* 452 * Create pools of mbuf. 453 * If NUMA support is disabled, create a single pool of mbuf in 454 * socket 0 memory. 455 * Otherwise, create a pool of mbuf in the memory of sockets 0 and 1. 456 * 457 * Use the maximum value of nb_rxd and nb_txd here, then nb_rxd and 458 * nb_txd can be configured at run time. 459 */ 460 if (param_total_num_mbufs) 461 nb_mbuf_per_pool = param_total_num_mbufs; 462 else { 463 nb_mbuf_per_pool = RTE_TEST_RX_DESC_MAX + (nb_lcores * mb_mempool_cache) 464 + RTE_TEST_TX_DESC_MAX + MAX_PKT_BURST; 465 nb_mbuf_per_pool = (nb_mbuf_per_pool * nb_ports); 466 } 467 if (numa_support) { 468 nb_mbuf_per_pool /= 2; 469 mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0); 470 mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 1); 471 } else { 472 mbuf_pool_create(mbuf_data_size, nb_mbuf_per_pool, 0); 473 } 474 475 /* 476 * Records which Mbuf pool to use by each logical core, if needed. 477 */ 478 for (lc_id = 0; lc_id < nb_lcores; lc_id++) { 479 mbp = mbuf_pool_find(rte_lcore_to_socket_id(lc_id)); 480 if (mbp == NULL) 481 mbp = mbuf_pool_find(0); 482 fwd_lcores[lc_id]->mbp = mbp; 483 } 484 485 /* Configuration of Ethernet ports. */ 486 ports = rte_zmalloc("testpmd: ports", 487 sizeof(struct rte_port) * nb_ports, 488 CACHE_LINE_SIZE); 489 if (ports == NULL) { 490 rte_exit(EXIT_FAILURE, "rte_zmalloc(%d struct rte_port) " 491 "failed\n", nb_ports); 492 } 493 494 for (pid = 0; pid < nb_ports; pid++) { 495 port = &ports[pid]; 496 rte_eth_dev_info_get(pid, &port->dev_info); 497 498 /* set flag to initialize port/queue */ 499 port->need_reconfig = 1; 500 port->need_reconfig_queues = 1; 501 } 502 503 init_port_config(); 504 505 /* Configuration of packet forwarding streams. */ 506 if (init_fwd_streams() < 0) 507 rte_exit(EXIT_FAILURE, "FAIL from init_fwd_streams()\n"); 508 } 509 510 int 511 init_fwd_streams(void) 512 { 513 portid_t pid; 514 struct rte_port *port; 515 streamid_t sm_id, nb_fwd_streams_new; 516 517 /* set socket id according to numa or not */ 518 for (pid = 0; pid < nb_ports; pid++) { 519 port = &ports[pid]; 520 if (nb_rxq > port->dev_info.max_rx_queues) { 521 printf("Fail: nb_rxq(%d) is greater than " 522 "max_rx_queues(%d)\n", nb_rxq, 523 port->dev_info.max_rx_queues); 524 return -1; 525 } 526 if (nb_txq > port->dev_info.max_tx_queues) { 527 printf("Fail: nb_txq(%d) is greater than " 528 "max_tx_queues(%d)\n", nb_txq, 529 port->dev_info.max_tx_queues); 530 return -1; 531 } 532 if (numa_support) 533 port->socket_id = (pid < (nb_ports >> 1)) ? 0 : 1; 534 else 535 port->socket_id = 0; 536 } 537 538 nb_fwd_streams_new = (streamid_t)(nb_ports * nb_rxq); 539 if (nb_fwd_streams_new == nb_fwd_streams) 540 return 0; 541 /* clear the old */ 542 if (fwd_streams != NULL) { 543 for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { 544 if (fwd_streams[sm_id] == NULL) 545 continue; 546 rte_free(fwd_streams[sm_id]); 547 fwd_streams[sm_id] = NULL; 548 } 549 rte_free(fwd_streams); 550 fwd_streams = NULL; 551 } 552 553 /* init new */ 554 nb_fwd_streams = nb_fwd_streams_new; 555 fwd_streams = rte_zmalloc("testpmd: fwd_streams", 556 sizeof(struct fwd_stream *) * nb_fwd_streams, CACHE_LINE_SIZE); 557 if (fwd_streams == NULL) 558 rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) " 559 "failed\n", nb_fwd_streams); 560 561 for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) { 562 fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream", 563 sizeof(struct fwd_stream), CACHE_LINE_SIZE); 564 if (fwd_streams[sm_id] == NULL) 565 rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)" 566 " failed\n"); 567 } 568 569 return 0; 570 } 571 572 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 573 static void 574 pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs) 575 { 576 unsigned int total_burst; 577 unsigned int nb_burst; 578 unsigned int burst_stats[3]; 579 uint16_t pktnb_stats[3]; 580 uint16_t nb_pkt; 581 int burst_percent[3]; 582 583 /* 584 * First compute the total number of packet bursts and the 585 * two highest numbers of bursts of the same number of packets. 586 */ 587 total_burst = 0; 588 burst_stats[0] = burst_stats[1] = burst_stats[2] = 0; 589 pktnb_stats[0] = pktnb_stats[1] = pktnb_stats[2] = 0; 590 for (nb_pkt = 0; nb_pkt < MAX_PKT_BURST; nb_pkt++) { 591 nb_burst = pbs->pkt_burst_spread[nb_pkt]; 592 if (nb_burst == 0) 593 continue; 594 total_burst += nb_burst; 595 if (nb_burst > burst_stats[0]) { 596 burst_stats[1] = burst_stats[0]; 597 pktnb_stats[1] = pktnb_stats[0]; 598 burst_stats[0] = nb_burst; 599 pktnb_stats[0] = nb_pkt; 600 } 601 } 602 if (total_burst == 0) 603 return; 604 burst_percent[0] = (burst_stats[0] * 100) / total_burst; 605 printf(" %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst, 606 burst_percent[0], (int) pktnb_stats[0]); 607 if (burst_stats[0] == total_burst) { 608 printf("]\n"); 609 return; 610 } 611 if (burst_stats[0] + burst_stats[1] == total_burst) { 612 printf(" + %d%% of %d pkts]\n", 613 100 - burst_percent[0], pktnb_stats[1]); 614 return; 615 } 616 burst_percent[1] = (burst_stats[1] * 100) / total_burst; 617 burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]); 618 if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) { 619 printf(" + %d%% of others]\n", 100 - burst_percent[0]); 620 return; 621 } 622 printf(" + %d%% of %d pkts + %d%% of others]\n", 623 burst_percent[1], (int) pktnb_stats[1], burst_percent[2]); 624 } 625 #endif /* RTE_TEST_PMD_RECORD_BURST_STATS */ 626 627 static void 628 fwd_port_stats_display(portid_t port_id, struct rte_eth_stats *stats) 629 { 630 struct rte_port *port; 631 632 static const char *fwd_stats_border = "----------------------"; 633 634 port = &ports[port_id]; 635 printf("\n %s Forward statistics for port %-2d %s\n", 636 fwd_stats_border, port_id, fwd_stats_border); 637 printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " 638 "%-"PRIu64"\n", 639 stats->ipackets, stats->ierrors, 640 (uint64_t) (stats->ipackets + stats->ierrors)); 641 642 if (cur_fwd_eng == &csum_fwd_engine) 643 printf(" Bad-ipcsum: %-14"PRIu64" Bad-l4csum: %-14"PRIu64" \n", 644 port->rx_bad_ip_csum, port->rx_bad_l4_csum); 645 646 printf(" TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " 647 "%-"PRIu64"\n", 648 stats->opackets, port->tx_dropped, 649 (uint64_t) (stats->opackets + port->tx_dropped)); 650 651 if (stats->rx_nombuf > 0) 652 printf(" RX-nombufs: %-14"PRIu64"\n", stats->rx_nombuf); 653 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 654 if (port->rx_stream) 655 pkt_burst_stats_display("RX", &port->rx_stream->rx_burst_stats); 656 if (port->tx_stream) 657 pkt_burst_stats_display("TX", &port->tx_stream->tx_burst_stats); 658 #endif 659 /* stats fdir */ 660 if (fdir_conf.mode != RTE_FDIR_MODE_NONE) 661 printf(" Fdirmiss: %-14"PRIu64" Fdirmatch: %-14"PRIu64"\n", 662 stats->fdirmiss, 663 stats->fdirmatch); 664 665 printf(" %s--------------------------------%s\n", 666 fwd_stats_border, fwd_stats_border); 667 } 668 669 static void 670 fwd_stream_stats_display(streamid_t stream_id) 671 { 672 struct fwd_stream *fs; 673 static const char *fwd_top_stats_border = "-------"; 674 675 fs = fwd_streams[stream_id]; 676 if ((fs->rx_packets == 0) && (fs->tx_packets == 0) && 677 (fs->fwd_dropped == 0)) 678 return; 679 printf("\n %s Forward Stats for RX Port=%2d/Queue=%2d -> " 680 "TX Port=%2d/Queue=%2d %s\n", 681 fwd_top_stats_border, fs->rx_port, fs->rx_queue, 682 fs->tx_port, fs->tx_queue, fwd_top_stats_border); 683 printf(" RX-packets: %-14u TX-packets: %-14u TX-dropped: %-14u", 684 fs->rx_packets, fs->tx_packets, fs->fwd_dropped); 685 686 /* if checksum mode */ 687 if (cur_fwd_eng == &csum_fwd_engine) { 688 printf(" RX- bad IP checksum: %-14u Rx- bad L4 checksum: %-14u\n", 689 fs->rx_bad_ip_csum, fs->rx_bad_l4_csum); 690 } 691 692 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 693 pkt_burst_stats_display("RX", &fs->rx_burst_stats); 694 pkt_burst_stats_display("TX", &fs->tx_burst_stats); 695 #endif 696 } 697 698 static void 699 flush_all_rx_queues(void) 700 { 701 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 702 portid_t rxp; 703 queueid_t rxq; 704 uint16_t nb_rx; 705 uint16_t i; 706 uint8_t j; 707 708 for (j = 0; j < 2; j++) { 709 for (rxp = 0; rxp < nb_ports; rxp++) { 710 for (rxq = 0; rxq < nb_rxq; rxq++) { 711 do { 712 nb_rx = rte_eth_rx_burst(rxp, rxq, 713 pkts_burst, 714 MAX_PKT_BURST); 715 for (i = 0; i < nb_rx; i++) 716 rte_pktmbuf_free(pkts_burst[i]); 717 } while (nb_rx > 0); 718 } 719 } 720 rte_delay_ms(10); /* wait 10 milli-seconds before retrying */ 721 } 722 } 723 724 static void 725 run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) 726 { 727 struct fwd_stream **fsm; 728 streamid_t nb_fs; 729 streamid_t sm_id; 730 731 fsm = &fwd_streams[fc->stream_idx]; 732 nb_fs = fc->stream_nb; 733 do { 734 for (sm_id = 0; sm_id < nb_fs; sm_id++) 735 (*pkt_fwd)(fsm[sm_id]); 736 } while (! fc->stopped); 737 } 738 739 static int 740 start_pkt_forward_on_core(void *fwd_arg) 741 { 742 run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg, 743 cur_fwd_config.fwd_eng->packet_fwd); 744 return 0; 745 } 746 747 /* 748 * Run the TXONLY packet forwarding engine to send a single burst of packets. 749 * Used to start communication flows in network loopback test configurations. 750 */ 751 static int 752 run_one_txonly_burst_on_core(void *fwd_arg) 753 { 754 struct fwd_lcore *fwd_lc; 755 struct fwd_lcore tmp_lcore; 756 757 fwd_lc = (struct fwd_lcore *) fwd_arg; 758 tmp_lcore = *fwd_lc; 759 tmp_lcore.stopped = 1; 760 run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd); 761 return 0; 762 } 763 764 /* 765 * Launch packet forwarding: 766 * - Setup per-port forwarding context. 767 * - launch logical cores with their forwarding configuration. 768 */ 769 static void 770 launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore) 771 { 772 port_fwd_begin_t port_fwd_begin; 773 unsigned int i; 774 unsigned int lc_id; 775 int diag; 776 777 port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin; 778 if (port_fwd_begin != NULL) { 779 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 780 (*port_fwd_begin)(fwd_ports_ids[i]); 781 } 782 for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) { 783 lc_id = fwd_lcores_cpuids[i]; 784 if ((interactive == 0) || (lc_id != rte_lcore_id())) { 785 fwd_lcores[i]->stopped = 0; 786 diag = rte_eal_remote_launch(pkt_fwd_on_lcore, 787 fwd_lcores[i], lc_id); 788 if (diag != 0) 789 printf("launch lcore %u failed - diag=%d\n", 790 lc_id, diag); 791 } 792 } 793 } 794 795 /* 796 * Launch packet forwarding configuration. 797 */ 798 void 799 start_packet_forwarding(int with_tx_first) 800 { 801 port_fwd_begin_t port_fwd_begin; 802 port_fwd_end_t port_fwd_end; 803 struct rte_port *port; 804 unsigned int i; 805 portid_t pt_id; 806 streamid_t sm_id; 807 808 if (all_ports_started() == 0) { 809 printf("Not all ports were started\n"); 810 return; 811 } 812 if (test_done == 0) { 813 printf("Packet forwarding already started\n"); 814 return; 815 } 816 test_done = 0; 817 flush_all_rx_queues(); 818 fwd_config_setup(); 819 rxtx_config_display(); 820 821 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 822 pt_id = fwd_ports_ids[i]; 823 port = &ports[pt_id]; 824 rte_eth_stats_get(pt_id, &port->stats); 825 port->tx_dropped = 0; 826 } 827 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 828 fwd_streams[sm_id]->rx_packets = 0; 829 fwd_streams[sm_id]->tx_packets = 0; 830 fwd_streams[sm_id]->fwd_dropped = 0; 831 fwd_streams[sm_id]->rx_bad_ip_csum = 0; 832 fwd_streams[sm_id]->rx_bad_l4_csum = 0; 833 834 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 835 memset(&fwd_streams[sm_id]->rx_burst_stats, 0, 836 sizeof(fwd_streams[sm_id]->rx_burst_stats)); 837 memset(&fwd_streams[sm_id]->tx_burst_stats, 0, 838 sizeof(fwd_streams[sm_id]->tx_burst_stats)); 839 #endif 840 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 841 fwd_streams[sm_id]->core_cycles = 0; 842 #endif 843 } 844 if (with_tx_first) { 845 port_fwd_begin = tx_only_engine.port_fwd_begin; 846 if (port_fwd_begin != NULL) { 847 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 848 (*port_fwd_begin)(fwd_ports_ids[i]); 849 } 850 launch_packet_forwarding(run_one_txonly_burst_on_core); 851 rte_eal_mp_wait_lcore(); 852 port_fwd_end = tx_only_engine.port_fwd_end; 853 if (port_fwd_end != NULL) { 854 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 855 (*port_fwd_end)(fwd_ports_ids[i]); 856 } 857 } 858 launch_packet_forwarding(start_pkt_forward_on_core); 859 } 860 861 void 862 stop_packet_forwarding(void) 863 { 864 struct rte_eth_stats stats; 865 struct rte_port *port; 866 port_fwd_end_t port_fwd_end; 867 int i; 868 portid_t pt_id; 869 streamid_t sm_id; 870 lcoreid_t lc_id; 871 uint64_t total_recv; 872 uint64_t total_xmit; 873 uint64_t total_rx_dropped; 874 uint64_t total_tx_dropped; 875 uint64_t total_rx_nombuf; 876 uint64_t tx_dropped; 877 uint64_t rx_bad_ip_csum; 878 uint64_t rx_bad_l4_csum; 879 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 880 uint64_t fwd_cycles; 881 #endif 882 static const char *acc_stats_border = "+++++++++++++++"; 883 884 if (all_ports_started() == 0) { 885 printf("Not all ports were started\n"); 886 return; 887 } 888 if (test_done) { 889 printf("Packet forwarding not started\n"); 890 return; 891 } 892 printf("Telling cores to stop..."); 893 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) 894 fwd_lcores[lc_id]->stopped = 1; 895 printf("\nWaiting for lcores to finish...\n"); 896 rte_eal_mp_wait_lcore(); 897 port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end; 898 if (port_fwd_end != NULL) { 899 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 900 pt_id = fwd_ports_ids[i]; 901 (*port_fwd_end)(pt_id); 902 } 903 } 904 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 905 fwd_cycles = 0; 906 #endif 907 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 908 if (cur_fwd_config.nb_fwd_streams > 909 cur_fwd_config.nb_fwd_ports) { 910 fwd_stream_stats_display(sm_id); 911 ports[fwd_streams[sm_id]->tx_port].tx_stream = NULL; 912 ports[fwd_streams[sm_id]->rx_port].rx_stream = NULL; 913 } else { 914 ports[fwd_streams[sm_id]->tx_port].tx_stream = 915 fwd_streams[sm_id]; 916 ports[fwd_streams[sm_id]->rx_port].rx_stream = 917 fwd_streams[sm_id]; 918 } 919 tx_dropped = ports[fwd_streams[sm_id]->tx_port].tx_dropped; 920 tx_dropped = (uint64_t) (tx_dropped + 921 fwd_streams[sm_id]->fwd_dropped); 922 ports[fwd_streams[sm_id]->tx_port].tx_dropped = tx_dropped; 923 924 rx_bad_ip_csum = ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum; 925 rx_bad_ip_csum = (uint64_t) (rx_bad_ip_csum + 926 fwd_streams[sm_id]->rx_bad_ip_csum); 927 ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum = rx_bad_ip_csum; 928 929 rx_bad_l4_csum = ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum; 930 rx_bad_l4_csum = (uint64_t) (rx_bad_l4_csum + 931 fwd_streams[sm_id]->rx_bad_l4_csum); 932 ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum = rx_bad_l4_csum; 933 934 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 935 fwd_cycles = (uint64_t) (fwd_cycles + 936 fwd_streams[sm_id]->core_cycles); 937 #endif 938 } 939 total_recv = 0; 940 total_xmit = 0; 941 total_rx_dropped = 0; 942 total_tx_dropped = 0; 943 total_rx_nombuf = 0; 944 for (i = 0; i < ((cur_fwd_config.nb_fwd_ports + 1) & ~0x1); i++) { 945 pt_id = fwd_ports_ids[i]; 946 947 port = &ports[pt_id]; 948 rte_eth_stats_get(pt_id, &stats); 949 stats.ipackets -= port->stats.ipackets; 950 port->stats.ipackets = 0; 951 stats.opackets -= port->stats.opackets; 952 port->stats.opackets = 0; 953 stats.ibytes -= port->stats.ibytes; 954 port->stats.ibytes = 0; 955 stats.obytes -= port->stats.obytes; 956 port->stats.obytes = 0; 957 stats.ierrors -= port->stats.ierrors; 958 port->stats.ierrors = 0; 959 stats.oerrors -= port->stats.oerrors; 960 port->stats.oerrors = 0; 961 stats.rx_nombuf -= port->stats.rx_nombuf; 962 port->stats.rx_nombuf = 0; 963 stats.fdirmatch -= port->stats.fdirmatch; 964 port->stats.rx_nombuf = 0; 965 stats.fdirmiss -= port->stats.fdirmiss; 966 port->stats.rx_nombuf = 0; 967 968 total_recv += stats.ipackets; 969 total_xmit += stats.opackets; 970 total_rx_dropped += stats.ierrors; 971 total_tx_dropped += port->tx_dropped; 972 total_rx_nombuf += stats.rx_nombuf; 973 974 fwd_port_stats_display(pt_id, &stats); 975 } 976 printf("\n %s Accumulated forward statistics for all ports" 977 "%s\n", 978 acc_stats_border, acc_stats_border); 979 printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " 980 "%-"PRIu64"\n" 981 " TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " 982 "%-"PRIu64"\n", 983 total_recv, total_rx_dropped, total_recv + total_rx_dropped, 984 total_xmit, total_tx_dropped, total_xmit + total_tx_dropped); 985 if (total_rx_nombuf > 0) 986 printf(" RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf); 987 printf(" %s++++++++++++++++++++++++++++++++++++++++++++++" 988 "%s\n", 989 acc_stats_border, acc_stats_border); 990 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 991 if (total_recv > 0) 992 printf("\n CPU cycles/packet=%u (total cycles=" 993 "%"PRIu64" / total RX packets=%"PRIu64")\n", 994 (unsigned int)(fwd_cycles / total_recv), 995 fwd_cycles, total_recv); 996 #endif 997 printf("\nDone.\n"); 998 test_done = 1; 999 } 1000 1001 static int 1002 all_ports_started(void) 1003 { 1004 portid_t pi; 1005 struct rte_port *port; 1006 1007 for (pi = 0; pi < nb_ports; pi++) { 1008 port = &ports[pi]; 1009 /* Check if there is a port which is not started */ 1010 if (port->port_status != RTE_PORT_STARTED) 1011 return 0; 1012 } 1013 1014 /* No port is not started */ 1015 return 1; 1016 } 1017 1018 void 1019 start_port(portid_t pid) 1020 { 1021 int diag, need_check_link_status = 0; 1022 portid_t pi; 1023 queueid_t qi; 1024 struct rte_port *port; 1025 1026 if (test_done == 0) { 1027 printf("Please stop forwarding first\n"); 1028 return; 1029 } 1030 1031 if (init_fwd_streams() < 0) { 1032 printf("Fail from init_fwd_streams()\n"); 1033 return; 1034 } 1035 1036 if(dcb_config) 1037 dcb_test = 1; 1038 for (pi = 0; pi < nb_ports; pi++) { 1039 if (pid < nb_ports && pid != pi) 1040 continue; 1041 1042 port = &ports[pi]; 1043 if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED, 1044 RTE_PORT_HANDLING) == 0) { 1045 printf("Port %d is now not stopped\n", pi); 1046 continue; 1047 } 1048 1049 if (port->need_reconfig > 0) { 1050 port->need_reconfig = 0; 1051 1052 printf("Configuring Port %d\n", pi); 1053 /* configure port */ 1054 diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, 1055 &(port->dev_conf)); 1056 if (diag != 0) { 1057 if (rte_atomic16_cmpset(&(port->port_status), 1058 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1059 printf("Port %d can not be set back " 1060 "to stopped\n", pi); 1061 printf("Fail to configure port %d\n", pi); 1062 /* try to reconfigure port next time */ 1063 port->need_reconfig = 1; 1064 return; 1065 } 1066 } 1067 1068 if (port->need_reconfig_queues > 0) { 1069 port->need_reconfig_queues = 0; 1070 1071 /* setup tx queues */ 1072 for (qi = 0; qi < nb_txq; qi++) { 1073 diag = rte_eth_tx_queue_setup(pi, qi, nb_txd, 1074 port->socket_id, &(port->tx_conf)); 1075 if (diag == 0) 1076 continue; 1077 1078 /* Fail to setup tx queue, return */ 1079 if (rte_atomic16_cmpset(&(port->port_status), 1080 RTE_PORT_HANDLING, 1081 RTE_PORT_STOPPED) == 0) 1082 printf("Port %d can not be set back " 1083 "to stopped\n", pi); 1084 printf("Fail to configure port %d tx queues\n", pi); 1085 /* try to reconfigure queues next time */ 1086 port->need_reconfig_queues = 1; 1087 return; 1088 } 1089 /* setup rx queues */ 1090 for (qi = 0; qi < nb_rxq; qi++) { 1091 diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd, 1092 port->socket_id, &(port->rx_conf), 1093 mbuf_pool_find(port->socket_id)); 1094 if (diag == 0) 1095 continue; 1096 1097 /* Fail to setup rx queue, return */ 1098 if (rte_atomic16_cmpset(&(port->port_status), 1099 RTE_PORT_HANDLING, 1100 RTE_PORT_STOPPED) == 0) 1101 printf("Port %d can not be set back " 1102 "to stopped\n", pi); 1103 printf("Fail to configure port %d rx queues\n", pi); 1104 /* try to reconfigure queues next time */ 1105 port->need_reconfig_queues = 1; 1106 return; 1107 } 1108 } 1109 1110 /* start port */ 1111 if (rte_eth_dev_start(pi) < 0) { 1112 printf("Fail to start port %d\n", pi); 1113 1114 /* Fail to setup rx queue, return */ 1115 if (rte_atomic16_cmpset(&(port->port_status), 1116 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1117 printf("Port %d can not be set back to " 1118 "stopped\n", pi); 1119 continue; 1120 } 1121 1122 if (rte_atomic16_cmpset(&(port->port_status), 1123 RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0) 1124 printf("Port %d can not be set into started\n", pi); 1125 1126 /* at least one port started, need checking link status */ 1127 need_check_link_status = 1; 1128 } 1129 1130 if (need_check_link_status) 1131 check_all_ports_link_status(nb_ports, RTE_PORT_ALL); 1132 else 1133 printf("Please stop the ports first\n"); 1134 1135 printf("Done\n"); 1136 } 1137 1138 void 1139 stop_port(portid_t pid) 1140 { 1141 portid_t pi; 1142 struct rte_port *port; 1143 int need_check_link_status = 0; 1144 1145 if (test_done == 0) { 1146 printf("Please stop forwarding first\n"); 1147 return; 1148 } 1149 if (dcb_test) { 1150 dcb_test = 0; 1151 dcb_config = 0; 1152 } 1153 printf("Stopping ports...\n"); 1154 1155 for (pi = 0; pi < nb_ports; pi++) { 1156 if (pid < nb_ports && pid != pi) 1157 continue; 1158 1159 port = &ports[pi]; 1160 if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED, 1161 RTE_PORT_HANDLING) == 0) 1162 continue; 1163 1164 rte_eth_dev_stop(pi); 1165 1166 if (rte_atomic16_cmpset(&(port->port_status), 1167 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1168 printf("Port %d can not be set into stopped\n", pi); 1169 need_check_link_status = 1; 1170 } 1171 if (need_check_link_status) 1172 check_all_ports_link_status(nb_ports, RTE_PORT_ALL); 1173 1174 printf("Done\n"); 1175 } 1176 1177 void 1178 close_port(portid_t pid) 1179 { 1180 portid_t pi; 1181 struct rte_port *port; 1182 1183 if (test_done == 0) { 1184 printf("Please stop forwarding first\n"); 1185 return; 1186 } 1187 1188 printf("Closing ports...\n"); 1189 1190 for (pi = 0; pi < nb_ports; pi++) { 1191 if (pid < nb_ports && pid != pi) 1192 continue; 1193 1194 port = &ports[pi]; 1195 if (rte_atomic16_cmpset(&(port->port_status), 1196 RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) { 1197 printf("Port %d is now not stopped\n", pi); 1198 continue; 1199 } 1200 1201 rte_eth_dev_close(pi); 1202 1203 if (rte_atomic16_cmpset(&(port->port_status), 1204 RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0) 1205 printf("Port %d can not be set into stopped\n", pi); 1206 } 1207 1208 printf("Done\n"); 1209 } 1210 1211 int 1212 all_ports_stopped(void) 1213 { 1214 portid_t pi; 1215 struct rte_port *port; 1216 1217 for (pi = 0; pi < nb_ports; pi++) { 1218 port = &ports[pi]; 1219 if (port->port_status != RTE_PORT_STOPPED) 1220 return 0; 1221 } 1222 1223 return 1; 1224 } 1225 1226 void 1227 pmd_test_exit(void) 1228 { 1229 portid_t pt_id; 1230 1231 for (pt_id = 0; pt_id < nb_ports; pt_id++) { 1232 printf("Stopping port %d...", pt_id); 1233 fflush(stdout); 1234 rte_eth_dev_close(pt_id); 1235 printf("done\n"); 1236 } 1237 printf("bye...\n"); 1238 } 1239 1240 typedef void (*cmd_func_t)(void); 1241 struct pmd_test_command { 1242 const char *cmd_name; 1243 cmd_func_t cmd_func; 1244 }; 1245 1246 #define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0])) 1247 1248 /* Check the link status of all ports in up to 9s, and print them finally */ 1249 static void 1250 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) 1251 { 1252 #define CHECK_INTERVAL 100 /* 100ms */ 1253 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1254 uint8_t portid, count, all_ports_up, print_flag = 0; 1255 struct rte_eth_link link; 1256 1257 printf("Checking link statuses...\n"); 1258 fflush(stdout); 1259 for (count = 0; count <= MAX_CHECK_TIME; count++) { 1260 all_ports_up = 1; 1261 for (portid = 0; portid < port_num; portid++) { 1262 if ((port_mask & (1 << portid)) == 0) 1263 continue; 1264 memset(&link, 0, sizeof(link)); 1265 rte_eth_link_get_nowait(portid, &link); 1266 /* print link status if flag set */ 1267 if (print_flag == 1) { 1268 if (link.link_status) 1269 printf("Port %d Link Up - speed %u " 1270 "Mbps - %s\n", (uint8_t)portid, 1271 (unsigned)link.link_speed, 1272 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 1273 ("full-duplex") : ("half-duplex\n")); 1274 else 1275 printf("Port %d Link Down\n", 1276 (uint8_t)portid); 1277 continue; 1278 } 1279 /* clear all_ports_up flag if any link down */ 1280 if (link.link_status == 0) { 1281 all_ports_up = 0; 1282 break; 1283 } 1284 } 1285 /* after finally printing all link status, get out */ 1286 if (print_flag == 1) 1287 break; 1288 1289 if (all_ports_up == 0) { 1290 fflush(stdout); 1291 rte_delay_ms(CHECK_INTERVAL); 1292 } 1293 1294 /* set the print_flag if all ports up or timeout */ 1295 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1296 print_flag = 1; 1297 } 1298 } 1299 } 1300 1301 static void 1302 init_ports(void) 1303 { 1304 struct rte_eth_link link; 1305 struct rte_eth_conf port_conf = { 1306 .intr_conf = { 1307 .lsc = 0, 1308 }, 1309 }; 1310 struct rte_eth_rxconf rx_conf; 1311 struct rte_eth_txconf tx_conf; 1312 struct rte_port *port; 1313 unsigned int sock_id; 1314 portid_t pi; 1315 queueid_t qi; 1316 int diag; 1317 1318 port_conf.rxmode = rx_mode; 1319 port_conf.fdir_conf = fdir_conf; 1320 1321 if (nb_rxq > 0) { /* configure RSS */ 1322 port_conf.rx_adv_conf.rss_conf.rss_key = NULL; 1323 /* use default hash key */ 1324 port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf; 1325 } else 1326 port_conf.rx_adv_conf.rss_conf.rss_hf = 0; 1327 rx_conf.rx_thresh = rx_thresh; 1328 rx_conf.rx_free_thresh = rx_free_thresh; 1329 tx_conf.tx_thresh = tx_thresh; 1330 tx_conf.tx_rs_thresh = tx_rs_thresh; 1331 tx_conf.tx_free_thresh = tx_free_thresh; 1332 1333 for (pi = 0; pi < nb_ports; pi++) { 1334 port = &ports[pi]; 1335 memcpy(&port->dev_conf, &port_conf, sizeof(port_conf)); 1336 sock_id = port->socket_id; 1337 printf("Initializing port %d... ", pi); 1338 fflush(stdout); 1339 diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, &port_conf); 1340 if (diag != 0) { 1341 fatal_init_error("rte_eth_dev_configure", pi, diag); 1342 /* NOT REACHED */ 1343 } 1344 rte_eth_macaddr_get(pi, &port->eth_addr); 1345 for (qi = 0; qi < nb_txq; qi++) { 1346 diag = rte_eth_tx_queue_setup(pi, qi, nb_txd, 1347 sock_id, 1348 &tx_conf); 1349 if (diag != 0) { 1350 fatal_init_error("rte_eth_tx_queue_setup", 1351 pi, diag); 1352 /* NOT REACHED */ 1353 } 1354 } 1355 for (qi = 0; qi < nb_rxq; qi++) { 1356 diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd, sock_id, 1357 &rx_conf, 1358 mbuf_pool_find(sock_id)); 1359 if (diag != 0) { 1360 fatal_init_error("rte_eth_rx_queue_setup", 1361 pi , diag); 1362 /* NOT REACHED */ 1363 } 1364 } 1365 1366 /* Start device */ 1367 diag = rte_eth_dev_start(pi); 1368 if (diag != 0) { 1369 fatal_init_error("rte_eth_dev_start", pi, diag); 1370 /* NOT REACHED */ 1371 } 1372 printf("done: "); 1373 rte_eth_link_get(pi, &link); 1374 if (link.link_status) { 1375 printf(" Link Up - speed %u Mbps - %s\n", 1376 (unsigned) link.link_speed, 1377 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 1378 ("full-duplex") : ("half-duplex\n")); 1379 } else { 1380 printf(" Link Down\n"); 1381 } 1382 1383 /* 1384 * If enabled, put device in promiscuous mode. 1385 * This allows the PMD test in IO forwarding mode to forward 1386 * packets to itself through 2 cross-connected ports of the 1387 * target machine. 1388 */ 1389 if (promiscuous_on) 1390 rte_eth_promiscuous_enable(pi); 1391 } 1392 } 1393 1394 #ifdef RTE_EXEC_ENV_BAREMETAL 1395 #define main _main 1396 #endif 1397 1398 int 1399 main(int argc, char** argv) 1400 { 1401 int diag; 1402 1403 diag = rte_eal_init(argc, argv); 1404 if (diag < 0) 1405 rte_panic("Cannot init EAL\n"); 1406 1407 if (rte_pmd_init_all()) 1408 rte_panic("Cannot init PMD\n"); 1409 1410 if (rte_eal_pci_probe()) 1411 rte_panic("Cannot probe PCI\n"); 1412 1413 nb_ports = (portid_t) rte_eth_dev_count(); 1414 if (nb_ports == 0) 1415 rte_exit(EXIT_FAILURE, "No probed ethernet devices - check that " 1416 "CONFIG_RTE_LIBRTE_IGB_PMD=y and that " 1417 "CONFIG_RTE_LIBRTE_EM_PMD=y and that " 1418 "CONFIG_RTE_LIBRTE_IXGBE_PMD=y in your " 1419 "configuration file\n"); 1420 1421 set_def_fwd_config(); 1422 if (nb_lcores == 0) 1423 rte_panic("Empty set of forwarding logical cores - check the " 1424 "core mask supplied in the command parameters\n"); 1425 1426 argc -= diag; 1427 argv += diag; 1428 if (argc > 1) 1429 launch_args_parse(argc, argv); 1430 1431 if (nb_rxq > nb_txq) 1432 printf("Warning: nb_rxq=%d enables RSS configuration, " 1433 "but nb_txq=%d will prevent to fully test it.\n", 1434 nb_rxq, nb_txq); 1435 1436 init_config(); 1437 start_port(RTE_PORT_ALL); 1438 1439 /* set all ports to promiscuous mode by default */ 1440 for (port_id = 0; port_id < nb_ports; port_id++) 1441 rte_eth_promiscuous_enable(port_id); 1442 1443 if (interactive == 1) 1444 prompt(); 1445 else { 1446 char c; 1447 int rc; 1448 1449 printf("No commandline core given, start packet forwarding\n"); 1450 start_packet_forwarding(0); 1451 printf("Press enter to exit\n"); 1452 rc = read(0, &c, 1); 1453 if (rc < 0) 1454 return 1; 1455 } 1456 1457 return 0; 1458 } 1459