13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 23998e2a0SBruce Richardson * Copyright(c) 2010-2016 Intel Corporation 3850f3733SSergio Gonzalez Monroy */ 4850f3733SSergio Gonzalez Monroy 5850f3733SSergio Gonzalez Monroy #include <signal.h> 6850f3733SSergio Gonzalez Monroy #include <getopt.h> 7850f3733SSergio Gonzalez Monroy 8850f3733SSergio Gonzalez Monroy #include <rte_eal.h> 9850f3733SSergio Gonzalez Monroy #include <rte_common.h> 10850f3733SSergio Gonzalez Monroy #include <rte_errno.h> 11850f3733SSergio Gonzalez Monroy #include <rte_ethdev.h> 12850f3733SSergio Gonzalez Monroy #include <rte_lcore.h> 13e2366e74STomasz Kulasek #include <rte_malloc.h> 14850f3733SSergio Gonzalez Monroy #include <rte_mbuf.h> 15850f3733SSergio Gonzalez Monroy #include <rte_mempool.h> 16850f3733SSergio Gonzalez Monroy #include <rte_ring.h> 17850f3733SSergio Gonzalez Monroy #include <rte_reorder.h> 18850f3733SSergio Gonzalez Monroy 19867a6c66SKevin Laatz #define RX_DESC_PER_QUEUE 1024 20867a6c66SKevin Laatz #define TX_DESC_PER_QUEUE 1024 21850f3733SSergio Gonzalez Monroy 22850f3733SSergio Gonzalez Monroy #define MAX_PKTS_BURST 32 23850f3733SSergio Gonzalez Monroy #define REORDER_BUFFER_SIZE 8192 24850f3733SSergio Gonzalez Monroy #define MBUF_PER_POOL 65535 25850f3733SSergio Gonzalez Monroy #define MBUF_POOL_CACHE_SIZE 250 26850f3733SSergio Gonzalez Monroy 27850f3733SSergio Gonzalez Monroy #define RING_SIZE 16384 28850f3733SSergio Gonzalez Monroy 29850f3733SSergio Gonzalez Monroy /* Macros for printing using RTE_LOG */ 30850f3733SSergio Gonzalez Monroy #define RTE_LOGTYPE_REORDERAPP RTE_LOGTYPE_USER1 31850f3733SSergio Gonzalez Monroy 32850f3733SSergio Gonzalez Monroy unsigned int portmask; 33850f3733SSergio Gonzalez Monroy unsigned int disable_reorder; 3401649330SPhil Yang unsigned int insight_worker; 35850f3733SSergio Gonzalez Monroy volatile uint8_t quit_signal; 36850f3733SSergio Gonzalez Monroy 37850f3733SSergio Gonzalez Monroy static struct rte_mempool *mbuf_pool; 38850f3733SSergio Gonzalez Monroy 39ab3ce1e0SFerruh Yigit static struct rte_eth_conf port_conf_default; 40850f3733SSergio Gonzalez Monroy 41850f3733SSergio Gonzalez Monroy struct worker_thread_args { 42850f3733SSergio Gonzalez Monroy struct rte_ring *ring_in; 43850f3733SSergio Gonzalez Monroy struct rte_ring *ring_out; 44850f3733SSergio Gonzalez Monroy }; 45850f3733SSergio Gonzalez Monroy 466ebc23d8SSergio Gonzalez Monroy struct send_thread_args { 476ebc23d8SSergio Gonzalez Monroy struct rte_ring *ring_in; 486ebc23d8SSergio Gonzalez Monroy struct rte_reorder_buffer *buffer; 496ebc23d8SSergio Gonzalez Monroy }; 506ebc23d8SSergio Gonzalez Monroy 51850f3733SSergio Gonzalez Monroy volatile struct app_stats { 52850f3733SSergio Gonzalez Monroy struct { 53850f3733SSergio Gonzalez Monroy uint64_t rx_pkts; 54850f3733SSergio Gonzalez Monroy uint64_t enqueue_pkts; 55850f3733SSergio Gonzalez Monroy uint64_t enqueue_failed_pkts; 56850f3733SSergio Gonzalez Monroy } rx __rte_cache_aligned; 57850f3733SSergio Gonzalez Monroy 58850f3733SSergio Gonzalez Monroy struct { 59850f3733SSergio Gonzalez Monroy uint64_t dequeue_pkts; 60850f3733SSergio Gonzalez Monroy uint64_t enqueue_pkts; 61850f3733SSergio Gonzalez Monroy uint64_t enqueue_failed_pkts; 62850f3733SSergio Gonzalez Monroy } wkr __rte_cache_aligned; 63850f3733SSergio Gonzalez Monroy 64850f3733SSergio Gonzalez Monroy struct { 65850f3733SSergio Gonzalez Monroy uint64_t dequeue_pkts; 66850f3733SSergio Gonzalez Monroy /* Too early pkts transmitted directly w/o reordering */ 67850f3733SSergio Gonzalez Monroy uint64_t early_pkts_txtd_woro; 68850f3733SSergio Gonzalez Monroy /* Too early pkts failed from direct transmit */ 69850f3733SSergio Gonzalez Monroy uint64_t early_pkts_tx_failed_woro; 70850f3733SSergio Gonzalez Monroy uint64_t ro_tx_pkts; 71850f3733SSergio Gonzalez Monroy uint64_t ro_tx_failed_pkts; 72850f3733SSergio Gonzalez Monroy } tx __rte_cache_aligned; 73850f3733SSergio Gonzalez Monroy } app_stats; 74850f3733SSergio Gonzalez Monroy 7501649330SPhil Yang /* per worker lcore stats */ 7601649330SPhil Yang struct wkr_stats_per { 7701649330SPhil Yang uint64_t deq_pkts; 7801649330SPhil Yang uint64_t enq_pkts; 7901649330SPhil Yang uint64_t enq_failed_pkts; 8001649330SPhil Yang } __rte_cache_aligned; 8101649330SPhil Yang 8201649330SPhil Yang static struct wkr_stats_per wkr_stats[RTE_MAX_LCORE] = { {0} }; 83850f3733SSergio Gonzalez Monroy /** 84850f3733SSergio Gonzalez Monroy * Get the last enabled lcore ID 85850f3733SSergio Gonzalez Monroy * 86850f3733SSergio Gonzalez Monroy * @return 87850f3733SSergio Gonzalez Monroy * The last enabled lcore ID. 88850f3733SSergio Gonzalez Monroy */ 89850f3733SSergio Gonzalez Monroy static unsigned int 90850f3733SSergio Gonzalez Monroy get_last_lcore_id(void) 91850f3733SSergio Gonzalez Monroy { 92850f3733SSergio Gonzalez Monroy int i; 93850f3733SSergio Gonzalez Monroy 94850f3733SSergio Gonzalez Monroy for (i = RTE_MAX_LCORE - 1; i >= 0; i--) 95850f3733SSergio Gonzalez Monroy if (rte_lcore_is_enabled(i)) 96850f3733SSergio Gonzalez Monroy return i; 97850f3733SSergio Gonzalez Monroy return 0; 98850f3733SSergio Gonzalez Monroy } 99850f3733SSergio Gonzalez Monroy 100850f3733SSergio Gonzalez Monroy /** 101850f3733SSergio Gonzalez Monroy * Get the previous enabled lcore ID 102850f3733SSergio Gonzalez Monroy * @param id 103850f3733SSergio Gonzalez Monroy * The current lcore ID 104850f3733SSergio Gonzalez Monroy * @return 105850f3733SSergio Gonzalez Monroy * The previous enabled lcore ID or the current lcore 106850f3733SSergio Gonzalez Monroy * ID if it is the first available core. 107850f3733SSergio Gonzalez Monroy */ 108850f3733SSergio Gonzalez Monroy static unsigned int 109850f3733SSergio Gonzalez Monroy get_previous_lcore_id(unsigned int id) 110850f3733SSergio Gonzalez Monroy { 111850f3733SSergio Gonzalez Monroy int i; 112850f3733SSergio Gonzalez Monroy 113850f3733SSergio Gonzalez Monroy for (i = id - 1; i >= 0; i--) 114850f3733SSergio Gonzalez Monroy if (rte_lcore_is_enabled(i)) 115850f3733SSergio Gonzalez Monroy return i; 116850f3733SSergio Gonzalez Monroy return id; 117850f3733SSergio Gonzalez Monroy } 118850f3733SSergio Gonzalez Monroy 119850f3733SSergio Gonzalez Monroy static inline void 120850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(struct rte_mbuf *mbuf_table[], unsigned n) 121850f3733SSergio Gonzalez Monroy { 122850f3733SSergio Gonzalez Monroy unsigned int i; 123850f3733SSergio Gonzalez Monroy 124850f3733SSergio Gonzalez Monroy for (i = 0; i < n; i++) 125850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbuf_table[i]); 126850f3733SSergio Gonzalez Monroy } 127850f3733SSergio Gonzalez Monroy 128850f3733SSergio Gonzalez Monroy /* display usage */ 129850f3733SSergio Gonzalez Monroy static void 130850f3733SSergio Gonzalez Monroy print_usage(const char *prgname) 131850f3733SSergio Gonzalez Monroy { 132850f3733SSergio Gonzalez Monroy printf("%s [EAL options] -- -p PORTMASK\n" 133850f3733SSergio Gonzalez Monroy " -p PORTMASK: hexadecimal bitmask of ports to configure\n", 134850f3733SSergio Gonzalez Monroy prgname); 135850f3733SSergio Gonzalez Monroy } 136850f3733SSergio Gonzalez Monroy 137850f3733SSergio Gonzalez Monroy static int 138850f3733SSergio Gonzalez Monroy parse_portmask(const char *portmask) 139850f3733SSergio Gonzalez Monroy { 140850f3733SSergio Gonzalez Monroy unsigned long pm; 141850f3733SSergio Gonzalez Monroy char *end = NULL; 142850f3733SSergio Gonzalez Monroy 143850f3733SSergio Gonzalez Monroy /* parse hexadecimal string */ 144850f3733SSergio Gonzalez Monroy pm = strtoul(portmask, &end, 16); 145850f3733SSergio Gonzalez Monroy if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 146850f3733SSergio Gonzalez Monroy return -1; 147850f3733SSergio Gonzalez Monroy 148850f3733SSergio Gonzalez Monroy if (pm == 0) 149850f3733SSergio Gonzalez Monroy return -1; 150850f3733SSergio Gonzalez Monroy 151850f3733SSergio Gonzalez Monroy return pm; 152850f3733SSergio Gonzalez Monroy } 153850f3733SSergio Gonzalez Monroy 154850f3733SSergio Gonzalez Monroy /* Parse the argument given in the command line of the application */ 155850f3733SSergio Gonzalez Monroy static int 156850f3733SSergio Gonzalez Monroy parse_args(int argc, char **argv) 157850f3733SSergio Gonzalez Monroy { 158850f3733SSergio Gonzalez Monroy int opt; 159850f3733SSergio Gonzalez Monroy int option_index; 160850f3733SSergio Gonzalez Monroy char **argvopt; 161850f3733SSergio Gonzalez Monroy char *prgname = argv[0]; 162850f3733SSergio Gonzalez Monroy static struct option lgopts[] = { 163850f3733SSergio Gonzalez Monroy {"disable-reorder", 0, 0, 0}, 16401649330SPhil Yang {"insight-worker", 0, 0, 0}, 165850f3733SSergio Gonzalez Monroy {NULL, 0, 0, 0} 166850f3733SSergio Gonzalez Monroy }; 167850f3733SSergio Gonzalez Monroy 168850f3733SSergio Gonzalez Monroy argvopt = argv; 169850f3733SSergio Gonzalez Monroy 170850f3733SSergio Gonzalez Monroy while ((opt = getopt_long(argc, argvopt, "p:", 171850f3733SSergio Gonzalez Monroy lgopts, &option_index)) != EOF) { 172850f3733SSergio Gonzalez Monroy switch (opt) { 173850f3733SSergio Gonzalez Monroy /* portmask */ 174850f3733SSergio Gonzalez Monroy case 'p': 175850f3733SSergio Gonzalez Monroy portmask = parse_portmask(optarg); 176850f3733SSergio Gonzalez Monroy if (portmask == 0) { 177850f3733SSergio Gonzalez Monroy printf("invalid portmask\n"); 178850f3733SSergio Gonzalez Monroy print_usage(prgname); 179850f3733SSergio Gonzalez Monroy return -1; 180850f3733SSergio Gonzalez Monroy } 181850f3733SSergio Gonzalez Monroy break; 182850f3733SSergio Gonzalez Monroy /* long options */ 183850f3733SSergio Gonzalez Monroy case 0: 184850f3733SSergio Gonzalez Monroy if (!strcmp(lgopts[option_index].name, "disable-reorder")) { 185850f3733SSergio Gonzalez Monroy printf("reorder disabled\n"); 186850f3733SSergio Gonzalez Monroy disable_reorder = 1; 187850f3733SSergio Gonzalez Monroy } 18801649330SPhil Yang if (!strcmp(lgopts[option_index].name, 18901649330SPhil Yang "insight-worker")) { 19001649330SPhil Yang printf("print all worker statistics\n"); 19101649330SPhil Yang insight_worker = 1; 19201649330SPhil Yang } 193850f3733SSergio Gonzalez Monroy break; 194850f3733SSergio Gonzalez Monroy default: 195850f3733SSergio Gonzalez Monroy print_usage(prgname); 196850f3733SSergio Gonzalez Monroy return -1; 197850f3733SSergio Gonzalez Monroy } 198850f3733SSergio Gonzalez Monroy } 199850f3733SSergio Gonzalez Monroy if (optind <= 1) { 200850f3733SSergio Gonzalez Monroy print_usage(prgname); 201850f3733SSergio Gonzalez Monroy return -1; 202850f3733SSergio Gonzalez Monroy } 203850f3733SSergio Gonzalez Monroy 204850f3733SSergio Gonzalez Monroy argv[optind-1] = prgname; 2059d5ca532SKeith Wiles optind = 1; /* reset getopt lib */ 206850f3733SSergio Gonzalez Monroy return 0; 207850f3733SSergio Gonzalez Monroy } 208850f3733SSergio Gonzalez Monroy 209e2366e74STomasz Kulasek /* 210e2366e74STomasz Kulasek * Tx buffer error callback 211e2366e74STomasz Kulasek */ 212e2366e74STomasz Kulasek static void 213e2366e74STomasz Kulasek flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count, 214e2366e74STomasz Kulasek void *userdata __rte_unused) { 215e2366e74STomasz Kulasek 216e2366e74STomasz Kulasek /* free the mbufs which failed from transmit */ 217e2366e74STomasz Kulasek app_stats.tx.ro_tx_failed_pkts += count; 2185d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, "%s:Packet loss with tx_burst\n", __func__); 219e2366e74STomasz Kulasek pktmbuf_free_bulk(unsent, count); 220e2366e74STomasz Kulasek 221e2366e74STomasz Kulasek } 222e2366e74STomasz Kulasek 223e2366e74STomasz Kulasek static inline int 224e2366e74STomasz Kulasek free_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) { 2258728ccf3SThomas Monjalon uint16_t port_id; 226e2366e74STomasz Kulasek 227e2366e74STomasz Kulasek /* initialize buffers for all ports */ 2288728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 229e2366e74STomasz Kulasek /* skip ports that are not enabled */ 230e2366e74STomasz Kulasek if ((portmask & (1 << port_id)) == 0) 231e2366e74STomasz Kulasek continue; 232e2366e74STomasz Kulasek 233e2366e74STomasz Kulasek rte_free(tx_buffer[port_id]); 234e2366e74STomasz Kulasek } 235e2366e74STomasz Kulasek return 0; 236e2366e74STomasz Kulasek } 237e2366e74STomasz Kulasek 238e2366e74STomasz Kulasek static inline int 239e2366e74STomasz Kulasek configure_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) 240e2366e74STomasz Kulasek { 2418728ccf3SThomas Monjalon uint16_t port_id; 242e2366e74STomasz Kulasek int ret; 243e2366e74STomasz Kulasek 244e2366e74STomasz Kulasek /* initialize buffers for all ports */ 2458728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 246e2366e74STomasz Kulasek /* skip ports that are not enabled */ 247e2366e74STomasz Kulasek if ((portmask & (1 << port_id)) == 0) 248e2366e74STomasz Kulasek continue; 249e2366e74STomasz Kulasek 250e2366e74STomasz Kulasek /* Initialize TX buffers */ 251e2366e74STomasz Kulasek tx_buffer[port_id] = rte_zmalloc_socket("tx_buffer", 252e2366e74STomasz Kulasek RTE_ETH_TX_BUFFER_SIZE(MAX_PKTS_BURST), 0, 253e2366e74STomasz Kulasek rte_eth_dev_socket_id(port_id)); 254e2366e74STomasz Kulasek if (tx_buffer[port_id] == NULL) 255e2366e74STomasz Kulasek rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", 256f8244c63SZhiyong Yang port_id); 257e2366e74STomasz Kulasek 258e2366e74STomasz Kulasek rte_eth_tx_buffer_init(tx_buffer[port_id], MAX_PKTS_BURST); 259e2366e74STomasz Kulasek 260e2366e74STomasz Kulasek ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[port_id], 261e2366e74STomasz Kulasek flush_tx_error_callback, NULL); 262e2366e74STomasz Kulasek if (ret < 0) 263f8244c63SZhiyong Yang rte_exit(EXIT_FAILURE, 264f8244c63SZhiyong Yang "Cannot set error callback for tx buffer on port %u\n", 265f8244c63SZhiyong Yang port_id); 266e2366e74STomasz Kulasek } 267e2366e74STomasz Kulasek return 0; 268e2366e74STomasz Kulasek } 269e2366e74STomasz Kulasek 270850f3733SSergio Gonzalez Monroy static inline int 271f8244c63SZhiyong Yang configure_eth_port(uint16_t port_id) 272850f3733SSergio Gonzalez Monroy { 2736d13ea8eSOlivier Matz struct rte_ether_addr addr; 274850f3733SSergio Gonzalez Monroy const uint16_t rxRings = 1, txRings = 1; 275850f3733SSergio Gonzalez Monroy int ret; 276850f3733SSergio Gonzalez Monroy uint16_t q; 27760efb44fSRoman Zhukov uint16_t nb_rxd = RX_DESC_PER_QUEUE; 27860efb44fSRoman Zhukov uint16_t nb_txd = TX_DESC_PER_QUEUE; 2796833f919SShahaf Shuler struct rte_eth_dev_info dev_info; 2806833f919SShahaf Shuler struct rte_eth_txconf txconf; 2816833f919SShahaf Shuler struct rte_eth_conf port_conf = port_conf_default; 282850f3733SSergio Gonzalez Monroy 283a9dbe180SThomas Monjalon if (!rte_eth_dev_is_valid_port(port_id)) 284850f3733SSergio Gonzalez Monroy return -1; 285850f3733SSergio Gonzalez Monroy 286089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(port_id, &dev_info); 287089e5ed7SIvan Ilchenko if (ret != 0) { 288089e5ed7SIvan Ilchenko printf("Error during getting device (port %u) info: %s\n", 289089e5ed7SIvan Ilchenko port_id, strerror(-ret)); 290089e5ed7SIvan Ilchenko return ret; 291089e5ed7SIvan Ilchenko } 292089e5ed7SIvan Ilchenko 2936833f919SShahaf Shuler if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 2946833f919SShahaf Shuler port_conf.txmode.offloads |= 2956833f919SShahaf Shuler DEV_TX_OFFLOAD_MBUF_FAST_FREE; 296850f3733SSergio Gonzalez Monroy ret = rte_eth_dev_configure(port_id, rxRings, txRings, &port_conf_default); 297850f3733SSergio Gonzalez Monroy if (ret != 0) 298850f3733SSergio Gonzalez Monroy return ret; 299850f3733SSergio Gonzalez Monroy 30060efb44fSRoman Zhukov ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd); 30160efb44fSRoman Zhukov if (ret != 0) 30260efb44fSRoman Zhukov return ret; 30360efb44fSRoman Zhukov 304850f3733SSergio Gonzalez Monroy for (q = 0; q < rxRings; q++) { 30560efb44fSRoman Zhukov ret = rte_eth_rx_queue_setup(port_id, q, nb_rxd, 306850f3733SSergio Gonzalez Monroy rte_eth_dev_socket_id(port_id), NULL, 307850f3733SSergio Gonzalez Monroy mbuf_pool); 308850f3733SSergio Gonzalez Monroy if (ret < 0) 309850f3733SSergio Gonzalez Monroy return ret; 310850f3733SSergio Gonzalez Monroy } 311850f3733SSergio Gonzalez Monroy 3126833f919SShahaf Shuler txconf = dev_info.default_txconf; 3136833f919SShahaf Shuler txconf.offloads = port_conf.txmode.offloads; 314850f3733SSergio Gonzalez Monroy for (q = 0; q < txRings; q++) { 31560efb44fSRoman Zhukov ret = rte_eth_tx_queue_setup(port_id, q, nb_txd, 3166833f919SShahaf Shuler rte_eth_dev_socket_id(port_id), &txconf); 317850f3733SSergio Gonzalez Monroy if (ret < 0) 318850f3733SSergio Gonzalez Monroy return ret; 319850f3733SSergio Gonzalez Monroy } 320850f3733SSergio Gonzalez Monroy 321850f3733SSergio Gonzalez Monroy ret = rte_eth_dev_start(port_id); 322850f3733SSergio Gonzalez Monroy if (ret < 0) 323850f3733SSergio Gonzalez Monroy return ret; 324850f3733SSergio Gonzalez Monroy 325850f3733SSergio Gonzalez Monroy rte_eth_macaddr_get(port_id, &addr); 326850f3733SSergio Gonzalez Monroy printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 327850f3733SSergio Gonzalez Monroy " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", 328f8244c63SZhiyong Yang port_id, 329850f3733SSergio Gonzalez Monroy addr.addr_bytes[0], addr.addr_bytes[1], 330850f3733SSergio Gonzalez Monroy addr.addr_bytes[2], addr.addr_bytes[3], 331850f3733SSergio Gonzalez Monroy addr.addr_bytes[4], addr.addr_bytes[5]); 332850f3733SSergio Gonzalez Monroy 333*f430bbceSIvan Ilchenko ret = rte_eth_promiscuous_enable(port_id); 334*f430bbceSIvan Ilchenko if (ret != 0) 335*f430bbceSIvan Ilchenko return ret; 336850f3733SSergio Gonzalez Monroy 337850f3733SSergio Gonzalez Monroy return 0; 338850f3733SSergio Gonzalez Monroy } 339850f3733SSergio Gonzalez Monroy 340850f3733SSergio Gonzalez Monroy static void 341850f3733SSergio Gonzalez Monroy print_stats(void) 342850f3733SSergio Gonzalez Monroy { 3438728ccf3SThomas Monjalon uint16_t i; 344850f3733SSergio Gonzalez Monroy struct rte_eth_stats eth_stats; 34501649330SPhil Yang unsigned int lcore_id, last_lcore_id, master_lcore_id, end_w_lcore_id; 34601649330SPhil Yang 34701649330SPhil Yang last_lcore_id = get_last_lcore_id(); 34801649330SPhil Yang master_lcore_id = rte_get_master_lcore(); 34901649330SPhil Yang end_w_lcore_id = get_previous_lcore_id(last_lcore_id); 350850f3733SSergio Gonzalez Monroy 351850f3733SSergio Gonzalez Monroy printf("\nRX thread stats:\n"); 352850f3733SSergio Gonzalez Monroy printf(" - Pkts rxd: %"PRIu64"\n", 353850f3733SSergio Gonzalez Monroy app_stats.rx.rx_pkts); 354850f3733SSergio Gonzalez Monroy printf(" - Pkts enqd to workers ring: %"PRIu64"\n", 355850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_pkts); 356850f3733SSergio Gonzalez Monroy 35701649330SPhil Yang for (lcore_id = 0; lcore_id <= end_w_lcore_id; lcore_id++) { 35801649330SPhil Yang if (insight_worker 35901649330SPhil Yang && rte_lcore_is_enabled(lcore_id) 36001649330SPhil Yang && lcore_id != master_lcore_id) { 36101649330SPhil Yang printf("\nWorker thread stats on core [%u]:\n", 36201649330SPhil Yang lcore_id); 36301649330SPhil Yang printf(" - Pkts deqd from workers ring: %"PRIu64"\n", 36401649330SPhil Yang wkr_stats[lcore_id].deq_pkts); 36501649330SPhil Yang printf(" - Pkts enqd to tx ring: %"PRIu64"\n", 36601649330SPhil Yang wkr_stats[lcore_id].enq_pkts); 36701649330SPhil Yang printf(" - Pkts enq to tx failed: %"PRIu64"\n", 36801649330SPhil Yang wkr_stats[lcore_id].enq_failed_pkts); 36901649330SPhil Yang } 37001649330SPhil Yang 37101649330SPhil Yang app_stats.wkr.dequeue_pkts += wkr_stats[lcore_id].deq_pkts; 37201649330SPhil Yang app_stats.wkr.enqueue_pkts += wkr_stats[lcore_id].enq_pkts; 37301649330SPhil Yang app_stats.wkr.enqueue_failed_pkts += 37401649330SPhil Yang wkr_stats[lcore_id].enq_failed_pkts; 37501649330SPhil Yang } 37601649330SPhil Yang 377850f3733SSergio Gonzalez Monroy printf("\nWorker thread stats:\n"); 378850f3733SSergio Gonzalez Monroy printf(" - Pkts deqd from workers ring: %"PRIu64"\n", 379850f3733SSergio Gonzalez Monroy app_stats.wkr.dequeue_pkts); 380850f3733SSergio Gonzalez Monroy printf(" - Pkts enqd to tx ring: %"PRIu64"\n", 381850f3733SSergio Gonzalez Monroy app_stats.wkr.enqueue_pkts); 382850f3733SSergio Gonzalez Monroy printf(" - Pkts enq to tx failed: %"PRIu64"\n", 383850f3733SSergio Gonzalez Monroy app_stats.wkr.enqueue_failed_pkts); 384850f3733SSergio Gonzalez Monroy 385850f3733SSergio Gonzalez Monroy printf("\nTX stats:\n"); 386850f3733SSergio Gonzalez Monroy printf(" - Pkts deqd from tx ring: %"PRIu64"\n", 387850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts); 388850f3733SSergio Gonzalez Monroy printf(" - Ro Pkts transmitted: %"PRIu64"\n", 389850f3733SSergio Gonzalez Monroy app_stats.tx.ro_tx_pkts); 390850f3733SSergio Gonzalez Monroy printf(" - Ro Pkts tx failed: %"PRIu64"\n", 391850f3733SSergio Gonzalez Monroy app_stats.tx.ro_tx_failed_pkts); 392850f3733SSergio Gonzalez Monroy printf(" - Pkts transmitted w/o reorder: %"PRIu64"\n", 393850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_txtd_woro); 394850f3733SSergio Gonzalez Monroy printf(" - Pkts tx failed w/o reorder: %"PRIu64"\n", 395850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_tx_failed_woro); 396850f3733SSergio Gonzalez Monroy 3978728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(i) { 398850f3733SSergio Gonzalez Monroy rte_eth_stats_get(i, ð_stats); 399850f3733SSergio Gonzalez Monroy printf("\nPort %u stats:\n", i); 400850f3733SSergio Gonzalez Monroy printf(" - Pkts in: %"PRIu64"\n", eth_stats.ipackets); 401850f3733SSergio Gonzalez Monroy printf(" - Pkts out: %"PRIu64"\n", eth_stats.opackets); 402850f3733SSergio Gonzalez Monroy printf(" - In Errs: %"PRIu64"\n", eth_stats.ierrors); 403850f3733SSergio Gonzalez Monroy printf(" - Out Errs: %"PRIu64"\n", eth_stats.oerrors); 404850f3733SSergio Gonzalez Monroy printf(" - Mbuf Errs: %"PRIu64"\n", eth_stats.rx_nombuf); 405850f3733SSergio Gonzalez Monroy } 406850f3733SSergio Gonzalez Monroy } 407850f3733SSergio Gonzalez Monroy 408850f3733SSergio Gonzalez Monroy static void 409850f3733SSergio Gonzalez Monroy int_handler(int sig_num) 410850f3733SSergio Gonzalez Monroy { 411850f3733SSergio Gonzalez Monroy printf("Exiting on signal %d\n", sig_num); 412850f3733SSergio Gonzalez Monroy quit_signal = 1; 413850f3733SSergio Gonzalez Monroy } 414850f3733SSergio Gonzalez Monroy 415850f3733SSergio Gonzalez Monroy /** 416850f3733SSergio Gonzalez Monroy * This thread receives mbufs from the port and affects them an internal 417850f3733SSergio Gonzalez Monroy * sequence number to keep track of their order of arrival through an 418850f3733SSergio Gonzalez Monroy * mbuf structure. 419850f3733SSergio Gonzalez Monroy * The mbufs are then passed to the worker threads via the rx_to_workers 420850f3733SSergio Gonzalez Monroy * ring. 421850f3733SSergio Gonzalez Monroy */ 422850f3733SSergio Gonzalez Monroy static int 423850f3733SSergio Gonzalez Monroy rx_thread(struct rte_ring *ring_out) 424850f3733SSergio Gonzalez Monroy { 425850f3733SSergio Gonzalez Monroy uint32_t seqn = 0; 426850f3733SSergio Gonzalez Monroy uint16_t i, ret = 0; 427850f3733SSergio Gonzalez Monroy uint16_t nb_rx_pkts; 428f8244c63SZhiyong Yang uint16_t port_id; 429850f3733SSergio Gonzalez Monroy struct rte_mbuf *pkts[MAX_PKTS_BURST]; 430850f3733SSergio Gonzalez Monroy 431850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 432850f3733SSergio Gonzalez Monroy rte_lcore_id()); 433850f3733SSergio Gonzalez Monroy 434850f3733SSergio Gonzalez Monroy while (!quit_signal) { 435850f3733SSergio Gonzalez Monroy 4368728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 437850f3733SSergio Gonzalez Monroy if ((portmask & (1 << port_id)) != 0) { 438850f3733SSergio Gonzalez Monroy 439850f3733SSergio Gonzalez Monroy /* receive packets */ 440850f3733SSergio Gonzalez Monroy nb_rx_pkts = rte_eth_rx_burst(port_id, 0, 441850f3733SSergio Gonzalez Monroy pkts, MAX_PKTS_BURST); 442850f3733SSergio Gonzalez Monroy if (nb_rx_pkts == 0) { 4435d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, 444850f3733SSergio Gonzalez Monroy "%s():Received zero packets\n", __func__); 445850f3733SSergio Gonzalez Monroy continue; 446850f3733SSergio Gonzalez Monroy } 447850f3733SSergio Gonzalez Monroy app_stats.rx.rx_pkts += nb_rx_pkts; 448850f3733SSergio Gonzalez Monroy 449850f3733SSergio Gonzalez Monroy /* mark sequence number */ 450850f3733SSergio Gonzalez Monroy for (i = 0; i < nb_rx_pkts; ) 451850f3733SSergio Gonzalez Monroy pkts[i++]->seqn = seqn++; 452850f3733SSergio Gonzalez Monroy 453850f3733SSergio Gonzalez Monroy /* enqueue to rx_to_workers ring */ 45414fbffb0SBruce Richardson ret = rte_ring_enqueue_burst(ring_out, 45514fbffb0SBruce Richardson (void *)pkts, nb_rx_pkts, NULL); 456850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_pkts += ret; 457850f3733SSergio Gonzalez Monroy if (unlikely(ret < nb_rx_pkts)) { 458850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_failed_pkts += 459850f3733SSergio Gonzalez Monroy (nb_rx_pkts-ret); 460850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(&pkts[ret], nb_rx_pkts - ret); 461850f3733SSergio Gonzalez Monroy } 462850f3733SSergio Gonzalez Monroy } 463850f3733SSergio Gonzalez Monroy } 464850f3733SSergio Gonzalez Monroy } 465850f3733SSergio Gonzalez Monroy return 0; 466850f3733SSergio Gonzalez Monroy } 467850f3733SSergio Gonzalez Monroy 468850f3733SSergio Gonzalez Monroy /** 469850f3733SSergio Gonzalez Monroy * This thread takes bursts of packets from the rx_to_workers ring and 470850f3733SSergio Gonzalez Monroy * Changes the input port value to output port value. And feds it to 471850f3733SSergio Gonzalez Monroy * workers_to_tx 472850f3733SSergio Gonzalez Monroy */ 473850f3733SSergio Gonzalez Monroy static int 474850f3733SSergio Gonzalez Monroy worker_thread(void *args_ptr) 475850f3733SSergio Gonzalez Monroy { 476d9a42a69SThomas Monjalon const uint16_t nb_ports = rte_eth_dev_count_avail(); 477850f3733SSergio Gonzalez Monroy uint16_t i, ret = 0; 478850f3733SSergio Gonzalez Monroy uint16_t burst_size = 0; 479850f3733SSergio Gonzalez Monroy struct worker_thread_args *args; 480850f3733SSergio Gonzalez Monroy struct rte_mbuf *burst_buffer[MAX_PKTS_BURST] = { NULL }; 481850f3733SSergio Gonzalez Monroy struct rte_ring *ring_in, *ring_out; 482850f3733SSergio Gonzalez Monroy const unsigned xor_val = (nb_ports > 1); 48301649330SPhil Yang unsigned int core_id = rte_lcore_id(); 484850f3733SSergio Gonzalez Monroy 485850f3733SSergio Gonzalez Monroy args = (struct worker_thread_args *) args_ptr; 486850f3733SSergio Gonzalez Monroy ring_in = args->ring_in; 487850f3733SSergio Gonzalez Monroy ring_out = args->ring_out; 488850f3733SSergio Gonzalez Monroy 489850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 49001649330SPhil Yang core_id); 491850f3733SSergio Gonzalez Monroy 492850f3733SSergio Gonzalez Monroy while (!quit_signal) { 493850f3733SSergio Gonzalez Monroy 494850f3733SSergio Gonzalez Monroy /* dequeue the mbufs from rx_to_workers ring */ 495850f3733SSergio Gonzalez Monroy burst_size = rte_ring_dequeue_burst(ring_in, 496ecaed092SBruce Richardson (void *)burst_buffer, MAX_PKTS_BURST, NULL); 497850f3733SSergio Gonzalez Monroy if (unlikely(burst_size == 0)) 498850f3733SSergio Gonzalez Monroy continue; 499850f3733SSergio Gonzalez Monroy 50001649330SPhil Yang wkr_stats[core_id].deq_pkts += burst_size; 501850f3733SSergio Gonzalez Monroy 502850f3733SSergio Gonzalez Monroy /* just do some operation on mbuf */ 503850f3733SSergio Gonzalez Monroy for (i = 0; i < burst_size;) 504850f3733SSergio Gonzalez Monroy burst_buffer[i++]->port ^= xor_val; 505850f3733SSergio Gonzalez Monroy 506850f3733SSergio Gonzalez Monroy /* enqueue the modified mbufs to workers_to_tx ring */ 50714fbffb0SBruce Richardson ret = rte_ring_enqueue_burst(ring_out, (void *)burst_buffer, 50814fbffb0SBruce Richardson burst_size, NULL); 50901649330SPhil Yang wkr_stats[core_id].enq_pkts += ret; 510850f3733SSergio Gonzalez Monroy if (unlikely(ret < burst_size)) { 511850f3733SSergio Gonzalez Monroy /* Return the mbufs to their respective pool, dropping packets */ 51201649330SPhil Yang wkr_stats[core_id].enq_failed_pkts += burst_size - ret; 513850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(&burst_buffer[ret], burst_size - ret); 514850f3733SSergio Gonzalez Monroy } 515850f3733SSergio Gonzalez Monroy } 516850f3733SSergio Gonzalez Monroy return 0; 517850f3733SSergio Gonzalez Monroy } 518850f3733SSergio Gonzalez Monroy 519850f3733SSergio Gonzalez Monroy /** 520850f3733SSergio Gonzalez Monroy * Dequeue mbufs from the workers_to_tx ring and reorder them before 521850f3733SSergio Gonzalez Monroy * transmitting. 522850f3733SSergio Gonzalez Monroy */ 523850f3733SSergio Gonzalez Monroy static int 5246ebc23d8SSergio Gonzalez Monroy send_thread(struct send_thread_args *args) 525850f3733SSergio Gonzalez Monroy { 526850f3733SSergio Gonzalez Monroy int ret; 527850f3733SSergio Gonzalez Monroy unsigned int i, dret; 528850f3733SSergio Gonzalez Monroy uint16_t nb_dq_mbufs; 529850f3733SSergio Gonzalez Monroy uint8_t outp; 530e2366e74STomasz Kulasek unsigned sent; 531850f3733SSergio Gonzalez Monroy struct rte_mbuf *mbufs[MAX_PKTS_BURST]; 532850f3733SSergio Gonzalez Monroy struct rte_mbuf *rombufs[MAX_PKTS_BURST] = {NULL}; 533e2366e74STomasz Kulasek static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 534850f3733SSergio Gonzalez Monroy 5356ebc23d8SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); 5366ebc23d8SSergio Gonzalez Monroy 537e2366e74STomasz Kulasek configure_tx_buffers(tx_buffer); 538e2366e74STomasz Kulasek 539850f3733SSergio Gonzalez Monroy while (!quit_signal) { 540850f3733SSergio Gonzalez Monroy 541850f3733SSergio Gonzalez Monroy /* deque the mbufs from workers_to_tx ring */ 5426ebc23d8SSergio Gonzalez Monroy nb_dq_mbufs = rte_ring_dequeue_burst(args->ring_in, 543ecaed092SBruce Richardson (void *)mbufs, MAX_PKTS_BURST, NULL); 544850f3733SSergio Gonzalez Monroy 545850f3733SSergio Gonzalez Monroy if (unlikely(nb_dq_mbufs == 0)) 546850f3733SSergio Gonzalez Monroy continue; 547850f3733SSergio Gonzalez Monroy 548850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts += nb_dq_mbufs; 549850f3733SSergio Gonzalez Monroy 550850f3733SSergio Gonzalez Monroy for (i = 0; i < nb_dq_mbufs; i++) { 551850f3733SSergio Gonzalez Monroy /* send dequeued mbufs for reordering */ 5526ebc23d8SSergio Gonzalez Monroy ret = rte_reorder_insert(args->buffer, mbufs[i]); 553850f3733SSergio Gonzalez Monroy 554850f3733SSergio Gonzalez Monroy if (ret == -1 && rte_errno == ERANGE) { 555850f3733SSergio Gonzalez Monroy /* Too early pkts should be transmitted out directly */ 5565d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, 5571f49ec15SThomas Monjalon "%s():Cannot reorder early packet " 558850f3733SSergio Gonzalez Monroy "direct enqueuing to TX\n", __func__); 559850f3733SSergio Gonzalez Monroy outp = mbufs[i]->port; 560850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp)) == 0) { 561850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 562850f3733SSergio Gonzalez Monroy continue; 563850f3733SSergio Gonzalez Monroy } 564850f3733SSergio Gonzalez Monroy if (rte_eth_tx_burst(outp, 0, (void *)mbufs[i], 1) != 1) { 565850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 566850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_tx_failed_woro++; 567850f3733SSergio Gonzalez Monroy } else 568850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_txtd_woro++; 569850f3733SSergio Gonzalez Monroy } else if (ret == -1 && rte_errno == ENOSPC) { 570850f3733SSergio Gonzalez Monroy /** 571850f3733SSergio Gonzalez Monroy * Early pkts just outside of window should be dropped 572850f3733SSergio Gonzalez Monroy */ 573850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 574850f3733SSergio Gonzalez Monroy } 575850f3733SSergio Gonzalez Monroy } 576850f3733SSergio Gonzalez Monroy 577850f3733SSergio Gonzalez Monroy /* 578850f3733SSergio Gonzalez Monroy * drain MAX_PKTS_BURST of reordered 579850f3733SSergio Gonzalez Monroy * mbufs for transmit 580850f3733SSergio Gonzalez Monroy */ 5816ebc23d8SSergio Gonzalez Monroy dret = rte_reorder_drain(args->buffer, rombufs, MAX_PKTS_BURST); 582850f3733SSergio Gonzalez Monroy for (i = 0; i < dret; i++) { 583850f3733SSergio Gonzalez Monroy 584e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *outbuf; 585850f3733SSergio Gonzalez Monroy uint8_t outp1; 586850f3733SSergio Gonzalez Monroy 587850f3733SSergio Gonzalez Monroy outp1 = rombufs[i]->port; 588850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 589850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp1)) == 0) { 590850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(rombufs[i]); 591850f3733SSergio Gonzalez Monroy continue; 592850f3733SSergio Gonzalez Monroy } 593850f3733SSergio Gonzalez Monroy 594e2366e74STomasz Kulasek outbuf = tx_buffer[outp1]; 595e2366e74STomasz Kulasek sent = rte_eth_tx_buffer(outp1, 0, outbuf, rombufs[i]); 596e2366e74STomasz Kulasek if (sent) 597e2366e74STomasz Kulasek app_stats.tx.ro_tx_pkts += sent; 598850f3733SSergio Gonzalez Monroy } 599850f3733SSergio Gonzalez Monroy } 600e2366e74STomasz Kulasek 601e2366e74STomasz Kulasek free_tx_buffers(tx_buffer); 602e2366e74STomasz Kulasek 603850f3733SSergio Gonzalez Monroy return 0; 604850f3733SSergio Gonzalez Monroy } 605850f3733SSergio Gonzalez Monroy 606850f3733SSergio Gonzalez Monroy /** 607850f3733SSergio Gonzalez Monroy * Dequeue mbufs from the workers_to_tx ring and transmit them 608850f3733SSergio Gonzalez Monroy */ 609850f3733SSergio Gonzalez Monroy static int 610850f3733SSergio Gonzalez Monroy tx_thread(struct rte_ring *ring_in) 611850f3733SSergio Gonzalez Monroy { 612850f3733SSergio Gonzalez Monroy uint32_t i, dqnum; 613850f3733SSergio Gonzalez Monroy uint8_t outp; 614e2366e74STomasz Kulasek unsigned sent; 615850f3733SSergio Gonzalez Monroy struct rte_mbuf *mbufs[MAX_PKTS_BURST]; 616e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *outbuf; 617e2366e74STomasz Kulasek static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 618850f3733SSergio Gonzalez Monroy 619850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 620850f3733SSergio Gonzalez Monroy rte_lcore_id()); 621e2366e74STomasz Kulasek 622e2366e74STomasz Kulasek configure_tx_buffers(tx_buffer); 623e2366e74STomasz Kulasek 624850f3733SSergio Gonzalez Monroy while (!quit_signal) { 625850f3733SSergio Gonzalez Monroy 626850f3733SSergio Gonzalez Monroy /* deque the mbufs from workers_to_tx ring */ 627850f3733SSergio Gonzalez Monroy dqnum = rte_ring_dequeue_burst(ring_in, 628ecaed092SBruce Richardson (void *)mbufs, MAX_PKTS_BURST, NULL); 629850f3733SSergio Gonzalez Monroy 630850f3733SSergio Gonzalez Monroy if (unlikely(dqnum == 0)) 631850f3733SSergio Gonzalez Monroy continue; 632850f3733SSergio Gonzalez Monroy 633850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts += dqnum; 634850f3733SSergio Gonzalez Monroy 635850f3733SSergio Gonzalez Monroy for (i = 0; i < dqnum; i++) { 636850f3733SSergio Gonzalez Monroy outp = mbufs[i]->port; 637850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 638850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp)) == 0) { 639850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 640850f3733SSergio Gonzalez Monroy continue; 641850f3733SSergio Gonzalez Monroy } 642850f3733SSergio Gonzalez Monroy 643e2366e74STomasz Kulasek outbuf = tx_buffer[outp]; 644e2366e74STomasz Kulasek sent = rte_eth_tx_buffer(outp, 0, outbuf, mbufs[i]); 645e2366e74STomasz Kulasek if (sent) 646e2366e74STomasz Kulasek app_stats.tx.ro_tx_pkts += sent; 647850f3733SSergio Gonzalez Monroy } 648850f3733SSergio Gonzalez Monroy } 649850f3733SSergio Gonzalez Monroy 650850f3733SSergio Gonzalez Monroy return 0; 651850f3733SSergio Gonzalez Monroy } 652850f3733SSergio Gonzalez Monroy 653850f3733SSergio Gonzalez Monroy int 654850f3733SSergio Gonzalez Monroy main(int argc, char **argv) 655850f3733SSergio Gonzalez Monroy { 656850f3733SSergio Gonzalez Monroy int ret; 657850f3733SSergio Gonzalez Monroy unsigned nb_ports; 658850f3733SSergio Gonzalez Monroy unsigned int lcore_id, last_lcore_id, master_lcore_id; 659f8244c63SZhiyong Yang uint16_t port_id; 660f8244c63SZhiyong Yang uint16_t nb_ports_available; 661850f3733SSergio Gonzalez Monroy struct worker_thread_args worker_args = {NULL, NULL}; 6626ebc23d8SSergio Gonzalez Monroy struct send_thread_args send_args = {NULL, NULL}; 663850f3733SSergio Gonzalez Monroy struct rte_ring *rx_to_workers; 664850f3733SSergio Gonzalez Monroy struct rte_ring *workers_to_tx; 665850f3733SSergio Gonzalez Monroy 666850f3733SSergio Gonzalez Monroy /* catch ctrl-c so we can print on exit */ 667850f3733SSergio Gonzalez Monroy signal(SIGINT, int_handler); 668850f3733SSergio Gonzalez Monroy 669850f3733SSergio Gonzalez Monroy /* Initialize EAL */ 670850f3733SSergio Gonzalez Monroy ret = rte_eal_init(argc, argv); 671850f3733SSergio Gonzalez Monroy if (ret < 0) 672850f3733SSergio Gonzalez Monroy return -1; 673850f3733SSergio Gonzalez Monroy 674850f3733SSergio Gonzalez Monroy argc -= ret; 675850f3733SSergio Gonzalez Monroy argv += ret; 676850f3733SSergio Gonzalez Monroy 677850f3733SSergio Gonzalez Monroy /* Parse the application specific arguments */ 678850f3733SSergio Gonzalez Monroy ret = parse_args(argc, argv); 679850f3733SSergio Gonzalez Monroy if (ret < 0) 680850f3733SSergio Gonzalez Monroy return -1; 681850f3733SSergio Gonzalez Monroy 682850f3733SSergio Gonzalez Monroy /* Check if we have enought cores */ 683850f3733SSergio Gonzalez Monroy if (rte_lcore_count() < 3) 684850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error, This application needs at " 685850f3733SSergio Gonzalez Monroy "least 3 logical cores to run:\n" 686850f3733SSergio Gonzalez Monroy "1 lcore for packet RX\n" 687850f3733SSergio Gonzalez Monroy "1 lcore for packet TX\n" 688850f3733SSergio Gonzalez Monroy "and at least 1 lcore for worker threads\n"); 689850f3733SSergio Gonzalez Monroy 690d9a42a69SThomas Monjalon nb_ports = rte_eth_dev_count_avail(); 691850f3733SSergio Gonzalez Monroy if (nb_ports == 0) 692850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); 693850f3733SSergio Gonzalez Monroy if (nb_ports != 1 && (nb_ports & 1)) 694850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error: number of ports must be even, except " 695850f3733SSergio Gonzalez Monroy "when using a single port\n"); 696850f3733SSergio Gonzalez Monroy 697ea0c20eaSOlivier Matz mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 698824cb29cSKonstantin Ananyev MBUF_POOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, 699ea0c20eaSOlivier Matz rte_socket_id()); 700850f3733SSergio Gonzalez Monroy if (mbuf_pool == NULL) 701850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 702850f3733SSergio Gonzalez Monroy 703850f3733SSergio Gonzalez Monroy nb_ports_available = nb_ports; 704850f3733SSergio Gonzalez Monroy 705850f3733SSergio Gonzalez Monroy /* initialize all ports */ 7068728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 707850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 708850f3733SSergio Gonzalez Monroy if ((portmask & (1 << port_id)) == 0) { 709850f3733SSergio Gonzalez Monroy printf("\nSkipping disabled port %d\n", port_id); 710850f3733SSergio Gonzalez Monroy nb_ports_available--; 711850f3733SSergio Gonzalez Monroy continue; 712850f3733SSergio Gonzalez Monroy } 713850f3733SSergio Gonzalez Monroy /* init port */ 714f8244c63SZhiyong Yang printf("Initializing port %u... done\n", port_id); 715850f3733SSergio Gonzalez Monroy 716850f3733SSergio Gonzalez Monroy if (configure_eth_port(port_id) != 0) 717850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Cannot initialize port %"PRIu8"\n", 718850f3733SSergio Gonzalez Monroy port_id); 719850f3733SSergio Gonzalez Monroy } 720850f3733SSergio Gonzalez Monroy 721850f3733SSergio Gonzalez Monroy if (!nb_ports_available) { 722850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, 723850f3733SSergio Gonzalez Monroy "All available ports are disabled. Please set portmask.\n"); 724850f3733SSergio Gonzalez Monroy } 725850f3733SSergio Gonzalez Monroy 726850f3733SSergio Gonzalez Monroy /* Create rings for inter core communication */ 727850f3733SSergio Gonzalez Monroy rx_to_workers = rte_ring_create("rx_to_workers", RING_SIZE, rte_socket_id(), 728850f3733SSergio Gonzalez Monroy RING_F_SP_ENQ); 729850f3733SSergio Gonzalez Monroy if (rx_to_workers == NULL) 730850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 731850f3733SSergio Gonzalez Monroy 732850f3733SSergio Gonzalez Monroy workers_to_tx = rte_ring_create("workers_to_tx", RING_SIZE, rte_socket_id(), 733850f3733SSergio Gonzalez Monroy RING_F_SC_DEQ); 734850f3733SSergio Gonzalez Monroy if (workers_to_tx == NULL) 735850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 736850f3733SSergio Gonzalez Monroy 7376ebc23d8SSergio Gonzalez Monroy if (!disable_reorder) { 7386ebc23d8SSergio Gonzalez Monroy send_args.buffer = rte_reorder_create("PKT_RO", rte_socket_id(), 7396ebc23d8SSergio Gonzalez Monroy REORDER_BUFFER_SIZE); 7406ebc23d8SSergio Gonzalez Monroy if (send_args.buffer == NULL) 7416ebc23d8SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 7426ebc23d8SSergio Gonzalez Monroy } 7436ebc23d8SSergio Gonzalez Monroy 744850f3733SSergio Gonzalez Monroy last_lcore_id = get_last_lcore_id(); 745850f3733SSergio Gonzalez Monroy master_lcore_id = rte_get_master_lcore(); 746850f3733SSergio Gonzalez Monroy 747850f3733SSergio Gonzalez Monroy worker_args.ring_in = rx_to_workers; 748850f3733SSergio Gonzalez Monroy worker_args.ring_out = workers_to_tx; 749850f3733SSergio Gonzalez Monroy 750850f3733SSergio Gonzalez Monroy /* Start worker_thread() on all the available slave cores but the last 1 */ 751850f3733SSergio Gonzalez Monroy for (lcore_id = 0; lcore_id <= get_previous_lcore_id(last_lcore_id); lcore_id++) 752850f3733SSergio Gonzalez Monroy if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) 753850f3733SSergio Gonzalez Monroy rte_eal_remote_launch(worker_thread, (void *)&worker_args, 754850f3733SSergio Gonzalez Monroy lcore_id); 755850f3733SSergio Gonzalez Monroy 7566ebc23d8SSergio Gonzalez Monroy if (disable_reorder) { 757850f3733SSergio Gonzalez Monroy /* Start tx_thread() on the last slave core */ 758850f3733SSergio Gonzalez Monroy rte_eal_remote_launch((lcore_function_t *)tx_thread, workers_to_tx, 759850f3733SSergio Gonzalez Monroy last_lcore_id); 7606ebc23d8SSergio Gonzalez Monroy } else { 7616ebc23d8SSergio Gonzalez Monroy send_args.ring_in = workers_to_tx; 762850f3733SSergio Gonzalez Monroy /* Start send_thread() on the last slave core */ 7636ebc23d8SSergio Gonzalez Monroy rte_eal_remote_launch((lcore_function_t *)send_thread, 7646ebc23d8SSergio Gonzalez Monroy (void *)&send_args, last_lcore_id); 7656ebc23d8SSergio Gonzalez Monroy } 766850f3733SSergio Gonzalez Monroy 767850f3733SSergio Gonzalez Monroy /* Start rx_thread() on the master core */ 768850f3733SSergio Gonzalez Monroy rx_thread(rx_to_workers); 769850f3733SSergio Gonzalez Monroy 770850f3733SSergio Gonzalez Monroy RTE_LCORE_FOREACH_SLAVE(lcore_id) { 771850f3733SSergio Gonzalez Monroy if (rte_eal_wait_lcore(lcore_id) < 0) 772850f3733SSergio Gonzalez Monroy return -1; 773850f3733SSergio Gonzalez Monroy } 774850f3733SSergio Gonzalez Monroy 775850f3733SSergio Gonzalez Monroy print_stats(); 776850f3733SSergio Gonzalez Monroy return 0; 777850f3733SSergio Gonzalez Monroy } 778