108bd1a17SNithin Dabilpuram /* SPDX-License-Identifier: BSD-3-Clause 208bd1a17SNithin Dabilpuram * Copyright(C) 2020 Marvell International Ltd. 308bd1a17SNithin Dabilpuram */ 408bd1a17SNithin Dabilpuram 508bd1a17SNithin Dabilpuram #include <arpa/inet.h> 608bd1a17SNithin Dabilpuram #include <errno.h> 708bd1a17SNithin Dabilpuram #include <getopt.h> 808bd1a17SNithin Dabilpuram #include <inttypes.h> 908bd1a17SNithin Dabilpuram #include <signal.h> 1008bd1a17SNithin Dabilpuram #include <stdarg.h> 1108bd1a17SNithin Dabilpuram #include <stdbool.h> 1208bd1a17SNithin Dabilpuram #include <stdint.h> 1308bd1a17SNithin Dabilpuram #include <stdio.h> 1408bd1a17SNithin Dabilpuram #include <stdlib.h> 1508bd1a17SNithin Dabilpuram #include <string.h> 1608bd1a17SNithin Dabilpuram #include <sys/socket.h> 1708bd1a17SNithin Dabilpuram #include <sys/types.h> 1808bd1a17SNithin Dabilpuram #include <sys/queue.h> 1908bd1a17SNithin Dabilpuram #include <unistd.h> 2008bd1a17SNithin Dabilpuram 2108bd1a17SNithin Dabilpuram #include <rte_branch_prediction.h> 2208bd1a17SNithin Dabilpuram #include <rte_common.h> 23*ef853f1fSNithin Dabilpuram #include <rte_cycles.h> 2408bd1a17SNithin Dabilpuram #include <rte_eal.h> 2508bd1a17SNithin Dabilpuram #include <rte_ethdev.h> 26*ef853f1fSNithin Dabilpuram #include <rte_lcore.h> 2708bd1a17SNithin Dabilpuram #include <rte_log.h> 2808bd1a17SNithin Dabilpuram #include <rte_mempool.h> 2908bd1a17SNithin Dabilpuram #include <rte_per_lcore.h> 3008bd1a17SNithin Dabilpuram #include <rte_string_fns.h> 3108bd1a17SNithin Dabilpuram #include <rte_vect.h> 3208bd1a17SNithin Dabilpuram 3308bd1a17SNithin Dabilpuram #include <cmdline_parse.h> 3408bd1a17SNithin Dabilpuram #include <cmdline_parse_etheraddr.h> 3508bd1a17SNithin Dabilpuram 3608bd1a17SNithin Dabilpuram /* Log type */ 3708bd1a17SNithin Dabilpuram #define RTE_LOGTYPE_L3FWD_GRAPH RTE_LOGTYPE_USER1 3808bd1a17SNithin Dabilpuram 3908bd1a17SNithin Dabilpuram /* 4008bd1a17SNithin Dabilpuram * Configurable number of RX/TX ring descriptors 4108bd1a17SNithin Dabilpuram */ 4208bd1a17SNithin Dabilpuram #define RTE_TEST_RX_DESC_DEFAULT 1024 4308bd1a17SNithin Dabilpuram #define RTE_TEST_TX_DESC_DEFAULT 1024 4408bd1a17SNithin Dabilpuram 4508bd1a17SNithin Dabilpuram #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS 4608bd1a17SNithin Dabilpuram #define MAX_RX_QUEUE_PER_PORT 128 4708bd1a17SNithin Dabilpuram 4808bd1a17SNithin Dabilpuram #define MAX_RX_QUEUE_PER_LCORE 16 4908bd1a17SNithin Dabilpuram 5008bd1a17SNithin Dabilpuram #define MAX_LCORE_PARAMS 1024 5108bd1a17SNithin Dabilpuram 5208bd1a17SNithin Dabilpuram #define NB_SOCKETS 8 5308bd1a17SNithin Dabilpuram 54*ef853f1fSNithin Dabilpuram /* Static global variables used within this file. */ 55*ef853f1fSNithin Dabilpuram static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 56*ef853f1fSNithin Dabilpuram static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 57*ef853f1fSNithin Dabilpuram 5808bd1a17SNithin Dabilpuram /**< Ports set in promiscuous mode off by default. */ 5908bd1a17SNithin Dabilpuram static int promiscuous_on; 6008bd1a17SNithin Dabilpuram 6108bd1a17SNithin Dabilpuram static int numa_on = 1; /**< NUMA is enabled by default. */ 6208bd1a17SNithin Dabilpuram static int per_port_pool; /**< Use separate buffer pools per port; disabled */ 6308bd1a17SNithin Dabilpuram /**< by default */ 6408bd1a17SNithin Dabilpuram 6508bd1a17SNithin Dabilpuram static volatile bool force_quit; 6608bd1a17SNithin Dabilpuram 6708bd1a17SNithin Dabilpuram /* Ethernet addresses of ports */ 6808bd1a17SNithin Dabilpuram static uint64_t dest_eth_addr[RTE_MAX_ETHPORTS]; 69*ef853f1fSNithin Dabilpuram static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 7008bd1a17SNithin Dabilpuram xmm_t val_eth[RTE_MAX_ETHPORTS]; 7108bd1a17SNithin Dabilpuram 7208bd1a17SNithin Dabilpuram /* Mask of enabled ports */ 7308bd1a17SNithin Dabilpuram static uint32_t enabled_port_mask; 7408bd1a17SNithin Dabilpuram 7508bd1a17SNithin Dabilpuram struct lcore_rx_queue { 7608bd1a17SNithin Dabilpuram uint16_t port_id; 7708bd1a17SNithin Dabilpuram uint8_t queue_id; 7808bd1a17SNithin Dabilpuram }; 7908bd1a17SNithin Dabilpuram 8008bd1a17SNithin Dabilpuram /* Lcore conf */ 8108bd1a17SNithin Dabilpuram struct lcore_conf { 8208bd1a17SNithin Dabilpuram uint16_t n_rx_queue; 8308bd1a17SNithin Dabilpuram struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 8408bd1a17SNithin Dabilpuram } __rte_cache_aligned; 8508bd1a17SNithin Dabilpuram 8608bd1a17SNithin Dabilpuram static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 8708bd1a17SNithin Dabilpuram 8808bd1a17SNithin Dabilpuram struct lcore_params { 8908bd1a17SNithin Dabilpuram uint16_t port_id; 9008bd1a17SNithin Dabilpuram uint8_t queue_id; 9108bd1a17SNithin Dabilpuram uint8_t lcore_id; 9208bd1a17SNithin Dabilpuram } __rte_cache_aligned; 9308bd1a17SNithin Dabilpuram 9408bd1a17SNithin Dabilpuram static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; 9508bd1a17SNithin Dabilpuram static struct lcore_params lcore_params_array_default[] = { 9608bd1a17SNithin Dabilpuram {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, 9708bd1a17SNithin Dabilpuram {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, 9808bd1a17SNithin Dabilpuram }; 9908bd1a17SNithin Dabilpuram 10008bd1a17SNithin Dabilpuram static struct lcore_params *lcore_params = lcore_params_array_default; 10108bd1a17SNithin Dabilpuram static uint16_t nb_lcore_params = RTE_DIM(lcore_params_array_default); 10208bd1a17SNithin Dabilpuram 10308bd1a17SNithin Dabilpuram static struct rte_eth_conf port_conf = { 10408bd1a17SNithin Dabilpuram .rxmode = { 10508bd1a17SNithin Dabilpuram .mq_mode = ETH_MQ_RX_RSS, 10608bd1a17SNithin Dabilpuram .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 10708bd1a17SNithin Dabilpuram .split_hdr_size = 0, 10808bd1a17SNithin Dabilpuram }, 10908bd1a17SNithin Dabilpuram .rx_adv_conf = { 11008bd1a17SNithin Dabilpuram .rss_conf = { 11108bd1a17SNithin Dabilpuram .rss_key = NULL, 11208bd1a17SNithin Dabilpuram .rss_hf = ETH_RSS_IP, 11308bd1a17SNithin Dabilpuram }, 11408bd1a17SNithin Dabilpuram }, 11508bd1a17SNithin Dabilpuram .txmode = { 11608bd1a17SNithin Dabilpuram .mq_mode = ETH_MQ_TX_NONE, 11708bd1a17SNithin Dabilpuram }, 11808bd1a17SNithin Dabilpuram }; 11908bd1a17SNithin Dabilpuram 120*ef853f1fSNithin Dabilpuram static struct rte_mempool *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS]; 121*ef853f1fSNithin Dabilpuram 12208bd1a17SNithin Dabilpuram static int 12308bd1a17SNithin Dabilpuram check_lcore_params(void) 12408bd1a17SNithin Dabilpuram { 12508bd1a17SNithin Dabilpuram uint8_t queue, lcore; 12608bd1a17SNithin Dabilpuram int socketid; 12708bd1a17SNithin Dabilpuram uint16_t i; 12808bd1a17SNithin Dabilpuram 12908bd1a17SNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 13008bd1a17SNithin Dabilpuram queue = lcore_params[i].queue_id; 13108bd1a17SNithin Dabilpuram if (queue >= MAX_RX_QUEUE_PER_PORT) { 13208bd1a17SNithin Dabilpuram printf("Invalid queue number: %hhu\n", queue); 13308bd1a17SNithin Dabilpuram return -1; 13408bd1a17SNithin Dabilpuram } 13508bd1a17SNithin Dabilpuram lcore = lcore_params[i].lcore_id; 13608bd1a17SNithin Dabilpuram if (!rte_lcore_is_enabled(lcore)) { 13708bd1a17SNithin Dabilpuram printf("Error: lcore %hhu is not enabled in lcore mask\n", 13808bd1a17SNithin Dabilpuram lcore); 13908bd1a17SNithin Dabilpuram return -1; 14008bd1a17SNithin Dabilpuram } 14108bd1a17SNithin Dabilpuram 14208bd1a17SNithin Dabilpuram if (lcore == rte_get_master_lcore()) { 14308bd1a17SNithin Dabilpuram printf("Error: lcore %u is master lcore\n", lcore); 14408bd1a17SNithin Dabilpuram return -1; 14508bd1a17SNithin Dabilpuram } 14608bd1a17SNithin Dabilpuram socketid = rte_lcore_to_socket_id(lcore); 14708bd1a17SNithin Dabilpuram if ((socketid != 0) && (numa_on == 0)) { 14808bd1a17SNithin Dabilpuram printf("Warning: lcore %hhu is on socket %d with numa off\n", 14908bd1a17SNithin Dabilpuram lcore, socketid); 15008bd1a17SNithin Dabilpuram } 15108bd1a17SNithin Dabilpuram } 15208bd1a17SNithin Dabilpuram 15308bd1a17SNithin Dabilpuram return 0; 15408bd1a17SNithin Dabilpuram } 15508bd1a17SNithin Dabilpuram 15608bd1a17SNithin Dabilpuram static int 15708bd1a17SNithin Dabilpuram check_port_config(void) 15808bd1a17SNithin Dabilpuram { 15908bd1a17SNithin Dabilpuram uint16_t portid; 16008bd1a17SNithin Dabilpuram uint16_t i; 16108bd1a17SNithin Dabilpuram 16208bd1a17SNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 16308bd1a17SNithin Dabilpuram portid = lcore_params[i].port_id; 16408bd1a17SNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) { 16508bd1a17SNithin Dabilpuram printf("Port %u is not enabled in port mask\n", portid); 16608bd1a17SNithin Dabilpuram return -1; 16708bd1a17SNithin Dabilpuram } 16808bd1a17SNithin Dabilpuram if (!rte_eth_dev_is_valid_port(portid)) { 16908bd1a17SNithin Dabilpuram printf("Port %u is not present on the board\n", portid); 17008bd1a17SNithin Dabilpuram return -1; 17108bd1a17SNithin Dabilpuram } 17208bd1a17SNithin Dabilpuram } 17308bd1a17SNithin Dabilpuram 17408bd1a17SNithin Dabilpuram return 0; 17508bd1a17SNithin Dabilpuram } 17608bd1a17SNithin Dabilpuram 177*ef853f1fSNithin Dabilpuram static uint8_t 178*ef853f1fSNithin Dabilpuram get_port_n_rx_queues(const uint16_t port) 179*ef853f1fSNithin Dabilpuram { 180*ef853f1fSNithin Dabilpuram int queue = -1; 181*ef853f1fSNithin Dabilpuram uint16_t i; 182*ef853f1fSNithin Dabilpuram 183*ef853f1fSNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 184*ef853f1fSNithin Dabilpuram if (lcore_params[i].port_id == port) { 185*ef853f1fSNithin Dabilpuram if (lcore_params[i].queue_id == queue + 1) 186*ef853f1fSNithin Dabilpuram queue = lcore_params[i].queue_id; 187*ef853f1fSNithin Dabilpuram else 188*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 189*ef853f1fSNithin Dabilpuram "Queue ids of the port %d must be" 190*ef853f1fSNithin Dabilpuram " in sequence and must start with 0\n", 191*ef853f1fSNithin Dabilpuram lcore_params[i].port_id); 192*ef853f1fSNithin Dabilpuram } 193*ef853f1fSNithin Dabilpuram } 194*ef853f1fSNithin Dabilpuram 195*ef853f1fSNithin Dabilpuram return (uint8_t)(++queue); 196*ef853f1fSNithin Dabilpuram } 197*ef853f1fSNithin Dabilpuram 19808bd1a17SNithin Dabilpuram static int 19908bd1a17SNithin Dabilpuram init_lcore_rx_queues(void) 20008bd1a17SNithin Dabilpuram { 20108bd1a17SNithin Dabilpuram uint16_t i, nb_rx_queue; 20208bd1a17SNithin Dabilpuram uint8_t lcore; 20308bd1a17SNithin Dabilpuram 20408bd1a17SNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 20508bd1a17SNithin Dabilpuram lcore = lcore_params[i].lcore_id; 20608bd1a17SNithin Dabilpuram nb_rx_queue = lcore_conf[lcore].n_rx_queue; 20708bd1a17SNithin Dabilpuram if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { 20808bd1a17SNithin Dabilpuram printf("Error: too many queues (%u) for lcore: %u\n", 20908bd1a17SNithin Dabilpuram (unsigned int)nb_rx_queue + 1, 21008bd1a17SNithin Dabilpuram (unsigned int)lcore); 21108bd1a17SNithin Dabilpuram return -1; 21208bd1a17SNithin Dabilpuram } 21308bd1a17SNithin Dabilpuram 21408bd1a17SNithin Dabilpuram lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = 21508bd1a17SNithin Dabilpuram lcore_params[i].port_id; 21608bd1a17SNithin Dabilpuram lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = 21708bd1a17SNithin Dabilpuram lcore_params[i].queue_id; 21808bd1a17SNithin Dabilpuram lcore_conf[lcore].n_rx_queue++; 21908bd1a17SNithin Dabilpuram } 22008bd1a17SNithin Dabilpuram 22108bd1a17SNithin Dabilpuram return 0; 22208bd1a17SNithin Dabilpuram } 22308bd1a17SNithin Dabilpuram 22408bd1a17SNithin Dabilpuram /* Display usage */ 22508bd1a17SNithin Dabilpuram static void 22608bd1a17SNithin Dabilpuram print_usage(const char *prgname) 22708bd1a17SNithin Dabilpuram { 22808bd1a17SNithin Dabilpuram fprintf(stderr, 22908bd1a17SNithin Dabilpuram "%s [EAL options] --" 23008bd1a17SNithin Dabilpuram " -p PORTMASK" 23108bd1a17SNithin Dabilpuram " [-P]" 23208bd1a17SNithin Dabilpuram " --config (port,queue,lcore)[,(port,queue,lcore)]" 23308bd1a17SNithin Dabilpuram " [--eth-dest=X,MM:MM:MM:MM:MM:MM]" 23408bd1a17SNithin Dabilpuram " [--enable-jumbo [--max-pkt-len PKTLEN]]" 23508bd1a17SNithin Dabilpuram " [--no-numa]" 23608bd1a17SNithin Dabilpuram " [--per-port-pool]\n\n" 23708bd1a17SNithin Dabilpuram 23808bd1a17SNithin Dabilpuram " -p PORTMASK: Hexadecimal bitmask of ports to configure\n" 23908bd1a17SNithin Dabilpuram " -P : Enable promiscuous mode\n" 24008bd1a17SNithin Dabilpuram " --config (port,queue,lcore): Rx queue configuration\n" 24108bd1a17SNithin Dabilpuram " --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for " 24208bd1a17SNithin Dabilpuram "port X\n" 24308bd1a17SNithin Dabilpuram " --enable-jumbo: Enable jumbo frames\n" 24408bd1a17SNithin Dabilpuram " --max-pkt-len: Under the premise of enabling jumbo,\n" 24508bd1a17SNithin Dabilpuram " maximum packet length in decimal (64-9600)\n" 24608bd1a17SNithin Dabilpuram " --no-numa: Disable numa awareness\n" 24708bd1a17SNithin Dabilpuram " --per-port-pool: Use separate buffer pool per port\n\n", 24808bd1a17SNithin Dabilpuram prgname); 24908bd1a17SNithin Dabilpuram } 25008bd1a17SNithin Dabilpuram 25108bd1a17SNithin Dabilpuram static int 25208bd1a17SNithin Dabilpuram parse_max_pkt_len(const char *pktlen) 25308bd1a17SNithin Dabilpuram { 25408bd1a17SNithin Dabilpuram unsigned long len; 25508bd1a17SNithin Dabilpuram char *end = NULL; 25608bd1a17SNithin Dabilpuram 25708bd1a17SNithin Dabilpuram /* Parse decimal string */ 25808bd1a17SNithin Dabilpuram len = strtoul(pktlen, &end, 10); 25908bd1a17SNithin Dabilpuram if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) 26008bd1a17SNithin Dabilpuram return -1; 26108bd1a17SNithin Dabilpuram 26208bd1a17SNithin Dabilpuram if (len == 0) 26308bd1a17SNithin Dabilpuram return -1; 26408bd1a17SNithin Dabilpuram 26508bd1a17SNithin Dabilpuram return len; 26608bd1a17SNithin Dabilpuram } 26708bd1a17SNithin Dabilpuram 26808bd1a17SNithin Dabilpuram static int 26908bd1a17SNithin Dabilpuram parse_portmask(const char *portmask) 27008bd1a17SNithin Dabilpuram { 27108bd1a17SNithin Dabilpuram char *end = NULL; 27208bd1a17SNithin Dabilpuram unsigned long pm; 27308bd1a17SNithin Dabilpuram 27408bd1a17SNithin Dabilpuram /* Parse hexadecimal string */ 27508bd1a17SNithin Dabilpuram pm = strtoul(portmask, &end, 16); 27608bd1a17SNithin Dabilpuram if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 27708bd1a17SNithin Dabilpuram return -1; 27808bd1a17SNithin Dabilpuram 27908bd1a17SNithin Dabilpuram if (pm == 0) 28008bd1a17SNithin Dabilpuram return -1; 28108bd1a17SNithin Dabilpuram 28208bd1a17SNithin Dabilpuram return pm; 28308bd1a17SNithin Dabilpuram } 28408bd1a17SNithin Dabilpuram 28508bd1a17SNithin Dabilpuram static int 28608bd1a17SNithin Dabilpuram parse_config(const char *q_arg) 28708bd1a17SNithin Dabilpuram { 28808bd1a17SNithin Dabilpuram enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; 28908bd1a17SNithin Dabilpuram unsigned long int_fld[_NUM_FLD]; 29008bd1a17SNithin Dabilpuram const char *p, *p0 = q_arg; 29108bd1a17SNithin Dabilpuram char *str_fld[_NUM_FLD]; 29208bd1a17SNithin Dabilpuram uint32_t size; 29308bd1a17SNithin Dabilpuram char s[256]; 29408bd1a17SNithin Dabilpuram char *end; 29508bd1a17SNithin Dabilpuram int i; 29608bd1a17SNithin Dabilpuram 29708bd1a17SNithin Dabilpuram nb_lcore_params = 0; 29808bd1a17SNithin Dabilpuram 29908bd1a17SNithin Dabilpuram while ((p = strchr(p0, '(')) != NULL) { 30008bd1a17SNithin Dabilpuram ++p; 30108bd1a17SNithin Dabilpuram p0 = strchr(p, ')'); 30208bd1a17SNithin Dabilpuram if (p0 == NULL) 30308bd1a17SNithin Dabilpuram return -1; 30408bd1a17SNithin Dabilpuram 30508bd1a17SNithin Dabilpuram size = p0 - p; 30608bd1a17SNithin Dabilpuram if (size >= sizeof(s)) 30708bd1a17SNithin Dabilpuram return -1; 30808bd1a17SNithin Dabilpuram 30908bd1a17SNithin Dabilpuram memcpy(s, p, size); 31008bd1a17SNithin Dabilpuram s[size] = '\0'; 31108bd1a17SNithin Dabilpuram if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 31208bd1a17SNithin Dabilpuram _NUM_FLD) 31308bd1a17SNithin Dabilpuram return -1; 31408bd1a17SNithin Dabilpuram for (i = 0; i < _NUM_FLD; i++) { 31508bd1a17SNithin Dabilpuram errno = 0; 31608bd1a17SNithin Dabilpuram int_fld[i] = strtoul(str_fld[i], &end, 0); 31708bd1a17SNithin Dabilpuram if (errno != 0 || end == str_fld[i]) 31808bd1a17SNithin Dabilpuram return -1; 31908bd1a17SNithin Dabilpuram } 32008bd1a17SNithin Dabilpuram 32108bd1a17SNithin Dabilpuram if (nb_lcore_params >= MAX_LCORE_PARAMS) { 32208bd1a17SNithin Dabilpuram printf("Exceeded max number of lcore params: %hu\n", 32308bd1a17SNithin Dabilpuram nb_lcore_params); 32408bd1a17SNithin Dabilpuram return -1; 32508bd1a17SNithin Dabilpuram } 32608bd1a17SNithin Dabilpuram 32708bd1a17SNithin Dabilpuram if (int_fld[FLD_PORT] >= RTE_MAX_ETHPORTS || 32808bd1a17SNithin Dabilpuram int_fld[FLD_LCORE] >= RTE_MAX_LCORE) { 32908bd1a17SNithin Dabilpuram printf("Invalid port/lcore id\n"); 33008bd1a17SNithin Dabilpuram return -1; 33108bd1a17SNithin Dabilpuram } 33208bd1a17SNithin Dabilpuram 33308bd1a17SNithin Dabilpuram lcore_params_array[nb_lcore_params].port_id = 33408bd1a17SNithin Dabilpuram (uint8_t)int_fld[FLD_PORT]; 33508bd1a17SNithin Dabilpuram lcore_params_array[nb_lcore_params].queue_id = 33608bd1a17SNithin Dabilpuram (uint8_t)int_fld[FLD_QUEUE]; 33708bd1a17SNithin Dabilpuram lcore_params_array[nb_lcore_params].lcore_id = 33808bd1a17SNithin Dabilpuram (uint8_t)int_fld[FLD_LCORE]; 33908bd1a17SNithin Dabilpuram ++nb_lcore_params; 34008bd1a17SNithin Dabilpuram } 34108bd1a17SNithin Dabilpuram lcore_params = lcore_params_array; 34208bd1a17SNithin Dabilpuram 34308bd1a17SNithin Dabilpuram return 0; 34408bd1a17SNithin Dabilpuram } 34508bd1a17SNithin Dabilpuram 34608bd1a17SNithin Dabilpuram static void 34708bd1a17SNithin Dabilpuram parse_eth_dest(const char *optarg) 34808bd1a17SNithin Dabilpuram { 34908bd1a17SNithin Dabilpuram uint8_t c, *dest, peer_addr[6]; 35008bd1a17SNithin Dabilpuram uint16_t portid; 35108bd1a17SNithin Dabilpuram char *port_end; 35208bd1a17SNithin Dabilpuram 35308bd1a17SNithin Dabilpuram errno = 0; 35408bd1a17SNithin Dabilpuram portid = strtoul(optarg, &port_end, 10); 35508bd1a17SNithin Dabilpuram if (errno != 0 || port_end == optarg || *port_end++ != ',') 35608bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid eth-dest: %s", optarg); 35708bd1a17SNithin Dabilpuram if (portid >= RTE_MAX_ETHPORTS) 35808bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, 35908bd1a17SNithin Dabilpuram "eth-dest: port %d >= RTE_MAX_ETHPORTS(%d)\n", portid, 36008bd1a17SNithin Dabilpuram RTE_MAX_ETHPORTS); 36108bd1a17SNithin Dabilpuram 36208bd1a17SNithin Dabilpuram if (cmdline_parse_etheraddr(NULL, port_end, &peer_addr, 36308bd1a17SNithin Dabilpuram sizeof(peer_addr)) < 0) 36408bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid ethernet address: %s\n", 36508bd1a17SNithin Dabilpuram port_end); 36608bd1a17SNithin Dabilpuram dest = (uint8_t *)&dest_eth_addr[portid]; 36708bd1a17SNithin Dabilpuram for (c = 0; c < 6; c++) 36808bd1a17SNithin Dabilpuram dest[c] = peer_addr[c]; 36908bd1a17SNithin Dabilpuram *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; 37008bd1a17SNithin Dabilpuram } 37108bd1a17SNithin Dabilpuram 37208bd1a17SNithin Dabilpuram #define MAX_JUMBO_PKT_LEN 9600 37308bd1a17SNithin Dabilpuram #define MEMPOOL_CACHE_SIZE 256 37408bd1a17SNithin Dabilpuram 37508bd1a17SNithin Dabilpuram static const char short_options[] = "p:" /* portmask */ 37608bd1a17SNithin Dabilpuram "P" /* promiscuous */ 37708bd1a17SNithin Dabilpuram ; 37808bd1a17SNithin Dabilpuram 37908bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_CONFIG "config" 38008bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_ETH_DEST "eth-dest" 38108bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_NO_NUMA "no-numa" 38208bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_ENABLE_JUMBO "enable-jumbo" 38308bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool" 38408bd1a17SNithin Dabilpuram enum { 38508bd1a17SNithin Dabilpuram /* Long options mapped to a short option */ 38608bd1a17SNithin Dabilpuram 38708bd1a17SNithin Dabilpuram /* First long only option value must be >= 256, so that we won't 38808bd1a17SNithin Dabilpuram * conflict with short options 38908bd1a17SNithin Dabilpuram */ 39008bd1a17SNithin Dabilpuram CMD_LINE_OPT_MIN_NUM = 256, 39108bd1a17SNithin Dabilpuram CMD_LINE_OPT_CONFIG_NUM, 39208bd1a17SNithin Dabilpuram CMD_LINE_OPT_ETH_DEST_NUM, 39308bd1a17SNithin Dabilpuram CMD_LINE_OPT_NO_NUMA_NUM, 39408bd1a17SNithin Dabilpuram CMD_LINE_OPT_ENABLE_JUMBO_NUM, 39508bd1a17SNithin Dabilpuram CMD_LINE_OPT_PARSE_PER_PORT_POOL, 39608bd1a17SNithin Dabilpuram }; 39708bd1a17SNithin Dabilpuram 39808bd1a17SNithin Dabilpuram static const struct option lgopts[] = { 39908bd1a17SNithin Dabilpuram {CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM}, 40008bd1a17SNithin Dabilpuram {CMD_LINE_OPT_ETH_DEST, 1, 0, CMD_LINE_OPT_ETH_DEST_NUM}, 40108bd1a17SNithin Dabilpuram {CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM}, 40208bd1a17SNithin Dabilpuram {CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, CMD_LINE_OPT_ENABLE_JUMBO_NUM}, 40308bd1a17SNithin Dabilpuram {CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL}, 40408bd1a17SNithin Dabilpuram {NULL, 0, 0, 0}, 40508bd1a17SNithin Dabilpuram }; 40608bd1a17SNithin Dabilpuram 40708bd1a17SNithin Dabilpuram /* 40808bd1a17SNithin Dabilpuram * This expression is used to calculate the number of mbufs needed 40908bd1a17SNithin Dabilpuram * depending on user input, taking into account memory for rx and 41008bd1a17SNithin Dabilpuram * tx hardware rings, cache per lcore and mtable per port per lcore. 41108bd1a17SNithin Dabilpuram * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum 41208bd1a17SNithin Dabilpuram * value of 8192 41308bd1a17SNithin Dabilpuram */ 41408bd1a17SNithin Dabilpuram #define NB_MBUF(nports) \ 41508bd1a17SNithin Dabilpuram RTE_MAX((nports * nb_rx_queue * nb_rxd + \ 41608bd1a17SNithin Dabilpuram nports * nb_lcores * RTE_GRAPH_BURST_SIZE + \ 41708bd1a17SNithin Dabilpuram nports * n_tx_queue * nb_txd + \ 41808bd1a17SNithin Dabilpuram nb_lcores * MEMPOOL_CACHE_SIZE), 8192u) 41908bd1a17SNithin Dabilpuram 42008bd1a17SNithin Dabilpuram /* Parse the argument given in the command line of the application */ 42108bd1a17SNithin Dabilpuram static int 42208bd1a17SNithin Dabilpuram parse_args(int argc, char **argv) 42308bd1a17SNithin Dabilpuram { 42408bd1a17SNithin Dabilpuram char *prgname = argv[0]; 42508bd1a17SNithin Dabilpuram int option_index; 42608bd1a17SNithin Dabilpuram char **argvopt; 42708bd1a17SNithin Dabilpuram int opt, ret; 42808bd1a17SNithin Dabilpuram 42908bd1a17SNithin Dabilpuram argvopt = argv; 43008bd1a17SNithin Dabilpuram 43108bd1a17SNithin Dabilpuram /* Error or normal output strings. */ 43208bd1a17SNithin Dabilpuram while ((opt = getopt_long(argc, argvopt, short_options, lgopts, 43308bd1a17SNithin Dabilpuram &option_index)) != EOF) { 43408bd1a17SNithin Dabilpuram 43508bd1a17SNithin Dabilpuram switch (opt) { 43608bd1a17SNithin Dabilpuram /* Portmask */ 43708bd1a17SNithin Dabilpuram case 'p': 43808bd1a17SNithin Dabilpuram enabled_port_mask = parse_portmask(optarg); 43908bd1a17SNithin Dabilpuram if (enabled_port_mask == 0) { 44008bd1a17SNithin Dabilpuram fprintf(stderr, "Invalid portmask\n"); 44108bd1a17SNithin Dabilpuram print_usage(prgname); 44208bd1a17SNithin Dabilpuram return -1; 44308bd1a17SNithin Dabilpuram } 44408bd1a17SNithin Dabilpuram break; 44508bd1a17SNithin Dabilpuram 44608bd1a17SNithin Dabilpuram case 'P': 44708bd1a17SNithin Dabilpuram promiscuous_on = 1; 44808bd1a17SNithin Dabilpuram break; 44908bd1a17SNithin Dabilpuram 45008bd1a17SNithin Dabilpuram /* Long options */ 45108bd1a17SNithin Dabilpuram case CMD_LINE_OPT_CONFIG_NUM: 45208bd1a17SNithin Dabilpuram ret = parse_config(optarg); 45308bd1a17SNithin Dabilpuram if (ret) { 45408bd1a17SNithin Dabilpuram fprintf(stderr, "Invalid config\n"); 45508bd1a17SNithin Dabilpuram print_usage(prgname); 45608bd1a17SNithin Dabilpuram return -1; 45708bd1a17SNithin Dabilpuram } 45808bd1a17SNithin Dabilpuram break; 45908bd1a17SNithin Dabilpuram 46008bd1a17SNithin Dabilpuram case CMD_LINE_OPT_ETH_DEST_NUM: 46108bd1a17SNithin Dabilpuram parse_eth_dest(optarg); 46208bd1a17SNithin Dabilpuram break; 46308bd1a17SNithin Dabilpuram 46408bd1a17SNithin Dabilpuram case CMD_LINE_OPT_NO_NUMA_NUM: 46508bd1a17SNithin Dabilpuram numa_on = 0; 46608bd1a17SNithin Dabilpuram break; 46708bd1a17SNithin Dabilpuram 46808bd1a17SNithin Dabilpuram case CMD_LINE_OPT_ENABLE_JUMBO_NUM: { 46908bd1a17SNithin Dabilpuram const struct option lenopts = {"max-pkt-len", 47008bd1a17SNithin Dabilpuram required_argument, 0, 0}; 47108bd1a17SNithin Dabilpuram 47208bd1a17SNithin Dabilpuram port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; 47308bd1a17SNithin Dabilpuram port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS; 47408bd1a17SNithin Dabilpuram 47508bd1a17SNithin Dabilpuram /* 47608bd1a17SNithin Dabilpuram * if no max-pkt-len set, use the default 47708bd1a17SNithin Dabilpuram * value RTE_ETHER_MAX_LEN. 47808bd1a17SNithin Dabilpuram */ 47908bd1a17SNithin Dabilpuram if (getopt_long(argc, argvopt, "", &lenopts, 48008bd1a17SNithin Dabilpuram &option_index) == 0) { 48108bd1a17SNithin Dabilpuram ret = parse_max_pkt_len(optarg); 48208bd1a17SNithin Dabilpuram if (ret < 64 || ret > MAX_JUMBO_PKT_LEN) { 48308bd1a17SNithin Dabilpuram fprintf(stderr, "Invalid maximum " 48408bd1a17SNithin Dabilpuram "packet length\n"); 48508bd1a17SNithin Dabilpuram print_usage(prgname); 48608bd1a17SNithin Dabilpuram return -1; 48708bd1a17SNithin Dabilpuram } 48808bd1a17SNithin Dabilpuram port_conf.rxmode.max_rx_pkt_len = ret; 48908bd1a17SNithin Dabilpuram } 49008bd1a17SNithin Dabilpuram break; 49108bd1a17SNithin Dabilpuram } 49208bd1a17SNithin Dabilpuram 49308bd1a17SNithin Dabilpuram case CMD_LINE_OPT_PARSE_PER_PORT_POOL: 49408bd1a17SNithin Dabilpuram printf("Per port buffer pool is enabled\n"); 49508bd1a17SNithin Dabilpuram per_port_pool = 1; 49608bd1a17SNithin Dabilpuram break; 49708bd1a17SNithin Dabilpuram 49808bd1a17SNithin Dabilpuram default: 49908bd1a17SNithin Dabilpuram print_usage(prgname); 50008bd1a17SNithin Dabilpuram return -1; 50108bd1a17SNithin Dabilpuram } 50208bd1a17SNithin Dabilpuram } 50308bd1a17SNithin Dabilpuram 50408bd1a17SNithin Dabilpuram if (optind >= 0) 50508bd1a17SNithin Dabilpuram argv[optind - 1] = prgname; 50608bd1a17SNithin Dabilpuram ret = optind - 1; 50708bd1a17SNithin Dabilpuram optind = 1; /* Reset getopt lib */ 50808bd1a17SNithin Dabilpuram 50908bd1a17SNithin Dabilpuram return ret; 51008bd1a17SNithin Dabilpuram } 51108bd1a17SNithin Dabilpuram 51208bd1a17SNithin Dabilpuram static void 513*ef853f1fSNithin Dabilpuram print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 514*ef853f1fSNithin Dabilpuram { 515*ef853f1fSNithin Dabilpuram char buf[RTE_ETHER_ADDR_FMT_SIZE]; 516*ef853f1fSNithin Dabilpuram rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 517*ef853f1fSNithin Dabilpuram printf("%s%s", name, buf); 518*ef853f1fSNithin Dabilpuram } 519*ef853f1fSNithin Dabilpuram 520*ef853f1fSNithin Dabilpuram static int 521*ef853f1fSNithin Dabilpuram init_mem(uint16_t portid, uint32_t nb_mbuf) 522*ef853f1fSNithin Dabilpuram { 523*ef853f1fSNithin Dabilpuram uint32_t lcore_id; 524*ef853f1fSNithin Dabilpuram int socketid; 525*ef853f1fSNithin Dabilpuram char s[64]; 526*ef853f1fSNithin Dabilpuram 527*ef853f1fSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 528*ef853f1fSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 529*ef853f1fSNithin Dabilpuram continue; 530*ef853f1fSNithin Dabilpuram 531*ef853f1fSNithin Dabilpuram if (numa_on) 532*ef853f1fSNithin Dabilpuram socketid = rte_lcore_to_socket_id(lcore_id); 533*ef853f1fSNithin Dabilpuram else 534*ef853f1fSNithin Dabilpuram socketid = 0; 535*ef853f1fSNithin Dabilpuram 536*ef853f1fSNithin Dabilpuram if (socketid >= NB_SOCKETS) { 537*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 538*ef853f1fSNithin Dabilpuram "Socket %d of lcore %u is out of range %d\n", 539*ef853f1fSNithin Dabilpuram socketid, lcore_id, NB_SOCKETS); 540*ef853f1fSNithin Dabilpuram } 541*ef853f1fSNithin Dabilpuram 542*ef853f1fSNithin Dabilpuram if (pktmbuf_pool[portid][socketid] == NULL) { 543*ef853f1fSNithin Dabilpuram snprintf(s, sizeof(s), "mbuf_pool_%d:%d", portid, 544*ef853f1fSNithin Dabilpuram socketid); 545*ef853f1fSNithin Dabilpuram /* Create a pool with priv size of a cacheline */ 546*ef853f1fSNithin Dabilpuram pktmbuf_pool[portid][socketid] = 547*ef853f1fSNithin Dabilpuram rte_pktmbuf_pool_create( 548*ef853f1fSNithin Dabilpuram s, nb_mbuf, MEMPOOL_CACHE_SIZE, 549*ef853f1fSNithin Dabilpuram RTE_CACHE_LINE_SIZE, 550*ef853f1fSNithin Dabilpuram RTE_MBUF_DEFAULT_BUF_SIZE, socketid); 551*ef853f1fSNithin Dabilpuram if (pktmbuf_pool[portid][socketid] == NULL) 552*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 553*ef853f1fSNithin Dabilpuram "Cannot init mbuf pool on socket %d\n", 554*ef853f1fSNithin Dabilpuram socketid); 555*ef853f1fSNithin Dabilpuram else 556*ef853f1fSNithin Dabilpuram printf("Allocated mbuf pool on socket %d\n", 557*ef853f1fSNithin Dabilpuram socketid); 558*ef853f1fSNithin Dabilpuram } 559*ef853f1fSNithin Dabilpuram } 560*ef853f1fSNithin Dabilpuram 561*ef853f1fSNithin Dabilpuram return 0; 562*ef853f1fSNithin Dabilpuram } 563*ef853f1fSNithin Dabilpuram 564*ef853f1fSNithin Dabilpuram /* Check the link status of all ports in up to 9s, and print them finally */ 565*ef853f1fSNithin Dabilpuram static void 566*ef853f1fSNithin Dabilpuram check_all_ports_link_status(uint32_t port_mask) 567*ef853f1fSNithin Dabilpuram { 568*ef853f1fSNithin Dabilpuram #define CHECK_INTERVAL 100 /* 100ms */ 569*ef853f1fSNithin Dabilpuram #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 570*ef853f1fSNithin Dabilpuram uint8_t count, all_ports_up, print_flag = 0; 571*ef853f1fSNithin Dabilpuram struct rte_eth_link link; 572*ef853f1fSNithin Dabilpuram uint16_t portid; 573*ef853f1fSNithin Dabilpuram 574*ef853f1fSNithin Dabilpuram printf("\nChecking link status"); 575*ef853f1fSNithin Dabilpuram fflush(stdout); 576*ef853f1fSNithin Dabilpuram for (count = 0; count <= MAX_CHECK_TIME; count++) { 577*ef853f1fSNithin Dabilpuram if (force_quit) 578*ef853f1fSNithin Dabilpuram return; 579*ef853f1fSNithin Dabilpuram all_ports_up = 1; 580*ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) 581*ef853f1fSNithin Dabilpuram { 582*ef853f1fSNithin Dabilpuram if (force_quit) 583*ef853f1fSNithin Dabilpuram return; 584*ef853f1fSNithin Dabilpuram if ((port_mask & (1 << portid)) == 0) 585*ef853f1fSNithin Dabilpuram continue; 586*ef853f1fSNithin Dabilpuram memset(&link, 0, sizeof(link)); 587*ef853f1fSNithin Dabilpuram rte_eth_link_get_nowait(portid, &link); 588*ef853f1fSNithin Dabilpuram /* Print link status if flag set */ 589*ef853f1fSNithin Dabilpuram if (print_flag == 1) { 590*ef853f1fSNithin Dabilpuram if (link.link_status) 591*ef853f1fSNithin Dabilpuram printf("Port%d Link Up. Speed %u Mbps " 592*ef853f1fSNithin Dabilpuram "-%s\n", 593*ef853f1fSNithin Dabilpuram portid, link.link_speed, 594*ef853f1fSNithin Dabilpuram (link.link_duplex == 595*ef853f1fSNithin Dabilpuram ETH_LINK_FULL_DUPLEX) 596*ef853f1fSNithin Dabilpuram ? ("full-duplex") 597*ef853f1fSNithin Dabilpuram : ("half-duplex\n")); 598*ef853f1fSNithin Dabilpuram else 599*ef853f1fSNithin Dabilpuram printf("Port %d Link Down\n", portid); 600*ef853f1fSNithin Dabilpuram continue; 601*ef853f1fSNithin Dabilpuram } 602*ef853f1fSNithin Dabilpuram /* Clear all_ports_up flag if any link down */ 603*ef853f1fSNithin Dabilpuram if (link.link_status == ETH_LINK_DOWN) { 604*ef853f1fSNithin Dabilpuram all_ports_up = 0; 605*ef853f1fSNithin Dabilpuram break; 606*ef853f1fSNithin Dabilpuram } 607*ef853f1fSNithin Dabilpuram } 608*ef853f1fSNithin Dabilpuram /* After finally printing all link status, get out */ 609*ef853f1fSNithin Dabilpuram if (print_flag == 1) 610*ef853f1fSNithin Dabilpuram break; 611*ef853f1fSNithin Dabilpuram 612*ef853f1fSNithin Dabilpuram if (all_ports_up == 0) { 613*ef853f1fSNithin Dabilpuram printf("."); 614*ef853f1fSNithin Dabilpuram fflush(stdout); 615*ef853f1fSNithin Dabilpuram rte_delay_ms(CHECK_INTERVAL); 616*ef853f1fSNithin Dabilpuram } 617*ef853f1fSNithin Dabilpuram 618*ef853f1fSNithin Dabilpuram /* Set the print_flag if all ports up or timeout */ 619*ef853f1fSNithin Dabilpuram if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 620*ef853f1fSNithin Dabilpuram print_flag = 1; 621*ef853f1fSNithin Dabilpuram printf("Done\n"); 622*ef853f1fSNithin Dabilpuram } 623*ef853f1fSNithin Dabilpuram } 624*ef853f1fSNithin Dabilpuram } 625*ef853f1fSNithin Dabilpuram 626*ef853f1fSNithin Dabilpuram static void 62708bd1a17SNithin Dabilpuram signal_handler(int signum) 62808bd1a17SNithin Dabilpuram { 62908bd1a17SNithin Dabilpuram if (signum == SIGINT || signum == SIGTERM) { 63008bd1a17SNithin Dabilpuram printf("\n\nSignal %d received, preparing to exit...\n", 63108bd1a17SNithin Dabilpuram signum); 63208bd1a17SNithin Dabilpuram force_quit = true; 63308bd1a17SNithin Dabilpuram } 63408bd1a17SNithin Dabilpuram } 63508bd1a17SNithin Dabilpuram 63608bd1a17SNithin Dabilpuram int 63708bd1a17SNithin Dabilpuram main(int argc, char **argv) 63808bd1a17SNithin Dabilpuram { 639*ef853f1fSNithin Dabilpuram uint8_t nb_rx_queue, queue, socketid; 640*ef853f1fSNithin Dabilpuram struct rte_eth_dev_info dev_info; 641*ef853f1fSNithin Dabilpuram uint32_t n_tx_queue, nb_lcores; 642*ef853f1fSNithin Dabilpuram struct rte_eth_txconf *txconf; 643*ef853f1fSNithin Dabilpuram uint16_t queueid, portid; 644*ef853f1fSNithin Dabilpuram struct lcore_conf *qconf; 645*ef853f1fSNithin Dabilpuram uint32_t lcore_id; 646*ef853f1fSNithin Dabilpuram uint32_t nb_ports; 64708bd1a17SNithin Dabilpuram int ret; 64808bd1a17SNithin Dabilpuram 64908bd1a17SNithin Dabilpuram /* Init EAL */ 65008bd1a17SNithin Dabilpuram ret = rte_eal_init(argc, argv); 65108bd1a17SNithin Dabilpuram if (ret < 0) 65208bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); 65308bd1a17SNithin Dabilpuram argc -= ret; 65408bd1a17SNithin Dabilpuram argv += ret; 65508bd1a17SNithin Dabilpuram 65608bd1a17SNithin Dabilpuram force_quit = false; 65708bd1a17SNithin Dabilpuram signal(SIGINT, signal_handler); 65808bd1a17SNithin Dabilpuram signal(SIGTERM, signal_handler); 65908bd1a17SNithin Dabilpuram 66008bd1a17SNithin Dabilpuram /* Pre-init dst MACs for all ports to 02:00:00:00:00:xx */ 66108bd1a17SNithin Dabilpuram for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 66208bd1a17SNithin Dabilpuram dest_eth_addr[portid] = 66308bd1a17SNithin Dabilpuram RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); 66408bd1a17SNithin Dabilpuram *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; 66508bd1a17SNithin Dabilpuram } 66608bd1a17SNithin Dabilpuram 66708bd1a17SNithin Dabilpuram /* Parse application arguments (after the EAL ones) */ 66808bd1a17SNithin Dabilpuram ret = parse_args(argc, argv); 66908bd1a17SNithin Dabilpuram if (ret < 0) 67008bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid L3FWD_GRAPH parameters\n"); 67108bd1a17SNithin Dabilpuram 67208bd1a17SNithin Dabilpuram if (check_lcore_params() < 0) 67308bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "check_lcore_params() failed\n"); 67408bd1a17SNithin Dabilpuram 67508bd1a17SNithin Dabilpuram ret = init_lcore_rx_queues(); 67608bd1a17SNithin Dabilpuram if (ret < 0) 67708bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "init_lcore_rx_queues() failed\n"); 67808bd1a17SNithin Dabilpuram 67908bd1a17SNithin Dabilpuram if (check_port_config() < 0) 68008bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "check_port_config() failed\n"); 68108bd1a17SNithin Dabilpuram 682*ef853f1fSNithin Dabilpuram nb_ports = rte_eth_dev_count_avail(); 683*ef853f1fSNithin Dabilpuram nb_lcores = rte_lcore_count(); 684*ef853f1fSNithin Dabilpuram 685*ef853f1fSNithin Dabilpuram /* Initialize all ports */ 686*ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) 687*ef853f1fSNithin Dabilpuram { 688*ef853f1fSNithin Dabilpuram struct rte_eth_conf local_port_conf = port_conf; 689*ef853f1fSNithin Dabilpuram 690*ef853f1fSNithin Dabilpuram /* Skip ports that are not enabled */ 691*ef853f1fSNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) { 692*ef853f1fSNithin Dabilpuram printf("\nSkipping disabled port %d\n", portid); 693*ef853f1fSNithin Dabilpuram continue; 694*ef853f1fSNithin Dabilpuram } 695*ef853f1fSNithin Dabilpuram 696*ef853f1fSNithin Dabilpuram /* Init port */ 697*ef853f1fSNithin Dabilpuram printf("Initializing port %d ... ", portid); 698*ef853f1fSNithin Dabilpuram fflush(stdout); 699*ef853f1fSNithin Dabilpuram 700*ef853f1fSNithin Dabilpuram nb_rx_queue = get_port_n_rx_queues(portid); 701*ef853f1fSNithin Dabilpuram n_tx_queue = nb_lcores; 702*ef853f1fSNithin Dabilpuram if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) 703*ef853f1fSNithin Dabilpuram n_tx_queue = MAX_TX_QUEUE_PER_PORT; 704*ef853f1fSNithin Dabilpuram printf("Creating queues: nb_rxq=%d nb_txq=%u... ", 705*ef853f1fSNithin Dabilpuram nb_rx_queue, n_tx_queue); 706*ef853f1fSNithin Dabilpuram 707*ef853f1fSNithin Dabilpuram rte_eth_dev_info_get(portid, &dev_info); 708*ef853f1fSNithin Dabilpuram if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 709*ef853f1fSNithin Dabilpuram local_port_conf.txmode.offloads |= 710*ef853f1fSNithin Dabilpuram DEV_TX_OFFLOAD_MBUF_FAST_FREE; 711*ef853f1fSNithin Dabilpuram 712*ef853f1fSNithin Dabilpuram local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 713*ef853f1fSNithin Dabilpuram dev_info.flow_type_rss_offloads; 714*ef853f1fSNithin Dabilpuram if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 715*ef853f1fSNithin Dabilpuram port_conf.rx_adv_conf.rss_conf.rss_hf) { 716*ef853f1fSNithin Dabilpuram printf("Port %u modified RSS hash function based on " 717*ef853f1fSNithin Dabilpuram "hardware support," 718*ef853f1fSNithin Dabilpuram "requested:%#" PRIx64 " configured:%#" PRIx64 719*ef853f1fSNithin Dabilpuram "\n", 720*ef853f1fSNithin Dabilpuram portid, port_conf.rx_adv_conf.rss_conf.rss_hf, 721*ef853f1fSNithin Dabilpuram local_port_conf.rx_adv_conf.rss_conf.rss_hf); 722*ef853f1fSNithin Dabilpuram } 723*ef853f1fSNithin Dabilpuram 724*ef853f1fSNithin Dabilpuram ret = rte_eth_dev_configure(portid, nb_rx_queue, 725*ef853f1fSNithin Dabilpuram n_tx_queue, &local_port_conf); 726*ef853f1fSNithin Dabilpuram if (ret < 0) 727*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 728*ef853f1fSNithin Dabilpuram "Cannot configure device: err=%d, port=%d\n", 729*ef853f1fSNithin Dabilpuram ret, portid); 730*ef853f1fSNithin Dabilpuram 731*ef853f1fSNithin Dabilpuram ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, 732*ef853f1fSNithin Dabilpuram &nb_txd); 733*ef853f1fSNithin Dabilpuram if (ret < 0) 734*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 735*ef853f1fSNithin Dabilpuram "Cannot adjust number of descriptors: err=%d, " 736*ef853f1fSNithin Dabilpuram "port=%d\n", 737*ef853f1fSNithin Dabilpuram ret, portid); 738*ef853f1fSNithin Dabilpuram 739*ef853f1fSNithin Dabilpuram rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 740*ef853f1fSNithin Dabilpuram print_ethaddr(" Address:", &ports_eth_addr[portid]); 741*ef853f1fSNithin Dabilpuram printf(", "); 742*ef853f1fSNithin Dabilpuram print_ethaddr( 743*ef853f1fSNithin Dabilpuram "Destination:", 744*ef853f1fSNithin Dabilpuram (const struct rte_ether_addr *)&dest_eth_addr[portid]); 745*ef853f1fSNithin Dabilpuram printf(", "); 746*ef853f1fSNithin Dabilpuram 747*ef853f1fSNithin Dabilpuram /* 748*ef853f1fSNithin Dabilpuram * prepare src MACs for each port. 749*ef853f1fSNithin Dabilpuram */ 750*ef853f1fSNithin Dabilpuram rte_ether_addr_copy( 751*ef853f1fSNithin Dabilpuram &ports_eth_addr[portid], 752*ef853f1fSNithin Dabilpuram (struct rte_ether_addr *)(val_eth + portid) + 1); 753*ef853f1fSNithin Dabilpuram 754*ef853f1fSNithin Dabilpuram /* Init memory */ 755*ef853f1fSNithin Dabilpuram if (!per_port_pool) { 756*ef853f1fSNithin Dabilpuram /* portid = 0; this is *not* signifying the first port, 757*ef853f1fSNithin Dabilpuram * rather, it signifies that portid is ignored. 758*ef853f1fSNithin Dabilpuram */ 759*ef853f1fSNithin Dabilpuram ret = init_mem(0, NB_MBUF(nb_ports)); 760*ef853f1fSNithin Dabilpuram } else { 761*ef853f1fSNithin Dabilpuram ret = init_mem(portid, NB_MBUF(1)); 762*ef853f1fSNithin Dabilpuram } 763*ef853f1fSNithin Dabilpuram if (ret < 0) 764*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, "init_mem() failed\n"); 765*ef853f1fSNithin Dabilpuram 766*ef853f1fSNithin Dabilpuram /* Init one TX queue per couple (lcore,port) */ 767*ef853f1fSNithin Dabilpuram queueid = 0; 768*ef853f1fSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 769*ef853f1fSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 770*ef853f1fSNithin Dabilpuram continue; 771*ef853f1fSNithin Dabilpuram 772*ef853f1fSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 773*ef853f1fSNithin Dabilpuram 774*ef853f1fSNithin Dabilpuram if (numa_on) 775*ef853f1fSNithin Dabilpuram socketid = (uint8_t)rte_lcore_to_socket_id( 776*ef853f1fSNithin Dabilpuram lcore_id); 777*ef853f1fSNithin Dabilpuram else 778*ef853f1fSNithin Dabilpuram socketid = 0; 779*ef853f1fSNithin Dabilpuram 780*ef853f1fSNithin Dabilpuram printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); 781*ef853f1fSNithin Dabilpuram fflush(stdout); 782*ef853f1fSNithin Dabilpuram 783*ef853f1fSNithin Dabilpuram txconf = &dev_info.default_txconf; 784*ef853f1fSNithin Dabilpuram txconf->offloads = local_port_conf.txmode.offloads; 785*ef853f1fSNithin Dabilpuram ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, 786*ef853f1fSNithin Dabilpuram socketid, txconf); 787*ef853f1fSNithin Dabilpuram if (ret < 0) 788*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 789*ef853f1fSNithin Dabilpuram "rte_eth_tx_queue_setup: err=%d, " 790*ef853f1fSNithin Dabilpuram "port=%d\n", 791*ef853f1fSNithin Dabilpuram ret, portid); 792*ef853f1fSNithin Dabilpuram queueid++; 793*ef853f1fSNithin Dabilpuram } 794*ef853f1fSNithin Dabilpuram 795*ef853f1fSNithin Dabilpuram printf("\n"); 796*ef853f1fSNithin Dabilpuram } 797*ef853f1fSNithin Dabilpuram 798*ef853f1fSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 799*ef853f1fSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 800*ef853f1fSNithin Dabilpuram continue; 801*ef853f1fSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 802*ef853f1fSNithin Dabilpuram printf("\nInitializing rx queues on lcore %u ... ", lcore_id); 803*ef853f1fSNithin Dabilpuram fflush(stdout); 804*ef853f1fSNithin Dabilpuram /* Init RX queues */ 805*ef853f1fSNithin Dabilpuram for (queue = 0; queue < qconf->n_rx_queue; ++queue) { 806*ef853f1fSNithin Dabilpuram struct rte_eth_rxconf rxq_conf; 807*ef853f1fSNithin Dabilpuram 808*ef853f1fSNithin Dabilpuram portid = qconf->rx_queue_list[queue].port_id; 809*ef853f1fSNithin Dabilpuram queueid = qconf->rx_queue_list[queue].queue_id; 810*ef853f1fSNithin Dabilpuram 811*ef853f1fSNithin Dabilpuram if (numa_on) 812*ef853f1fSNithin Dabilpuram socketid = (uint8_t)rte_lcore_to_socket_id( 813*ef853f1fSNithin Dabilpuram lcore_id); 814*ef853f1fSNithin Dabilpuram else 815*ef853f1fSNithin Dabilpuram socketid = 0; 816*ef853f1fSNithin Dabilpuram 817*ef853f1fSNithin Dabilpuram printf("rxq=%d,%d,%d ", portid, queueid, socketid); 818*ef853f1fSNithin Dabilpuram fflush(stdout); 819*ef853f1fSNithin Dabilpuram 820*ef853f1fSNithin Dabilpuram rte_eth_dev_info_get(portid, &dev_info); 821*ef853f1fSNithin Dabilpuram rxq_conf = dev_info.default_rxconf; 822*ef853f1fSNithin Dabilpuram rxq_conf.offloads = port_conf.rxmode.offloads; 823*ef853f1fSNithin Dabilpuram if (!per_port_pool) 824*ef853f1fSNithin Dabilpuram ret = rte_eth_rx_queue_setup( 825*ef853f1fSNithin Dabilpuram portid, queueid, nb_rxd, socketid, 826*ef853f1fSNithin Dabilpuram &rxq_conf, pktmbuf_pool[0][socketid]); 827*ef853f1fSNithin Dabilpuram else 828*ef853f1fSNithin Dabilpuram ret = rte_eth_rx_queue_setup( 829*ef853f1fSNithin Dabilpuram portid, queueid, nb_rxd, socketid, 830*ef853f1fSNithin Dabilpuram &rxq_conf, 831*ef853f1fSNithin Dabilpuram pktmbuf_pool[portid][socketid]); 832*ef853f1fSNithin Dabilpuram if (ret < 0) 833*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 834*ef853f1fSNithin Dabilpuram "rte_eth_rx_queue_setup: err=%d, " 835*ef853f1fSNithin Dabilpuram "port=%d\n", 836*ef853f1fSNithin Dabilpuram ret, portid); 837*ef853f1fSNithin Dabilpuram 838*ef853f1fSNithin Dabilpuram } 839*ef853f1fSNithin Dabilpuram } 840*ef853f1fSNithin Dabilpuram 841*ef853f1fSNithin Dabilpuram printf("\n"); 842*ef853f1fSNithin Dabilpuram 843*ef853f1fSNithin Dabilpuram /* Start ports */ 844*ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) 845*ef853f1fSNithin Dabilpuram { 846*ef853f1fSNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) 847*ef853f1fSNithin Dabilpuram continue; 848*ef853f1fSNithin Dabilpuram 849*ef853f1fSNithin Dabilpuram /* Start device */ 850*ef853f1fSNithin Dabilpuram ret = rte_eth_dev_start(portid); 851*ef853f1fSNithin Dabilpuram if (ret < 0) 852*ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 853*ef853f1fSNithin Dabilpuram "rte_eth_dev_start: err=%d, port=%d\n", ret, 854*ef853f1fSNithin Dabilpuram portid); 855*ef853f1fSNithin Dabilpuram 856*ef853f1fSNithin Dabilpuram /* 857*ef853f1fSNithin Dabilpuram * If enabled, put device in promiscuous mode. 858*ef853f1fSNithin Dabilpuram * This allows IO forwarding mode to forward packets 859*ef853f1fSNithin Dabilpuram * to itself through 2 cross-connected ports of the 860*ef853f1fSNithin Dabilpuram * target machine. 861*ef853f1fSNithin Dabilpuram */ 862*ef853f1fSNithin Dabilpuram if (promiscuous_on) 863*ef853f1fSNithin Dabilpuram rte_eth_promiscuous_enable(portid); 864*ef853f1fSNithin Dabilpuram } 865*ef853f1fSNithin Dabilpuram 866*ef853f1fSNithin Dabilpuram printf("\n"); 867*ef853f1fSNithin Dabilpuram 868*ef853f1fSNithin Dabilpuram check_all_ports_link_status(enabled_port_mask); 869*ef853f1fSNithin Dabilpuram 870*ef853f1fSNithin Dabilpuram /* Stop ports */ 871*ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) { 872*ef853f1fSNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) 873*ef853f1fSNithin Dabilpuram continue; 874*ef853f1fSNithin Dabilpuram printf("Closing port %d...", portid); 875*ef853f1fSNithin Dabilpuram rte_eth_dev_stop(portid); 876*ef853f1fSNithin Dabilpuram rte_eth_dev_close(portid); 877*ef853f1fSNithin Dabilpuram printf(" Done\n"); 878*ef853f1fSNithin Dabilpuram } 87908bd1a17SNithin Dabilpuram printf("Bye...\n"); 88008bd1a17SNithin Dabilpuram 88108bd1a17SNithin Dabilpuram return ret; 88208bd1a17SNithin Dabilpuram } 883