1af75078fSIntel /*- 2af75078fSIntel * BSD LICENSE 3af75078fSIntel * 4e9d48c00SBruce 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 /* basic constants used in application */ 74af75078fSIntel #define NUM_QUEUES 128 75af75078fSIntel 76af75078fSIntel #define NUM_MBUFS 64*1024 77af75078fSIntel #define MBUF_CACHE_SIZE 64 78af75078fSIntel #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) 79af75078fSIntel 80d4f37b09SIntel #define INVALID_PORT_ID 0xFF 81d4f37b09SIntel 82d4f37b09SIntel /* mask of enabled ports */ 83d4f37b09SIntel static uint32_t enabled_port_mask = 0; 84af75078fSIntel 851d8d954bSIntel /* number of pools (if user does not specify any, 16 by default */ 861d8d954bSIntel static enum rte_eth_nb_pools num_pools = ETH_16_POOLS; 871d8d954bSIntel 88af75078fSIntel /* empty vmdq+dcb configuration structure. Filled in programatically */ 89af75078fSIntel static const struct rte_eth_conf vmdq_dcb_conf_default = { 90af75078fSIntel .rxmode = { 9132e7aa0bSIntel .mq_mode = ETH_MQ_RX_VMDQ_DCB, 92af75078fSIntel .split_hdr_size = 0, 93af75078fSIntel .header_split = 0, /**< Header Split disabled */ 94af75078fSIntel .hw_ip_checksum = 0, /**< IP checksum offload disabled */ 95af75078fSIntel .hw_vlan_filter = 0, /**< VLAN filtering disabled */ 96af75078fSIntel .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ 97af75078fSIntel }, 98af75078fSIntel .txmode = { 9932e7aa0bSIntel .mq_mode = ETH_MQ_TX_NONE, 100af75078fSIntel }, 101af75078fSIntel .rx_adv_conf = { 102af75078fSIntel /* 103af75078fSIntel * should be overridden separately in code with 104af75078fSIntel * appropriate values 105af75078fSIntel */ 106af75078fSIntel .vmdq_dcb_conf = { 1071d8d954bSIntel .nb_queue_pools = ETH_16_POOLS, 108af75078fSIntel .enable_default_pool = 0, 109af75078fSIntel .default_pool = 0, 110af75078fSIntel .nb_pool_maps = 0, 111af75078fSIntel .pool_map = {{0, 0},}, 112af75078fSIntel .dcb_queue = {0}, 113af75078fSIntel }, 114af75078fSIntel }, 115af75078fSIntel }; 116af75078fSIntel 117d4f37b09SIntel static uint8_t ports[RTE_MAX_ETHPORTS]; 118d4f37b09SIntel static unsigned num_ports = 0; 119d4f37b09SIntel 120af75078fSIntel /* array used for printing out statistics */ 121af75078fSIntel volatile unsigned long rxPackets[ NUM_QUEUES ] = {0}; 122af75078fSIntel 123af75078fSIntel const uint16_t vlan_tags[] = { 124af75078fSIntel 0, 1, 2, 3, 4, 5, 6, 7, 125af75078fSIntel 8, 9, 10, 11, 12, 13, 14, 15, 126af75078fSIntel 16, 17, 18, 19, 20, 21, 22, 23, 127af75078fSIntel 24, 25, 26, 27, 28, 29, 30, 31 128af75078fSIntel }; 129af75078fSIntel 130af75078fSIntel /* Builds up the correct configuration for vmdq+dcb based on the vlan tags array 131af75078fSIntel * given above, and the number of traffic classes available for use. */ 132af75078fSIntel static inline int 133af75078fSIntel get_eth_conf(struct rte_eth_conf *eth_conf, enum rte_eth_nb_pools num_pools) 134af75078fSIntel { 135af75078fSIntel struct rte_eth_vmdq_dcb_conf conf; 136af75078fSIntel unsigned i; 137af75078fSIntel 138af75078fSIntel if (num_pools != ETH_16_POOLS && num_pools != ETH_32_POOLS ) return -1; 139af75078fSIntel 140af75078fSIntel conf.nb_queue_pools = num_pools; 141af75078fSIntel conf.enable_default_pool = 0; 1421d8d954bSIntel conf.default_pool = 0; /* set explicit value, even if not used */ 143af75078fSIntel conf.nb_pool_maps = sizeof( vlan_tags )/sizeof( vlan_tags[ 0 ]); 144af75078fSIntel for (i = 0; i < conf.nb_pool_maps; i++){ 145af75078fSIntel conf.pool_map[i].vlan_id = vlan_tags[ i ]; 146af75078fSIntel conf.pool_map[i].pools = 1 << (i % num_pools); 147af75078fSIntel } 148af75078fSIntel for (i = 0; i < ETH_DCB_NUM_USER_PRIORITIES; i++){ 149af75078fSIntel conf.dcb_queue[i] = (uint8_t)(i % (NUM_QUEUES/num_pools)); 150af75078fSIntel } 1511d8d954bSIntel (void)(rte_memcpy(eth_conf, &vmdq_dcb_conf_default, sizeof(*eth_conf))); 1521d8d954bSIntel (void)(rte_memcpy(ð_conf->rx_adv_conf.vmdq_dcb_conf, &conf, 1531d8d954bSIntel sizeof(eth_conf->rx_adv_conf.vmdq_dcb_conf))); 154af75078fSIntel return 0; 155af75078fSIntel } 156af75078fSIntel 157af75078fSIntel /* 158af75078fSIntel * Initialises a given port using global settings and with the rx buffers 159af75078fSIntel * coming from the mbuf_pool passed as parameter 160af75078fSIntel */ 161af75078fSIntel static inline int 162af75078fSIntel port_init(uint8_t port, struct rte_mempool *mbuf_pool) 163af75078fSIntel { 164af75078fSIntel struct rte_eth_conf port_conf; 165af75078fSIntel const uint16_t rxRings = ETH_VMDQ_DCB_NUM_QUEUES, 166af75078fSIntel txRings = (uint16_t)rte_lcore_count(); 167af75078fSIntel const uint16_t rxRingSize = 128, txRingSize = 512; 168af75078fSIntel int retval; 169af75078fSIntel uint16_t q; 170af75078fSIntel 1711d8d954bSIntel retval = get_eth_conf(&port_conf, num_pools); 1721d8d954bSIntel if (retval < 0) 1731d8d954bSIntel return retval; 174af75078fSIntel 175af75078fSIntel if (port >= rte_eth_dev_count()) return -1; 176af75078fSIntel 177af75078fSIntel retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); 178af75078fSIntel if (retval != 0) 179af75078fSIntel return retval; 180af75078fSIntel 181af75078fSIntel for (q = 0; q < rxRings; q ++) { 182af75078fSIntel retval = rte_eth_rx_queue_setup(port, q, rxRingSize, 18381f7ecd9SPablo de Lara rte_eth_dev_socket_id(port), 18481f7ecd9SPablo de Lara NULL, 185af75078fSIntel mbuf_pool); 186af75078fSIntel if (retval < 0) 187af75078fSIntel return retval; 188af75078fSIntel } 189af75078fSIntel 190af75078fSIntel for (q = 0; q < txRings; q ++) { 191af75078fSIntel retval = rte_eth_tx_queue_setup(port, q, txRingSize, 19281f7ecd9SPablo de Lara rte_eth_dev_socket_id(port), 19381f7ecd9SPablo de Lara NULL); 194af75078fSIntel if (retval < 0) 195af75078fSIntel return retval; 196af75078fSIntel } 197af75078fSIntel 198af75078fSIntel retval = rte_eth_dev_start(port); 199af75078fSIntel if (retval < 0) 200af75078fSIntel return retval; 201af75078fSIntel 202967b6294SIntel struct ether_addr addr; 203967b6294SIntel rte_eth_macaddr_get(port, &addr); 204967b6294SIntel printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 205967b6294SIntel " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", 206967b6294SIntel (unsigned)port, 207967b6294SIntel addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2], 208967b6294SIntel addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]); 209967b6294SIntel 210af75078fSIntel return 0; 211af75078fSIntel } 212af75078fSIntel 2131d8d954bSIntel /* Check num_pools parameter and set it if OK*/ 2141d8d954bSIntel static int 2151d8d954bSIntel vmdq_parse_num_pools(const char *q_arg) 2161d8d954bSIntel { 2171d8d954bSIntel char *end = NULL; 2181d8d954bSIntel int n; 2191d8d954bSIntel 2201d8d954bSIntel /* parse number string */ 2211d8d954bSIntel n = strtol(q_arg, &end, 10); 2221d8d954bSIntel if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) 2231d8d954bSIntel return -1; 2241d8d954bSIntel if (n != 16 && n != 32) 2251d8d954bSIntel return -1; 2261d8d954bSIntel if (n == 16) 2271d8d954bSIntel num_pools = ETH_16_POOLS; 2281d8d954bSIntel else 2291d8d954bSIntel num_pools = ETH_32_POOLS; 2301d8d954bSIntel 2311d8d954bSIntel return 0; 2321d8d954bSIntel } 2331d8d954bSIntel 234d4f37b09SIntel static int 235d4f37b09SIntel parse_portmask(const char *portmask) 236d4f37b09SIntel { 237d4f37b09SIntel char *end = NULL; 238d4f37b09SIntel unsigned long pm; 239d4f37b09SIntel 240d4f37b09SIntel /* parse hexadecimal string */ 241d4f37b09SIntel pm = strtoul(portmask, &end, 16); 242d4f37b09SIntel if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 243d4f37b09SIntel return -1; 244d4f37b09SIntel 245d4f37b09SIntel if (pm == 0) 246d4f37b09SIntel return -1; 247d4f37b09SIntel 248d4f37b09SIntel return pm; 249d4f37b09SIntel } 250d4f37b09SIntel 2511d8d954bSIntel /* Display usage */ 2521d8d954bSIntel static void 2531d8d954bSIntel vmdq_usage(const char *prgname) 2541d8d954bSIntel { 255d4f37b09SIntel printf("%s [EAL options] -- -p PORTMASK]\n" 256d4f37b09SIntel " --nb-pools NP: number of pools (16 default, 32)\n", 2571d8d954bSIntel prgname); 2581d8d954bSIntel } 2591d8d954bSIntel 2601d8d954bSIntel /* Parse the argument (num_pools) given in the command line of the application */ 2611d8d954bSIntel static int 2621d8d954bSIntel vmdq_parse_args(int argc, char **argv) 2631d8d954bSIntel { 2641d8d954bSIntel int opt; 2651d8d954bSIntel int option_index; 266d4f37b09SIntel unsigned i; 2671d8d954bSIntel const char *prgname = argv[0]; 2681d8d954bSIntel static struct option long_option[] = { 2691d8d954bSIntel {"nb-pools", required_argument, NULL, 0}, 2701d8d954bSIntel {NULL, 0, 0, 0} 2711d8d954bSIntel }; 2721d8d954bSIntel 2731d8d954bSIntel /* Parse command line */ 274d4f37b09SIntel while ((opt = getopt_long(argc, argv, "p:",long_option,&option_index)) != EOF) { 2751d8d954bSIntel switch (opt) { 276d4f37b09SIntel /* portmask */ 277d4f37b09SIntel case 'p': 278d4f37b09SIntel enabled_port_mask = parse_portmask(optarg); 279d4f37b09SIntel if (enabled_port_mask == 0) { 280d4f37b09SIntel printf("invalid portmask\n"); 281d4f37b09SIntel vmdq_usage(prgname); 282d4f37b09SIntel return -1; 283d4f37b09SIntel } 284d4f37b09SIntel break; 2851d8d954bSIntel case 0: 2861d8d954bSIntel if (vmdq_parse_num_pools(optarg) == -1){ 2871d8d954bSIntel printf("invalid number of pools\n"); 2881d8d954bSIntel vmdq_usage(prgname); 2891d8d954bSIntel return -1; 2901d8d954bSIntel } 2911d8d954bSIntel break; 2921d8d954bSIntel default: 2931d8d954bSIntel vmdq_usage(prgname); 2941d8d954bSIntel return -1; 2951d8d954bSIntel } 2961d8d954bSIntel } 297d4f37b09SIntel 298d4f37b09SIntel for(i = 0; i < RTE_MAX_ETHPORTS; i++) 299d4f37b09SIntel { 300d4f37b09SIntel if (enabled_port_mask & (1 << i)) 301d4f37b09SIntel ports[num_ports++] = (uint8_t)i; 302d4f37b09SIntel } 303d4f37b09SIntel 304d4f37b09SIntel if (num_ports < 2 || num_ports % 2) { 305d4f37b09SIntel printf("Current enabled port number is %u," 306d4f37b09SIntel "but it should be even and at least 2\n",num_ports); 307d4f37b09SIntel return -1; 308d4f37b09SIntel } 309d4f37b09SIntel 3101d8d954bSIntel return 0; 3111d8d954bSIntel } 3121d8d954bSIntel 3131d8d954bSIntel 314af75078fSIntel /* When we receive a HUP signal, print out our stats */ 315af75078fSIntel static void 316af75078fSIntel sighup_handler(int signum) 317af75078fSIntel { 318af75078fSIntel unsigned q; 319af75078fSIntel for (q = 0; q < NUM_QUEUES; q ++) { 3201d8d954bSIntel if (q % (NUM_QUEUES/num_pools) == 0) 3211d8d954bSIntel printf("\nPool %u: ", q/(NUM_QUEUES/num_pools)); 322af75078fSIntel printf("%lu ", rxPackets[ q ]); 323af75078fSIntel } 324af75078fSIntel printf("\nFinished handling signal %d\n", signum); 325af75078fSIntel } 326af75078fSIntel 327af75078fSIntel /* 328af75078fSIntel * Main thread that does the work, reading from INPUT_PORT 329af75078fSIntel * and writing to OUTPUT_PORT 330af75078fSIntel */ 331af75078fSIntel static __attribute__((noreturn)) int 332af75078fSIntel lcore_main(void *arg) 333af75078fSIntel { 334af75078fSIntel const uintptr_t core_num = (uintptr_t)arg; 335af75078fSIntel const unsigned num_cores = rte_lcore_count(); 336af75078fSIntel uint16_t startQueue = (uint16_t)(core_num * (NUM_QUEUES/num_cores)); 337af75078fSIntel uint16_t endQueue = (uint16_t)(startQueue + (NUM_QUEUES/num_cores)); 338d4f37b09SIntel uint16_t q, i, p; 339af75078fSIntel 340af75078fSIntel printf("Core %u(lcore %u) reading queues %i-%i\n", (unsigned)core_num, 341af75078fSIntel rte_lcore_id(), startQueue, endQueue - 1); 342af75078fSIntel 343af75078fSIntel for (;;) { 344af75078fSIntel struct rte_mbuf *buf[32]; 345af75078fSIntel const uint16_t buf_size = sizeof(buf) / sizeof(buf[0]); 346d4f37b09SIntel for (p = 0; p < num_ports; p++) { 347d4f37b09SIntel const uint8_t src = ports[p]; 348d4f37b09SIntel const uint8_t dst = ports[p ^ 1]; /* 0 <-> 1, 2 <-> 3 etc */ 349d4f37b09SIntel 350d4f37b09SIntel if ((src == INVALID_PORT_ID) || (dst == INVALID_PORT_ID)) 351d4f37b09SIntel continue; 352af75078fSIntel 353af75078fSIntel for (q = startQueue; q < endQueue; q++) { 354d4f37b09SIntel const uint16_t rxCount = rte_eth_rx_burst(src, 355af75078fSIntel q, buf, buf_size); 356af75078fSIntel if (rxCount == 0) 357af75078fSIntel continue; 358af75078fSIntel rxPackets[q] += rxCount; 359af75078fSIntel 360d4f37b09SIntel const uint16_t txCount = rte_eth_tx_burst(dst, 361af75078fSIntel (uint16_t)core_num, buf, rxCount); 362af75078fSIntel if (txCount != rxCount) { 363af75078fSIntel for (i = txCount; i < rxCount; i++) 364af75078fSIntel rte_pktmbuf_free(buf[i]); 365af75078fSIntel } 366af75078fSIntel } 367af75078fSIntel } 368af75078fSIntel } 369d4f37b09SIntel } 370d4f37b09SIntel 371d4f37b09SIntel /* 372d4f37b09SIntel * Update the global var NUM_PORTS and array PORTS according to system ports number 373d4f37b09SIntel * and return valid ports number 374d4f37b09SIntel */ 375d4f37b09SIntel static unsigned check_ports_num(unsigned nb_ports) 376d4f37b09SIntel { 377d4f37b09SIntel unsigned valid_num_ports = num_ports; 378d4f37b09SIntel unsigned portid; 379d4f37b09SIntel 380d4f37b09SIntel if (num_ports > nb_ports) { 381d4f37b09SIntel printf("\nSpecified port number(%u) exceeds total system port number(%u)\n", 382d4f37b09SIntel num_ports, nb_ports); 383d4f37b09SIntel num_ports = nb_ports; 384d4f37b09SIntel } 385d4f37b09SIntel 386d4f37b09SIntel for (portid = 0; portid < num_ports; portid ++) { 387d4f37b09SIntel if (ports[portid] >= nb_ports) { 388d4f37b09SIntel printf("\nSpecified port ID(%u) exceeds max system port ID(%u)\n", 389d4f37b09SIntel ports[portid], (nb_ports - 1)); 390d4f37b09SIntel ports[portid] = INVALID_PORT_ID; 391d4f37b09SIntel valid_num_ports --; 392d4f37b09SIntel } 393d4f37b09SIntel } 394d4f37b09SIntel return valid_num_ports; 395d4f37b09SIntel } 396d4f37b09SIntel 397af75078fSIntel 398af75078fSIntel /* Main function, does initialisation and calls the per-lcore functions */ 399af75078fSIntel int 400*98a16481SDavid Marchand main(int argc, char *argv[]) 401af75078fSIntel { 402af75078fSIntel unsigned cores; 403af75078fSIntel struct rte_mempool *mbuf_pool; 404af75078fSIntel unsigned lcore_id; 405af75078fSIntel uintptr_t i; 4061d8d954bSIntel int ret; 407d4f37b09SIntel unsigned nb_ports, valid_num_ports; 408d4f37b09SIntel uint8_t portid; 409af75078fSIntel 410af75078fSIntel signal(SIGHUP, sighup_handler); 411af75078fSIntel 4121d8d954bSIntel /* init EAL */ 4131d8d954bSIntel ret = rte_eal_init(argc, argv); 4141d8d954bSIntel if (ret < 0) 415af75078fSIntel rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); 4161d8d954bSIntel argc -= ret; 4171d8d954bSIntel argv += ret; 4181d8d954bSIntel 4191d8d954bSIntel /* parse app arguments */ 4201d8d954bSIntel ret = vmdq_parse_args(argc, argv); 4211d8d954bSIntel if (ret < 0) 4221d8d954bSIntel rte_exit(EXIT_FAILURE, "Invalid VMDQ argument\n"); 4231d8d954bSIntel 424af75078fSIntel cores = rte_lcore_count(); 425d4f37b09SIntel if ((cores & (cores - 1)) != 0 || cores > 128) { 426d4f37b09SIntel rte_exit(EXIT_FAILURE,"This program can only run on an even" 427d4f37b09SIntel "number of cores(1-128)\n\n"); 428af75078fSIntel } 429af75078fSIntel 430d4f37b09SIntel nb_ports = rte_eth_dev_count(); 431d4f37b09SIntel if (nb_ports > RTE_MAX_ETHPORTS) 432d4f37b09SIntel nb_ports = RTE_MAX_ETHPORTS; 433d4f37b09SIntel 434d4f37b09SIntel /* 435d4f37b09SIntel * Update the global var NUM_PORTS and global array PORTS 436d4f37b09SIntel * and get value of var VALID_NUM_PORTS according to system ports number 437d4f37b09SIntel */ 438d4f37b09SIntel valid_num_ports = check_ports_num(nb_ports); 439d4f37b09SIntel 440d4f37b09SIntel if (valid_num_ports < 2 || valid_num_ports % 2) { 441d4f37b09SIntel printf("Current valid ports number is %u\n", valid_num_ports); 442d4f37b09SIntel rte_exit(EXIT_FAILURE, "Error with valid ports number is not even or less than 2\n"); 443d4f37b09SIntel } 444d4f37b09SIntel 445d4f37b09SIntel mbuf_pool = rte_mempool_create("MBUF_POOL", NUM_MBUFS * nb_ports, 446af75078fSIntel MBUF_SIZE, MBUF_CACHE_SIZE, 447af75078fSIntel sizeof(struct rte_pktmbuf_pool_private), 448af75078fSIntel rte_pktmbuf_pool_init, NULL, 449af75078fSIntel rte_pktmbuf_init, NULL, 450e60f71ebSIntel rte_socket_id(), 0); 451af75078fSIntel if (mbuf_pool == NULL) 452af75078fSIntel rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); 453af75078fSIntel 454d4f37b09SIntel /* initialize all ports */ 455d4f37b09SIntel for (portid = 0; portid < nb_ports; portid++) { 456d4f37b09SIntel /* skip ports that are not enabled */ 457d4f37b09SIntel if ((enabled_port_mask & (1 << portid)) == 0) { 458d4f37b09SIntel printf("\nSkipping disabled port %d\n", portid); 459d4f37b09SIntel continue; 460d4f37b09SIntel } 461d4f37b09SIntel if (port_init(portid, mbuf_pool) != 0) 462af75078fSIntel rte_exit(EXIT_FAILURE, "Cannot initialize network ports\n"); 463d4f37b09SIntel } 464af75078fSIntel 465af75078fSIntel /* call lcore_main() on every slave lcore */ 466af75078fSIntel i = 0; 467af75078fSIntel RTE_LCORE_FOREACH_SLAVE(lcore_id) { 468af75078fSIntel rte_eal_remote_launch(lcore_main, (void*)i++, lcore_id); 469af75078fSIntel } 470af75078fSIntel /* call on master too */ 471af75078fSIntel (void) lcore_main((void*)i); 472af75078fSIntel 473af75078fSIntel return 0; 474af75078fSIntel } 475