1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <stdint.h> 38 #include <inttypes.h> 39 #include <sys/types.h> 40 #include <sys/queue.h> 41 #include <netinet/in.h> 42 #include <setjmp.h> 43 #include <stdarg.h> 44 #include <ctype.h> 45 #include <errno.h> 46 #include <getopt.h> 47 48 #include <rte_common.h> 49 #include <rte_log.h> 50 #include <rte_malloc.h> 51 #include <rte_memory.h> 52 #include <rte_memcpy.h> 53 #include <rte_memzone.h> 54 #include <rte_eal.h> 55 #include <rte_per_lcore.h> 56 #include <rte_launch.h> 57 #include <rte_atomic.h> 58 #include <rte_cycles.h> 59 #include <rte_prefetch.h> 60 #include <rte_lcore.h> 61 #include <rte_per_lcore.h> 62 #include <rte_branch_prediction.h> 63 #include <rte_interrupts.h> 64 #include <rte_pci.h> 65 #include <rte_random.h> 66 #include <rte_debug.h> 67 #include <rte_ether.h> 68 #include <rte_ethdev.h> 69 #include <rte_mempool.h> 70 #include <rte_mbuf.h> 71 #include <rte_timer.h> 72 #include <rte_keepalive.h> 73 74 #include "shm.h" 75 76 #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 77 78 #define NB_MBUF 8192 79 80 #define MAX_PKT_BURST 32 81 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ 82 83 /* 84 * Configurable number of RX/TX ring descriptors 85 */ 86 #define RTE_TEST_RX_DESC_DEFAULT 128 87 #define RTE_TEST_TX_DESC_DEFAULT 512 88 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 89 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 90 91 /* ethernet addresses of ports */ 92 static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; 93 94 /* mask of enabled ports */ 95 static uint32_t l2fwd_enabled_port_mask; 96 97 /* list of enabled ports */ 98 static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; 99 100 static unsigned int l2fwd_rx_queue_per_lcore = 1; 101 102 #define MAX_RX_QUEUE_PER_LCORE 16 103 #define MAX_TX_QUEUE_PER_PORT 16 104 struct lcore_queue_conf { 105 unsigned n_rx_port; 106 unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; 107 } __rte_cache_aligned; 108 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; 109 110 struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 111 112 static const struct rte_eth_conf port_conf = { 113 .rxmode = { 114 .split_hdr_size = 0, 115 .header_split = 0, /**< Header Split disabled */ 116 .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 117 .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 118 .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 119 .hw_strip_crc = 1, /**< CRC stripped by hardware */ 120 }, 121 .txmode = { 122 .mq_mode = ETH_MQ_TX_NONE, 123 }, 124 }; 125 126 struct rte_mempool *l2fwd_pktmbuf_pool = NULL; 127 128 /* Per-port statistics struct */ 129 struct l2fwd_port_statistics { 130 uint64_t tx; 131 uint64_t rx; 132 uint64_t dropped; 133 } __rte_cache_aligned; 134 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS]; 135 136 /* A tsc-based timer responsible for triggering statistics printout */ 137 #define TIMER_MILLISECOND 1 138 #define MAX_TIMER_PERIOD 86400 /* 1 day max */ 139 static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* 10 seconds */ 140 static int64_t check_period = 5; /* default check cycle is 5ms */ 141 142 /* Keepalive structure */ 143 struct rte_keepalive *rte_global_keepalive_info; 144 145 /* Print out statistics on packets dropped */ 146 static void 147 print_stats(__attribute__((unused)) struct rte_timer *ptr_timer, 148 __attribute__((unused)) void *ptr_data) 149 { 150 uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; 151 unsigned portid; 152 153 total_packets_dropped = 0; 154 total_packets_tx = 0; 155 total_packets_rx = 0; 156 157 const char clr[] = { 27, '[', '2', 'J', '\0' }; 158 const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' }; 159 160 /* Clear screen and move to top left */ 161 printf("%s%s", clr, topLeft); 162 163 printf("\nPort statistics ===================================="); 164 165 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 166 /* skip disabled ports */ 167 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 168 continue; 169 printf("\nStatistics for port %u ------------------------------" 170 "\nPackets sent: %24"PRIu64 171 "\nPackets received: %20"PRIu64 172 "\nPackets dropped: %21"PRIu64, 173 portid, 174 port_statistics[portid].tx, 175 port_statistics[portid].rx, 176 port_statistics[portid].dropped); 177 178 total_packets_dropped += port_statistics[portid].dropped; 179 total_packets_tx += port_statistics[portid].tx; 180 total_packets_rx += port_statistics[portid].rx; 181 } 182 printf("\nAggregate statistics ===============================" 183 "\nTotal packets sent: %18"PRIu64 184 "\nTotal packets received: %14"PRIu64 185 "\nTotal packets dropped: %15"PRIu64, 186 total_packets_tx, 187 total_packets_rx, 188 total_packets_dropped); 189 printf("\n====================================================\n"); 190 } 191 192 static void 193 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) 194 { 195 struct ether_hdr *eth; 196 void *tmp; 197 int sent; 198 unsigned dst_port; 199 struct rte_eth_dev_tx_buffer *buffer; 200 201 dst_port = l2fwd_dst_ports[portid]; 202 eth = rte_pktmbuf_mtod(m, struct ether_hdr *); 203 204 /* 02:00:00:00:00:xx */ 205 tmp = ð->d_addr.addr_bytes[0]; 206 *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); 207 208 /* src addr */ 209 ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); 210 211 buffer = tx_buffer[dst_port]; 212 sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); 213 if (sent) 214 port_statistics[dst_port].tx += sent; 215 } 216 217 /* main processing loop */ 218 static void 219 l2fwd_main_loop(void) 220 { 221 struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; 222 struct rte_mbuf *m; 223 int sent; 224 unsigned lcore_id; 225 uint64_t prev_tsc, diff_tsc, cur_tsc; 226 unsigned i, j, portid, nb_rx; 227 struct lcore_queue_conf *qconf; 228 const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) 229 / US_PER_S * BURST_TX_DRAIN_US; 230 struct rte_eth_dev_tx_buffer *buffer; 231 232 prev_tsc = 0; 233 234 lcore_id = rte_lcore_id(); 235 qconf = &lcore_queue_conf[lcore_id]; 236 237 if (qconf->n_rx_port == 0) { 238 RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); 239 return; 240 } 241 242 RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); 243 244 for (i = 0; i < qconf->n_rx_port; i++) { 245 246 portid = qconf->rx_port_list[i]; 247 RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, 248 portid); 249 } 250 251 uint64_t tsc_initial = rte_rdtsc(); 252 uint64_t tsc_lifetime = (rand()&0x07) * rte_get_tsc_hz(); 253 254 while (1) { 255 /* Keepalive heartbeat */ 256 rte_keepalive_mark_alive(rte_global_keepalive_info); 257 258 cur_tsc = rte_rdtsc(); 259 260 /* 261 * Die randomly within 7 secs for demo purposes if 262 * keepalive enabled 263 */ 264 if (check_period > 0 && cur_tsc - tsc_initial > tsc_lifetime) 265 break; 266 267 /* 268 * TX burst queue drain 269 */ 270 diff_tsc = cur_tsc - prev_tsc; 271 if (unlikely(diff_tsc > drain_tsc)) { 272 273 for (i = 0; i < qconf->n_rx_port; i++) { 274 275 portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; 276 buffer = tx_buffer[portid]; 277 278 sent = rte_eth_tx_buffer_flush(portid, 0, buffer); 279 if (sent) 280 port_statistics[portid].tx += sent; 281 282 } 283 284 prev_tsc = cur_tsc; 285 } 286 287 /* 288 * Read packet from RX queues 289 */ 290 for (i = 0; i < qconf->n_rx_port; i++) { 291 292 portid = qconf->rx_port_list[i]; 293 nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, 294 pkts_burst, MAX_PKT_BURST); 295 296 port_statistics[portid].rx += nb_rx; 297 298 for (j = 0; j < nb_rx; j++) { 299 m = pkts_burst[j]; 300 rte_prefetch0(rte_pktmbuf_mtod(m, void *)); 301 l2fwd_simple_forward(m, portid); 302 } 303 } 304 } 305 } 306 307 static int 308 l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy) 309 { 310 l2fwd_main_loop(); 311 return 0; 312 } 313 314 /* display usage */ 315 static void 316 l2fwd_usage(const char *prgname) 317 { 318 printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n" 319 " -p PORTMASK: hexadecimal bitmask of ports to configure\n" 320 " -q NQ: number of queue (=ports) per lcore (default is 1)\n" 321 " -K PERIOD: Keepalive check period (5 default; 86400 max)\n" 322 " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", 323 prgname); 324 } 325 326 static int 327 l2fwd_parse_portmask(const char *portmask) 328 { 329 char *end = NULL; 330 unsigned long pm; 331 332 /* parse hexadecimal string */ 333 pm = strtoul(portmask, &end, 16); 334 if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 335 return -1; 336 337 if (pm == 0) 338 return -1; 339 340 return pm; 341 } 342 343 static unsigned int 344 l2fwd_parse_nqueue(const char *q_arg) 345 { 346 char *end = NULL; 347 unsigned long n; 348 349 /* parse hexadecimal string */ 350 n = strtoul(q_arg, &end, 10); 351 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 352 return 0; 353 if (n == 0) 354 return 0; 355 if (n >= MAX_RX_QUEUE_PER_LCORE) 356 return 0; 357 358 return n; 359 } 360 361 static int 362 l2fwd_parse_timer_period(const char *q_arg) 363 { 364 char *end = NULL; 365 int n; 366 367 /* parse number string */ 368 n = strtol(q_arg, &end, 10); 369 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 370 return -1; 371 if (n >= MAX_TIMER_PERIOD) 372 return -1; 373 374 return n; 375 } 376 377 static int 378 l2fwd_parse_check_period(const char *q_arg) 379 { 380 char *end = NULL; 381 int n; 382 383 /* parse number string */ 384 n = strtol(q_arg, &end, 10); 385 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 386 return -1; 387 if (n >= MAX_TIMER_PERIOD) 388 return -1; 389 390 return n; 391 } 392 393 /* Parse the argument given in the command line of the application */ 394 static int 395 l2fwd_parse_args(int argc, char **argv) 396 { 397 int opt, ret; 398 char **argvopt; 399 int option_index; 400 char *prgname = argv[0]; 401 static struct option lgopts[] = { 402 {NULL, 0, 0, 0} 403 }; 404 405 argvopt = argv; 406 407 while ((opt = getopt_long(argc, argvopt, "p:q:T:K:", 408 lgopts, &option_index)) != EOF) { 409 410 switch (opt) { 411 /* portmask */ 412 case 'p': 413 l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); 414 if (l2fwd_enabled_port_mask == 0) { 415 printf("invalid portmask\n"); 416 l2fwd_usage(prgname); 417 return -1; 418 } 419 break; 420 421 /* nqueue */ 422 case 'q': 423 l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); 424 if (l2fwd_rx_queue_per_lcore == 0) { 425 printf("invalid queue number\n"); 426 l2fwd_usage(prgname); 427 return -1; 428 } 429 break; 430 431 /* timer period */ 432 case 'T': 433 timer_period = l2fwd_parse_timer_period(optarg) 434 * (int64_t)(1000 * TIMER_MILLISECOND); 435 if (timer_period < 0) { 436 printf("invalid timer period\n"); 437 l2fwd_usage(prgname); 438 return -1; 439 } 440 break; 441 442 /* Check period */ 443 case 'K': 444 check_period = l2fwd_parse_check_period(optarg); 445 if (check_period < 0) { 446 printf("invalid check period\n"); 447 l2fwd_usage(prgname); 448 return -1; 449 } 450 break; 451 452 /* long options */ 453 case 0: 454 l2fwd_usage(prgname); 455 return -1; 456 457 default: 458 l2fwd_usage(prgname); 459 return -1; 460 } 461 } 462 463 if (optind >= 0) 464 argv[optind-1] = prgname; 465 466 ret = optind-1; 467 optind = 1; /* reset getopt lib */ 468 return ret; 469 } 470 471 /* Check the link status of all ports in up to 9s, and print them finally */ 472 static void 473 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) 474 { 475 #define CHECK_INTERVAL 100 /* 100ms */ 476 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 477 uint8_t portid, count, all_ports_up, print_flag = 0; 478 struct rte_eth_link link; 479 480 printf("\nChecking link status"); 481 fflush(stdout); 482 for (count = 0; count <= MAX_CHECK_TIME; count++) { 483 all_ports_up = 1; 484 for (portid = 0; portid < port_num; portid++) { 485 if ((port_mask & (1 << portid)) == 0) 486 continue; 487 memset(&link, 0, sizeof(link)); 488 rte_eth_link_get_nowait(portid, &link); 489 /* print link status if flag set */ 490 if (print_flag == 1) { 491 if (link.link_status) 492 printf("Port %d Link Up - speed %u " 493 "Mbps - %s\n", (uint8_t)portid, 494 (unsigned)link.link_speed, 495 (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? 496 ("full-duplex") : ("half-duplex\n")); 497 else 498 printf("Port %d Link Down\n", 499 (uint8_t)portid); 500 continue; 501 } 502 /* clear all_ports_up flag if any link down */ 503 if (link.link_status == ETH_LINK_DOWN) { 504 all_ports_up = 0; 505 break; 506 } 507 } 508 /* after finally printing all link status, get out */ 509 if (print_flag == 1) 510 break; 511 512 if (all_ports_up == 0) { 513 printf("."); 514 fflush(stdout); 515 rte_delay_ms(CHECK_INTERVAL); 516 } 517 518 /* set the print_flag if all ports up or timeout */ 519 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 520 print_flag = 1; 521 printf("done\n"); 522 } 523 } 524 } 525 526 static void 527 dead_core(__rte_unused void *ptr_data, const int id_core) 528 { 529 printf("Dead core %i - restarting..\n", id_core); 530 if (rte_eal_get_lcore_state(id_core) == FINISHED) { 531 rte_eal_wait_lcore(id_core); 532 rte_eal_remote_launch(l2fwd_launch_one_lcore, NULL, id_core); 533 } else { 534 printf("..false positive!\n"); 535 } 536 } 537 538 static void 539 relay_core_state(void *ptr_data, const int id_core, 540 const enum rte_keepalive_state core_state, uint64_t last_alive) 541 { 542 rte_keepalive_relayed_state((struct rte_keepalive_shm *)ptr_data, 543 id_core, core_state, last_alive); 544 } 545 546 int 547 main(int argc, char **argv) 548 { 549 struct lcore_queue_conf *qconf; 550 struct rte_eth_dev_info dev_info; 551 int ret; 552 uint8_t nb_ports; 553 uint8_t nb_ports_available; 554 uint8_t portid, last_port; 555 unsigned lcore_id, rx_lcore_id; 556 unsigned nb_ports_in_mask = 0; 557 558 /* init EAL */ 559 ret = rte_eal_init(argc, argv); 560 if (ret < 0) 561 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); 562 argc -= ret; 563 argv += ret; 564 565 l2fwd_enabled_port_mask = 0; 566 567 /* parse application arguments (after the EAL ones) */ 568 ret = l2fwd_parse_args(argc, argv); 569 if (ret < 0) 570 rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); 571 572 /* create the mbuf pool */ 573 l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32, 574 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); 575 if (l2fwd_pktmbuf_pool == NULL) 576 rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); 577 578 nb_ports = rte_eth_dev_count(); 579 if (nb_ports == 0) 580 rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); 581 582 /* reset l2fwd_dst_ports */ 583 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) 584 l2fwd_dst_ports[portid] = 0; 585 last_port = 0; 586 587 /* 588 * Each logical core is assigned a dedicated TX queue on each port. 589 */ 590 for (portid = 0; portid < nb_ports; portid++) { 591 /* skip ports that are not enabled */ 592 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 593 continue; 594 595 if (nb_ports_in_mask % 2) { 596 l2fwd_dst_ports[portid] = last_port; 597 l2fwd_dst_ports[last_port] = portid; 598 } else 599 last_port = portid; 600 601 nb_ports_in_mask++; 602 603 rte_eth_dev_info_get(portid, &dev_info); 604 } 605 if (nb_ports_in_mask % 2) { 606 printf("Notice: odd number of ports in portmask.\n"); 607 l2fwd_dst_ports[last_port] = last_port; 608 } 609 610 rx_lcore_id = 1; 611 qconf = NULL; 612 613 /* Initialize the port/queue configuration of each logical core */ 614 for (portid = 0; portid < nb_ports; portid++) { 615 /* skip ports that are not enabled */ 616 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) 617 continue; 618 619 /* get the lcore_id for this port */ 620 while (rte_lcore_is_enabled(rx_lcore_id) == 0 || 621 lcore_queue_conf[rx_lcore_id].n_rx_port == 622 l2fwd_rx_queue_per_lcore) { 623 rx_lcore_id++; 624 if (rx_lcore_id >= RTE_MAX_LCORE) 625 rte_exit(EXIT_FAILURE, "Not enough cores\n"); 626 } 627 628 if (qconf != &lcore_queue_conf[rx_lcore_id]) 629 /* Assigned a new logical core in the loop above. */ 630 qconf = &lcore_queue_conf[rx_lcore_id]; 631 632 qconf->rx_port_list[qconf->n_rx_port] = portid; 633 qconf->n_rx_port++; 634 printf("Lcore %u: RX port %u\n", 635 rx_lcore_id, (unsigned) portid); 636 } 637 638 nb_ports_available = nb_ports; 639 640 /* Initialise each port */ 641 for (portid = 0; portid < nb_ports; portid++) { 642 /* skip ports that are not enabled */ 643 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { 644 printf("Skipping disabled port %u\n", 645 (unsigned) portid); 646 nb_ports_available--; 647 continue; 648 } 649 /* init port */ 650 printf("Initializing port %u... ", (unsigned) portid); 651 fflush(stdout); 652 ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); 653 if (ret < 0) 654 rte_exit(EXIT_FAILURE, 655 "Cannot configure device: err=%d, port=%u\n", 656 ret, (unsigned) portid); 657 658 rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]); 659 660 /* init one RX queue */ 661 fflush(stdout); 662 ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, 663 rte_eth_dev_socket_id(portid), 664 NULL, 665 l2fwd_pktmbuf_pool); 666 if (ret < 0) 667 rte_exit(EXIT_FAILURE, 668 "rte_eth_rx_queue_setup:err=%d, port=%u\n", 669 ret, (unsigned) portid); 670 671 /* init one TX queue on each port */ 672 fflush(stdout); 673 ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, 674 rte_eth_dev_socket_id(portid), 675 NULL); 676 if (ret < 0) 677 rte_exit(EXIT_FAILURE, 678 "rte_eth_tx_queue_setup:err=%d, port=%u\n", 679 ret, (unsigned) portid); 680 681 /* Initialize TX buffers */ 682 tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", 683 RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, 684 rte_eth_dev_socket_id(portid)); 685 if (tx_buffer[portid] == NULL) 686 rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", 687 (unsigned) portid); 688 689 rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); 690 691 ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], 692 rte_eth_tx_buffer_count_callback, 693 &port_statistics[portid].dropped); 694 if (ret < 0) 695 rte_exit(EXIT_FAILURE, "Cannot set error callback for " 696 "tx buffer on port %u\n", (unsigned) portid); 697 698 /* Start device */ 699 ret = rte_eth_dev_start(portid); 700 if (ret < 0) 701 rte_exit(EXIT_FAILURE, 702 "rte_eth_dev_start:err=%d, port=%u\n", 703 ret, (unsigned) portid); 704 705 rte_eth_promiscuous_enable(portid); 706 707 printf("Port %u, MAC address: " 708 "%02X:%02X:%02X:%02X:%02X:%02X\n\n", 709 (unsigned) portid, 710 l2fwd_ports_eth_addr[portid].addr_bytes[0], 711 l2fwd_ports_eth_addr[portid].addr_bytes[1], 712 l2fwd_ports_eth_addr[portid].addr_bytes[2], 713 l2fwd_ports_eth_addr[portid].addr_bytes[3], 714 l2fwd_ports_eth_addr[portid].addr_bytes[4], 715 l2fwd_ports_eth_addr[portid].addr_bytes[5]); 716 717 /* initialize port stats */ 718 memset(&port_statistics, 0, sizeof(port_statistics)); 719 } 720 721 if (!nb_ports_available) { 722 rte_exit(EXIT_FAILURE, 723 "All available ports are disabled. Please set portmask.\n"); 724 } 725 726 check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask); 727 728 struct rte_timer hb_timer, stats_timer; 729 730 rte_timer_subsystem_init(); 731 rte_timer_init(&stats_timer); 732 733 if (check_period > 0) { 734 struct rte_keepalive_shm *ka_shm; 735 736 ka_shm = rte_keepalive_shm_create(); 737 if (ka_shm == NULL) 738 rte_exit(EXIT_FAILURE, 739 "rte_keepalive_shm_create() failed"); 740 rte_global_keepalive_info = 741 rte_keepalive_create(&dead_core, ka_shm); 742 if (rte_global_keepalive_info == NULL) 743 rte_exit(EXIT_FAILURE, "init_keep_alive() failed"); 744 rte_keepalive_register_relay_callback(rte_global_keepalive_info, 745 relay_core_state, ka_shm); 746 rte_timer_init(&hb_timer); 747 if (rte_timer_reset(&hb_timer, 748 (check_period * rte_get_timer_hz()) / 1000, 749 PERIODICAL, 750 rte_lcore_id(), 751 (void(*)(struct rte_timer*, void*)) 752 &rte_keepalive_dispatch_pings, 753 rte_global_keepalive_info 754 ) != 0 ) 755 rte_exit(EXIT_FAILURE, "Keepalive setup failure.\n"); 756 } 757 if (timer_period > 0) { 758 if (rte_timer_reset(&stats_timer, 759 (timer_period * rte_get_timer_hz()) / 1000, 760 PERIODICAL, 761 rte_lcore_id(), 762 &print_stats, NULL 763 ) != 0 ) 764 rte_exit(EXIT_FAILURE, "Stats setup failure.\n"); 765 } 766 /* launch per-lcore init on every slave lcore */ 767 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 768 struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id]; 769 770 if (qconf->n_rx_port == 0) 771 RTE_LOG(INFO, L2FWD, 772 "lcore %u has nothing to do\n", 773 lcore_id 774 ); 775 else { 776 rte_eal_remote_launch( 777 l2fwd_launch_one_lcore, 778 NULL, 779 lcore_id 780 ); 781 rte_keepalive_register_core(rte_global_keepalive_info, 782 lcore_id); 783 } 784 } 785 for (;;) { 786 rte_timer_manage(); 787 rte_delay_ms(5); 788 } 789 790 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 791 if (rte_eal_wait_lcore(lcore_id) < 0) 792 return -1; 793 } 794 795 return 0; 796 } 797