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 uint8_t i; 632 633 static const char *fwd_stats_border = "----------------------"; 634 635 port = &ports[port_id]; 636 printf("\n %s Forward statistics for port %-2d %s\n", 637 fwd_stats_border, port_id, fwd_stats_border); 638 639 if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) { 640 printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " 641 "%-"PRIu64"\n", 642 stats->ipackets, stats->ierrors, 643 (uint64_t) (stats->ipackets + stats->ierrors)); 644 645 if (cur_fwd_eng == &csum_fwd_engine) 646 printf(" Bad-ipcsum: %-14"PRIu64" Bad-l4csum: %-14"PRIu64" \n", 647 port->rx_bad_ip_csum, port->rx_bad_l4_csum); 648 649 printf(" TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " 650 "%-"PRIu64"\n", 651 stats->opackets, port->tx_dropped, 652 (uint64_t) (stats->opackets + port->tx_dropped)); 653 654 if (stats->rx_nombuf > 0) 655 printf(" RX-nombufs: %-14"PRIu64"\n", stats->rx_nombuf); 656 657 } 658 else { 659 printf(" RX-packets: %14"PRIu64" RX-dropped:%14"PRIu64" RX-total:" 660 "%14"PRIu64"\n", 661 stats->ipackets, stats->ierrors, 662 (uint64_t) (stats->ipackets + stats->ierrors)); 663 664 if (cur_fwd_eng == &csum_fwd_engine) 665 printf(" Bad-ipcsum:%14"PRIu64" Bad-l4csum:%14"PRIu64"\n", 666 port->rx_bad_ip_csum, port->rx_bad_l4_csum); 667 668 printf(" TX-packets: %14"PRIu64" TX-dropped:%14"PRIu64" TX-total:" 669 "%14"PRIu64"\n", 670 stats->opackets, port->tx_dropped, 671 (uint64_t) (stats->opackets + port->tx_dropped)); 672 673 if (stats->rx_nombuf > 0) 674 printf(" RX-nombufs:%14"PRIu64"\n", stats->rx_nombuf); 675 } 676 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 677 if (port->rx_stream) 678 pkt_burst_stats_display("RX", 679 &port->rx_stream->rx_burst_stats); 680 if (port->tx_stream) 681 pkt_burst_stats_display("TX", 682 &port->tx_stream->tx_burst_stats); 683 #endif 684 /* stats fdir */ 685 if (fdir_conf.mode != RTE_FDIR_MODE_NONE) 686 printf(" Fdirmiss:%14"PRIu64" Fdirmatch:%14"PRIu64"\n", 687 stats->fdirmiss, 688 stats->fdirmatch); 689 690 if (port->rx_queue_stats_mapping_enabled) { 691 printf("\n"); 692 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 693 printf(" Stats reg %2d RX-packets:%14"PRIu64 694 " RX-errors:%14"PRIu64 695 " RX-bytes:%14"PRIu64"\n", 696 i, stats->q_ipackets[i], stats->q_errors[i], stats->q_ibytes[i]); 697 } 698 printf("\n"); 699 } 700 if (port->tx_queue_stats_mapping_enabled) { 701 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) { 702 printf(" Stats reg %2d TX-packets:%14"PRIu64 703 " TX-bytes:%14"PRIu64"\n", 704 i, stats->q_opackets[i], stats->q_obytes[i]); 705 } 706 } 707 708 printf(" %s--------------------------------%s\n", 709 fwd_stats_border, fwd_stats_border); 710 } 711 712 static void 713 fwd_stream_stats_display(streamid_t stream_id) 714 { 715 struct fwd_stream *fs; 716 static const char *fwd_top_stats_border = "-------"; 717 718 fs = fwd_streams[stream_id]; 719 if ((fs->rx_packets == 0) && (fs->tx_packets == 0) && 720 (fs->fwd_dropped == 0)) 721 return; 722 printf("\n %s Forward Stats for RX Port=%2d/Queue=%2d -> " 723 "TX Port=%2d/Queue=%2d %s\n", 724 fwd_top_stats_border, fs->rx_port, fs->rx_queue, 725 fs->tx_port, fs->tx_queue, fwd_top_stats_border); 726 printf(" RX-packets: %-14u TX-packets: %-14u TX-dropped: %-14u", 727 fs->rx_packets, fs->tx_packets, fs->fwd_dropped); 728 729 /* if checksum mode */ 730 if (cur_fwd_eng == &csum_fwd_engine) { 731 printf(" RX- bad IP checksum: %-14u Rx- bad L4 checksum: " 732 "%-14u\n", fs->rx_bad_ip_csum, fs->rx_bad_l4_csum); 733 } 734 735 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 736 pkt_burst_stats_display("RX", &fs->rx_burst_stats); 737 pkt_burst_stats_display("TX", &fs->tx_burst_stats); 738 #endif 739 } 740 741 static void 742 flush_all_rx_queues(void) 743 { 744 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 745 portid_t rxp; 746 queueid_t rxq; 747 uint16_t nb_rx; 748 uint16_t i; 749 uint8_t j; 750 751 for (j = 0; j < 2; j++) { 752 for (rxp = 0; rxp < nb_ports; rxp++) { 753 for (rxq = 0; rxq < nb_rxq; rxq++) { 754 do { 755 nb_rx = rte_eth_rx_burst(rxp, rxq, 756 pkts_burst, MAX_PKT_BURST); 757 for (i = 0; i < nb_rx; i++) 758 rte_pktmbuf_free(pkts_burst[i]); 759 } while (nb_rx > 0); 760 } 761 } 762 rte_delay_ms(10); /* wait 10 milli-seconds before retrying */ 763 } 764 } 765 766 static void 767 run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) 768 { 769 struct fwd_stream **fsm; 770 streamid_t nb_fs; 771 streamid_t sm_id; 772 773 fsm = &fwd_streams[fc->stream_idx]; 774 nb_fs = fc->stream_nb; 775 do { 776 for (sm_id = 0; sm_id < nb_fs; sm_id++) 777 (*pkt_fwd)(fsm[sm_id]); 778 } while (! fc->stopped); 779 } 780 781 static int 782 start_pkt_forward_on_core(void *fwd_arg) 783 { 784 run_pkt_fwd_on_lcore((struct fwd_lcore *) fwd_arg, 785 cur_fwd_config.fwd_eng->packet_fwd); 786 return 0; 787 } 788 789 /* 790 * Run the TXONLY packet forwarding engine to send a single burst of packets. 791 * Used to start communication flows in network loopback test configurations. 792 */ 793 static int 794 run_one_txonly_burst_on_core(void *fwd_arg) 795 { 796 struct fwd_lcore *fwd_lc; 797 struct fwd_lcore tmp_lcore; 798 799 fwd_lc = (struct fwd_lcore *) fwd_arg; 800 tmp_lcore = *fwd_lc; 801 tmp_lcore.stopped = 1; 802 run_pkt_fwd_on_lcore(&tmp_lcore, tx_only_engine.packet_fwd); 803 return 0; 804 } 805 806 /* 807 * Launch packet forwarding: 808 * - Setup per-port forwarding context. 809 * - launch logical cores with their forwarding configuration. 810 */ 811 static void 812 launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore) 813 { 814 port_fwd_begin_t port_fwd_begin; 815 unsigned int i; 816 unsigned int lc_id; 817 int diag; 818 819 port_fwd_begin = cur_fwd_config.fwd_eng->port_fwd_begin; 820 if (port_fwd_begin != NULL) { 821 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 822 (*port_fwd_begin)(fwd_ports_ids[i]); 823 } 824 for (i = 0; i < cur_fwd_config.nb_fwd_lcores; i++) { 825 lc_id = fwd_lcores_cpuids[i]; 826 if ((interactive == 0) || (lc_id != rte_lcore_id())) { 827 fwd_lcores[i]->stopped = 0; 828 diag = rte_eal_remote_launch(pkt_fwd_on_lcore, 829 fwd_lcores[i], lc_id); 830 if (diag != 0) 831 printf("launch lcore %u failed - diag=%d\n", 832 lc_id, diag); 833 } 834 } 835 } 836 837 /* 838 * Launch packet forwarding configuration. 839 */ 840 void 841 start_packet_forwarding(int with_tx_first) 842 { 843 port_fwd_begin_t port_fwd_begin; 844 port_fwd_end_t port_fwd_end; 845 struct rte_port *port; 846 unsigned int i; 847 portid_t pt_id; 848 streamid_t sm_id; 849 850 if (all_ports_started() == 0) { 851 printf("Not all ports were started\n"); 852 return; 853 } 854 if (test_done == 0) { 855 printf("Packet forwarding already started\n"); 856 return; 857 } 858 if((dcb_test) && (nb_fwd_lcores == 1)) { 859 printf("In DCB mode,the nb forwarding cores should be larger than 1.\n"); 860 return; 861 } 862 test_done = 0; 863 flush_all_rx_queues(); 864 fwd_config_setup(); 865 rxtx_config_display(); 866 867 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 868 pt_id = fwd_ports_ids[i]; 869 port = &ports[pt_id]; 870 rte_eth_stats_get(pt_id, &port->stats); 871 port->tx_dropped = 0; 872 873 map_port_queue_stats_mapping_registers(pt_id, port); 874 } 875 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 876 fwd_streams[sm_id]->rx_packets = 0; 877 fwd_streams[sm_id]->tx_packets = 0; 878 fwd_streams[sm_id]->fwd_dropped = 0; 879 fwd_streams[sm_id]->rx_bad_ip_csum = 0; 880 fwd_streams[sm_id]->rx_bad_l4_csum = 0; 881 882 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS 883 memset(&fwd_streams[sm_id]->rx_burst_stats, 0, 884 sizeof(fwd_streams[sm_id]->rx_burst_stats)); 885 memset(&fwd_streams[sm_id]->tx_burst_stats, 0, 886 sizeof(fwd_streams[sm_id]->tx_burst_stats)); 887 #endif 888 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 889 fwd_streams[sm_id]->core_cycles = 0; 890 #endif 891 } 892 if (with_tx_first) { 893 port_fwd_begin = tx_only_engine.port_fwd_begin; 894 if (port_fwd_begin != NULL) { 895 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 896 (*port_fwd_begin)(fwd_ports_ids[i]); 897 } 898 launch_packet_forwarding(run_one_txonly_burst_on_core); 899 rte_eal_mp_wait_lcore(); 900 port_fwd_end = tx_only_engine.port_fwd_end; 901 if (port_fwd_end != NULL) { 902 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) 903 (*port_fwd_end)(fwd_ports_ids[i]); 904 } 905 } 906 launch_packet_forwarding(start_pkt_forward_on_core); 907 } 908 909 void 910 stop_packet_forwarding(void) 911 { 912 struct rte_eth_stats stats; 913 struct rte_port *port; 914 port_fwd_end_t port_fwd_end; 915 int i; 916 portid_t pt_id; 917 streamid_t sm_id; 918 lcoreid_t lc_id; 919 uint64_t total_recv; 920 uint64_t total_xmit; 921 uint64_t total_rx_dropped; 922 uint64_t total_tx_dropped; 923 uint64_t total_rx_nombuf; 924 uint64_t tx_dropped; 925 uint64_t rx_bad_ip_csum; 926 uint64_t rx_bad_l4_csum; 927 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 928 uint64_t fwd_cycles; 929 #endif 930 static const char *acc_stats_border = "+++++++++++++++"; 931 932 if (all_ports_started() == 0) { 933 printf("Not all ports were started\n"); 934 return; 935 } 936 if (test_done) { 937 printf("Packet forwarding not started\n"); 938 return; 939 } 940 printf("Telling cores to stop..."); 941 for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) 942 fwd_lcores[lc_id]->stopped = 1; 943 printf("\nWaiting for lcores to finish...\n"); 944 rte_eal_mp_wait_lcore(); 945 port_fwd_end = cur_fwd_config.fwd_eng->port_fwd_end; 946 if (port_fwd_end != NULL) { 947 for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) { 948 pt_id = fwd_ports_ids[i]; 949 (*port_fwd_end)(pt_id); 950 } 951 } 952 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 953 fwd_cycles = 0; 954 #endif 955 for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) { 956 if (cur_fwd_config.nb_fwd_streams > 957 cur_fwd_config.nb_fwd_ports) { 958 fwd_stream_stats_display(sm_id); 959 ports[fwd_streams[sm_id]->tx_port].tx_stream = NULL; 960 ports[fwd_streams[sm_id]->rx_port].rx_stream = NULL; 961 } else { 962 ports[fwd_streams[sm_id]->tx_port].tx_stream = 963 fwd_streams[sm_id]; 964 ports[fwd_streams[sm_id]->rx_port].rx_stream = 965 fwd_streams[sm_id]; 966 } 967 tx_dropped = ports[fwd_streams[sm_id]->tx_port].tx_dropped; 968 tx_dropped = (uint64_t) (tx_dropped + 969 fwd_streams[sm_id]->fwd_dropped); 970 ports[fwd_streams[sm_id]->tx_port].tx_dropped = tx_dropped; 971 972 rx_bad_ip_csum = 973 ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum; 974 rx_bad_ip_csum = (uint64_t) (rx_bad_ip_csum + 975 fwd_streams[sm_id]->rx_bad_ip_csum); 976 ports[fwd_streams[sm_id]->rx_port].rx_bad_ip_csum = 977 rx_bad_ip_csum; 978 979 rx_bad_l4_csum = 980 ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum; 981 rx_bad_l4_csum = (uint64_t) (rx_bad_l4_csum + 982 fwd_streams[sm_id]->rx_bad_l4_csum); 983 ports[fwd_streams[sm_id]->rx_port].rx_bad_l4_csum = 984 rx_bad_l4_csum; 985 986 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 987 fwd_cycles = (uint64_t) (fwd_cycles + 988 fwd_streams[sm_id]->core_cycles); 989 #endif 990 } 991 total_recv = 0; 992 total_xmit = 0; 993 total_rx_dropped = 0; 994 total_tx_dropped = 0; 995 total_rx_nombuf = 0; 996 for (i = 0; i < ((cur_fwd_config.nb_fwd_ports + 1) & ~0x1); i++) { 997 pt_id = fwd_ports_ids[i]; 998 999 port = &ports[pt_id]; 1000 rte_eth_stats_get(pt_id, &stats); 1001 stats.ipackets -= port->stats.ipackets; 1002 port->stats.ipackets = 0; 1003 stats.opackets -= port->stats.opackets; 1004 port->stats.opackets = 0; 1005 stats.ibytes -= port->stats.ibytes; 1006 port->stats.ibytes = 0; 1007 stats.obytes -= port->stats.obytes; 1008 port->stats.obytes = 0; 1009 stats.ierrors -= port->stats.ierrors; 1010 port->stats.ierrors = 0; 1011 stats.oerrors -= port->stats.oerrors; 1012 port->stats.oerrors = 0; 1013 stats.rx_nombuf -= port->stats.rx_nombuf; 1014 port->stats.rx_nombuf = 0; 1015 stats.fdirmatch -= port->stats.fdirmatch; 1016 port->stats.rx_nombuf = 0; 1017 stats.fdirmiss -= port->stats.fdirmiss; 1018 port->stats.rx_nombuf = 0; 1019 1020 total_recv += stats.ipackets; 1021 total_xmit += stats.opackets; 1022 total_rx_dropped += stats.ierrors; 1023 total_tx_dropped += port->tx_dropped; 1024 total_rx_nombuf += stats.rx_nombuf; 1025 1026 fwd_port_stats_display(pt_id, &stats); 1027 } 1028 printf("\n %s Accumulated forward statistics for all ports" 1029 "%s\n", 1030 acc_stats_border, acc_stats_border); 1031 printf(" RX-packets: %-14"PRIu64" RX-dropped: %-14"PRIu64"RX-total: " 1032 "%-"PRIu64"\n" 1033 " TX-packets: %-14"PRIu64" TX-dropped: %-14"PRIu64"TX-total: " 1034 "%-"PRIu64"\n", 1035 total_recv, total_rx_dropped, total_recv + total_rx_dropped, 1036 total_xmit, total_tx_dropped, total_xmit + total_tx_dropped); 1037 if (total_rx_nombuf > 0) 1038 printf(" RX-nombufs: %-14"PRIu64"\n", total_rx_nombuf); 1039 printf(" %s++++++++++++++++++++++++++++++++++++++++++++++" 1040 "%s\n", 1041 acc_stats_border, acc_stats_border); 1042 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES 1043 if (total_recv > 0) 1044 printf("\n CPU cycles/packet=%u (total cycles=" 1045 "%"PRIu64" / total RX packets=%"PRIu64")\n", 1046 (unsigned int)(fwd_cycles / total_recv), 1047 fwd_cycles, total_recv); 1048 #endif 1049 printf("\nDone.\n"); 1050 test_done = 1; 1051 } 1052 1053 static int 1054 all_ports_started(void) 1055 { 1056 portid_t pi; 1057 struct rte_port *port; 1058 1059 for (pi = 0; pi < nb_ports; pi++) { 1060 port = &ports[pi]; 1061 /* Check if there is a port which is not started */ 1062 if (port->port_status != RTE_PORT_STARTED) 1063 return 0; 1064 } 1065 1066 /* No port is not started */ 1067 return 1; 1068 } 1069 1070 void 1071 start_port(portid_t pid) 1072 { 1073 int diag, need_check_link_status = 0; 1074 portid_t pi; 1075 queueid_t qi; 1076 struct rte_port *port; 1077 1078 if (test_done == 0) { 1079 printf("Please stop forwarding first\n"); 1080 return; 1081 } 1082 1083 if (init_fwd_streams() < 0) { 1084 printf("Fail from init_fwd_streams()\n"); 1085 return; 1086 } 1087 1088 if(dcb_config) 1089 dcb_test = 1; 1090 for (pi = 0; pi < nb_ports; pi++) { 1091 if (pid < nb_ports && pid != pi) 1092 continue; 1093 1094 port = &ports[pi]; 1095 if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STOPPED, 1096 RTE_PORT_HANDLING) == 0) { 1097 printf("Port %d is now not stopped\n", pi); 1098 continue; 1099 } 1100 1101 if (port->need_reconfig > 0) { 1102 port->need_reconfig = 0; 1103 1104 printf("Configuring Port %d\n", pi); 1105 /* configure port */ 1106 diag = rte_eth_dev_configure(pi, nb_rxq, nb_txq, 1107 &(port->dev_conf)); 1108 if (diag != 0) { 1109 if (rte_atomic16_cmpset(&(port->port_status), 1110 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1111 printf("Port %d can not be set back " 1112 "to stopped\n", pi); 1113 printf("Fail to configure port %d\n", pi); 1114 /* try to reconfigure port next time */ 1115 port->need_reconfig = 1; 1116 return; 1117 } 1118 } 1119 1120 if (port->need_reconfig_queues > 0) { 1121 port->need_reconfig_queues = 0; 1122 1123 /* setup tx queues */ 1124 for (qi = 0; qi < nb_txq; qi++) { 1125 diag = rte_eth_tx_queue_setup(pi, qi, nb_txd, 1126 port->socket_id, &(port->tx_conf)); 1127 if (diag == 0) 1128 continue; 1129 1130 /* Fail to setup tx queue, return */ 1131 if (rte_atomic16_cmpset(&(port->port_status), 1132 RTE_PORT_HANDLING, 1133 RTE_PORT_STOPPED) == 0) 1134 printf("Port %d can not be set back " 1135 "to stopped\n", pi); 1136 printf("Fail to configure port %d tx queues\n", pi); 1137 /* try to reconfigure queues next time */ 1138 port->need_reconfig_queues = 1; 1139 return; 1140 } 1141 /* setup rx queues */ 1142 for (qi = 0; qi < nb_rxq; qi++) { 1143 diag = rte_eth_rx_queue_setup(pi, qi, nb_rxd, 1144 port->socket_id, &(port->rx_conf), 1145 mbuf_pool_find(port->socket_id)); 1146 if (diag == 0) 1147 continue; 1148 1149 /* Fail to setup rx queue, return */ 1150 if (rte_atomic16_cmpset(&(port->port_status), 1151 RTE_PORT_HANDLING, 1152 RTE_PORT_STOPPED) == 0) 1153 printf("Port %d can not be set back " 1154 "to stopped\n", pi); 1155 printf("Fail to configure port %d rx queues\n", pi); 1156 /* try to reconfigure queues next time */ 1157 port->need_reconfig_queues = 1; 1158 return; 1159 } 1160 } 1161 1162 /* start port */ 1163 if (rte_eth_dev_start(pi) < 0) { 1164 printf("Fail to start port %d\n", pi); 1165 1166 /* Fail to setup rx queue, return */ 1167 if (rte_atomic16_cmpset(&(port->port_status), 1168 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1169 printf("Port %d can not be set back to " 1170 "stopped\n", pi); 1171 continue; 1172 } 1173 1174 if (rte_atomic16_cmpset(&(port->port_status), 1175 RTE_PORT_HANDLING, RTE_PORT_STARTED) == 0) 1176 printf("Port %d can not be set into started\n", pi); 1177 1178 /* at least one port started, need checking link status */ 1179 need_check_link_status = 1; 1180 } 1181 1182 if (need_check_link_status) 1183 check_all_ports_link_status(nb_ports, RTE_PORT_ALL); 1184 else 1185 printf("Please stop the ports first\n"); 1186 1187 printf("Done\n"); 1188 } 1189 1190 void 1191 stop_port(portid_t pid) 1192 { 1193 portid_t pi; 1194 struct rte_port *port; 1195 int need_check_link_status = 0; 1196 1197 if (test_done == 0) { 1198 printf("Please stop forwarding first\n"); 1199 return; 1200 } 1201 if (dcb_test) { 1202 dcb_test = 0; 1203 dcb_config = 0; 1204 } 1205 printf("Stopping ports...\n"); 1206 1207 for (pi = 0; pi < nb_ports; pi++) { 1208 if (pid < nb_ports && pid != pi) 1209 continue; 1210 1211 port = &ports[pi]; 1212 if (rte_atomic16_cmpset(&(port->port_status), RTE_PORT_STARTED, 1213 RTE_PORT_HANDLING) == 0) 1214 continue; 1215 1216 rte_eth_dev_stop(pi); 1217 1218 if (rte_atomic16_cmpset(&(port->port_status), 1219 RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0) 1220 printf("Port %d can not be set into stopped\n", pi); 1221 need_check_link_status = 1; 1222 } 1223 if (need_check_link_status) 1224 check_all_ports_link_status(nb_ports, RTE_PORT_ALL); 1225 1226 printf("Done\n"); 1227 } 1228 1229 void 1230 close_port(portid_t pid) 1231 { 1232 portid_t pi; 1233 struct rte_port *port; 1234 1235 if (test_done == 0) { 1236 printf("Please stop forwarding first\n"); 1237 return; 1238 } 1239 1240 printf("Closing ports...\n"); 1241 1242 for (pi = 0; pi < nb_ports; pi++) { 1243 if (pid < nb_ports && pid != pi) 1244 continue; 1245 1246 port = &ports[pi]; 1247 if (rte_atomic16_cmpset(&(port->port_status), 1248 RTE_PORT_STOPPED, RTE_PORT_HANDLING) == 0) { 1249 printf("Port %d is now not stopped\n", pi); 1250 continue; 1251 } 1252 1253 rte_eth_dev_close(pi); 1254 1255 if (rte_atomic16_cmpset(&(port->port_status), 1256 RTE_PORT_HANDLING, RTE_PORT_CLOSED) == 0) 1257 printf("Port %d can not be set into stopped\n", pi); 1258 } 1259 1260 printf("Done\n"); 1261 } 1262 1263 int 1264 all_ports_stopped(void) 1265 { 1266 portid_t pi; 1267 struct rte_port *port; 1268 1269 for (pi = 0; pi < nb_ports; pi++) { 1270 port = &ports[pi]; 1271 if (port->port_status != RTE_PORT_STOPPED) 1272 return 0; 1273 } 1274 1275 return 1; 1276 } 1277 1278 void 1279 pmd_test_exit(void) 1280 { 1281 portid_t pt_id; 1282 1283 for (pt_id = 0; pt_id < nb_ports; pt_id++) { 1284 printf("Stopping port %d...", pt_id); 1285 fflush(stdout); 1286 rte_eth_dev_close(pt_id); 1287 printf("done\n"); 1288 } 1289 printf("bye...\n"); 1290 } 1291 1292 typedef void (*cmd_func_t)(void); 1293 struct pmd_test_command { 1294 const char *cmd_name; 1295 cmd_func_t cmd_func; 1296 }; 1297 1298 #define PMD_TEST_CMD_NB (sizeof(pmd_test_menu) / sizeof(pmd_test_menu[0])) 1299 1300 /* Check the link status of all ports in up to 9s, and print them finally */ 1301 static void 1302 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) 1303 { 1304 #define CHECK_INTERVAL 100 /* 100ms */ 1305 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 1306 uint8_t portid, count, all_ports_up, print_flag = 0; 1307 struct rte_eth_link link; 1308 1309 printf("Checking link statuses...\n"); 1310 fflush(stdout); 1311 for (count = 0; count <= MAX_CHECK_TIME; count++) { 1312 all_ports_up = 1; 1313 for (portid = 0; portid < port_num; portid++) { 1314 if ((port_mask & (1 << portid)) == 0) 1315 continue; 1316 memset(&link, 0, sizeof(link)); 1317 rte_eth_link_get_nowait(portid, &link); 1318 /* print link status if flag set */ 1319 if (print_flag == 1) { 1320 if (link.link_status) 1321 printf("Port %d Link Up - speed %u " 1322 "Mbps - %s\n", (uint8_t)portid, 1323 (unsigned)link.link_speed, 1324 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 1325 ("full-duplex") : ("half-duplex\n")); 1326 else 1327 printf("Port %d Link Down\n", 1328 (uint8_t)portid); 1329 continue; 1330 } 1331 /* clear all_ports_up flag if any link down */ 1332 if (link.link_status == 0) { 1333 all_ports_up = 0; 1334 break; 1335 } 1336 } 1337 /* after finally printing all link status, get out */ 1338 if (print_flag == 1) 1339 break; 1340 1341 if (all_ports_up == 0) { 1342 fflush(stdout); 1343 rte_delay_ms(CHECK_INTERVAL); 1344 } 1345 1346 /* set the print_flag if all ports up or timeout */ 1347 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 1348 print_flag = 1; 1349 } 1350 } 1351 } 1352 1353 static int 1354 set_tx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port) 1355 { 1356 uint16_t i; 1357 int diag; 1358 uint8_t mapping_found = 0; 1359 1360 for (i = 0; i < nb_tx_queue_stats_mappings; i++) { 1361 if ((tx_queue_stats_mappings[i].port_id == port_id) && 1362 (tx_queue_stats_mappings[i].queue_id < nb_txq )) { 1363 diag = rte_eth_dev_set_tx_queue_stats_mapping(port_id, 1364 tx_queue_stats_mappings[i].queue_id, 1365 tx_queue_stats_mappings[i].stats_counter_id); 1366 if (diag != 0) 1367 return diag; 1368 mapping_found = 1; 1369 } 1370 } 1371 if (mapping_found) 1372 port->tx_queue_stats_mapping_enabled = 1; 1373 return 0; 1374 } 1375 1376 static int 1377 set_rx_queue_stats_mapping_registers(uint8_t port_id, struct rte_port *port) 1378 { 1379 uint16_t i; 1380 int diag; 1381 uint8_t mapping_found = 0; 1382 1383 for (i = 0; i < nb_rx_queue_stats_mappings; i++) { 1384 if ((rx_queue_stats_mappings[i].port_id == port_id) && 1385 (rx_queue_stats_mappings[i].queue_id < nb_rxq )) { 1386 diag = rte_eth_dev_set_rx_queue_stats_mapping(port_id, 1387 rx_queue_stats_mappings[i].queue_id, 1388 rx_queue_stats_mappings[i].stats_counter_id); 1389 if (diag != 0) 1390 return diag; 1391 mapping_found = 1; 1392 } 1393 } 1394 if (mapping_found) 1395 port->rx_queue_stats_mapping_enabled = 1; 1396 return 0; 1397 } 1398 1399 static void 1400 map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port) 1401 { 1402 int diag = 0; 1403 1404 diag = set_tx_queue_stats_mapping_registers(pi, port); 1405 if (diag != 0) { 1406 if (diag == -ENOTSUP) { 1407 port->tx_queue_stats_mapping_enabled = 0; 1408 printf("TX queue stats mapping not supported port id=%d\n", pi); 1409 } 1410 else 1411 rte_exit(EXIT_FAILURE, 1412 "set_tx_queue_stats_mapping_registers " 1413 "failed for port id=%d diag=%d\n", 1414 pi, diag); 1415 } 1416 1417 diag = set_rx_queue_stats_mapping_registers(pi, port); 1418 if (diag != 0) { 1419 if (diag == -ENOTSUP) { 1420 port->rx_queue_stats_mapping_enabled = 0; 1421 printf("RX queue stats mapping not supported port id=%d\n", pi); 1422 } 1423 else 1424 rte_exit(EXIT_FAILURE, 1425 "set_rx_queue_stats_mapping_registers " 1426 "failed for port id=%d diag=%d\n", 1427 pi, diag); 1428 } 1429 } 1430 1431 void 1432 init_port_config(void) 1433 { 1434 portid_t pid; 1435 struct rte_port *port; 1436 1437 for (pid = 0; pid < nb_ports; pid++) { 1438 port = &ports[pid]; 1439 port->dev_conf.rxmode = rx_mode; 1440 port->dev_conf.fdir_conf = fdir_conf; 1441 if (nb_rxq > 0) { 1442 port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL; 1443 port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf; 1444 } else { 1445 port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL; 1446 port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0; 1447 } 1448 port->rx_conf.rx_thresh = rx_thresh; 1449 port->rx_conf.rx_free_thresh = rx_free_thresh; 1450 port->rx_conf.rx_drop_en = rx_drop_en; 1451 port->tx_conf.tx_thresh = tx_thresh; 1452 port->tx_conf.tx_rs_thresh = tx_rs_thresh; 1453 port->tx_conf.tx_free_thresh = tx_free_thresh; 1454 port->tx_conf.txq_flags = txq_flags; 1455 1456 rte_eth_macaddr_get(pid, &port->eth_addr); 1457 1458 map_port_queue_stats_mapping_registers(pid, port); 1459 } 1460 } 1461 1462 const uint16_t vlan_tags[] = { 1463 0, 1, 2, 3, 4, 5, 6, 7, 1464 8, 9, 10, 11, 12, 13, 14, 15, 1465 16, 17, 18, 19, 20, 21, 22, 23, 1466 24, 25, 26, 27, 28, 29, 30, 31 1467 }; 1468 1469 static int 1470 get_eth_dcb_conf(struct rte_eth_conf *eth_conf, struct dcb_config *dcb_conf) 1471 { 1472 uint8_t i; 1473 1474 /* 1475 * Builds up the correct configuration for dcb+vt based on the vlan tags array 1476 * given above, and the number of traffic classes available for use. 1477 */ 1478 if (dcb_conf->dcb_mode == DCB_VT_ENABLED) { 1479 struct rte_eth_vmdq_dcb_conf vmdq_rx_conf; 1480 struct rte_eth_vmdq_dcb_tx_conf vmdq_tx_conf; 1481 1482 /* VMDQ+DCB RX and TX configrations */ 1483 vmdq_rx_conf.enable_default_pool = 0; 1484 vmdq_rx_conf.default_pool = 0; 1485 vmdq_rx_conf.nb_queue_pools = 1486 (dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); 1487 vmdq_tx_conf.nb_queue_pools = 1488 (dcb_conf->num_tcs == ETH_4_TCS ? ETH_32_POOLS : ETH_16_POOLS); 1489 1490 vmdq_rx_conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); 1491 for (i = 0; i < vmdq_rx_conf.nb_pool_maps; i++) { 1492 vmdq_rx_conf.pool_map[i].vlan_id = vlan_tags[ i ]; 1493 vmdq_rx_conf.pool_map[i].pools = 1 << (i % vmdq_rx_conf.nb_queue_pools); 1494 } 1495 for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++) { 1496 vmdq_rx_conf.dcb_queue[i] = i; 1497 vmdq_tx_conf.dcb_queue[i] = i; 1498 } 1499 1500 /*set DCB mode of RX and TX of multiple queues*/ 1501 eth_conf->rxmode.mq_mode = ETH_VMDQ_DCB; 1502 eth_conf->txmode.mq_mode = ETH_VMDQ_DCB_TX; 1503 if (dcb_conf->pfc_en) 1504 eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT; 1505 else 1506 eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT; 1507 1508 (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_dcb_conf, &vmdq_rx_conf, 1509 sizeof(struct rte_eth_vmdq_dcb_conf))); 1510 (void)(rte_memcpy(ð_conf->tx_adv_conf.vmdq_dcb_tx_conf, &vmdq_tx_conf, 1511 sizeof(struct rte_eth_vmdq_dcb_tx_conf))); 1512 } 1513 else { 1514 struct rte_eth_dcb_rx_conf rx_conf; 1515 struct rte_eth_dcb_tx_conf tx_conf; 1516 1517 /* queue mapping configuration of DCB RX and TX */ 1518 if (dcb_conf->num_tcs == ETH_4_TCS) 1519 dcb_q_mapping = DCB_4_TCS_Q_MAPPING; 1520 else 1521 dcb_q_mapping = DCB_8_TCS_Q_MAPPING; 1522 1523 rx_conf.nb_tcs = dcb_conf->num_tcs; 1524 tx_conf.nb_tcs = dcb_conf->num_tcs; 1525 1526 for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){ 1527 rx_conf.dcb_queue[i] = i; 1528 tx_conf.dcb_queue[i] = i; 1529 } 1530 eth_conf->rxmode.mq_mode = ETH_DCB_RX; 1531 eth_conf->txmode.mq_mode = ETH_DCB_TX; 1532 if (dcb_conf->pfc_en) 1533 eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT|ETH_DCB_PFC_SUPPORT; 1534 else 1535 eth_conf->dcb_capability_en = ETH_DCB_PG_SUPPORT; 1536 1537 (void)(rte_memcpy(ð_conf->rx_adv_conf.dcb_rx_conf, &rx_conf, 1538 sizeof(struct rte_eth_dcb_rx_conf))); 1539 (void)(rte_memcpy(ð_conf->tx_adv_conf.dcb_tx_conf, &tx_conf, 1540 sizeof(struct rte_eth_dcb_tx_conf))); 1541 } 1542 1543 return 0; 1544 } 1545 1546 int 1547 init_port_dcb_config(portid_t pid,struct dcb_config *dcb_conf) 1548 { 1549 struct rte_eth_conf port_conf; 1550 struct rte_port *rte_port; 1551 int retval; 1552 uint16_t nb_vlan; 1553 uint16_t i; 1554 1555 /* rxq and txq configuration in dcb mode */ 1556 nb_rxq = 128; 1557 nb_txq = 128; 1558 rx_free_thresh = 64; 1559 1560 memset(&port_conf,0,sizeof(struct rte_eth_conf)); 1561 /* Enter DCB configuration status */ 1562 dcb_config = 1; 1563 1564 nb_vlan = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); 1565 /*set configuration of DCB in vt mode and DCB in non-vt mode*/ 1566 retval = get_eth_dcb_conf(&port_conf, dcb_conf); 1567 if (retval < 0) 1568 return retval; 1569 1570 rte_port = &ports[pid]; 1571 memcpy(&rte_port->dev_conf, &port_conf,sizeof(struct rte_eth_conf)); 1572 1573 rte_port->rx_conf.rx_thresh = rx_thresh; 1574 rte_port->rx_conf.rx_free_thresh = rx_free_thresh; 1575 rte_port->tx_conf.tx_thresh = tx_thresh; 1576 rte_port->tx_conf.tx_rs_thresh = tx_rs_thresh; 1577 rte_port->tx_conf.tx_free_thresh = tx_free_thresh; 1578 /* VLAN filter */ 1579 rte_port->dev_conf.rxmode.hw_vlan_filter = 1; 1580 for (i = 0; i < nb_vlan; i++){ 1581 rx_vft_set(pid, vlan_tags[i], 1); 1582 } 1583 1584 rte_eth_macaddr_get(pid, &rte_port->eth_addr); 1585 map_port_queue_stats_mapping_registers(pid, rte_port); 1586 1587 return 0; 1588 } 1589 1590 #ifdef RTE_EXEC_ENV_BAREMETAL 1591 #define main _main 1592 #endif 1593 1594 int 1595 main(int argc, char** argv) 1596 { 1597 int diag; 1598 uint8_t port_id; 1599 1600 diag = rte_eal_init(argc, argv); 1601 if (diag < 0) 1602 rte_panic("Cannot init EAL\n"); 1603 1604 if (rte_pmd_init_all()) 1605 rte_panic("Cannot init PMD\n"); 1606 1607 if (rte_eal_pci_probe()) 1608 rte_panic("Cannot probe PCI\n"); 1609 1610 nb_ports = (portid_t) rte_eth_dev_count(); 1611 if (nb_ports == 0) 1612 rte_exit(EXIT_FAILURE, "No probed ethernet devices - " 1613 "check that " 1614 "CONFIG_RTE_LIBRTE_IGB_PMD=y and that " 1615 "CONFIG_RTE_LIBRTE_EM_PMD=y and that " 1616 "CONFIG_RTE_LIBRTE_IXGBE_PMD=y in your " 1617 "configuration file\n"); 1618 1619 set_def_fwd_config(); 1620 if (nb_lcores == 0) 1621 rte_panic("Empty set of forwarding logical cores - check the " 1622 "core mask supplied in the command parameters\n"); 1623 1624 argc -= diag; 1625 argv += diag; 1626 if (argc > 1) 1627 launch_args_parse(argc, argv); 1628 1629 if (nb_rxq > nb_txq) 1630 printf("Warning: nb_rxq=%d enables RSS configuration, " 1631 "but nb_txq=%d will prevent to fully test it.\n", 1632 nb_rxq, nb_txq); 1633 1634 init_config(); 1635 start_port(RTE_PORT_ALL); 1636 1637 /* set all ports to promiscuous mode by default */ 1638 for (port_id = 0; port_id < nb_ports; port_id++) 1639 rte_eth_promiscuous_enable(port_id); 1640 1641 if (interactive == 1) 1642 prompt(); 1643 else { 1644 char c; 1645 int rc; 1646 1647 printf("No commandline core given, start packet forwarding\n"); 1648 start_packet_forwarding(0); 1649 printf("Press enter to exit\n"); 1650 rc = read(0, &c, 1); 1651 if (rc < 0) 1652 return 1; 1653 } 1654 1655 return 0; 1656 } 1657