1af75078fSIntel /*- 2af75078fSIntel * BSD LICENSE 3af75078fSIntel * 4*e9d48c00SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 5af75078fSIntel * All rights reserved. 6af75078fSIntel * 7af75078fSIntel * Redistribution and use in source and binary forms, with or without 8af75078fSIntel * modification, are permitted provided that the following conditions 9af75078fSIntel * are met: 10af75078fSIntel * 11af75078fSIntel * * Redistributions of source code must retain the above copyright 12af75078fSIntel * notice, this list of conditions and the following disclaimer. 13af75078fSIntel * * Redistributions in binary form must reproduce the above copyright 14af75078fSIntel * notice, this list of conditions and the following disclaimer in 15af75078fSIntel * the documentation and/or other materials provided with the 16af75078fSIntel * distribution. 17af75078fSIntel * * Neither the name of Intel Corporation nor the names of its 18af75078fSIntel * contributors may be used to endorse or promote products derived 19af75078fSIntel * from this software without specific prior written permission. 20af75078fSIntel * 21af75078fSIntel * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22af75078fSIntel * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23af75078fSIntel * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24af75078fSIntel * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25af75078fSIntel * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26af75078fSIntel * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27af75078fSIntel * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28af75078fSIntel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29af75078fSIntel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30af75078fSIntel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31af75078fSIntel * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32af75078fSIntel */ 33af75078fSIntel 34af75078fSIntel #include <stdint.h> 35af75078fSIntel #include <sys/queue.h> 36af75078fSIntel #include <stdlib.h> 37af75078fSIntel #include <string.h> 38af75078fSIntel #include <stdio.h> 39af75078fSIntel #include <assert.h> 40af75078fSIntel #include <errno.h> 41af75078fSIntel #include <signal.h> 42af75078fSIntel #include <stdarg.h> 43af75078fSIntel #include <inttypes.h> 441d8d954bSIntel #include <getopt.h> 45af75078fSIntel 46af75078fSIntel #include <rte_common.h> 47af75078fSIntel #include <rte_log.h> 48af75078fSIntel #include <rte_memory.h> 49af75078fSIntel #include <rte_memcpy.h> 50af75078fSIntel #include <rte_memzone.h> 51af75078fSIntel #include <rte_tailq.h> 52af75078fSIntel #include <rte_eal.h> 53af75078fSIntel #include <rte_per_lcore.h> 54af75078fSIntel #include <rte_launch.h> 55af75078fSIntel #include <rte_atomic.h> 56af75078fSIntel #include <rte_cycles.h> 57af75078fSIntel #include <rte_prefetch.h> 58af75078fSIntel #include <rte_lcore.h> 59af75078fSIntel #include <rte_per_lcore.h> 60af75078fSIntel #include <rte_branch_prediction.h> 61af75078fSIntel #include <rte_interrupts.h> 62af75078fSIntel #include <rte_pci.h> 63af75078fSIntel #include <rte_random.h> 64af75078fSIntel #include <rte_debug.h> 65af75078fSIntel #include <rte_ether.h> 66af75078fSIntel #include <rte_ethdev.h> 67af75078fSIntel #include <rte_ring.h> 68af75078fSIntel #include <rte_log.h> 69af75078fSIntel #include <rte_mempool.h> 70af75078fSIntel #include <rte_mbuf.h> 71af75078fSIntel #include <rte_memcpy.h> 72af75078fSIntel 73af75078fSIntel #include "main.h" 74af75078fSIntel 75af75078fSIntel /* basic constants used in application */ 76af75078fSIntel #define NUM_QUEUES 128 77af75078fSIntel 78af75078fSIntel #define NUM_MBUFS 64*1024 79af75078fSIntel #define MBUF_CACHE_SIZE 64 80af75078fSIntel #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) 81af75078fSIntel 82d4f37b09SIntel #define INVALID_PORT_ID 0xFF 83d4f37b09SIntel 84d4f37b09SIntel /* mask of enabled ports */ 85d4f37b09SIntel static uint32_t enabled_port_mask = 0; 86af75078fSIntel 871d8d954bSIntel /* number of pools (if user does not specify any, 16 by default */ 881d8d954bSIntel static enum rte_eth_nb_pools num_pools = ETH_16_POOLS; 891d8d954bSIntel 90af75078fSIntel /* 91af75078fSIntel * RX and TX Prefetch, Host, and Write-back threshold values should be 92af75078fSIntel * carefully set for optimal performance. Consult the network 93af75078fSIntel * controller's datasheet and supporting DPDK documentation for guidance 94af75078fSIntel * on how these parameters should be set. 95af75078fSIntel */ 96af75078fSIntel /* Default configuration for rx and tx thresholds etc. */ 97af75078fSIntel static const struct rte_eth_rxconf rx_conf_default = { 98af75078fSIntel .rx_thresh = { 99af75078fSIntel .pthresh = 8, 100af75078fSIntel .hthresh = 8, 101af75078fSIntel .wthresh = 4, 102af75078fSIntel }, 103af75078fSIntel }; 104af75078fSIntel 105af75078fSIntel /* 106af75078fSIntel * These default values are optimized for use with the Intel(R) 82599 10 GbE 107af75078fSIntel * Controller and the DPDK ixgbe PMD. Consider using other values for other 108af75078fSIntel * network controllers and/or network drivers. 109af75078fSIntel */ 110af75078fSIntel static const struct rte_eth_txconf tx_conf_default = { 111af75078fSIntel .tx_thresh = { 112af75078fSIntel .pthresh = 36, 113af75078fSIntel .hthresh = 0, 114af75078fSIntel .wthresh = 0, 115af75078fSIntel }, 116af75078fSIntel .tx_free_thresh = 0, /* Use PMD default values */ 117af75078fSIntel .tx_rs_thresh = 0, /* Use PMD default values */ 118af75078fSIntel }; 119af75078fSIntel 120af75078fSIntel /* empty vmdq+dcb configuration structure. Filled in programatically */ 121af75078fSIntel static const struct rte_eth_conf vmdq_dcb_conf_default = { 122af75078fSIntel .rxmode = { 12332e7aa0bSIntel .mq_mode = ETH_MQ_RX_VMDQ_DCB, 124af75078fSIntel .split_hdr_size = 0, 125af75078fSIntel .header_split = 0, /**< Header Split disabled */ 126af75078fSIntel .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 127af75078fSIntel .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 128af75078fSIntel .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 129af75078fSIntel }, 130af75078fSIntel .txmode = { 13132e7aa0bSIntel .mq_mode = ETH_MQ_TX_NONE, 132af75078fSIntel }, 133af75078fSIntel .rx_adv_conf = { 134af75078fSIntel /* 135af75078fSIntel * should be overridden separately in code with 136af75078fSIntel * appropriate values 137af75078fSIntel */ 138af75078fSIntel .vmdq_dcb_conf = { 1391d8d954bSIntel .nb_queue_pools = ETH_16_POOLS, 140af75078fSIntel .enable_default_pool = 0, 141af75078fSIntel .default_pool = 0, 142af75078fSIntel .nb_pool_maps = 0, 143af75078fSIntel .pool_map = {{0, 0},}, 144af75078fSIntel .dcb_queue = {0}, 145af75078fSIntel }, 146af75078fSIntel }, 147af75078fSIntel }; 148af75078fSIntel 149d4f37b09SIntel static uint8_t ports[RTE_MAX_ETHPORTS]; 150d4f37b09SIntel static unsigned num_ports = 0; 151d4f37b09SIntel 152af75078fSIntel /* array used for printing out statistics */ 153af75078fSIntel volatile unsigned long rxPackets[ NUM_QUEUES ] = {0}; 154af75078fSIntel 155af75078fSIntel const uint16_t vlan_tags[] = { 156af75078fSIntel 0, 1, 2, 3, 4, 5, 6, 7, 157af75078fSIntel 8, 9, 10, 11, 12, 13, 14, 15, 158af75078fSIntel 16, 17, 18, 19, 20, 21, 22, 23, 159af75078fSIntel 24, 25, 26, 27, 28, 29, 30, 31 160af75078fSIntel }; 161af75078fSIntel 162af75078fSIntel /* Builds up the correct configuration for vmdq+dcb based on the vlan tags array 163af75078fSIntel * given above, and the number of traffic classes available for use. */ 164af75078fSIntel static inline int 165af75078fSIntel get_eth_conf(struct rte_eth_conf *eth_conf, enum rte_eth_nb_pools num_pools) 166af75078fSIntel { 167af75078fSIntel struct rte_eth_vmdq_dcb_conf conf; 168af75078fSIntel unsigned i; 169af75078fSIntel 170af75078fSIntel if (num_pools != ETH_16_POOLS && num_pools != ETH_32_POOLS ) return -1; 171af75078fSIntel 172af75078fSIntel conf.nb_queue_pools = num_pools; 173af75078fSIntel conf.enable_default_pool = 0; 1741d8d954bSIntel conf.default_pool = 0; /* set explicit value, even if not used */ 175af75078fSIntel conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); 176af75078fSIntel for (i = 0; i < conf.nb_pool_maps; i++){ 177af75078fSIntel conf.pool_map[i].vlan_id = vlan_tags[ i ]; 178af75078fSIntel conf.pool_map[i].pools = 1 << (i % num_pools); 179af75078fSIntel } 180af75078fSIntel for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){ 181af75078fSIntel conf.dcb_queue[i] = (uint8_t)(i % (NUM_QUEUES/num_pools)); 182af75078fSIntel } 1831d8d954bSIntel (void)(rte_memcpy(eth_conf, &vmdq_dcb_conf_default, sizeof(*eth_conf))); 1841d8d954bSIntel (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_dcb_conf, &conf, 1851d8d954bSIntel sizeof(eth_conf->rx_adv_conf.vmdq_dcb_conf))); 186af75078fSIntel return 0; 187af75078fSIntel } 188af75078fSIntel 189af75078fSIntel /* 190af75078fSIntel * Initialises a given port using global settings and with the rx buffers 191af75078fSIntel * coming from the mbuf_pool passed as parameter 192af75078fSIntel */ 193af75078fSIntel static inline int 194af75078fSIntel port_init(uint8_t port, struct rte_mempool *mbuf_pool) 195af75078fSIntel { 196af75078fSIntel struct rte_eth_conf port_conf; 197af75078fSIntel const uint16_t rxRings = ETH_VMDQ_DCB_NUM_QUEUES, 198af75078fSIntel txRings = (uint16_t)rte_lcore_count(); 199af75078fSIntel const uint16_t rxRingSize = 128, txRingSize = 512; 200af75078fSIntel int retval; 201af75078fSIntel uint16_t q; 202af75078fSIntel 2031d8d954bSIntel retval = get_eth_conf(&port_conf, num_pools); 2041d8d954bSIntel if (retval < 0) 2051d8d954bSIntel return retval; 206af75078fSIntel 207af75078fSIntel if (port >= rte_eth_dev_count()) return -1; 208af75078fSIntel 209af75078fSIntel retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); 210af75078fSIntel if (retval != 0) 211af75078fSIntel return retval; 212af75078fSIntel 213af75078fSIntel for (q = 0; q < rxRings; q ++) { 214af75078fSIntel retval = rte_eth_rx_queue_setup(port, q, rxRingSize, 215e60f71ebSIntel rte_eth_dev_socket_id(port), &rx_conf_default, 216af75078fSIntel mbuf_pool); 217af75078fSIntel if (retval < 0) 218af75078fSIntel return retval; 219af75078fSIntel } 220af75078fSIntel 221af75078fSIntel for (q = 0; q < txRings; q ++) { 222af75078fSIntel retval = rte_eth_tx_queue_setup(port, q, txRingSize, 223e60f71ebSIntel rte_eth_dev_socket_id(port), &tx_conf_default); 224af75078fSIntel if (retval < 0) 225af75078fSIntel return retval; 226af75078fSIntel } 227af75078fSIntel 228af75078fSIntel retval = rte_eth_dev_start(port); 229af75078fSIntel if (retval < 0) 230af75078fSIntel return retval; 231af75078fSIntel 232967b6294SIntel struct ether_addr addr; 233967b6294SIntel rte_eth_macaddr_get(port, &addr); 234967b6294SIntel printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 235967b6294SIntel " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", 236967b6294SIntel (unsigned)port, 237967b6294SIntel addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], 238967b6294SIntel addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); 239967b6294SIntel 240af75078fSIntel return 0; 241af75078fSIntel } 242af75078fSIntel 2431d8d954bSIntel /* Check num_pools parameter and set it if OK*/ 2441d8d954bSIntel static int 2451d8d954bSIntel vmdq_parse_num_pools(const char *q_arg) 2461d8d954bSIntel { 2471d8d954bSIntel char *end = NULL; 2481d8d954bSIntel int n; 2491d8d954bSIntel 2501d8d954bSIntel /* parse number string */ 2511d8d954bSIntel n = strtol(q_arg, &end, 10); 2521d8d954bSIntel if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 2531d8d954bSIntel return -1; 2541d8d954bSIntel if (n != 16 && n != 32) 2551d8d954bSIntel return -1; 2561d8d954bSIntel if (n == 16) 2571d8d954bSIntel num_pools = ETH_16_POOLS; 2581d8d954bSIntel else 2591d8d954bSIntel num_pools = ETH_32_POOLS; 2601d8d954bSIntel 2611d8d954bSIntel return 0; 2621d8d954bSIntel } 2631d8d954bSIntel 264d4f37b09SIntel static int 265d4f37b09SIntel parse_portmask(const char *portmask) 266d4f37b09SIntel { 267d4f37b09SIntel char *end = NULL; 268d4f37b09SIntel unsigned long pm; 269d4f37b09SIntel 270d4f37b09SIntel /* parse hexadecimal string */ 271d4f37b09SIntel pm = strtoul(portmask, &end, 16); 272d4f37b09SIntel if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 273d4f37b09SIntel return -1; 274d4f37b09SIntel 275d4f37b09SIntel if (pm == 0) 276d4f37b09SIntel return -1; 277d4f37b09SIntel 278d4f37b09SIntel return pm; 279d4f37b09SIntel } 280d4f37b09SIntel 2811d8d954bSIntel /* Display usage */ 2821d8d954bSIntel static void 2831d8d954bSIntel vmdq_usage(const char *prgname) 2841d8d954bSIntel { 285d4f37b09SIntel printf("%s [EAL options] -- -p PORTMASK]\n" 286d4f37b09SIntel " --nb-pools NP: number of pools (16 default, 32)\n", 2871d8d954bSIntel prgname); 2881d8d954bSIntel } 2891d8d954bSIntel 2901d8d954bSIntel /* Parse the argument (num_pools) given in the command line of the application */ 2911d8d954bSIntel static int 2921d8d954bSIntel vmdq_parse_args(int argc, char **argv) 2931d8d954bSIntel { 2941d8d954bSIntel int opt; 2951d8d954bSIntel int option_index; 296d4f37b09SIntel unsigned i; 2971d8d954bSIntel const char *prgname = argv[0]; 2981d8d954bSIntel static struct option long_option[] = { 2991d8d954bSIntel {"nb-pools", required_argument, NULL, 0}, 3001d8d954bSIntel {NULL, 0, 0, 0} 3011d8d954bSIntel }; 3021d8d954bSIntel 3031d8d954bSIntel /* Parse command line */ 304d4f37b09SIntel while ((opt = getopt_long(argc, argv, "p:",long_option,&option_index)) != EOF) { 3051d8d954bSIntel switch (opt) { 306d4f37b09SIntel /* portmask */ 307d4f37b09SIntel case 'p': 308d4f37b09SIntel enabled_port_mask = parse_portmask(optarg); 309d4f37b09SIntel if (enabled_port_mask == 0) { 310d4f37b09SIntel printf("invalid portmask\n"); 311d4f37b09SIntel vmdq_usage(prgname); 312d4f37b09SIntel return -1; 313d4f37b09SIntel } 314d4f37b09SIntel break; 3151d8d954bSIntel case 0: 3161d8d954bSIntel if (vmdq_parse_num_pools(optarg) == -1){ 3171d8d954bSIntel printf("invalid number of pools\n"); 3181d8d954bSIntel vmdq_usage(prgname); 3191d8d954bSIntel return -1; 3201d8d954bSIntel } 3211d8d954bSIntel break; 3221d8d954bSIntel default: 3231d8d954bSIntel vmdq_usage(prgname); 3241d8d954bSIntel return -1; 3251d8d954bSIntel } 3261d8d954bSIntel } 327d4f37b09SIntel 328d4f37b09SIntel for(i = 0; i < RTE_MAX_ETHPORTS; i++) 329d4f37b09SIntel { 330d4f37b09SIntel if (enabled_port_mask & (1 << i)) 331d4f37b09SIntel ports[num_ports++] = (uint8_t)i; 332d4f37b09SIntel } 333d4f37b09SIntel 334d4f37b09SIntel if (num_ports < 2 || num_ports % 2) { 335d4f37b09SIntel printf("Current enabled port number is %u," 336d4f37b09SIntel "but it should be even and at least 2\n",num_ports); 337d4f37b09SIntel return -1; 338d4f37b09SIntel } 339d4f37b09SIntel 3401d8d954bSIntel return 0; 3411d8d954bSIntel } 3421d8d954bSIntel 3431d8d954bSIntel 344af75078fSIntel #ifndef RTE_EXEC_ENV_BAREMETAL 345af75078fSIntel /* When we receive a HUP signal, print out our stats */ 346af75078fSIntel static void 347af75078fSIntel sighup_handler(int signum) 348af75078fSIntel { 349af75078fSIntel unsigned q; 350af75078fSIntel for (q = 0; q < NUM_QUEUES; q ++) { 3511d8d954bSIntel if (q % (NUM_QUEUES/num_pools) == 0) 3521d8d954bSIntel printf("\nPool %u: ", q/(NUM_QUEUES/num_pools)); 353af75078fSIntel printf("%lu ", rxPackets[ q ]); 354af75078fSIntel } 355af75078fSIntel printf("\nFinished handling signal %d\n", signum); 356af75078fSIntel } 357af75078fSIntel #endif 358af75078fSIntel 359af75078fSIntel /* 360af75078fSIntel * Main thread that does the work, reading from INPUT_PORT 361af75078fSIntel * and writing to OUTPUT_PORT 362af75078fSIntel */ 363af75078fSIntel static __attribute__((noreturn)) int 364af75078fSIntel lcore_main(void *arg) 365af75078fSIntel { 366af75078fSIntel const uintptr_t core_num = (uintptr_t)arg; 367af75078fSIntel const unsigned num_cores = rte_lcore_count(); 368af75078fSIntel uint16_t startQueue = (uint16_t)(core_num * (NUM_QUEUES/num_cores)); 369af75078fSIntel uint16_t endQueue = (uint16_t)(startQueue + (NUM_QUEUES/num_cores)); 370d4f37b09SIntel uint16_t q, i, p; 371af75078fSIntel 372af75078fSIntel printf("Core %u(lcore %u) reading queues %i-%i\n", (unsigned)core_num, 373af75078fSIntel rte_lcore_id(), startQueue, endQueue - 1); 374af75078fSIntel 375af75078fSIntel for (;;) { 376af75078fSIntel struct rte_mbuf *buf[32]; 377af75078fSIntel const uint16_t buf_size = sizeof(buf) / sizeof(buf[0]); 378d4f37b09SIntel for (p = 0; p < num_ports; p++) { 379d4f37b09SIntel const uint8_t src = ports[p]; 380d4f37b09SIntel const uint8_t dst = ports[p ^ 1]; /* 0 <-> 1, 2 <-> 3 etc */ 381d4f37b09SIntel 382d4f37b09SIntel if ((src == INVALID_PORT_ID) || (dst == INVALID_PORT_ID)) 383d4f37b09SIntel continue; 384af75078fSIntel 385af75078fSIntel for (q = startQueue; q < endQueue; q++) { 386d4f37b09SIntel const uint16_t rxCount = rte_eth_rx_burst(src, 387af75078fSIntel q, buf, buf_size); 388af75078fSIntel if (rxCount == 0) 389af75078fSIntel continue; 390af75078fSIntel rxPackets[q] += rxCount; 391af75078fSIntel 392d4f37b09SIntel const uint16_t txCount = rte_eth_tx_burst(dst, 393af75078fSIntel (uint16_t)core_num, buf, rxCount); 394af75078fSIntel if (txCount != rxCount) { 395af75078fSIntel for (i = txCount; i < rxCount; i++) 396af75078fSIntel rte_pktmbuf_free(buf[i]); 397af75078fSIntel } 398af75078fSIntel } 399af75078fSIntel } 400af75078fSIntel } 401d4f37b09SIntel } 402d4f37b09SIntel 403d4f37b09SIntel /* 404d4f37b09SIntel * Update the global var NUM_PORTS and array PORTS according to system ports number 405d4f37b09SIntel * and return valid ports number 406d4f37b09SIntel */ 407d4f37b09SIntel static unsigned check_ports_num(unsigned nb_ports) 408d4f37b09SIntel { 409d4f37b09SIntel unsigned valid_num_ports = num_ports; 410d4f37b09SIntel unsigned portid; 411d4f37b09SIntel 412d4f37b09SIntel if (num_ports > nb_ports) { 413d4f37b09SIntel printf("\nSpecified port number(%u) exceeds total system port number(%u)\n", 414d4f37b09SIntel num_ports, nb_ports); 415d4f37b09SIntel num_ports = nb_ports; 416d4f37b09SIntel } 417d4f37b09SIntel 418d4f37b09SIntel for (portid = 0; portid < num_ports; portid ++) { 419d4f37b09SIntel if (ports[portid] >= nb_ports) { 420d4f37b09SIntel printf("\nSpecified port ID(%u) exceeds max system port ID(%u)\n", 421d4f37b09SIntel ports[portid], (nb_ports - 1)); 422d4f37b09SIntel ports[portid] = INVALID_PORT_ID; 423d4f37b09SIntel valid_num_ports --; 424d4f37b09SIntel } 425d4f37b09SIntel } 426d4f37b09SIntel return valid_num_ports; 427d4f37b09SIntel } 428d4f37b09SIntel 429af75078fSIntel 430af75078fSIntel /* Main function, does initialisation and calls the per-lcore functions */ 431af75078fSIntel int 432af75078fSIntel MAIN(int argc, char *argv[]) 433af75078fSIntel { 434af75078fSIntel unsigned cores; 435af75078fSIntel struct rte_mempool *mbuf_pool; 436af75078fSIntel unsigned lcore_id; 437af75078fSIntel uintptr_t i; 4381d8d954bSIntel int ret; 439d4f37b09SIntel unsigned nb_ports, valid_num_ports; 440d4f37b09SIntel uint8_t portid; 441af75078fSIntel 442af75078fSIntel #ifndef RTE_EXEC_ENV_BAREMETAL 443af75078fSIntel signal(SIGHUP, sighup_handler); 444af75078fSIntel #endif 445af75078fSIntel 4461d8d954bSIntel /* init EAL */ 4471d8d954bSIntel ret = rte_eal_init(argc, argv); 4481d8d954bSIntel if (ret < 0) 449af75078fSIntel rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); 4501d8d954bSIntel argc -= ret; 4511d8d954bSIntel argv += ret; 4521d8d954bSIntel 4531d8d954bSIntel /* parse app arguments */ 4541d8d954bSIntel ret = vmdq_parse_args(argc, argv); 4551d8d954bSIntel if (ret < 0) 4561d8d954bSIntel rte_exit(EXIT_FAILURE, "Invalid VMDQ argument\n"); 4571d8d954bSIntel 4581d8d954bSIntel if (rte_ixgbe_pmd_init() != 0 || 459af75078fSIntel rte_eal_pci_probe() != 0) 460af75078fSIntel rte_exit(EXIT_FAILURE, "Error with NIC driver initialization\n"); 461af75078fSIntel 462af75078fSIntel cores = rte_lcore_count(); 463d4f37b09SIntel if ((cores & (cores - 1)) != 0 || cores > 128) { 464d4f37b09SIntel rte_exit(EXIT_FAILURE,"This program can only run on an even" 465d4f37b09SIntel "number of cores(1-128)\n\n"); 466af75078fSIntel } 467af75078fSIntel 468d4f37b09SIntel nb_ports = rte_eth_dev_count(); 469d4f37b09SIntel if (nb_ports > RTE_MAX_ETHPORTS) 470d4f37b09SIntel nb_ports = RTE_MAX_ETHPORTS; 471d4f37b09SIntel 472d4f37b09SIntel /* 473d4f37b09SIntel * Update the global var NUM_PORTS and global array PORTS 474d4f37b09SIntel * and get value of var VALID_NUM_PORTS according to system ports number 475d4f37b09SIntel */ 476d4f37b09SIntel valid_num_ports = check_ports_num(nb_ports); 477d4f37b09SIntel 478d4f37b09SIntel if (valid_num_ports < 2 || valid_num_ports % 2) { 479d4f37b09SIntel printf("Current valid ports number is %u\n", valid_num_ports); 480d4f37b09SIntel rte_exit(EXIT_FAILURE, "Error with valid ports number is not even or less than 2\n"); 481d4f37b09SIntel } 482d4f37b09SIntel 483d4f37b09SIntel mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS * nb_ports, 484af75078fSIntel MBUF_SIZE, MBUF_CACHE_SIZE, 485af75078fSIntel sizeof(struct rte_pktmbuf_pool_private), 486af75078fSIntel rte_pktmbuf_pool_init, NULL, 487af75078fSIntel rte_pktmbuf_init, NULL, 488e60f71ebSIntel rte_socket_id(), 0); 489af75078fSIntel if (mbuf_pool == NULL) 490af75078fSIntel rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 491af75078fSIntel 492d4f37b09SIntel /* initialize all ports */ 493d4f37b09SIntel for (portid = 0; portid < nb_ports; portid++) { 494d4f37b09SIntel /* skip ports that are not enabled */ 495d4f37b09SIntel if ((enabled_port_mask & (1 << portid)) == 0) { 496d4f37b09SIntel printf("\nSkipping disabled port %d\n", portid); 497d4f37b09SIntel continue; 498d4f37b09SIntel } 499d4f37b09SIntel if (port_init(portid, mbuf_pool) != 0) 500af75078fSIntel rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); 501d4f37b09SIntel } 502af75078fSIntel 503af75078fSIntel /* call lcore_main() on every slave lcore */ 504af75078fSIntel i = 0; 505af75078fSIntel RTE_LCORE_FOREACH_SLAVE(lcore_id) { 506af75078fSIntel rte_eal_remote_launch(lcore_main, (void*)i++, lcore_id); 507af75078fSIntel } 508af75078fSIntel /* call on master too */ 509af75078fSIntel (void) lcore_main((void*)i); 510af75078fSIntel 511af75078fSIntel return 0; 512af75078fSIntel } 513