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> 23ef853f1fSNithin Dabilpuram #include <rte_cycles.h> 2408bd1a17SNithin Dabilpuram #include <rte_eal.h> 2508bd1a17SNithin Dabilpuram #include <rte_ethdev.h> 263087ec1cSNithin Dabilpuram #include <rte_graph_worker.h> 273087ec1cSNithin Dabilpuram #include <rte_launch.h> 28ef853f1fSNithin Dabilpuram #include <rte_lcore.h> 2908bd1a17SNithin Dabilpuram #include <rte_log.h> 3008bd1a17SNithin Dabilpuram #include <rte_mempool.h> 313087ec1cSNithin Dabilpuram #include <rte_node_eth_api.h> 323087ec1cSNithin Dabilpuram #include <rte_node_ip4_api.h> 3308bd1a17SNithin Dabilpuram #include <rte_per_lcore.h> 3408bd1a17SNithin Dabilpuram #include <rte_string_fns.h> 3508bd1a17SNithin Dabilpuram #include <rte_vect.h> 3608bd1a17SNithin Dabilpuram 3708bd1a17SNithin Dabilpuram #include <cmdline_parse.h> 3808bd1a17SNithin Dabilpuram #include <cmdline_parse_etheraddr.h> 3908bd1a17SNithin Dabilpuram 4008bd1a17SNithin Dabilpuram /* Log type */ 4108bd1a17SNithin Dabilpuram #define RTE_LOGTYPE_L3FWD_GRAPH RTE_LOGTYPE_USER1 4208bd1a17SNithin Dabilpuram 4308bd1a17SNithin Dabilpuram /* 4408bd1a17SNithin Dabilpuram * Configurable number of RX/TX ring descriptors 4508bd1a17SNithin Dabilpuram */ 4608bd1a17SNithin Dabilpuram #define RTE_TEST_RX_DESC_DEFAULT 1024 4708bd1a17SNithin Dabilpuram #define RTE_TEST_TX_DESC_DEFAULT 1024 4808bd1a17SNithin Dabilpuram 4908bd1a17SNithin Dabilpuram #define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS 5008bd1a17SNithin Dabilpuram #define MAX_RX_QUEUE_PER_PORT 128 5108bd1a17SNithin Dabilpuram 5208bd1a17SNithin Dabilpuram #define MAX_RX_QUEUE_PER_LCORE 16 5308bd1a17SNithin Dabilpuram 5408bd1a17SNithin Dabilpuram #define MAX_LCORE_PARAMS 1024 5508bd1a17SNithin Dabilpuram 5608bd1a17SNithin Dabilpuram #define NB_SOCKETS 8 5708bd1a17SNithin Dabilpuram 58ef853f1fSNithin Dabilpuram /* Static global variables used within this file. */ 59ef853f1fSNithin Dabilpuram static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; 60ef853f1fSNithin Dabilpuram static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; 61ef853f1fSNithin Dabilpuram 6208bd1a17SNithin Dabilpuram /**< Ports set in promiscuous mode off by default. */ 6308bd1a17SNithin Dabilpuram static int promiscuous_on; 6408bd1a17SNithin Dabilpuram 6508bd1a17SNithin Dabilpuram static int numa_on = 1; /**< NUMA is enabled by default. */ 6608bd1a17SNithin Dabilpuram static int per_port_pool; /**< Use separate buffer pools per port; disabled */ 6708bd1a17SNithin Dabilpuram /**< by default */ 6808bd1a17SNithin Dabilpuram 6908bd1a17SNithin Dabilpuram static volatile bool force_quit; 7008bd1a17SNithin Dabilpuram 7108bd1a17SNithin Dabilpuram /* Ethernet addresses of ports */ 7208bd1a17SNithin Dabilpuram static uint64_t dest_eth_addr[RTE_MAX_ETHPORTS]; 73ef853f1fSNithin Dabilpuram static struct rte_ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; 7408bd1a17SNithin Dabilpuram xmm_t val_eth[RTE_MAX_ETHPORTS]; 7508bd1a17SNithin Dabilpuram 7608bd1a17SNithin Dabilpuram /* Mask of enabled ports */ 7708bd1a17SNithin Dabilpuram static uint32_t enabled_port_mask; 7808bd1a17SNithin Dabilpuram 7908bd1a17SNithin Dabilpuram struct lcore_rx_queue { 8008bd1a17SNithin Dabilpuram uint16_t port_id; 8108bd1a17SNithin Dabilpuram uint8_t queue_id; 823087ec1cSNithin Dabilpuram char node_name[RTE_NODE_NAMESIZE]; 8308bd1a17SNithin Dabilpuram }; 8408bd1a17SNithin Dabilpuram 8508bd1a17SNithin Dabilpuram /* Lcore conf */ 8608bd1a17SNithin Dabilpuram struct lcore_conf { 8708bd1a17SNithin Dabilpuram uint16_t n_rx_queue; 8808bd1a17SNithin Dabilpuram struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; 893087ec1cSNithin Dabilpuram 903087ec1cSNithin Dabilpuram struct rte_graph *graph; 913087ec1cSNithin Dabilpuram char name[RTE_GRAPH_NAMESIZE]; 923087ec1cSNithin Dabilpuram rte_graph_t graph_id; 9308bd1a17SNithin Dabilpuram } __rte_cache_aligned; 9408bd1a17SNithin Dabilpuram 9508bd1a17SNithin Dabilpuram static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; 9608bd1a17SNithin Dabilpuram 9708bd1a17SNithin Dabilpuram struct lcore_params { 9808bd1a17SNithin Dabilpuram uint16_t port_id; 9908bd1a17SNithin Dabilpuram uint8_t queue_id; 10008bd1a17SNithin Dabilpuram uint8_t lcore_id; 10108bd1a17SNithin Dabilpuram } __rte_cache_aligned; 10208bd1a17SNithin Dabilpuram 10308bd1a17SNithin Dabilpuram static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; 10408bd1a17SNithin Dabilpuram static struct lcore_params lcore_params_array_default[] = { 10508bd1a17SNithin Dabilpuram {0, 0, 2}, {0, 1, 2}, {0, 2, 2}, {1, 0, 2}, {1, 1, 2}, 10608bd1a17SNithin Dabilpuram {1, 2, 2}, {2, 0, 2}, {3, 0, 3}, {3, 1, 3}, 10708bd1a17SNithin Dabilpuram }; 10808bd1a17SNithin Dabilpuram 10908bd1a17SNithin Dabilpuram static struct lcore_params *lcore_params = lcore_params_array_default; 11008bd1a17SNithin Dabilpuram static uint16_t nb_lcore_params = RTE_DIM(lcore_params_array_default); 11108bd1a17SNithin Dabilpuram 11208bd1a17SNithin Dabilpuram static struct rte_eth_conf port_conf = { 11308bd1a17SNithin Dabilpuram .rxmode = { 11408bd1a17SNithin Dabilpuram .mq_mode = ETH_MQ_RX_RSS, 11508bd1a17SNithin Dabilpuram .max_rx_pkt_len = RTE_ETHER_MAX_LEN, 11608bd1a17SNithin Dabilpuram .split_hdr_size = 0, 11708bd1a17SNithin Dabilpuram }, 11808bd1a17SNithin Dabilpuram .rx_adv_conf = { 11908bd1a17SNithin Dabilpuram .rss_conf = { 12008bd1a17SNithin Dabilpuram .rss_key = NULL, 12108bd1a17SNithin Dabilpuram .rss_hf = ETH_RSS_IP, 12208bd1a17SNithin Dabilpuram }, 12308bd1a17SNithin Dabilpuram }, 12408bd1a17SNithin Dabilpuram .txmode = { 12508bd1a17SNithin Dabilpuram .mq_mode = ETH_MQ_TX_NONE, 12608bd1a17SNithin Dabilpuram }, 12708bd1a17SNithin Dabilpuram }; 12808bd1a17SNithin Dabilpuram 129ef853f1fSNithin Dabilpuram static struct rte_mempool *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS]; 130ef853f1fSNithin Dabilpuram 1313087ec1cSNithin Dabilpuram static struct rte_node_ethdev_config ethdev_conf[RTE_MAX_ETHPORTS]; 1323087ec1cSNithin Dabilpuram 1333087ec1cSNithin Dabilpuram struct ipv4_l3fwd_lpm_route { 1343087ec1cSNithin Dabilpuram uint32_t ip; 1353087ec1cSNithin Dabilpuram uint8_t depth; 1363087ec1cSNithin Dabilpuram uint8_t if_out; 1373087ec1cSNithin Dabilpuram }; 1383087ec1cSNithin Dabilpuram 1393087ec1cSNithin Dabilpuram #define IPV4_L3FWD_LPM_NUM_ROUTES \ 1403087ec1cSNithin Dabilpuram (sizeof(ipv4_l3fwd_lpm_route_array) / \ 1413087ec1cSNithin Dabilpuram sizeof(ipv4_l3fwd_lpm_route_array[0])) 1423087ec1cSNithin Dabilpuram /* 198.18.0.0/16 are set aside for RFC2544 benchmarking. */ 1433087ec1cSNithin Dabilpuram static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = { 1443087ec1cSNithin Dabilpuram {RTE_IPV4(198, 18, 0, 0), 24, 0}, {RTE_IPV4(198, 18, 1, 0), 24, 1}, 1453087ec1cSNithin Dabilpuram {RTE_IPV4(198, 18, 2, 0), 24, 2}, {RTE_IPV4(198, 18, 3, 0), 24, 3}, 1463087ec1cSNithin Dabilpuram {RTE_IPV4(198, 18, 4, 0), 24, 4}, {RTE_IPV4(198, 18, 5, 0), 24, 5}, 1473087ec1cSNithin Dabilpuram {RTE_IPV4(198, 18, 6, 0), 24, 6}, {RTE_IPV4(198, 18, 7, 0), 24, 7}, 1483087ec1cSNithin Dabilpuram }; 1493087ec1cSNithin Dabilpuram 15008bd1a17SNithin Dabilpuram static int 15108bd1a17SNithin Dabilpuram check_lcore_params(void) 15208bd1a17SNithin Dabilpuram { 15308bd1a17SNithin Dabilpuram uint8_t queue, lcore; 15408bd1a17SNithin Dabilpuram int socketid; 15508bd1a17SNithin Dabilpuram uint16_t i; 15608bd1a17SNithin Dabilpuram 15708bd1a17SNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 15808bd1a17SNithin Dabilpuram queue = lcore_params[i].queue_id; 15908bd1a17SNithin Dabilpuram if (queue >= MAX_RX_QUEUE_PER_PORT) { 16008bd1a17SNithin Dabilpuram printf("Invalid queue number: %hhu\n", queue); 16108bd1a17SNithin Dabilpuram return -1; 16208bd1a17SNithin Dabilpuram } 16308bd1a17SNithin Dabilpuram lcore = lcore_params[i].lcore_id; 16408bd1a17SNithin Dabilpuram if (!rte_lcore_is_enabled(lcore)) { 16508bd1a17SNithin Dabilpuram printf("Error: lcore %hhu is not enabled in lcore mask\n", 16608bd1a17SNithin Dabilpuram lcore); 16708bd1a17SNithin Dabilpuram return -1; 16808bd1a17SNithin Dabilpuram } 16908bd1a17SNithin Dabilpuram 17008bd1a17SNithin Dabilpuram if (lcore == rte_get_master_lcore()) { 17108bd1a17SNithin Dabilpuram printf("Error: lcore %u is master lcore\n", lcore); 17208bd1a17SNithin Dabilpuram return -1; 17308bd1a17SNithin Dabilpuram } 17408bd1a17SNithin Dabilpuram socketid = rte_lcore_to_socket_id(lcore); 17508bd1a17SNithin Dabilpuram if ((socketid != 0) && (numa_on == 0)) { 17608bd1a17SNithin Dabilpuram printf("Warning: lcore %hhu is on socket %d with numa off\n", 17708bd1a17SNithin Dabilpuram lcore, socketid); 17808bd1a17SNithin Dabilpuram } 17908bd1a17SNithin Dabilpuram } 18008bd1a17SNithin Dabilpuram 18108bd1a17SNithin Dabilpuram return 0; 18208bd1a17SNithin Dabilpuram } 18308bd1a17SNithin Dabilpuram 18408bd1a17SNithin Dabilpuram static int 18508bd1a17SNithin Dabilpuram check_port_config(void) 18608bd1a17SNithin Dabilpuram { 18708bd1a17SNithin Dabilpuram uint16_t portid; 18808bd1a17SNithin Dabilpuram uint16_t i; 18908bd1a17SNithin Dabilpuram 19008bd1a17SNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 19108bd1a17SNithin Dabilpuram portid = lcore_params[i].port_id; 19208bd1a17SNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) { 19308bd1a17SNithin Dabilpuram printf("Port %u is not enabled in port mask\n", portid); 19408bd1a17SNithin Dabilpuram return -1; 19508bd1a17SNithin Dabilpuram } 19608bd1a17SNithin Dabilpuram if (!rte_eth_dev_is_valid_port(portid)) { 19708bd1a17SNithin Dabilpuram printf("Port %u is not present on the board\n", portid); 19808bd1a17SNithin Dabilpuram return -1; 19908bd1a17SNithin Dabilpuram } 20008bd1a17SNithin Dabilpuram } 20108bd1a17SNithin Dabilpuram 20208bd1a17SNithin Dabilpuram return 0; 20308bd1a17SNithin Dabilpuram } 20408bd1a17SNithin Dabilpuram 205ef853f1fSNithin Dabilpuram static uint8_t 206ef853f1fSNithin Dabilpuram get_port_n_rx_queues(const uint16_t port) 207ef853f1fSNithin Dabilpuram { 208ef853f1fSNithin Dabilpuram int queue = -1; 209ef853f1fSNithin Dabilpuram uint16_t i; 210ef853f1fSNithin Dabilpuram 211ef853f1fSNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 212ef853f1fSNithin Dabilpuram if (lcore_params[i].port_id == port) { 213ef853f1fSNithin Dabilpuram if (lcore_params[i].queue_id == queue + 1) 214ef853f1fSNithin Dabilpuram queue = lcore_params[i].queue_id; 215ef853f1fSNithin Dabilpuram else 216ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 217ef853f1fSNithin Dabilpuram "Queue ids of the port %d must be" 218ef853f1fSNithin Dabilpuram " in sequence and must start with 0\n", 219ef853f1fSNithin Dabilpuram lcore_params[i].port_id); 220ef853f1fSNithin Dabilpuram } 221ef853f1fSNithin Dabilpuram } 222ef853f1fSNithin Dabilpuram 223ef853f1fSNithin Dabilpuram return (uint8_t)(++queue); 224ef853f1fSNithin Dabilpuram } 225ef853f1fSNithin Dabilpuram 22608bd1a17SNithin Dabilpuram static int 22708bd1a17SNithin Dabilpuram init_lcore_rx_queues(void) 22808bd1a17SNithin Dabilpuram { 22908bd1a17SNithin Dabilpuram uint16_t i, nb_rx_queue; 23008bd1a17SNithin Dabilpuram uint8_t lcore; 23108bd1a17SNithin Dabilpuram 23208bd1a17SNithin Dabilpuram for (i = 0; i < nb_lcore_params; ++i) { 23308bd1a17SNithin Dabilpuram lcore = lcore_params[i].lcore_id; 23408bd1a17SNithin Dabilpuram nb_rx_queue = lcore_conf[lcore].n_rx_queue; 23508bd1a17SNithin Dabilpuram if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { 23608bd1a17SNithin Dabilpuram printf("Error: too many queues (%u) for lcore: %u\n", 23708bd1a17SNithin Dabilpuram (unsigned int)nb_rx_queue + 1, 23808bd1a17SNithin Dabilpuram (unsigned int)lcore); 23908bd1a17SNithin Dabilpuram return -1; 24008bd1a17SNithin Dabilpuram } 24108bd1a17SNithin Dabilpuram 24208bd1a17SNithin Dabilpuram lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = 24308bd1a17SNithin Dabilpuram lcore_params[i].port_id; 24408bd1a17SNithin Dabilpuram lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = 24508bd1a17SNithin Dabilpuram lcore_params[i].queue_id; 24608bd1a17SNithin Dabilpuram lcore_conf[lcore].n_rx_queue++; 24708bd1a17SNithin Dabilpuram } 24808bd1a17SNithin Dabilpuram 24908bd1a17SNithin Dabilpuram return 0; 25008bd1a17SNithin Dabilpuram } 25108bd1a17SNithin Dabilpuram 25208bd1a17SNithin Dabilpuram /* Display usage */ 25308bd1a17SNithin Dabilpuram static void 25408bd1a17SNithin Dabilpuram print_usage(const char *prgname) 25508bd1a17SNithin Dabilpuram { 25608bd1a17SNithin Dabilpuram fprintf(stderr, 25708bd1a17SNithin Dabilpuram "%s [EAL options] --" 25808bd1a17SNithin Dabilpuram " -p PORTMASK" 25908bd1a17SNithin Dabilpuram " [-P]" 26008bd1a17SNithin Dabilpuram " --config (port,queue,lcore)[,(port,queue,lcore)]" 26108bd1a17SNithin Dabilpuram " [--eth-dest=X,MM:MM:MM:MM:MM:MM]" 26208bd1a17SNithin Dabilpuram " [--enable-jumbo [--max-pkt-len PKTLEN]]" 26308bd1a17SNithin Dabilpuram " [--no-numa]" 26408bd1a17SNithin Dabilpuram " [--per-port-pool]\n\n" 26508bd1a17SNithin Dabilpuram 26608bd1a17SNithin Dabilpuram " -p PORTMASK: Hexadecimal bitmask of ports to configure\n" 26708bd1a17SNithin Dabilpuram " -P : Enable promiscuous mode\n" 26808bd1a17SNithin Dabilpuram " --config (port,queue,lcore): Rx queue configuration\n" 26908bd1a17SNithin Dabilpuram " --eth-dest=X,MM:MM:MM:MM:MM:MM: Ethernet destination for " 27008bd1a17SNithin Dabilpuram "port X\n" 27108bd1a17SNithin Dabilpuram " --enable-jumbo: Enable jumbo frames\n" 27208bd1a17SNithin Dabilpuram " --max-pkt-len: Under the premise of enabling jumbo,\n" 27308bd1a17SNithin Dabilpuram " maximum packet length in decimal (64-9600)\n" 27408bd1a17SNithin Dabilpuram " --no-numa: Disable numa awareness\n" 27508bd1a17SNithin Dabilpuram " --per-port-pool: Use separate buffer pool per port\n\n", 27608bd1a17SNithin Dabilpuram prgname); 27708bd1a17SNithin Dabilpuram } 27808bd1a17SNithin Dabilpuram 27908bd1a17SNithin Dabilpuram static int 28008bd1a17SNithin Dabilpuram parse_max_pkt_len(const char *pktlen) 28108bd1a17SNithin Dabilpuram { 28208bd1a17SNithin Dabilpuram unsigned long len; 28308bd1a17SNithin Dabilpuram char *end = NULL; 28408bd1a17SNithin Dabilpuram 28508bd1a17SNithin Dabilpuram /* Parse decimal string */ 28608bd1a17SNithin Dabilpuram len = strtoul(pktlen, &end, 10); 28708bd1a17SNithin Dabilpuram if ((pktlen[0] == '\0') || (end == NULL) || (*end != '\0')) 28808bd1a17SNithin Dabilpuram return -1; 28908bd1a17SNithin Dabilpuram 29008bd1a17SNithin Dabilpuram if (len == 0) 29108bd1a17SNithin Dabilpuram return -1; 29208bd1a17SNithin Dabilpuram 29308bd1a17SNithin Dabilpuram return len; 29408bd1a17SNithin Dabilpuram } 29508bd1a17SNithin Dabilpuram 29608bd1a17SNithin Dabilpuram static int 29708bd1a17SNithin Dabilpuram parse_portmask(const char *portmask) 29808bd1a17SNithin Dabilpuram { 29908bd1a17SNithin Dabilpuram char *end = NULL; 30008bd1a17SNithin Dabilpuram unsigned long pm; 30108bd1a17SNithin Dabilpuram 30208bd1a17SNithin Dabilpuram /* Parse hexadecimal string */ 30308bd1a17SNithin Dabilpuram pm = strtoul(portmask, &end, 16); 30408bd1a17SNithin Dabilpuram if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 305*ce6b8c31SSarosh Arif return 0; 30608bd1a17SNithin Dabilpuram 30708bd1a17SNithin Dabilpuram return pm; 30808bd1a17SNithin Dabilpuram } 30908bd1a17SNithin Dabilpuram 31008bd1a17SNithin Dabilpuram static int 31108bd1a17SNithin Dabilpuram parse_config(const char *q_arg) 31208bd1a17SNithin Dabilpuram { 31308bd1a17SNithin Dabilpuram enum fieldnames { FLD_PORT = 0, FLD_QUEUE, FLD_LCORE, _NUM_FLD }; 31408bd1a17SNithin Dabilpuram unsigned long int_fld[_NUM_FLD]; 31508bd1a17SNithin Dabilpuram const char *p, *p0 = q_arg; 31608bd1a17SNithin Dabilpuram char *str_fld[_NUM_FLD]; 31708bd1a17SNithin Dabilpuram uint32_t size; 31808bd1a17SNithin Dabilpuram char s[256]; 31908bd1a17SNithin Dabilpuram char *end; 32008bd1a17SNithin Dabilpuram int i; 32108bd1a17SNithin Dabilpuram 32208bd1a17SNithin Dabilpuram nb_lcore_params = 0; 32308bd1a17SNithin Dabilpuram 32408bd1a17SNithin Dabilpuram while ((p = strchr(p0, '(')) != NULL) { 32508bd1a17SNithin Dabilpuram ++p; 32608bd1a17SNithin Dabilpuram p0 = strchr(p, ')'); 32708bd1a17SNithin Dabilpuram if (p0 == NULL) 32808bd1a17SNithin Dabilpuram return -1; 32908bd1a17SNithin Dabilpuram 33008bd1a17SNithin Dabilpuram size = p0 - p; 33108bd1a17SNithin Dabilpuram if (size >= sizeof(s)) 33208bd1a17SNithin Dabilpuram return -1; 33308bd1a17SNithin Dabilpuram 33408bd1a17SNithin Dabilpuram memcpy(s, p, size); 33508bd1a17SNithin Dabilpuram s[size] = '\0'; 33608bd1a17SNithin Dabilpuram if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != 33708bd1a17SNithin Dabilpuram _NUM_FLD) 33808bd1a17SNithin Dabilpuram return -1; 33908bd1a17SNithin Dabilpuram for (i = 0; i < _NUM_FLD; i++) { 34008bd1a17SNithin Dabilpuram errno = 0; 34108bd1a17SNithin Dabilpuram int_fld[i] = strtoul(str_fld[i], &end, 0); 34208bd1a17SNithin Dabilpuram if (errno != 0 || end == str_fld[i]) 34308bd1a17SNithin Dabilpuram return -1; 34408bd1a17SNithin Dabilpuram } 34508bd1a17SNithin Dabilpuram 34608bd1a17SNithin Dabilpuram if (nb_lcore_params >= MAX_LCORE_PARAMS) { 34708bd1a17SNithin Dabilpuram printf("Exceeded max number of lcore params: %hu\n", 34808bd1a17SNithin Dabilpuram nb_lcore_params); 34908bd1a17SNithin Dabilpuram return -1; 35008bd1a17SNithin Dabilpuram } 35108bd1a17SNithin Dabilpuram 35208bd1a17SNithin Dabilpuram if (int_fld[FLD_PORT] >= RTE_MAX_ETHPORTS || 35308bd1a17SNithin Dabilpuram int_fld[FLD_LCORE] >= RTE_MAX_LCORE) { 35408bd1a17SNithin Dabilpuram printf("Invalid port/lcore id\n"); 35508bd1a17SNithin Dabilpuram return -1; 35608bd1a17SNithin Dabilpuram } 35708bd1a17SNithin Dabilpuram 35808bd1a17SNithin Dabilpuram lcore_params_array[nb_lcore_params].port_id = 35908bd1a17SNithin Dabilpuram (uint8_t)int_fld[FLD_PORT]; 36008bd1a17SNithin Dabilpuram lcore_params_array[nb_lcore_params].queue_id = 36108bd1a17SNithin Dabilpuram (uint8_t)int_fld[FLD_QUEUE]; 36208bd1a17SNithin Dabilpuram lcore_params_array[nb_lcore_params].lcore_id = 36308bd1a17SNithin Dabilpuram (uint8_t)int_fld[FLD_LCORE]; 36408bd1a17SNithin Dabilpuram ++nb_lcore_params; 36508bd1a17SNithin Dabilpuram } 36608bd1a17SNithin Dabilpuram lcore_params = lcore_params_array; 36708bd1a17SNithin Dabilpuram 36808bd1a17SNithin Dabilpuram return 0; 36908bd1a17SNithin Dabilpuram } 37008bd1a17SNithin Dabilpuram 37108bd1a17SNithin Dabilpuram static void 37208bd1a17SNithin Dabilpuram parse_eth_dest(const char *optarg) 37308bd1a17SNithin Dabilpuram { 37408bd1a17SNithin Dabilpuram uint8_t c, *dest, peer_addr[6]; 37508bd1a17SNithin Dabilpuram uint16_t portid; 37608bd1a17SNithin Dabilpuram char *port_end; 37708bd1a17SNithin Dabilpuram 37808bd1a17SNithin Dabilpuram errno = 0; 37908bd1a17SNithin Dabilpuram portid = strtoul(optarg, &port_end, 10); 38008bd1a17SNithin Dabilpuram if (errno != 0 || port_end == optarg || *port_end++ != ',') 38108bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid eth-dest: %s", optarg); 38208bd1a17SNithin Dabilpuram if (portid >= RTE_MAX_ETHPORTS) 38308bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, 38408bd1a17SNithin Dabilpuram "eth-dest: port %d >= RTE_MAX_ETHPORTS(%d)\n", portid, 38508bd1a17SNithin Dabilpuram RTE_MAX_ETHPORTS); 38608bd1a17SNithin Dabilpuram 38708bd1a17SNithin Dabilpuram if (cmdline_parse_etheraddr(NULL, port_end, &peer_addr, 38808bd1a17SNithin Dabilpuram sizeof(peer_addr)) < 0) 38908bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid ethernet address: %s\n", 39008bd1a17SNithin Dabilpuram port_end); 39108bd1a17SNithin Dabilpuram dest = (uint8_t *)&dest_eth_addr[portid]; 39208bd1a17SNithin Dabilpuram for (c = 0; c < 6; c++) 39308bd1a17SNithin Dabilpuram dest[c] = peer_addr[c]; 39408bd1a17SNithin Dabilpuram *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; 39508bd1a17SNithin Dabilpuram } 39608bd1a17SNithin Dabilpuram 39708bd1a17SNithin Dabilpuram #define MAX_JUMBO_PKT_LEN 9600 39808bd1a17SNithin Dabilpuram #define MEMPOOL_CACHE_SIZE 256 39908bd1a17SNithin Dabilpuram 40008bd1a17SNithin Dabilpuram static const char short_options[] = "p:" /* portmask */ 40108bd1a17SNithin Dabilpuram "P" /* promiscuous */ 40208bd1a17SNithin Dabilpuram ; 40308bd1a17SNithin Dabilpuram 40408bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_CONFIG "config" 40508bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_ETH_DEST "eth-dest" 40608bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_NO_NUMA "no-numa" 40708bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_ENABLE_JUMBO "enable-jumbo" 40808bd1a17SNithin Dabilpuram #define CMD_LINE_OPT_PER_PORT_POOL "per-port-pool" 40908bd1a17SNithin Dabilpuram enum { 41008bd1a17SNithin Dabilpuram /* Long options mapped to a short option */ 41108bd1a17SNithin Dabilpuram 41208bd1a17SNithin Dabilpuram /* First long only option value must be >= 256, so that we won't 41308bd1a17SNithin Dabilpuram * conflict with short options 41408bd1a17SNithin Dabilpuram */ 41508bd1a17SNithin Dabilpuram CMD_LINE_OPT_MIN_NUM = 256, 41608bd1a17SNithin Dabilpuram CMD_LINE_OPT_CONFIG_NUM, 41708bd1a17SNithin Dabilpuram CMD_LINE_OPT_ETH_DEST_NUM, 41808bd1a17SNithin Dabilpuram CMD_LINE_OPT_NO_NUMA_NUM, 41908bd1a17SNithin Dabilpuram CMD_LINE_OPT_ENABLE_JUMBO_NUM, 42008bd1a17SNithin Dabilpuram CMD_LINE_OPT_PARSE_PER_PORT_POOL, 42108bd1a17SNithin Dabilpuram }; 42208bd1a17SNithin Dabilpuram 42308bd1a17SNithin Dabilpuram static const struct option lgopts[] = { 42408bd1a17SNithin Dabilpuram {CMD_LINE_OPT_CONFIG, 1, 0, CMD_LINE_OPT_CONFIG_NUM}, 42508bd1a17SNithin Dabilpuram {CMD_LINE_OPT_ETH_DEST, 1, 0, CMD_LINE_OPT_ETH_DEST_NUM}, 42608bd1a17SNithin Dabilpuram {CMD_LINE_OPT_NO_NUMA, 0, 0, CMD_LINE_OPT_NO_NUMA_NUM}, 42708bd1a17SNithin Dabilpuram {CMD_LINE_OPT_ENABLE_JUMBO, 0, 0, CMD_LINE_OPT_ENABLE_JUMBO_NUM}, 42808bd1a17SNithin Dabilpuram {CMD_LINE_OPT_PER_PORT_POOL, 0, 0, CMD_LINE_OPT_PARSE_PER_PORT_POOL}, 42908bd1a17SNithin Dabilpuram {NULL, 0, 0, 0}, 43008bd1a17SNithin Dabilpuram }; 43108bd1a17SNithin Dabilpuram 43208bd1a17SNithin Dabilpuram /* 43308bd1a17SNithin Dabilpuram * This expression is used to calculate the number of mbufs needed 43408bd1a17SNithin Dabilpuram * depending on user input, taking into account memory for rx and 43508bd1a17SNithin Dabilpuram * tx hardware rings, cache per lcore and mtable per port per lcore. 43608bd1a17SNithin Dabilpuram * RTE_MAX is used to ensure that NB_MBUF never goes below a minimum 43708bd1a17SNithin Dabilpuram * value of 8192 43808bd1a17SNithin Dabilpuram */ 43908bd1a17SNithin Dabilpuram #define NB_MBUF(nports) \ 44008bd1a17SNithin Dabilpuram RTE_MAX((nports * nb_rx_queue * nb_rxd + \ 44108bd1a17SNithin Dabilpuram nports * nb_lcores * RTE_GRAPH_BURST_SIZE + \ 44208bd1a17SNithin Dabilpuram nports * n_tx_queue * nb_txd + \ 44308bd1a17SNithin Dabilpuram nb_lcores * MEMPOOL_CACHE_SIZE), 8192u) 44408bd1a17SNithin Dabilpuram 44508bd1a17SNithin Dabilpuram /* Parse the argument given in the command line of the application */ 44608bd1a17SNithin Dabilpuram static int 44708bd1a17SNithin Dabilpuram parse_args(int argc, char **argv) 44808bd1a17SNithin Dabilpuram { 44908bd1a17SNithin Dabilpuram char *prgname = argv[0]; 45008bd1a17SNithin Dabilpuram int option_index; 45108bd1a17SNithin Dabilpuram char **argvopt; 45208bd1a17SNithin Dabilpuram int opt, ret; 45308bd1a17SNithin Dabilpuram 45408bd1a17SNithin Dabilpuram argvopt = argv; 45508bd1a17SNithin Dabilpuram 45608bd1a17SNithin Dabilpuram /* Error or normal output strings. */ 45708bd1a17SNithin Dabilpuram while ((opt = getopt_long(argc, argvopt, short_options, lgopts, 45808bd1a17SNithin Dabilpuram &option_index)) != EOF) { 45908bd1a17SNithin Dabilpuram 46008bd1a17SNithin Dabilpuram switch (opt) { 46108bd1a17SNithin Dabilpuram /* Portmask */ 46208bd1a17SNithin Dabilpuram case 'p': 46308bd1a17SNithin Dabilpuram enabled_port_mask = parse_portmask(optarg); 46408bd1a17SNithin Dabilpuram if (enabled_port_mask == 0) { 46508bd1a17SNithin Dabilpuram fprintf(stderr, "Invalid portmask\n"); 46608bd1a17SNithin Dabilpuram print_usage(prgname); 46708bd1a17SNithin Dabilpuram return -1; 46808bd1a17SNithin Dabilpuram } 46908bd1a17SNithin Dabilpuram break; 47008bd1a17SNithin Dabilpuram 47108bd1a17SNithin Dabilpuram case 'P': 47208bd1a17SNithin Dabilpuram promiscuous_on = 1; 47308bd1a17SNithin Dabilpuram break; 47408bd1a17SNithin Dabilpuram 47508bd1a17SNithin Dabilpuram /* Long options */ 47608bd1a17SNithin Dabilpuram case CMD_LINE_OPT_CONFIG_NUM: 47708bd1a17SNithin Dabilpuram ret = parse_config(optarg); 47808bd1a17SNithin Dabilpuram if (ret) { 47908bd1a17SNithin Dabilpuram fprintf(stderr, "Invalid config\n"); 48008bd1a17SNithin Dabilpuram print_usage(prgname); 48108bd1a17SNithin Dabilpuram return -1; 48208bd1a17SNithin Dabilpuram } 48308bd1a17SNithin Dabilpuram break; 48408bd1a17SNithin Dabilpuram 48508bd1a17SNithin Dabilpuram case CMD_LINE_OPT_ETH_DEST_NUM: 48608bd1a17SNithin Dabilpuram parse_eth_dest(optarg); 48708bd1a17SNithin Dabilpuram break; 48808bd1a17SNithin Dabilpuram 48908bd1a17SNithin Dabilpuram case CMD_LINE_OPT_NO_NUMA_NUM: 49008bd1a17SNithin Dabilpuram numa_on = 0; 49108bd1a17SNithin Dabilpuram break; 49208bd1a17SNithin Dabilpuram 49308bd1a17SNithin Dabilpuram case CMD_LINE_OPT_ENABLE_JUMBO_NUM: { 49408bd1a17SNithin Dabilpuram const struct option lenopts = {"max-pkt-len", 49508bd1a17SNithin Dabilpuram required_argument, 0, 0}; 49608bd1a17SNithin Dabilpuram 49708bd1a17SNithin Dabilpuram port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; 49808bd1a17SNithin Dabilpuram port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MULTI_SEGS; 49908bd1a17SNithin Dabilpuram 50008bd1a17SNithin Dabilpuram /* 50108bd1a17SNithin Dabilpuram * if no max-pkt-len set, use the default 50208bd1a17SNithin Dabilpuram * value RTE_ETHER_MAX_LEN. 50308bd1a17SNithin Dabilpuram */ 50408bd1a17SNithin Dabilpuram if (getopt_long(argc, argvopt, "", &lenopts, 50508bd1a17SNithin Dabilpuram &option_index) == 0) { 50608bd1a17SNithin Dabilpuram ret = parse_max_pkt_len(optarg); 50708bd1a17SNithin Dabilpuram if (ret < 64 || ret > MAX_JUMBO_PKT_LEN) { 50808bd1a17SNithin Dabilpuram fprintf(stderr, "Invalid maximum " 50908bd1a17SNithin Dabilpuram "packet length\n"); 51008bd1a17SNithin Dabilpuram print_usage(prgname); 51108bd1a17SNithin Dabilpuram return -1; 51208bd1a17SNithin Dabilpuram } 51308bd1a17SNithin Dabilpuram port_conf.rxmode.max_rx_pkt_len = ret; 51408bd1a17SNithin Dabilpuram } 51508bd1a17SNithin Dabilpuram break; 51608bd1a17SNithin Dabilpuram } 51708bd1a17SNithin Dabilpuram 51808bd1a17SNithin Dabilpuram case CMD_LINE_OPT_PARSE_PER_PORT_POOL: 51908bd1a17SNithin Dabilpuram printf("Per port buffer pool is enabled\n"); 52008bd1a17SNithin Dabilpuram per_port_pool = 1; 52108bd1a17SNithin Dabilpuram break; 52208bd1a17SNithin Dabilpuram 52308bd1a17SNithin Dabilpuram default: 52408bd1a17SNithin Dabilpuram print_usage(prgname); 52508bd1a17SNithin Dabilpuram return -1; 52608bd1a17SNithin Dabilpuram } 52708bd1a17SNithin Dabilpuram } 52808bd1a17SNithin Dabilpuram 52908bd1a17SNithin Dabilpuram if (optind >= 0) 53008bd1a17SNithin Dabilpuram argv[optind - 1] = prgname; 53108bd1a17SNithin Dabilpuram ret = optind - 1; 53208bd1a17SNithin Dabilpuram optind = 1; /* Reset getopt lib */ 53308bd1a17SNithin Dabilpuram 53408bd1a17SNithin Dabilpuram return ret; 53508bd1a17SNithin Dabilpuram } 53608bd1a17SNithin Dabilpuram 53708bd1a17SNithin Dabilpuram static void 538ef853f1fSNithin Dabilpuram print_ethaddr(const char *name, const struct rte_ether_addr *eth_addr) 539ef853f1fSNithin Dabilpuram { 540ef853f1fSNithin Dabilpuram char buf[RTE_ETHER_ADDR_FMT_SIZE]; 541ef853f1fSNithin Dabilpuram rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr); 542ef853f1fSNithin Dabilpuram printf("%s%s", name, buf); 543ef853f1fSNithin Dabilpuram } 544ef853f1fSNithin Dabilpuram 545ef853f1fSNithin Dabilpuram static int 546ef853f1fSNithin Dabilpuram init_mem(uint16_t portid, uint32_t nb_mbuf) 547ef853f1fSNithin Dabilpuram { 548ef853f1fSNithin Dabilpuram uint32_t lcore_id; 549ef853f1fSNithin Dabilpuram int socketid; 550ef853f1fSNithin Dabilpuram char s[64]; 551ef853f1fSNithin Dabilpuram 552ef853f1fSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 553ef853f1fSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 554ef853f1fSNithin Dabilpuram continue; 555ef853f1fSNithin Dabilpuram 556ef853f1fSNithin Dabilpuram if (numa_on) 557ef853f1fSNithin Dabilpuram socketid = rte_lcore_to_socket_id(lcore_id); 558ef853f1fSNithin Dabilpuram else 559ef853f1fSNithin Dabilpuram socketid = 0; 560ef853f1fSNithin Dabilpuram 561ef853f1fSNithin Dabilpuram if (socketid >= NB_SOCKETS) { 562ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 563ef853f1fSNithin Dabilpuram "Socket %d of lcore %u is out of range %d\n", 564ef853f1fSNithin Dabilpuram socketid, lcore_id, NB_SOCKETS); 565ef853f1fSNithin Dabilpuram } 566ef853f1fSNithin Dabilpuram 567ef853f1fSNithin Dabilpuram if (pktmbuf_pool[portid][socketid] == NULL) { 568ef853f1fSNithin Dabilpuram snprintf(s, sizeof(s), "mbuf_pool_%d:%d", portid, 569ef853f1fSNithin Dabilpuram socketid); 570ef853f1fSNithin Dabilpuram /* Create a pool with priv size of a cacheline */ 571ef853f1fSNithin Dabilpuram pktmbuf_pool[portid][socketid] = 572ef853f1fSNithin Dabilpuram rte_pktmbuf_pool_create( 573ef853f1fSNithin Dabilpuram s, nb_mbuf, MEMPOOL_CACHE_SIZE, 574ef853f1fSNithin Dabilpuram RTE_CACHE_LINE_SIZE, 575ef853f1fSNithin Dabilpuram RTE_MBUF_DEFAULT_BUF_SIZE, socketid); 576ef853f1fSNithin Dabilpuram if (pktmbuf_pool[portid][socketid] == NULL) 577ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 578ef853f1fSNithin Dabilpuram "Cannot init mbuf pool on socket %d\n", 579ef853f1fSNithin Dabilpuram socketid); 580ef853f1fSNithin Dabilpuram else 581ef853f1fSNithin Dabilpuram printf("Allocated mbuf pool on socket %d\n", 582ef853f1fSNithin Dabilpuram socketid); 583ef853f1fSNithin Dabilpuram } 584ef853f1fSNithin Dabilpuram } 585ef853f1fSNithin Dabilpuram 586ef853f1fSNithin Dabilpuram return 0; 587ef853f1fSNithin Dabilpuram } 588ef853f1fSNithin Dabilpuram 589ef853f1fSNithin Dabilpuram /* Check the link status of all ports in up to 9s, and print them finally */ 590ef853f1fSNithin Dabilpuram static void 591ef853f1fSNithin Dabilpuram check_all_ports_link_status(uint32_t port_mask) 592ef853f1fSNithin Dabilpuram { 593ef853f1fSNithin Dabilpuram #define CHECK_INTERVAL 100 /* 100ms */ 594ef853f1fSNithin Dabilpuram #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ 595ef853f1fSNithin Dabilpuram uint8_t count, all_ports_up, print_flag = 0; 596ef853f1fSNithin Dabilpuram struct rte_eth_link link; 597ef853f1fSNithin Dabilpuram uint16_t portid; 5981d049dc7SPavan Nikhilesh int ret; 599ef853f1fSNithin Dabilpuram 600ef853f1fSNithin Dabilpuram printf("\nChecking link status"); 601ef853f1fSNithin Dabilpuram fflush(stdout); 602ef853f1fSNithin Dabilpuram for (count = 0; count <= MAX_CHECK_TIME; count++) { 603ef853f1fSNithin Dabilpuram if (force_quit) 604ef853f1fSNithin Dabilpuram return; 605ef853f1fSNithin Dabilpuram all_ports_up = 1; 606ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) 607ef853f1fSNithin Dabilpuram { 608ef853f1fSNithin Dabilpuram if (force_quit) 609ef853f1fSNithin Dabilpuram return; 610ef853f1fSNithin Dabilpuram if ((port_mask & (1 << portid)) == 0) 611ef853f1fSNithin Dabilpuram continue; 612ef853f1fSNithin Dabilpuram memset(&link, 0, sizeof(link)); 6131d049dc7SPavan Nikhilesh ret = rte_eth_link_get_nowait(portid, &link); 6141d049dc7SPavan Nikhilesh if (ret < 0) { 6151d049dc7SPavan Nikhilesh all_ports_up = 0; 6161d049dc7SPavan Nikhilesh if (print_flag == 1) 6171d049dc7SPavan Nikhilesh printf("Port %u link get failed: %s\n", 6181d049dc7SPavan Nikhilesh portid, rte_strerror(-ret)); 6191d049dc7SPavan Nikhilesh continue; 6201d049dc7SPavan Nikhilesh } 621ef853f1fSNithin Dabilpuram /* Print link status if flag set */ 622ef853f1fSNithin Dabilpuram if (print_flag == 1) { 623ef853f1fSNithin Dabilpuram if (link.link_status) 624ef853f1fSNithin Dabilpuram printf("Port%d Link Up. Speed %u Mbps " 625ef853f1fSNithin Dabilpuram "-%s\n", 626ef853f1fSNithin Dabilpuram portid, link.link_speed, 627ef853f1fSNithin Dabilpuram (link.link_duplex == 628ef853f1fSNithin Dabilpuram ETH_LINK_FULL_DUPLEX) 629ef853f1fSNithin Dabilpuram ? ("full-duplex") 630ef853f1fSNithin Dabilpuram : ("half-duplex\n")); 631ef853f1fSNithin Dabilpuram else 632ef853f1fSNithin Dabilpuram printf("Port %d Link Down\n", portid); 633ef853f1fSNithin Dabilpuram continue; 634ef853f1fSNithin Dabilpuram } 635ef853f1fSNithin Dabilpuram /* Clear all_ports_up flag if any link down */ 636ef853f1fSNithin Dabilpuram if (link.link_status == ETH_LINK_DOWN) { 637ef853f1fSNithin Dabilpuram all_ports_up = 0; 638ef853f1fSNithin Dabilpuram break; 639ef853f1fSNithin Dabilpuram } 640ef853f1fSNithin Dabilpuram } 641ef853f1fSNithin Dabilpuram /* After finally printing all link status, get out */ 642ef853f1fSNithin Dabilpuram if (print_flag == 1) 643ef853f1fSNithin Dabilpuram break; 644ef853f1fSNithin Dabilpuram 645ef853f1fSNithin Dabilpuram if (all_ports_up == 0) { 646ef853f1fSNithin Dabilpuram printf("."); 647ef853f1fSNithin Dabilpuram fflush(stdout); 648ef853f1fSNithin Dabilpuram rte_delay_ms(CHECK_INTERVAL); 649ef853f1fSNithin Dabilpuram } 650ef853f1fSNithin Dabilpuram 651ef853f1fSNithin Dabilpuram /* Set the print_flag if all ports up or timeout */ 652ef853f1fSNithin Dabilpuram if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { 653ef853f1fSNithin Dabilpuram print_flag = 1; 654ef853f1fSNithin Dabilpuram printf("Done\n"); 655ef853f1fSNithin Dabilpuram } 656ef853f1fSNithin Dabilpuram } 657ef853f1fSNithin Dabilpuram } 658ef853f1fSNithin Dabilpuram 659ef853f1fSNithin Dabilpuram static void 66008bd1a17SNithin Dabilpuram signal_handler(int signum) 66108bd1a17SNithin Dabilpuram { 66208bd1a17SNithin Dabilpuram if (signum == SIGINT || signum == SIGTERM) { 66308bd1a17SNithin Dabilpuram printf("\n\nSignal %d received, preparing to exit...\n", 66408bd1a17SNithin Dabilpuram signum); 66508bd1a17SNithin Dabilpuram force_quit = true; 66608bd1a17SNithin Dabilpuram } 66708bd1a17SNithin Dabilpuram } 66808bd1a17SNithin Dabilpuram 6693087ec1cSNithin Dabilpuram static void 6703087ec1cSNithin Dabilpuram print_stats(void) 6713087ec1cSNithin Dabilpuram { 6723087ec1cSNithin Dabilpuram const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; 6733087ec1cSNithin Dabilpuram const char clr[] = {27, '[', '2', 'J', '\0'}; 6743087ec1cSNithin Dabilpuram struct rte_graph_cluster_stats_param s_param; 6753087ec1cSNithin Dabilpuram struct rte_graph_cluster_stats *stats; 6763087ec1cSNithin Dabilpuram const char *pattern = "worker_*"; 6773087ec1cSNithin Dabilpuram 6783087ec1cSNithin Dabilpuram /* Prepare stats object */ 6793087ec1cSNithin Dabilpuram memset(&s_param, 0, sizeof(s_param)); 6803087ec1cSNithin Dabilpuram s_param.f = stdout; 6813087ec1cSNithin Dabilpuram s_param.socket_id = SOCKET_ID_ANY; 6823087ec1cSNithin Dabilpuram s_param.graph_patterns = &pattern; 6833087ec1cSNithin Dabilpuram s_param.nb_graph_patterns = 1; 6843087ec1cSNithin Dabilpuram 6853087ec1cSNithin Dabilpuram stats = rte_graph_cluster_stats_create(&s_param); 6863087ec1cSNithin Dabilpuram if (stats == NULL) 6873087ec1cSNithin Dabilpuram rte_exit(EXIT_FAILURE, "Unable to create stats object\n"); 6883087ec1cSNithin Dabilpuram 6893087ec1cSNithin Dabilpuram while (!force_quit) { 6903087ec1cSNithin Dabilpuram /* Clear screen and move to top left */ 6913087ec1cSNithin Dabilpuram printf("%s%s", clr, topLeft); 6923087ec1cSNithin Dabilpuram rte_graph_cluster_stats_get(stats, 0); 6933087ec1cSNithin Dabilpuram rte_delay_ms(1E3); 6943087ec1cSNithin Dabilpuram } 6953087ec1cSNithin Dabilpuram 6963087ec1cSNithin Dabilpuram rte_graph_cluster_stats_destroy(stats); 6973087ec1cSNithin Dabilpuram } 6983087ec1cSNithin Dabilpuram 6993087ec1cSNithin Dabilpuram /* Main processing loop */ 7003087ec1cSNithin Dabilpuram static int 7013087ec1cSNithin Dabilpuram graph_main_loop(void *conf) 7023087ec1cSNithin Dabilpuram { 7033087ec1cSNithin Dabilpuram struct lcore_conf *qconf; 7043087ec1cSNithin Dabilpuram struct rte_graph *graph; 7053087ec1cSNithin Dabilpuram uint32_t lcore_id; 7063087ec1cSNithin Dabilpuram 7073087ec1cSNithin Dabilpuram RTE_SET_USED(conf); 7083087ec1cSNithin Dabilpuram 7093087ec1cSNithin Dabilpuram lcore_id = rte_lcore_id(); 7103087ec1cSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 7113087ec1cSNithin Dabilpuram graph = qconf->graph; 7123087ec1cSNithin Dabilpuram 7133087ec1cSNithin Dabilpuram if (!graph) { 7143087ec1cSNithin Dabilpuram RTE_LOG(INFO, L3FWD_GRAPH, "Lcore %u has nothing to do\n", 7153087ec1cSNithin Dabilpuram lcore_id); 7163087ec1cSNithin Dabilpuram return 0; 7173087ec1cSNithin Dabilpuram } 7183087ec1cSNithin Dabilpuram 7193087ec1cSNithin Dabilpuram RTE_LOG(INFO, L3FWD_GRAPH, 7203087ec1cSNithin Dabilpuram "Entering main loop on lcore %u, graph %s(%p)\n", lcore_id, 7213087ec1cSNithin Dabilpuram qconf->name, graph); 7223087ec1cSNithin Dabilpuram 7233087ec1cSNithin Dabilpuram while (likely(!force_quit)) 7243087ec1cSNithin Dabilpuram rte_graph_walk(graph); 7253087ec1cSNithin Dabilpuram 7263087ec1cSNithin Dabilpuram return 0; 7273087ec1cSNithin Dabilpuram } 7283087ec1cSNithin Dabilpuram 72908bd1a17SNithin Dabilpuram int 73008bd1a17SNithin Dabilpuram main(int argc, char **argv) 73108bd1a17SNithin Dabilpuram { 7323087ec1cSNithin Dabilpuram /* Rewrite data of src and dst ether addr */ 7333087ec1cSNithin Dabilpuram uint8_t rewrite_data[2 * sizeof(struct rte_ether_addr)]; 7343087ec1cSNithin Dabilpuram static const char * const default_patterns[] = { 7353087ec1cSNithin Dabilpuram "ip4*", 7363087ec1cSNithin Dabilpuram "ethdev_tx-*", 7373087ec1cSNithin Dabilpuram "pkt_drop", 7383087ec1cSNithin Dabilpuram }; 739ef853f1fSNithin Dabilpuram uint8_t nb_rx_queue, queue, socketid; 7403087ec1cSNithin Dabilpuram struct rte_graph_param graph_conf; 741ef853f1fSNithin Dabilpuram struct rte_eth_dev_info dev_info; 7423087ec1cSNithin Dabilpuram uint32_t nb_ports, nb_conf = 0; 743ef853f1fSNithin Dabilpuram uint32_t n_tx_queue, nb_lcores; 744ef853f1fSNithin Dabilpuram struct rte_eth_txconf *txconf; 7453087ec1cSNithin Dabilpuram uint16_t queueid, portid, i; 7463087ec1cSNithin Dabilpuram const char **node_patterns; 747ef853f1fSNithin Dabilpuram struct lcore_conf *qconf; 7483087ec1cSNithin Dabilpuram uint16_t nb_graphs = 0; 7493087ec1cSNithin Dabilpuram uint16_t nb_patterns; 7503087ec1cSNithin Dabilpuram uint8_t rewrite_len; 751ef853f1fSNithin Dabilpuram uint32_t lcore_id; 75208bd1a17SNithin Dabilpuram int ret; 75308bd1a17SNithin Dabilpuram 75408bd1a17SNithin Dabilpuram /* Init EAL */ 75508bd1a17SNithin Dabilpuram ret = rte_eal_init(argc, argv); 75608bd1a17SNithin Dabilpuram if (ret < 0) 75708bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid EAL parameters\n"); 75808bd1a17SNithin Dabilpuram argc -= ret; 75908bd1a17SNithin Dabilpuram argv += ret; 76008bd1a17SNithin Dabilpuram 76108bd1a17SNithin Dabilpuram force_quit = false; 76208bd1a17SNithin Dabilpuram signal(SIGINT, signal_handler); 76308bd1a17SNithin Dabilpuram signal(SIGTERM, signal_handler); 76408bd1a17SNithin Dabilpuram 76508bd1a17SNithin Dabilpuram /* Pre-init dst MACs for all ports to 02:00:00:00:00:xx */ 76608bd1a17SNithin Dabilpuram for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { 76708bd1a17SNithin Dabilpuram dest_eth_addr[portid] = 76808bd1a17SNithin Dabilpuram RTE_ETHER_LOCAL_ADMIN_ADDR + ((uint64_t)portid << 40); 76908bd1a17SNithin Dabilpuram *(uint64_t *)(val_eth + portid) = dest_eth_addr[portid]; 77008bd1a17SNithin Dabilpuram } 77108bd1a17SNithin Dabilpuram 77208bd1a17SNithin Dabilpuram /* Parse application arguments (after the EAL ones) */ 77308bd1a17SNithin Dabilpuram ret = parse_args(argc, argv); 77408bd1a17SNithin Dabilpuram if (ret < 0) 77508bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "Invalid L3FWD_GRAPH parameters\n"); 77608bd1a17SNithin Dabilpuram 77708bd1a17SNithin Dabilpuram if (check_lcore_params() < 0) 77808bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "check_lcore_params() failed\n"); 77908bd1a17SNithin Dabilpuram 78008bd1a17SNithin Dabilpuram ret = init_lcore_rx_queues(); 78108bd1a17SNithin Dabilpuram if (ret < 0) 78208bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "init_lcore_rx_queues() failed\n"); 78308bd1a17SNithin Dabilpuram 78408bd1a17SNithin Dabilpuram if (check_port_config() < 0) 78508bd1a17SNithin Dabilpuram rte_exit(EXIT_FAILURE, "check_port_config() failed\n"); 78608bd1a17SNithin Dabilpuram 787ef853f1fSNithin Dabilpuram nb_ports = rte_eth_dev_count_avail(); 788ef853f1fSNithin Dabilpuram nb_lcores = rte_lcore_count(); 789ef853f1fSNithin Dabilpuram 790ef853f1fSNithin Dabilpuram /* Initialize all ports */ 791ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) 792ef853f1fSNithin Dabilpuram { 793ef853f1fSNithin Dabilpuram struct rte_eth_conf local_port_conf = port_conf; 794ef853f1fSNithin Dabilpuram 795ef853f1fSNithin Dabilpuram /* Skip ports that are not enabled */ 796ef853f1fSNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) { 797ef853f1fSNithin Dabilpuram printf("\nSkipping disabled port %d\n", portid); 798ef853f1fSNithin Dabilpuram continue; 799ef853f1fSNithin Dabilpuram } 800ef853f1fSNithin Dabilpuram 801ef853f1fSNithin Dabilpuram /* Init port */ 802ef853f1fSNithin Dabilpuram printf("Initializing port %d ... ", portid); 803ef853f1fSNithin Dabilpuram fflush(stdout); 804ef853f1fSNithin Dabilpuram 805ef853f1fSNithin Dabilpuram nb_rx_queue = get_port_n_rx_queues(portid); 806ef853f1fSNithin Dabilpuram n_tx_queue = nb_lcores; 807ef853f1fSNithin Dabilpuram if (n_tx_queue > MAX_TX_QUEUE_PER_PORT) 808ef853f1fSNithin Dabilpuram n_tx_queue = MAX_TX_QUEUE_PER_PORT; 809ef853f1fSNithin Dabilpuram printf("Creating queues: nb_rxq=%d nb_txq=%u... ", 810ef853f1fSNithin Dabilpuram nb_rx_queue, n_tx_queue); 811ef853f1fSNithin Dabilpuram 812ef853f1fSNithin Dabilpuram rte_eth_dev_info_get(portid, &dev_info); 813ef853f1fSNithin Dabilpuram if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 814ef853f1fSNithin Dabilpuram local_port_conf.txmode.offloads |= 815ef853f1fSNithin Dabilpuram DEV_TX_OFFLOAD_MBUF_FAST_FREE; 816ef853f1fSNithin Dabilpuram 817ef853f1fSNithin Dabilpuram local_port_conf.rx_adv_conf.rss_conf.rss_hf &= 818ef853f1fSNithin Dabilpuram dev_info.flow_type_rss_offloads; 819ef853f1fSNithin Dabilpuram if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != 820ef853f1fSNithin Dabilpuram port_conf.rx_adv_conf.rss_conf.rss_hf) { 821ef853f1fSNithin Dabilpuram printf("Port %u modified RSS hash function based on " 822ef853f1fSNithin Dabilpuram "hardware support," 823ef853f1fSNithin Dabilpuram "requested:%#" PRIx64 " configured:%#" PRIx64 824ef853f1fSNithin Dabilpuram "\n", 825ef853f1fSNithin Dabilpuram portid, port_conf.rx_adv_conf.rss_conf.rss_hf, 826ef853f1fSNithin Dabilpuram local_port_conf.rx_adv_conf.rss_conf.rss_hf); 827ef853f1fSNithin Dabilpuram } 828ef853f1fSNithin Dabilpuram 829ef853f1fSNithin Dabilpuram ret = rte_eth_dev_configure(portid, nb_rx_queue, 830ef853f1fSNithin Dabilpuram n_tx_queue, &local_port_conf); 831ef853f1fSNithin Dabilpuram if (ret < 0) 832ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 833ef853f1fSNithin Dabilpuram "Cannot configure device: err=%d, port=%d\n", 834ef853f1fSNithin Dabilpuram ret, portid); 835ef853f1fSNithin Dabilpuram 836ef853f1fSNithin Dabilpuram ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, 837ef853f1fSNithin Dabilpuram &nb_txd); 838ef853f1fSNithin Dabilpuram if (ret < 0) 839ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 840ef853f1fSNithin Dabilpuram "Cannot adjust number of descriptors: err=%d, " 841ef853f1fSNithin Dabilpuram "port=%d\n", 842ef853f1fSNithin Dabilpuram ret, portid); 843ef853f1fSNithin Dabilpuram 844ef853f1fSNithin Dabilpuram rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); 845ef853f1fSNithin Dabilpuram print_ethaddr(" Address:", &ports_eth_addr[portid]); 846ef853f1fSNithin Dabilpuram printf(", "); 847ef853f1fSNithin Dabilpuram print_ethaddr( 848ef853f1fSNithin Dabilpuram "Destination:", 849ef853f1fSNithin Dabilpuram (const struct rte_ether_addr *)&dest_eth_addr[portid]); 850ef853f1fSNithin Dabilpuram printf(", "); 851ef853f1fSNithin Dabilpuram 852ef853f1fSNithin Dabilpuram /* 853ef853f1fSNithin Dabilpuram * prepare src MACs for each port. 854ef853f1fSNithin Dabilpuram */ 855ef853f1fSNithin Dabilpuram rte_ether_addr_copy( 856ef853f1fSNithin Dabilpuram &ports_eth_addr[portid], 857ef853f1fSNithin Dabilpuram (struct rte_ether_addr *)(val_eth + portid) + 1); 858ef853f1fSNithin Dabilpuram 859ef853f1fSNithin Dabilpuram /* Init memory */ 860ef853f1fSNithin Dabilpuram if (!per_port_pool) { 861ef853f1fSNithin Dabilpuram /* portid = 0; this is *not* signifying the first port, 862ef853f1fSNithin Dabilpuram * rather, it signifies that portid is ignored. 863ef853f1fSNithin Dabilpuram */ 864ef853f1fSNithin Dabilpuram ret = init_mem(0, NB_MBUF(nb_ports)); 865ef853f1fSNithin Dabilpuram } else { 866ef853f1fSNithin Dabilpuram ret = init_mem(portid, NB_MBUF(1)); 867ef853f1fSNithin Dabilpuram } 868ef853f1fSNithin Dabilpuram if (ret < 0) 869ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, "init_mem() failed\n"); 870ef853f1fSNithin Dabilpuram 871ef853f1fSNithin Dabilpuram /* Init one TX queue per couple (lcore,port) */ 872ef853f1fSNithin Dabilpuram queueid = 0; 873ef853f1fSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 874ef853f1fSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 875ef853f1fSNithin Dabilpuram continue; 876ef853f1fSNithin Dabilpuram 877ef853f1fSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 878ef853f1fSNithin Dabilpuram 879ef853f1fSNithin Dabilpuram if (numa_on) 880ef853f1fSNithin Dabilpuram socketid = (uint8_t)rte_lcore_to_socket_id( 881ef853f1fSNithin Dabilpuram lcore_id); 882ef853f1fSNithin Dabilpuram else 883ef853f1fSNithin Dabilpuram socketid = 0; 884ef853f1fSNithin Dabilpuram 885ef853f1fSNithin Dabilpuram printf("txq=%u,%d,%d ", lcore_id, queueid, socketid); 886ef853f1fSNithin Dabilpuram fflush(stdout); 887ef853f1fSNithin Dabilpuram 888ef853f1fSNithin Dabilpuram txconf = &dev_info.default_txconf; 889ef853f1fSNithin Dabilpuram txconf->offloads = local_port_conf.txmode.offloads; 890ef853f1fSNithin Dabilpuram ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, 891ef853f1fSNithin Dabilpuram socketid, txconf); 892ef853f1fSNithin Dabilpuram if (ret < 0) 893ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 894ef853f1fSNithin Dabilpuram "rte_eth_tx_queue_setup: err=%d, " 895ef853f1fSNithin Dabilpuram "port=%d\n", 896ef853f1fSNithin Dabilpuram ret, portid); 897ef853f1fSNithin Dabilpuram queueid++; 898ef853f1fSNithin Dabilpuram } 899ef853f1fSNithin Dabilpuram 9003087ec1cSNithin Dabilpuram /* Setup ethdev node config */ 9013087ec1cSNithin Dabilpuram ethdev_conf[nb_conf].port_id = portid; 9023087ec1cSNithin Dabilpuram ethdev_conf[nb_conf].num_rx_queues = nb_rx_queue; 9033087ec1cSNithin Dabilpuram ethdev_conf[nb_conf].num_tx_queues = n_tx_queue; 9043087ec1cSNithin Dabilpuram if (!per_port_pool) 9053087ec1cSNithin Dabilpuram ethdev_conf[nb_conf].mp = pktmbuf_pool[0]; 9063087ec1cSNithin Dabilpuram 9073087ec1cSNithin Dabilpuram else 9083087ec1cSNithin Dabilpuram ethdev_conf[nb_conf].mp = pktmbuf_pool[portid]; 9093087ec1cSNithin Dabilpuram ethdev_conf[nb_conf].mp_count = NB_SOCKETS; 9103087ec1cSNithin Dabilpuram 9113087ec1cSNithin Dabilpuram nb_conf++; 912ef853f1fSNithin Dabilpuram printf("\n"); 913ef853f1fSNithin Dabilpuram } 914ef853f1fSNithin Dabilpuram 915ef853f1fSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 916ef853f1fSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 917ef853f1fSNithin Dabilpuram continue; 918ef853f1fSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 919ef853f1fSNithin Dabilpuram printf("\nInitializing rx queues on lcore %u ... ", lcore_id); 920ef853f1fSNithin Dabilpuram fflush(stdout); 921ef853f1fSNithin Dabilpuram /* Init RX queues */ 922ef853f1fSNithin Dabilpuram for (queue = 0; queue < qconf->n_rx_queue; ++queue) { 923ef853f1fSNithin Dabilpuram struct rte_eth_rxconf rxq_conf; 924ef853f1fSNithin Dabilpuram 925ef853f1fSNithin Dabilpuram portid = qconf->rx_queue_list[queue].port_id; 926ef853f1fSNithin Dabilpuram queueid = qconf->rx_queue_list[queue].queue_id; 927ef853f1fSNithin Dabilpuram 928ef853f1fSNithin Dabilpuram if (numa_on) 929ef853f1fSNithin Dabilpuram socketid = (uint8_t)rte_lcore_to_socket_id( 930ef853f1fSNithin Dabilpuram lcore_id); 931ef853f1fSNithin Dabilpuram else 932ef853f1fSNithin Dabilpuram socketid = 0; 933ef853f1fSNithin Dabilpuram 934ef853f1fSNithin Dabilpuram printf("rxq=%d,%d,%d ", portid, queueid, socketid); 935ef853f1fSNithin Dabilpuram fflush(stdout); 936ef853f1fSNithin Dabilpuram 937ef853f1fSNithin Dabilpuram rte_eth_dev_info_get(portid, &dev_info); 938ef853f1fSNithin Dabilpuram rxq_conf = dev_info.default_rxconf; 939ef853f1fSNithin Dabilpuram rxq_conf.offloads = port_conf.rxmode.offloads; 940ef853f1fSNithin Dabilpuram if (!per_port_pool) 941ef853f1fSNithin Dabilpuram ret = rte_eth_rx_queue_setup( 942ef853f1fSNithin Dabilpuram portid, queueid, nb_rxd, socketid, 943ef853f1fSNithin Dabilpuram &rxq_conf, pktmbuf_pool[0][socketid]); 944ef853f1fSNithin Dabilpuram else 945ef853f1fSNithin Dabilpuram ret = rte_eth_rx_queue_setup( 946ef853f1fSNithin Dabilpuram portid, queueid, nb_rxd, socketid, 947ef853f1fSNithin Dabilpuram &rxq_conf, 948ef853f1fSNithin Dabilpuram pktmbuf_pool[portid][socketid]); 949ef853f1fSNithin Dabilpuram if (ret < 0) 950ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 951ef853f1fSNithin Dabilpuram "rte_eth_rx_queue_setup: err=%d, " 952ef853f1fSNithin Dabilpuram "port=%d\n", 953ef853f1fSNithin Dabilpuram ret, portid); 954ef853f1fSNithin Dabilpuram 9553087ec1cSNithin Dabilpuram /* Add this queue node to its graph */ 9563087ec1cSNithin Dabilpuram snprintf(qconf->rx_queue_list[queue].node_name, 9573087ec1cSNithin Dabilpuram RTE_NODE_NAMESIZE, "ethdev_rx-%u-%u", portid, 9583087ec1cSNithin Dabilpuram queueid); 959ef853f1fSNithin Dabilpuram } 9603087ec1cSNithin Dabilpuram 9613087ec1cSNithin Dabilpuram /* Alloc a graph to this lcore only if source exists */ 9623087ec1cSNithin Dabilpuram if (qconf->n_rx_queue) 9633087ec1cSNithin Dabilpuram nb_graphs++; 964ef853f1fSNithin Dabilpuram } 965ef853f1fSNithin Dabilpuram 966ef853f1fSNithin Dabilpuram printf("\n"); 967ef853f1fSNithin Dabilpuram 9683087ec1cSNithin Dabilpuram /* Ethdev node config, skip rx queue mapping */ 9693087ec1cSNithin Dabilpuram ret = rte_node_eth_config(ethdev_conf, nb_conf, nb_graphs); 9703087ec1cSNithin Dabilpuram if (ret) 9713087ec1cSNithin Dabilpuram rte_exit(EXIT_FAILURE, "rte_node_eth_config: err=%d\n", ret); 9723087ec1cSNithin Dabilpuram 973ef853f1fSNithin Dabilpuram /* Start ports */ 974ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) 975ef853f1fSNithin Dabilpuram { 976ef853f1fSNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) 977ef853f1fSNithin Dabilpuram continue; 978ef853f1fSNithin Dabilpuram 979ef853f1fSNithin Dabilpuram /* Start device */ 980ef853f1fSNithin Dabilpuram ret = rte_eth_dev_start(portid); 981ef853f1fSNithin Dabilpuram if (ret < 0) 982ef853f1fSNithin Dabilpuram rte_exit(EXIT_FAILURE, 983ef853f1fSNithin Dabilpuram "rte_eth_dev_start: err=%d, port=%d\n", ret, 984ef853f1fSNithin Dabilpuram portid); 985ef853f1fSNithin Dabilpuram 986ef853f1fSNithin Dabilpuram /* 987ef853f1fSNithin Dabilpuram * If enabled, put device in promiscuous mode. 988ef853f1fSNithin Dabilpuram * This allows IO forwarding mode to forward packets 989ef853f1fSNithin Dabilpuram * to itself through 2 cross-connected ports of the 990ef853f1fSNithin Dabilpuram * target machine. 991ef853f1fSNithin Dabilpuram */ 992ef853f1fSNithin Dabilpuram if (promiscuous_on) 993ef853f1fSNithin Dabilpuram rte_eth_promiscuous_enable(portid); 994ef853f1fSNithin Dabilpuram } 995ef853f1fSNithin Dabilpuram 996ef853f1fSNithin Dabilpuram printf("\n"); 997ef853f1fSNithin Dabilpuram 998ef853f1fSNithin Dabilpuram check_all_ports_link_status(enabled_port_mask); 999ef853f1fSNithin Dabilpuram 10003087ec1cSNithin Dabilpuram /* Graph Initialization */ 10013087ec1cSNithin Dabilpuram nb_patterns = RTE_DIM(default_patterns); 10023087ec1cSNithin Dabilpuram node_patterns = malloc((MAX_RX_QUEUE_PER_LCORE + nb_patterns) * 10033087ec1cSNithin Dabilpuram sizeof(*node_patterns)); 10043087ec1cSNithin Dabilpuram if (!node_patterns) 10053087ec1cSNithin Dabilpuram return -ENOMEM; 10063087ec1cSNithin Dabilpuram memcpy(node_patterns, default_patterns, 10073087ec1cSNithin Dabilpuram nb_patterns * sizeof(*node_patterns)); 10083087ec1cSNithin Dabilpuram 10093087ec1cSNithin Dabilpuram memset(&graph_conf, 0, sizeof(graph_conf)); 10103087ec1cSNithin Dabilpuram graph_conf.node_patterns = node_patterns; 10113087ec1cSNithin Dabilpuram 10123087ec1cSNithin Dabilpuram for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { 10133087ec1cSNithin Dabilpuram rte_graph_t graph_id; 10143087ec1cSNithin Dabilpuram rte_edge_t i; 10153087ec1cSNithin Dabilpuram 10163087ec1cSNithin Dabilpuram if (rte_lcore_is_enabled(lcore_id) == 0) 10173087ec1cSNithin Dabilpuram continue; 10183087ec1cSNithin Dabilpuram 10193087ec1cSNithin Dabilpuram qconf = &lcore_conf[lcore_id]; 10203087ec1cSNithin Dabilpuram 10213087ec1cSNithin Dabilpuram /* Skip graph creation if no source exists */ 10223087ec1cSNithin Dabilpuram if (!qconf->n_rx_queue) 10233087ec1cSNithin Dabilpuram continue; 10243087ec1cSNithin Dabilpuram 10253087ec1cSNithin Dabilpuram /* Add rx node patterns of this lcore */ 10263087ec1cSNithin Dabilpuram for (i = 0; i < qconf->n_rx_queue; i++) { 10273087ec1cSNithin Dabilpuram graph_conf.node_patterns[nb_patterns + i] = 10283087ec1cSNithin Dabilpuram qconf->rx_queue_list[i].node_name; 10293087ec1cSNithin Dabilpuram } 10303087ec1cSNithin Dabilpuram 10313087ec1cSNithin Dabilpuram graph_conf.nb_node_patterns = nb_patterns + i; 10323087ec1cSNithin Dabilpuram graph_conf.socket_id = rte_lcore_to_socket_id(lcore_id); 10333087ec1cSNithin Dabilpuram 10343087ec1cSNithin Dabilpuram snprintf(qconf->name, sizeof(qconf->name), "worker_%u", 10353087ec1cSNithin Dabilpuram lcore_id); 10363087ec1cSNithin Dabilpuram 10373087ec1cSNithin Dabilpuram graph_id = rte_graph_create(qconf->name, &graph_conf); 10383087ec1cSNithin Dabilpuram if (graph_id == RTE_GRAPH_ID_INVALID) 10393087ec1cSNithin Dabilpuram rte_exit(EXIT_FAILURE, 10403087ec1cSNithin Dabilpuram "rte_graph_create(): graph_id invalid" 10413087ec1cSNithin Dabilpuram " for lcore %u\n", lcore_id); 10423087ec1cSNithin Dabilpuram 10433087ec1cSNithin Dabilpuram qconf->graph_id = graph_id; 10443087ec1cSNithin Dabilpuram qconf->graph = rte_graph_lookup(qconf->name); 10453087ec1cSNithin Dabilpuram if (!qconf->graph) 10463087ec1cSNithin Dabilpuram rte_exit(EXIT_FAILURE, 10473087ec1cSNithin Dabilpuram "rte_graph_lookup(): graph %s not found\n", 10483087ec1cSNithin Dabilpuram qconf->name); 10493087ec1cSNithin Dabilpuram } 10503087ec1cSNithin Dabilpuram 10513087ec1cSNithin Dabilpuram memset(&rewrite_data, 0, sizeof(rewrite_data)); 10523087ec1cSNithin Dabilpuram rewrite_len = sizeof(rewrite_data); 10533087ec1cSNithin Dabilpuram 10543087ec1cSNithin Dabilpuram /* Add route to ip4 graph infra */ 10553087ec1cSNithin Dabilpuram for (i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) { 10563087ec1cSNithin Dabilpuram char route_str[INET6_ADDRSTRLEN * 4]; 10573087ec1cSNithin Dabilpuram char abuf[INET6_ADDRSTRLEN]; 10583087ec1cSNithin Dabilpuram struct in_addr in; 10593087ec1cSNithin Dabilpuram uint32_t dst_port; 10603087ec1cSNithin Dabilpuram 10613087ec1cSNithin Dabilpuram /* Skip unused ports */ 10623087ec1cSNithin Dabilpuram if ((1 << ipv4_l3fwd_lpm_route_array[i].if_out & 10633087ec1cSNithin Dabilpuram enabled_port_mask) == 0) 10643087ec1cSNithin Dabilpuram continue; 10653087ec1cSNithin Dabilpuram 10663087ec1cSNithin Dabilpuram dst_port = ipv4_l3fwd_lpm_route_array[i].if_out; 10673087ec1cSNithin Dabilpuram 10683087ec1cSNithin Dabilpuram in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip); 10693087ec1cSNithin Dabilpuram snprintf(route_str, sizeof(route_str), "%s / %d (%d)", 10703087ec1cSNithin Dabilpuram inet_ntop(AF_INET, &in, abuf, sizeof(abuf)), 10713087ec1cSNithin Dabilpuram ipv4_l3fwd_lpm_route_array[i].depth, 10723087ec1cSNithin Dabilpuram ipv4_l3fwd_lpm_route_array[i].if_out); 10733087ec1cSNithin Dabilpuram 10743087ec1cSNithin Dabilpuram /* Use route index 'i' as next hop id */ 10753087ec1cSNithin Dabilpuram ret = rte_node_ip4_route_add( 10763087ec1cSNithin Dabilpuram ipv4_l3fwd_lpm_route_array[i].ip, 10773087ec1cSNithin Dabilpuram ipv4_l3fwd_lpm_route_array[i].depth, i, 10783087ec1cSNithin Dabilpuram RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); 10793087ec1cSNithin Dabilpuram 10803087ec1cSNithin Dabilpuram if (ret < 0) 10813087ec1cSNithin Dabilpuram rte_exit(EXIT_FAILURE, 10823087ec1cSNithin Dabilpuram "Unable to add ip4 route %s to graph\n", 10833087ec1cSNithin Dabilpuram route_str); 10843087ec1cSNithin Dabilpuram 10853087ec1cSNithin Dabilpuram memcpy(rewrite_data, val_eth + dst_port, rewrite_len); 10863087ec1cSNithin Dabilpuram 10873087ec1cSNithin Dabilpuram /* Add next hop rewrite data for id 'i' */ 10883087ec1cSNithin Dabilpuram ret = rte_node_ip4_rewrite_add(i, rewrite_data, 10893087ec1cSNithin Dabilpuram rewrite_len, dst_port); 10903087ec1cSNithin Dabilpuram if (ret < 0) 10913087ec1cSNithin Dabilpuram rte_exit(EXIT_FAILURE, 10923087ec1cSNithin Dabilpuram "Unable to add next hop %u for " 10933087ec1cSNithin Dabilpuram "route %s\n", i, route_str); 10943087ec1cSNithin Dabilpuram 10953087ec1cSNithin Dabilpuram RTE_LOG(INFO, L3FWD_GRAPH, "Added route %s, next_hop %u\n", 10963087ec1cSNithin Dabilpuram route_str, i); 10973087ec1cSNithin Dabilpuram } 10983087ec1cSNithin Dabilpuram 10993087ec1cSNithin Dabilpuram /* Launch per-lcore init on every slave lcore */ 11003087ec1cSNithin Dabilpuram rte_eal_mp_remote_launch(graph_main_loop, NULL, SKIP_MASTER); 11013087ec1cSNithin Dabilpuram 11023087ec1cSNithin Dabilpuram /* Accumulate and print stats on master until exit */ 11033087ec1cSNithin Dabilpuram if (rte_graph_has_stats_feature()) 11043087ec1cSNithin Dabilpuram print_stats(); 11053087ec1cSNithin Dabilpuram 11063087ec1cSNithin Dabilpuram /* Wait for slave cores to exit */ 11073087ec1cSNithin Dabilpuram ret = 0; 11083087ec1cSNithin Dabilpuram RTE_LCORE_FOREACH_SLAVE(lcore_id) { 11093087ec1cSNithin Dabilpuram ret = rte_eal_wait_lcore(lcore_id); 11103087ec1cSNithin Dabilpuram /* Destroy graph */ 11113087ec1cSNithin Dabilpuram if (ret < 0 || rte_graph_destroy( 11123087ec1cSNithin Dabilpuram rte_graph_from_name(lcore_conf[lcore_id].name))) { 11133087ec1cSNithin Dabilpuram ret = -1; 11143087ec1cSNithin Dabilpuram break; 11153087ec1cSNithin Dabilpuram } 11163087ec1cSNithin Dabilpuram } 11173087ec1cSNithin Dabilpuram free(node_patterns); 11183087ec1cSNithin Dabilpuram 1119ef853f1fSNithin Dabilpuram /* Stop ports */ 1120ef853f1fSNithin Dabilpuram RTE_ETH_FOREACH_DEV(portid) { 1121ef853f1fSNithin Dabilpuram if ((enabled_port_mask & (1 << portid)) == 0) 1122ef853f1fSNithin Dabilpuram continue; 1123ef853f1fSNithin Dabilpuram printf("Closing port %d...", portid); 1124ef853f1fSNithin Dabilpuram rte_eth_dev_stop(portid); 1125ef853f1fSNithin Dabilpuram rte_eth_dev_close(portid); 1126ef853f1fSNithin Dabilpuram printf(" Done\n"); 1127ef853f1fSNithin Dabilpuram } 112808bd1a17SNithin Dabilpuram printf("Bye...\n"); 112908bd1a17SNithin Dabilpuram 113008bd1a17SNithin Dabilpuram return ret; 113108bd1a17SNithin Dabilpuram } 1132