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 32*3bb3ebb5SIbtisam Tariq enum { 33*3bb3ebb5SIbtisam Tariq #define OPT_DISABLE_REORDER "disable-reorder" 34*3bb3ebb5SIbtisam Tariq OPT_DISABLE_REORDER_NUM = 256, 35*3bb3ebb5SIbtisam Tariq #define OPT_INSIGHT_WORKER "insight-worker" 36*3bb3ebb5SIbtisam Tariq OPT_INSIGHT_WORKER_NUM, 37*3bb3ebb5SIbtisam Tariq }; 38*3bb3ebb5SIbtisam Tariq 39850f3733SSergio Gonzalez Monroy unsigned int portmask; 40850f3733SSergio Gonzalez Monroy unsigned int disable_reorder; 4101649330SPhil Yang unsigned int insight_worker; 42850f3733SSergio Gonzalez Monroy volatile uint8_t quit_signal; 43850f3733SSergio Gonzalez Monroy 44850f3733SSergio Gonzalez Monroy static struct rte_mempool *mbuf_pool; 45850f3733SSergio Gonzalez Monroy 46ab3ce1e0SFerruh Yigit static struct rte_eth_conf port_conf_default; 47850f3733SSergio Gonzalez Monroy 48850f3733SSergio Gonzalez Monroy struct worker_thread_args { 49850f3733SSergio Gonzalez Monroy struct rte_ring *ring_in; 50850f3733SSergio Gonzalez Monroy struct rte_ring *ring_out; 51850f3733SSergio Gonzalez Monroy }; 52850f3733SSergio Gonzalez Monroy 536ebc23d8SSergio Gonzalez Monroy struct send_thread_args { 546ebc23d8SSergio Gonzalez Monroy struct rte_ring *ring_in; 556ebc23d8SSergio Gonzalez Monroy struct rte_reorder_buffer *buffer; 566ebc23d8SSergio Gonzalez Monroy }; 576ebc23d8SSergio Gonzalez Monroy 58850f3733SSergio Gonzalez Monroy volatile struct app_stats { 59850f3733SSergio Gonzalez Monroy struct { 60850f3733SSergio Gonzalez Monroy uint64_t rx_pkts; 61850f3733SSergio Gonzalez Monroy uint64_t enqueue_pkts; 62850f3733SSergio Gonzalez Monroy uint64_t enqueue_failed_pkts; 63850f3733SSergio Gonzalez Monroy } rx __rte_cache_aligned; 64850f3733SSergio Gonzalez Monroy 65850f3733SSergio Gonzalez Monroy struct { 66850f3733SSergio Gonzalez Monroy uint64_t dequeue_pkts; 67850f3733SSergio Gonzalez Monroy uint64_t enqueue_pkts; 68850f3733SSergio Gonzalez Monroy uint64_t enqueue_failed_pkts; 69850f3733SSergio Gonzalez Monroy } wkr __rte_cache_aligned; 70850f3733SSergio Gonzalez Monroy 71850f3733SSergio Gonzalez Monroy struct { 72850f3733SSergio Gonzalez Monroy uint64_t dequeue_pkts; 73850f3733SSergio Gonzalez Monroy /* Too early pkts transmitted directly w/o reordering */ 74850f3733SSergio Gonzalez Monroy uint64_t early_pkts_txtd_woro; 75850f3733SSergio Gonzalez Monroy /* Too early pkts failed from direct transmit */ 76850f3733SSergio Gonzalez Monroy uint64_t early_pkts_tx_failed_woro; 77850f3733SSergio Gonzalez Monroy uint64_t ro_tx_pkts; 78850f3733SSergio Gonzalez Monroy uint64_t ro_tx_failed_pkts; 79850f3733SSergio Gonzalez Monroy } tx __rte_cache_aligned; 80850f3733SSergio Gonzalez Monroy } app_stats; 81850f3733SSergio Gonzalez Monroy 8201649330SPhil Yang /* per worker lcore stats */ 8301649330SPhil Yang struct wkr_stats_per { 8401649330SPhil Yang uint64_t deq_pkts; 8501649330SPhil Yang uint64_t enq_pkts; 8601649330SPhil Yang uint64_t enq_failed_pkts; 8701649330SPhil Yang } __rte_cache_aligned; 8801649330SPhil Yang 8901649330SPhil Yang static struct wkr_stats_per wkr_stats[RTE_MAX_LCORE] = { {0} }; 90850f3733SSergio Gonzalez Monroy /** 91850f3733SSergio Gonzalez Monroy * Get the last enabled lcore ID 92850f3733SSergio Gonzalez Monroy * 93850f3733SSergio Gonzalez Monroy * @return 94850f3733SSergio Gonzalez Monroy * The last enabled lcore ID. 95850f3733SSergio Gonzalez Monroy */ 96850f3733SSergio Gonzalez Monroy static unsigned int 97850f3733SSergio Gonzalez Monroy get_last_lcore_id(void) 98850f3733SSergio Gonzalez Monroy { 99850f3733SSergio Gonzalez Monroy int i; 100850f3733SSergio Gonzalez Monroy 101850f3733SSergio Gonzalez Monroy for (i = RTE_MAX_LCORE - 1; i >= 0; i--) 102850f3733SSergio Gonzalez Monroy if (rte_lcore_is_enabled(i)) 103850f3733SSergio Gonzalez Monroy return i; 104850f3733SSergio Gonzalez Monroy return 0; 105850f3733SSergio Gonzalez Monroy } 106850f3733SSergio Gonzalez Monroy 107850f3733SSergio Gonzalez Monroy /** 108850f3733SSergio Gonzalez Monroy * Get the previous enabled lcore ID 109850f3733SSergio Gonzalez Monroy * @param id 110850f3733SSergio Gonzalez Monroy * The current lcore ID 111850f3733SSergio Gonzalez Monroy * @return 112850f3733SSergio Gonzalez Monroy * The previous enabled lcore ID or the current lcore 113850f3733SSergio Gonzalez Monroy * ID if it is the first available core. 114850f3733SSergio Gonzalez Monroy */ 115850f3733SSergio Gonzalez Monroy static unsigned int 116850f3733SSergio Gonzalez Monroy get_previous_lcore_id(unsigned int id) 117850f3733SSergio Gonzalez Monroy { 118850f3733SSergio Gonzalez Monroy int i; 119850f3733SSergio Gonzalez Monroy 120850f3733SSergio Gonzalez Monroy for (i = id - 1; i >= 0; i--) 121850f3733SSergio Gonzalez Monroy if (rte_lcore_is_enabled(i)) 122850f3733SSergio Gonzalez Monroy return i; 123850f3733SSergio Gonzalez Monroy return id; 124850f3733SSergio Gonzalez Monroy } 125850f3733SSergio Gonzalez Monroy 126850f3733SSergio Gonzalez Monroy static inline void 127850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(struct rte_mbuf *mbuf_table[], unsigned n) 128850f3733SSergio Gonzalez Monroy { 129850f3733SSergio Gonzalez Monroy unsigned int i; 130850f3733SSergio Gonzalez Monroy 131850f3733SSergio Gonzalez Monroy for (i = 0; i < n; i++) 132850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbuf_table[i]); 133850f3733SSergio Gonzalez Monroy } 134850f3733SSergio Gonzalez Monroy 135850f3733SSergio Gonzalez Monroy /* display usage */ 136850f3733SSergio Gonzalez Monroy static void 137850f3733SSergio Gonzalez Monroy print_usage(const char *prgname) 138850f3733SSergio Gonzalez Monroy { 139850f3733SSergio Gonzalez Monroy printf("%s [EAL options] -- -p PORTMASK\n" 140850f3733SSergio Gonzalez Monroy " -p PORTMASK: hexadecimal bitmask of ports to configure\n", 141850f3733SSergio Gonzalez Monroy prgname); 142850f3733SSergio Gonzalez Monroy } 143850f3733SSergio Gonzalez Monroy 144850f3733SSergio Gonzalez Monroy static int 145850f3733SSergio Gonzalez Monroy parse_portmask(const char *portmask) 146850f3733SSergio Gonzalez Monroy { 147850f3733SSergio Gonzalez Monroy unsigned long pm; 148850f3733SSergio Gonzalez Monroy char *end = NULL; 149850f3733SSergio Gonzalez Monroy 150850f3733SSergio Gonzalez Monroy /* parse hexadecimal string */ 151850f3733SSergio Gonzalez Monroy pm = strtoul(portmask, &end, 16); 152850f3733SSergio Gonzalez Monroy if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) 153ce6b8c31SSarosh Arif return 0; 154850f3733SSergio Gonzalez Monroy 155850f3733SSergio Gonzalez Monroy return pm; 156850f3733SSergio Gonzalez Monroy } 157850f3733SSergio Gonzalez Monroy 158850f3733SSergio Gonzalez Monroy /* Parse the argument given in the command line of the application */ 159850f3733SSergio Gonzalez Monroy static int 160850f3733SSergio Gonzalez Monroy parse_args(int argc, char **argv) 161850f3733SSergio Gonzalez Monroy { 162850f3733SSergio Gonzalez Monroy int opt; 163850f3733SSergio Gonzalez Monroy int option_index; 164850f3733SSergio Gonzalez Monroy char **argvopt; 165850f3733SSergio Gonzalez Monroy char *prgname = argv[0]; 166850f3733SSergio Gonzalez Monroy static struct option lgopts[] = { 167*3bb3ebb5SIbtisam Tariq {OPT_DISABLE_REORDER, 0, NULL, OPT_DISABLE_REORDER_NUM}, 168*3bb3ebb5SIbtisam Tariq {OPT_INSIGHT_WORKER, 0, NULL, OPT_INSIGHT_WORKER_NUM }, 169850f3733SSergio Gonzalez Monroy {NULL, 0, 0, 0 } 170850f3733SSergio Gonzalez Monroy }; 171850f3733SSergio Gonzalez Monroy 172850f3733SSergio Gonzalez Monroy argvopt = argv; 173850f3733SSergio Gonzalez Monroy 174850f3733SSergio Gonzalez Monroy while ((opt = getopt_long(argc, argvopt, "p:", 175850f3733SSergio Gonzalez Monroy lgopts, &option_index)) != EOF) { 176850f3733SSergio Gonzalez Monroy switch (opt) { 177850f3733SSergio Gonzalez Monroy /* portmask */ 178850f3733SSergio Gonzalez Monroy case 'p': 179850f3733SSergio Gonzalez Monroy portmask = parse_portmask(optarg); 180850f3733SSergio Gonzalez Monroy if (portmask == 0) { 181850f3733SSergio Gonzalez Monroy printf("invalid portmask\n"); 182850f3733SSergio Gonzalez Monroy print_usage(prgname); 183850f3733SSergio Gonzalez Monroy return -1; 184850f3733SSergio Gonzalez Monroy } 185850f3733SSergio Gonzalez Monroy break; 186*3bb3ebb5SIbtisam Tariq 187850f3733SSergio Gonzalez Monroy /* long options */ 188*3bb3ebb5SIbtisam Tariq case OPT_DISABLE_REORDER_NUM: 189850f3733SSergio Gonzalez Monroy printf("reorder disabled\n"); 190850f3733SSergio Gonzalez Monroy disable_reorder = 1; 191*3bb3ebb5SIbtisam Tariq break; 192*3bb3ebb5SIbtisam Tariq 193*3bb3ebb5SIbtisam Tariq case OPT_INSIGHT_WORKER_NUM: 19401649330SPhil Yang printf("print all worker statistics\n"); 19501649330SPhil Yang insight_worker = 1; 196850f3733SSergio Gonzalez Monroy break; 197*3bb3ebb5SIbtisam Tariq 198850f3733SSergio Gonzalez Monroy default: 199850f3733SSergio Gonzalez Monroy print_usage(prgname); 200850f3733SSergio Gonzalez Monroy return -1; 201850f3733SSergio Gonzalez Monroy } 202850f3733SSergio Gonzalez Monroy } 203850f3733SSergio Gonzalez Monroy if (optind <= 1) { 204850f3733SSergio Gonzalez Monroy print_usage(prgname); 205850f3733SSergio Gonzalez Monroy return -1; 206850f3733SSergio Gonzalez Monroy } 207850f3733SSergio Gonzalez Monroy 208850f3733SSergio Gonzalez Monroy argv[optind-1] = prgname; 2099d5ca532SKeith Wiles optind = 1; /* reset getopt lib */ 210850f3733SSergio Gonzalez Monroy return 0; 211850f3733SSergio Gonzalez Monroy } 212850f3733SSergio Gonzalez Monroy 213e2366e74STomasz Kulasek /* 214e2366e74STomasz Kulasek * Tx buffer error callback 215e2366e74STomasz Kulasek */ 216e2366e74STomasz Kulasek static void 217e2366e74STomasz Kulasek flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count, 218e2366e74STomasz Kulasek void *userdata __rte_unused) { 219e2366e74STomasz Kulasek 220e2366e74STomasz Kulasek /* free the mbufs which failed from transmit */ 221e2366e74STomasz Kulasek app_stats.tx.ro_tx_failed_pkts += count; 2225d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, "%s:Packet loss with tx_burst\n", __func__); 223e2366e74STomasz Kulasek pktmbuf_free_bulk(unsent, count); 224e2366e74STomasz Kulasek 225e2366e74STomasz Kulasek } 226e2366e74STomasz Kulasek 227e2366e74STomasz Kulasek static inline int 228e2366e74STomasz Kulasek free_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) { 2298728ccf3SThomas Monjalon uint16_t port_id; 230e2366e74STomasz Kulasek 231e2366e74STomasz Kulasek /* initialize buffers for all ports */ 2328728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 233e2366e74STomasz Kulasek /* skip ports that are not enabled */ 234e2366e74STomasz Kulasek if ((portmask & (1 << port_id)) == 0) 235e2366e74STomasz Kulasek continue; 236e2366e74STomasz Kulasek 237e2366e74STomasz Kulasek rte_free(tx_buffer[port_id]); 238e2366e74STomasz Kulasek } 239e2366e74STomasz Kulasek return 0; 240e2366e74STomasz Kulasek } 241e2366e74STomasz Kulasek 242e2366e74STomasz Kulasek static inline int 243e2366e74STomasz Kulasek configure_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) 244e2366e74STomasz Kulasek { 2458728ccf3SThomas Monjalon uint16_t port_id; 246e2366e74STomasz Kulasek int ret; 247e2366e74STomasz Kulasek 248e2366e74STomasz Kulasek /* initialize buffers for all ports */ 2498728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 250e2366e74STomasz Kulasek /* skip ports that are not enabled */ 251e2366e74STomasz Kulasek if ((portmask & (1 << port_id)) == 0) 252e2366e74STomasz Kulasek continue; 253e2366e74STomasz Kulasek 254e2366e74STomasz Kulasek /* Initialize TX buffers */ 255e2366e74STomasz Kulasek tx_buffer[port_id] = rte_zmalloc_socket("tx_buffer", 256e2366e74STomasz Kulasek RTE_ETH_TX_BUFFER_SIZE(MAX_PKTS_BURST), 0, 257e2366e74STomasz Kulasek rte_eth_dev_socket_id(port_id)); 258e2366e74STomasz Kulasek if (tx_buffer[port_id] == NULL) 259e2366e74STomasz Kulasek rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", 260f8244c63SZhiyong Yang port_id); 261e2366e74STomasz Kulasek 262e2366e74STomasz Kulasek rte_eth_tx_buffer_init(tx_buffer[port_id], MAX_PKTS_BURST); 263e2366e74STomasz Kulasek 264e2366e74STomasz Kulasek ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[port_id], 265e2366e74STomasz Kulasek flush_tx_error_callback, NULL); 266e2366e74STomasz Kulasek if (ret < 0) 267f8244c63SZhiyong Yang rte_exit(EXIT_FAILURE, 268f8244c63SZhiyong Yang "Cannot set error callback for tx buffer on port %u\n", 269f8244c63SZhiyong Yang port_id); 270e2366e74STomasz Kulasek } 271e2366e74STomasz Kulasek return 0; 272e2366e74STomasz Kulasek } 273e2366e74STomasz Kulasek 274850f3733SSergio Gonzalez Monroy static inline int 275f8244c63SZhiyong Yang configure_eth_port(uint16_t port_id) 276850f3733SSergio Gonzalez Monroy { 2776d13ea8eSOlivier Matz struct rte_ether_addr addr; 278850f3733SSergio Gonzalez Monroy const uint16_t rxRings = 1, txRings = 1; 279850f3733SSergio Gonzalez Monroy int ret; 280850f3733SSergio Gonzalez Monroy uint16_t q; 28160efb44fSRoman Zhukov uint16_t nb_rxd = RX_DESC_PER_QUEUE; 28260efb44fSRoman Zhukov uint16_t nb_txd = TX_DESC_PER_QUEUE; 2836833f919SShahaf Shuler struct rte_eth_dev_info dev_info; 2846833f919SShahaf Shuler struct rte_eth_txconf txconf; 2856833f919SShahaf Shuler struct rte_eth_conf port_conf = port_conf_default; 286850f3733SSergio Gonzalez Monroy 287a9dbe180SThomas Monjalon if (!rte_eth_dev_is_valid_port(port_id)) 288850f3733SSergio Gonzalez Monroy return -1; 289850f3733SSergio Gonzalez Monroy 290089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(port_id, &dev_info); 291089e5ed7SIvan Ilchenko if (ret != 0) { 292089e5ed7SIvan Ilchenko printf("Error during getting device (port %u) info: %s\n", 293089e5ed7SIvan Ilchenko port_id, strerror(-ret)); 294089e5ed7SIvan Ilchenko return ret; 295089e5ed7SIvan Ilchenko } 296089e5ed7SIvan Ilchenko 2976833f919SShahaf Shuler if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 2986833f919SShahaf Shuler port_conf.txmode.offloads |= 2996833f919SShahaf Shuler DEV_TX_OFFLOAD_MBUF_FAST_FREE; 300850f3733SSergio Gonzalez Monroy ret = rte_eth_dev_configure(port_id, rxRings, txRings, &port_conf_default); 301850f3733SSergio Gonzalez Monroy if (ret != 0) 302850f3733SSergio Gonzalez Monroy return ret; 303850f3733SSergio Gonzalez Monroy 30460efb44fSRoman Zhukov ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd); 30560efb44fSRoman Zhukov if (ret != 0) 30660efb44fSRoman Zhukov return ret; 30760efb44fSRoman Zhukov 308850f3733SSergio Gonzalez Monroy for (q = 0; q < rxRings; q++) { 30960efb44fSRoman Zhukov ret = rte_eth_rx_queue_setup(port_id, q, nb_rxd, 310850f3733SSergio Gonzalez Monroy rte_eth_dev_socket_id(port_id), NULL, 311850f3733SSergio Gonzalez Monroy mbuf_pool); 312850f3733SSergio Gonzalez Monroy if (ret < 0) 313850f3733SSergio Gonzalez Monroy return ret; 314850f3733SSergio Gonzalez Monroy } 315850f3733SSergio Gonzalez Monroy 3166833f919SShahaf Shuler txconf = dev_info.default_txconf; 3176833f919SShahaf Shuler txconf.offloads = port_conf.txmode.offloads; 318850f3733SSergio Gonzalez Monroy for (q = 0; q < txRings; q++) { 31960efb44fSRoman Zhukov ret = rte_eth_tx_queue_setup(port_id, q, nb_txd, 3206833f919SShahaf Shuler rte_eth_dev_socket_id(port_id), &txconf); 321850f3733SSergio Gonzalez Monroy if (ret < 0) 322850f3733SSergio Gonzalez Monroy return ret; 323850f3733SSergio Gonzalez Monroy } 324850f3733SSergio Gonzalez Monroy 325850f3733SSergio Gonzalez Monroy ret = rte_eth_dev_start(port_id); 326850f3733SSergio Gonzalez Monroy if (ret < 0) 327850f3733SSergio Gonzalez Monroy return ret; 328850f3733SSergio Gonzalez Monroy 32970febdcfSIgor Romanov ret = rte_eth_macaddr_get(port_id, &addr); 33070febdcfSIgor Romanov if (ret != 0) { 33170febdcfSIgor Romanov printf("Failed to get MAC address (port %u): %s\n", 33270febdcfSIgor Romanov port_id, rte_strerror(-ret)); 33370febdcfSIgor Romanov return ret; 33470febdcfSIgor Romanov } 33570febdcfSIgor Romanov 336850f3733SSergio Gonzalez Monroy printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 337850f3733SSergio Gonzalez Monroy " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", 338f8244c63SZhiyong Yang port_id, 339850f3733SSergio Gonzalez Monroy addr.addr_bytes[0], addr.addr_bytes[1], 340850f3733SSergio Gonzalez Monroy addr.addr_bytes[2], addr.addr_bytes[3], 341850f3733SSergio Gonzalez Monroy addr.addr_bytes[4], addr.addr_bytes[5]); 342850f3733SSergio Gonzalez Monroy 343f430bbceSIvan Ilchenko ret = rte_eth_promiscuous_enable(port_id); 344f430bbceSIvan Ilchenko if (ret != 0) 345f430bbceSIvan Ilchenko return ret; 346850f3733SSergio Gonzalez Monroy 347850f3733SSergio Gonzalez Monroy return 0; 348850f3733SSergio Gonzalez Monroy } 349850f3733SSergio Gonzalez Monroy 350850f3733SSergio Gonzalez Monroy static void 351850f3733SSergio Gonzalez Monroy print_stats(void) 352850f3733SSergio Gonzalez Monroy { 3538728ccf3SThomas Monjalon uint16_t i; 354850f3733SSergio Gonzalez Monroy struct rte_eth_stats eth_stats; 355cb056611SStephen Hemminger unsigned int lcore_id, last_lcore_id, main_lcore_id, end_w_lcore_id; 35601649330SPhil Yang 35701649330SPhil Yang last_lcore_id = get_last_lcore_id(); 358cb056611SStephen Hemminger main_lcore_id = rte_get_main_lcore(); 35901649330SPhil Yang end_w_lcore_id = get_previous_lcore_id(last_lcore_id); 360850f3733SSergio Gonzalez Monroy 361850f3733SSergio Gonzalez Monroy printf("\nRX thread stats:\n"); 362850f3733SSergio Gonzalez Monroy printf(" - Pkts rxd: %"PRIu64"\n", 363850f3733SSergio Gonzalez Monroy app_stats.rx.rx_pkts); 364850f3733SSergio Gonzalez Monroy printf(" - Pkts enqd to workers ring: %"PRIu64"\n", 365850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_pkts); 366850f3733SSergio Gonzalez Monroy 36701649330SPhil Yang for (lcore_id = 0; lcore_id <= end_w_lcore_id; lcore_id++) { 36801649330SPhil Yang if (insight_worker 36901649330SPhil Yang && rte_lcore_is_enabled(lcore_id) 370cb056611SStephen Hemminger && lcore_id != main_lcore_id) { 37101649330SPhil Yang printf("\nWorker thread stats on core [%u]:\n", 37201649330SPhil Yang lcore_id); 37301649330SPhil Yang printf(" - Pkts deqd from workers ring: %"PRIu64"\n", 37401649330SPhil Yang wkr_stats[lcore_id].deq_pkts); 37501649330SPhil Yang printf(" - Pkts enqd to tx ring: %"PRIu64"\n", 37601649330SPhil Yang wkr_stats[lcore_id].enq_pkts); 37701649330SPhil Yang printf(" - Pkts enq to tx failed: %"PRIu64"\n", 37801649330SPhil Yang wkr_stats[lcore_id].enq_failed_pkts); 37901649330SPhil Yang } 38001649330SPhil Yang 38101649330SPhil Yang app_stats.wkr.dequeue_pkts += wkr_stats[lcore_id].deq_pkts; 38201649330SPhil Yang app_stats.wkr.enqueue_pkts += wkr_stats[lcore_id].enq_pkts; 38301649330SPhil Yang app_stats.wkr.enqueue_failed_pkts += 38401649330SPhil Yang wkr_stats[lcore_id].enq_failed_pkts; 38501649330SPhil Yang } 38601649330SPhil Yang 387850f3733SSergio Gonzalez Monroy printf("\nWorker thread stats:\n"); 388850f3733SSergio Gonzalez Monroy printf(" - Pkts deqd from workers ring: %"PRIu64"\n", 389850f3733SSergio Gonzalez Monroy app_stats.wkr.dequeue_pkts); 390850f3733SSergio Gonzalez Monroy printf(" - Pkts enqd to tx ring: %"PRIu64"\n", 391850f3733SSergio Gonzalez Monroy app_stats.wkr.enqueue_pkts); 392850f3733SSergio Gonzalez Monroy printf(" - Pkts enq to tx failed: %"PRIu64"\n", 393850f3733SSergio Gonzalez Monroy app_stats.wkr.enqueue_failed_pkts); 394850f3733SSergio Gonzalez Monroy 395850f3733SSergio Gonzalez Monroy printf("\nTX stats:\n"); 396850f3733SSergio Gonzalez Monroy printf(" - Pkts deqd from tx ring: %"PRIu64"\n", 397850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts); 398850f3733SSergio Gonzalez Monroy printf(" - Ro Pkts transmitted: %"PRIu64"\n", 399850f3733SSergio Gonzalez Monroy app_stats.tx.ro_tx_pkts); 400850f3733SSergio Gonzalez Monroy printf(" - Ro Pkts tx failed: %"PRIu64"\n", 401850f3733SSergio Gonzalez Monroy app_stats.tx.ro_tx_failed_pkts); 402850f3733SSergio Gonzalez Monroy printf(" - Pkts transmitted w/o reorder: %"PRIu64"\n", 403850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_txtd_woro); 404850f3733SSergio Gonzalez Monroy printf(" - Pkts tx failed w/o reorder: %"PRIu64"\n", 405850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_tx_failed_woro); 406850f3733SSergio Gonzalez Monroy 4078728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(i) { 408850f3733SSergio Gonzalez Monroy rte_eth_stats_get(i, ð_stats); 409850f3733SSergio Gonzalez Monroy printf("\nPort %u stats:\n", i); 410850f3733SSergio Gonzalez Monroy printf(" - Pkts in: %"PRIu64"\n", eth_stats.ipackets); 411850f3733SSergio Gonzalez Monroy printf(" - Pkts out: %"PRIu64"\n", eth_stats.opackets); 412850f3733SSergio Gonzalez Monroy printf(" - In Errs: %"PRIu64"\n", eth_stats.ierrors); 413850f3733SSergio Gonzalez Monroy printf(" - Out Errs: %"PRIu64"\n", eth_stats.oerrors); 414850f3733SSergio Gonzalez Monroy printf(" - Mbuf Errs: %"PRIu64"\n", eth_stats.rx_nombuf); 415850f3733SSergio Gonzalez Monroy } 416850f3733SSergio Gonzalez Monroy } 417850f3733SSergio Gonzalez Monroy 418850f3733SSergio Gonzalez Monroy static void 419850f3733SSergio Gonzalez Monroy int_handler(int sig_num) 420850f3733SSergio Gonzalez Monroy { 421850f3733SSergio Gonzalez Monroy printf("Exiting on signal %d\n", sig_num); 422850f3733SSergio Gonzalez Monroy quit_signal = 1; 423850f3733SSergio Gonzalez Monroy } 424850f3733SSergio Gonzalez Monroy 425850f3733SSergio Gonzalez Monroy /** 426850f3733SSergio Gonzalez Monroy * This thread receives mbufs from the port and affects them an internal 427850f3733SSergio Gonzalez Monroy * sequence number to keep track of their order of arrival through an 428850f3733SSergio Gonzalez Monroy * mbuf structure. 429850f3733SSergio Gonzalez Monroy * The mbufs are then passed to the worker threads via the rx_to_workers 430850f3733SSergio Gonzalez Monroy * ring. 431850f3733SSergio Gonzalez Monroy */ 432850f3733SSergio Gonzalez Monroy static int 433850f3733SSergio Gonzalez Monroy rx_thread(struct rte_ring *ring_out) 434850f3733SSergio Gonzalez Monroy { 435850f3733SSergio Gonzalez Monroy uint32_t seqn = 0; 436850f3733SSergio Gonzalez Monroy uint16_t i, ret = 0; 437850f3733SSergio Gonzalez Monroy uint16_t nb_rx_pkts; 438f8244c63SZhiyong Yang uint16_t port_id; 439850f3733SSergio Gonzalez Monroy struct rte_mbuf *pkts[MAX_PKTS_BURST]; 440850f3733SSergio Gonzalez Monroy 441850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 442850f3733SSergio Gonzalez Monroy rte_lcore_id()); 443850f3733SSergio Gonzalez Monroy 444850f3733SSergio Gonzalez Monroy while (!quit_signal) { 445850f3733SSergio Gonzalez Monroy 4468728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 447850f3733SSergio Gonzalez Monroy if ((portmask & (1 << port_id)) != 0) { 448850f3733SSergio Gonzalez Monroy 449850f3733SSergio Gonzalez Monroy /* receive packets */ 450850f3733SSergio Gonzalez Monroy nb_rx_pkts = rte_eth_rx_burst(port_id, 0, 451850f3733SSergio Gonzalez Monroy pkts, MAX_PKTS_BURST); 452850f3733SSergio Gonzalez Monroy if (nb_rx_pkts == 0) { 4535d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, 454850f3733SSergio Gonzalez Monroy "%s():Received zero packets\n", __func__); 455850f3733SSergio Gonzalez Monroy continue; 456850f3733SSergio Gonzalez Monroy } 457850f3733SSergio Gonzalez Monroy app_stats.rx.rx_pkts += nb_rx_pkts; 458850f3733SSergio Gonzalez Monroy 459850f3733SSergio Gonzalez Monroy /* mark sequence number */ 460850f3733SSergio Gonzalez Monroy for (i = 0; i < nb_rx_pkts; ) 46101f34966SDavid Marchand *rte_reorder_seqn(pkts[i++]) = seqn++; 462850f3733SSergio Gonzalez Monroy 463850f3733SSergio Gonzalez Monroy /* enqueue to rx_to_workers ring */ 46414fbffb0SBruce Richardson ret = rte_ring_enqueue_burst(ring_out, 46514fbffb0SBruce Richardson (void *)pkts, nb_rx_pkts, NULL); 466850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_pkts += ret; 467850f3733SSergio Gonzalez Monroy if (unlikely(ret < nb_rx_pkts)) { 468850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_failed_pkts += 469850f3733SSergio Gonzalez Monroy (nb_rx_pkts-ret); 470850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(&pkts[ret], nb_rx_pkts - ret); 471850f3733SSergio Gonzalez Monroy } 472850f3733SSergio Gonzalez Monroy } 473850f3733SSergio Gonzalez Monroy } 474850f3733SSergio Gonzalez Monroy } 475850f3733SSergio Gonzalez Monroy return 0; 476850f3733SSergio Gonzalez Monroy } 477850f3733SSergio Gonzalez Monroy 478850f3733SSergio Gonzalez Monroy /** 479850f3733SSergio Gonzalez Monroy * This thread takes bursts of packets from the rx_to_workers ring and 480850f3733SSergio Gonzalez Monroy * Changes the input port value to output port value. And feds it to 481850f3733SSergio Gonzalez Monroy * workers_to_tx 482850f3733SSergio Gonzalez Monroy */ 483850f3733SSergio Gonzalez Monroy static int 484850f3733SSergio Gonzalez Monroy worker_thread(void *args_ptr) 485850f3733SSergio Gonzalez Monroy { 486d9a42a69SThomas Monjalon const uint16_t nb_ports = rte_eth_dev_count_avail(); 487850f3733SSergio Gonzalez Monroy uint16_t i, ret = 0; 488850f3733SSergio Gonzalez Monroy uint16_t burst_size = 0; 489850f3733SSergio Gonzalez Monroy struct worker_thread_args *args; 490850f3733SSergio Gonzalez Monroy struct rte_mbuf *burst_buffer[MAX_PKTS_BURST] = { NULL }; 491850f3733SSergio Gonzalez Monroy struct rte_ring *ring_in, *ring_out; 492850f3733SSergio Gonzalez Monroy const unsigned xor_val = (nb_ports > 1); 49301649330SPhil Yang unsigned int core_id = rte_lcore_id(); 494850f3733SSergio Gonzalez Monroy 495850f3733SSergio Gonzalez Monroy args = (struct worker_thread_args *) args_ptr; 496850f3733SSergio Gonzalez Monroy ring_in = args->ring_in; 497850f3733SSergio Gonzalez Monroy ring_out = args->ring_out; 498850f3733SSergio Gonzalez Monroy 499850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 50001649330SPhil Yang core_id); 501850f3733SSergio Gonzalez Monroy 502850f3733SSergio Gonzalez Monroy while (!quit_signal) { 503850f3733SSergio Gonzalez Monroy 504850f3733SSergio Gonzalez Monroy /* dequeue the mbufs from rx_to_workers ring */ 505850f3733SSergio Gonzalez Monroy burst_size = rte_ring_dequeue_burst(ring_in, 506ecaed092SBruce Richardson (void *)burst_buffer, MAX_PKTS_BURST, NULL); 507850f3733SSergio Gonzalez Monroy if (unlikely(burst_size == 0)) 508850f3733SSergio Gonzalez Monroy continue; 509850f3733SSergio Gonzalez Monroy 51001649330SPhil Yang wkr_stats[core_id].deq_pkts += burst_size; 511850f3733SSergio Gonzalez Monroy 512850f3733SSergio Gonzalez Monroy /* just do some operation on mbuf */ 513850f3733SSergio Gonzalez Monroy for (i = 0; i < burst_size;) 514850f3733SSergio Gonzalez Monroy burst_buffer[i++]->port ^= xor_val; 515850f3733SSergio Gonzalez Monroy 516850f3733SSergio Gonzalez Monroy /* enqueue the modified mbufs to workers_to_tx ring */ 51714fbffb0SBruce Richardson ret = rte_ring_enqueue_burst(ring_out, (void *)burst_buffer, 51814fbffb0SBruce Richardson burst_size, NULL); 51901649330SPhil Yang wkr_stats[core_id].enq_pkts += ret; 520850f3733SSergio Gonzalez Monroy if (unlikely(ret < burst_size)) { 521850f3733SSergio Gonzalez Monroy /* Return the mbufs to their respective pool, dropping packets */ 52201649330SPhil Yang wkr_stats[core_id].enq_failed_pkts += burst_size - ret; 523850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(&burst_buffer[ret], burst_size - ret); 524850f3733SSergio Gonzalez Monroy } 525850f3733SSergio Gonzalez Monroy } 526850f3733SSergio Gonzalez Monroy return 0; 527850f3733SSergio Gonzalez Monroy } 528850f3733SSergio Gonzalez Monroy 529850f3733SSergio Gonzalez Monroy /** 530850f3733SSergio Gonzalez Monroy * Dequeue mbufs from the workers_to_tx ring and reorder them before 531850f3733SSergio Gonzalez Monroy * transmitting. 532850f3733SSergio Gonzalez Monroy */ 533850f3733SSergio Gonzalez Monroy static int 5346ebc23d8SSergio Gonzalez Monroy send_thread(struct send_thread_args *args) 535850f3733SSergio Gonzalez Monroy { 536850f3733SSergio Gonzalez Monroy int ret; 537850f3733SSergio Gonzalez Monroy unsigned int i, dret; 538850f3733SSergio Gonzalez Monroy uint16_t nb_dq_mbufs; 539850f3733SSergio Gonzalez Monroy uint8_t outp; 540e2366e74STomasz Kulasek unsigned sent; 541850f3733SSergio Gonzalez Monroy struct rte_mbuf *mbufs[MAX_PKTS_BURST]; 542850f3733SSergio Gonzalez Monroy struct rte_mbuf *rombufs[MAX_PKTS_BURST] = {NULL}; 543e2366e74STomasz Kulasek static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 544850f3733SSergio Gonzalez Monroy 5456ebc23d8SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); 5466ebc23d8SSergio Gonzalez Monroy 547e2366e74STomasz Kulasek configure_tx_buffers(tx_buffer); 548e2366e74STomasz Kulasek 549850f3733SSergio Gonzalez Monroy while (!quit_signal) { 550850f3733SSergio Gonzalez Monroy 551850f3733SSergio Gonzalez Monroy /* deque the mbufs from workers_to_tx ring */ 5526ebc23d8SSergio Gonzalez Monroy nb_dq_mbufs = rte_ring_dequeue_burst(args->ring_in, 553ecaed092SBruce Richardson (void *)mbufs, MAX_PKTS_BURST, NULL); 554850f3733SSergio Gonzalez Monroy 555850f3733SSergio Gonzalez Monroy if (unlikely(nb_dq_mbufs == 0)) 556850f3733SSergio Gonzalez Monroy continue; 557850f3733SSergio Gonzalez Monroy 558850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts += nb_dq_mbufs; 559850f3733SSergio Gonzalez Monroy 560850f3733SSergio Gonzalez Monroy for (i = 0; i < nb_dq_mbufs; i++) { 561850f3733SSergio Gonzalez Monroy /* send dequeued mbufs for reordering */ 5626ebc23d8SSergio Gonzalez Monroy ret = rte_reorder_insert(args->buffer, mbufs[i]); 563850f3733SSergio Gonzalez Monroy 564850f3733SSergio Gonzalez Monroy if (ret == -1 && rte_errno == ERANGE) { 565850f3733SSergio Gonzalez Monroy /* Too early pkts should be transmitted out directly */ 5665d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, 5671f49ec15SThomas Monjalon "%s():Cannot reorder early packet " 568850f3733SSergio Gonzalez Monroy "direct enqueuing to TX\n", __func__); 569850f3733SSergio Gonzalez Monroy outp = mbufs[i]->port; 570850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp)) == 0) { 571850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 572850f3733SSergio Gonzalez Monroy continue; 573850f3733SSergio Gonzalez Monroy } 574850f3733SSergio Gonzalez Monroy if (rte_eth_tx_burst(outp, 0, (void *)mbufs[i], 1) != 1) { 575850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 576850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_tx_failed_woro++; 577850f3733SSergio Gonzalez Monroy } else 578850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_txtd_woro++; 579850f3733SSergio Gonzalez Monroy } else if (ret == -1 && rte_errno == ENOSPC) { 580850f3733SSergio Gonzalez Monroy /** 581850f3733SSergio Gonzalez Monroy * Early pkts just outside of window should be dropped 582850f3733SSergio Gonzalez Monroy */ 583850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 584850f3733SSergio Gonzalez Monroy } 585850f3733SSergio Gonzalez Monroy } 586850f3733SSergio Gonzalez Monroy 587850f3733SSergio Gonzalez Monroy /* 588850f3733SSergio Gonzalez Monroy * drain MAX_PKTS_BURST of reordered 589850f3733SSergio Gonzalez Monroy * mbufs for transmit 590850f3733SSergio Gonzalez Monroy */ 5916ebc23d8SSergio Gonzalez Monroy dret = rte_reorder_drain(args->buffer, rombufs, MAX_PKTS_BURST); 592850f3733SSergio Gonzalez Monroy for (i = 0; i < dret; i++) { 593850f3733SSergio Gonzalez Monroy 594e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *outbuf; 595850f3733SSergio Gonzalez Monroy uint8_t outp1; 596850f3733SSergio Gonzalez Monroy 597850f3733SSergio Gonzalez Monroy outp1 = rombufs[i]->port; 598850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 599850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp1)) == 0) { 600850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(rombufs[i]); 601850f3733SSergio Gonzalez Monroy continue; 602850f3733SSergio Gonzalez Monroy } 603850f3733SSergio Gonzalez Monroy 604e2366e74STomasz Kulasek outbuf = tx_buffer[outp1]; 605e2366e74STomasz Kulasek sent = rte_eth_tx_buffer(outp1, 0, outbuf, rombufs[i]); 606e2366e74STomasz Kulasek if (sent) 607e2366e74STomasz Kulasek app_stats.tx.ro_tx_pkts += sent; 608850f3733SSergio Gonzalez Monroy } 609850f3733SSergio Gonzalez Monroy } 610e2366e74STomasz Kulasek 611e2366e74STomasz Kulasek free_tx_buffers(tx_buffer); 612e2366e74STomasz Kulasek 613850f3733SSergio Gonzalez Monroy return 0; 614850f3733SSergio Gonzalez Monroy } 615850f3733SSergio Gonzalez Monroy 616850f3733SSergio Gonzalez Monroy /** 617850f3733SSergio Gonzalez Monroy * Dequeue mbufs from the workers_to_tx ring and transmit them 618850f3733SSergio Gonzalez Monroy */ 619850f3733SSergio Gonzalez Monroy static int 620850f3733SSergio Gonzalez Monroy tx_thread(struct rte_ring *ring_in) 621850f3733SSergio Gonzalez Monroy { 622850f3733SSergio Gonzalez Monroy uint32_t i, dqnum; 623850f3733SSergio Gonzalez Monroy uint8_t outp; 624e2366e74STomasz Kulasek unsigned sent; 625850f3733SSergio Gonzalez Monroy struct rte_mbuf *mbufs[MAX_PKTS_BURST]; 626e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *outbuf; 627e2366e74STomasz Kulasek static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 628850f3733SSergio Gonzalez Monroy 629850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 630850f3733SSergio Gonzalez Monroy rte_lcore_id()); 631e2366e74STomasz Kulasek 632e2366e74STomasz Kulasek configure_tx_buffers(tx_buffer); 633e2366e74STomasz Kulasek 634850f3733SSergio Gonzalez Monroy while (!quit_signal) { 635850f3733SSergio Gonzalez Monroy 636850f3733SSergio Gonzalez Monroy /* deque the mbufs from workers_to_tx ring */ 637850f3733SSergio Gonzalez Monroy dqnum = rte_ring_dequeue_burst(ring_in, 638ecaed092SBruce Richardson (void *)mbufs, MAX_PKTS_BURST, NULL); 639850f3733SSergio Gonzalez Monroy 640850f3733SSergio Gonzalez Monroy if (unlikely(dqnum == 0)) 641850f3733SSergio Gonzalez Monroy continue; 642850f3733SSergio Gonzalez Monroy 643850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts += dqnum; 644850f3733SSergio Gonzalez Monroy 645850f3733SSergio Gonzalez Monroy for (i = 0; i < dqnum; i++) { 646850f3733SSergio Gonzalez Monroy outp = mbufs[i]->port; 647850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 648850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp)) == 0) { 649850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 650850f3733SSergio Gonzalez Monroy continue; 651850f3733SSergio Gonzalez Monroy } 652850f3733SSergio Gonzalez Monroy 653e2366e74STomasz Kulasek outbuf = tx_buffer[outp]; 654e2366e74STomasz Kulasek sent = rte_eth_tx_buffer(outp, 0, outbuf, mbufs[i]); 655e2366e74STomasz Kulasek if (sent) 656e2366e74STomasz Kulasek app_stats.tx.ro_tx_pkts += sent; 657850f3733SSergio Gonzalez Monroy } 658850f3733SSergio Gonzalez Monroy } 659850f3733SSergio Gonzalez Monroy 660850f3733SSergio Gonzalez Monroy return 0; 661850f3733SSergio Gonzalez Monroy } 662850f3733SSergio Gonzalez Monroy 663850f3733SSergio Gonzalez Monroy int 664850f3733SSergio Gonzalez Monroy main(int argc, char **argv) 665850f3733SSergio Gonzalez Monroy { 666850f3733SSergio Gonzalez Monroy int ret; 667850f3733SSergio Gonzalez Monroy unsigned nb_ports; 668cb056611SStephen Hemminger unsigned int lcore_id, last_lcore_id, main_lcore_id; 669f8244c63SZhiyong Yang uint16_t port_id; 670f8244c63SZhiyong Yang uint16_t nb_ports_available; 671850f3733SSergio Gonzalez Monroy struct worker_thread_args worker_args = {NULL, NULL}; 6726ebc23d8SSergio Gonzalez Monroy struct send_thread_args send_args = {NULL, NULL}; 673850f3733SSergio Gonzalez Monroy struct rte_ring *rx_to_workers; 674850f3733SSergio Gonzalez Monroy struct rte_ring *workers_to_tx; 675850f3733SSergio Gonzalez Monroy 676850f3733SSergio Gonzalez Monroy /* catch ctrl-c so we can print on exit */ 677850f3733SSergio Gonzalez Monroy signal(SIGINT, int_handler); 678850f3733SSergio Gonzalez Monroy 679850f3733SSergio Gonzalez Monroy /* Initialize EAL */ 680850f3733SSergio Gonzalez Monroy ret = rte_eal_init(argc, argv); 681850f3733SSergio Gonzalez Monroy if (ret < 0) 682d74fab8eSSarosh Arif rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); 683850f3733SSergio Gonzalez Monroy 684850f3733SSergio Gonzalez Monroy argc -= ret; 685850f3733SSergio Gonzalez Monroy argv += ret; 686850f3733SSergio Gonzalez Monroy 687850f3733SSergio Gonzalez Monroy /* Parse the application specific arguments */ 688850f3733SSergio Gonzalez Monroy ret = parse_args(argc, argv); 689850f3733SSergio Gonzalez Monroy if (ret < 0) 690d74fab8eSSarosh Arif rte_exit(EXIT_FAILURE, "Invalid packet_ordering arguments\n"); 691850f3733SSergio Gonzalez Monroy 692850f3733SSergio Gonzalez Monroy /* Check if we have enought cores */ 693850f3733SSergio Gonzalez Monroy if (rte_lcore_count() < 3) 694850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error, This application needs at " 695850f3733SSergio Gonzalez Monroy "least 3 logical cores to run:\n" 696850f3733SSergio Gonzalez Monroy "1 lcore for packet RX\n" 697850f3733SSergio Gonzalez Monroy "1 lcore for packet TX\n" 698850f3733SSergio Gonzalez Monroy "and at least 1 lcore for worker threads\n"); 699850f3733SSergio Gonzalez Monroy 700d9a42a69SThomas Monjalon nb_ports = rte_eth_dev_count_avail(); 701850f3733SSergio Gonzalez Monroy if (nb_ports == 0) 702850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); 703850f3733SSergio Gonzalez Monroy if (nb_ports != 1 && (nb_ports & 1)) 704850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error: number of ports must be even, except " 705850f3733SSergio Gonzalez Monroy "when using a single port\n"); 706850f3733SSergio Gonzalez Monroy 707ea0c20eaSOlivier Matz mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 708824cb29cSKonstantin Ananyev MBUF_POOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, 709ea0c20eaSOlivier Matz rte_socket_id()); 710850f3733SSergio Gonzalez Monroy if (mbuf_pool == NULL) 711850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 712850f3733SSergio Gonzalez Monroy 713850f3733SSergio Gonzalez Monroy nb_ports_available = nb_ports; 714850f3733SSergio Gonzalez Monroy 715850f3733SSergio Gonzalez Monroy /* initialize all ports */ 7168728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 717850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 718850f3733SSergio Gonzalez Monroy if ((portmask & (1 << port_id)) == 0) { 719850f3733SSergio Gonzalez Monroy printf("\nSkipping disabled port %d\n", port_id); 720850f3733SSergio Gonzalez Monroy nb_ports_available--; 721850f3733SSergio Gonzalez Monroy continue; 722850f3733SSergio Gonzalez Monroy } 723850f3733SSergio Gonzalez Monroy /* init port */ 724f8244c63SZhiyong Yang printf("Initializing port %u... done\n", port_id); 725850f3733SSergio Gonzalez Monroy 726850f3733SSergio Gonzalez Monroy if (configure_eth_port(port_id) != 0) 727850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Cannot initialize port %"PRIu8"\n", 728850f3733SSergio Gonzalez Monroy port_id); 729850f3733SSergio Gonzalez Monroy } 730850f3733SSergio Gonzalez Monroy 731850f3733SSergio Gonzalez Monroy if (!nb_ports_available) { 732850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, 733850f3733SSergio Gonzalez Monroy "All available ports are disabled. Please set portmask.\n"); 734850f3733SSergio Gonzalez Monroy } 735850f3733SSergio Gonzalez Monroy 736850f3733SSergio Gonzalez Monroy /* Create rings for inter core communication */ 737850f3733SSergio Gonzalez Monroy rx_to_workers = rte_ring_create("rx_to_workers", RING_SIZE, rte_socket_id(), 738850f3733SSergio Gonzalez Monroy RING_F_SP_ENQ); 739850f3733SSergio Gonzalez Monroy if (rx_to_workers == NULL) 740850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 741850f3733SSergio Gonzalez Monroy 742850f3733SSergio Gonzalez Monroy workers_to_tx = rte_ring_create("workers_to_tx", RING_SIZE, rte_socket_id(), 743850f3733SSergio Gonzalez Monroy RING_F_SC_DEQ); 744850f3733SSergio Gonzalez Monroy if (workers_to_tx == NULL) 745850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 746850f3733SSergio Gonzalez Monroy 7476ebc23d8SSergio Gonzalez Monroy if (!disable_reorder) { 7486ebc23d8SSergio Gonzalez Monroy send_args.buffer = rte_reorder_create("PKT_RO", rte_socket_id(), 7496ebc23d8SSergio Gonzalez Monroy REORDER_BUFFER_SIZE); 7506ebc23d8SSergio Gonzalez Monroy if (send_args.buffer == NULL) 7516ebc23d8SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 7526ebc23d8SSergio Gonzalez Monroy } 7536ebc23d8SSergio Gonzalez Monroy 754850f3733SSergio Gonzalez Monroy last_lcore_id = get_last_lcore_id(); 755cb056611SStephen Hemminger main_lcore_id = rte_get_main_lcore(); 756850f3733SSergio Gonzalez Monroy 757850f3733SSergio Gonzalez Monroy worker_args.ring_in = rx_to_workers; 758850f3733SSergio Gonzalez Monroy worker_args.ring_out = workers_to_tx; 759850f3733SSergio Gonzalez Monroy 760cb056611SStephen Hemminger /* Start worker_thread() on all the available worker cores but the last 1 */ 761850f3733SSergio Gonzalez Monroy for (lcore_id = 0; lcore_id <= get_previous_lcore_id(last_lcore_id); lcore_id++) 762cb056611SStephen Hemminger if (rte_lcore_is_enabled(lcore_id) && lcore_id != main_lcore_id) 763850f3733SSergio Gonzalez Monroy rte_eal_remote_launch(worker_thread, (void *)&worker_args, 764850f3733SSergio Gonzalez Monroy lcore_id); 765850f3733SSergio Gonzalez Monroy 7666ebc23d8SSergio Gonzalez Monroy if (disable_reorder) { 767cb056611SStephen Hemminger /* Start tx_thread() on the last worker core */ 768850f3733SSergio Gonzalez Monroy rte_eal_remote_launch((lcore_function_t *)tx_thread, workers_to_tx, 769850f3733SSergio Gonzalez Monroy last_lcore_id); 7706ebc23d8SSergio Gonzalez Monroy } else { 7716ebc23d8SSergio Gonzalez Monroy send_args.ring_in = workers_to_tx; 772cb056611SStephen Hemminger /* Start send_thread() on the last worker core */ 7736ebc23d8SSergio Gonzalez Monroy rte_eal_remote_launch((lcore_function_t *)send_thread, 7746ebc23d8SSergio Gonzalez Monroy (void *)&send_args, last_lcore_id); 7756ebc23d8SSergio Gonzalez Monroy } 776850f3733SSergio Gonzalez Monroy 777cb056611SStephen Hemminger /* Start rx_thread() on the main core */ 778850f3733SSergio Gonzalez Monroy rx_thread(rx_to_workers); 779850f3733SSergio Gonzalez Monroy 780cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore_id) { 781850f3733SSergio Gonzalez Monroy if (rte_eal_wait_lcore(lcore_id) < 0) 782850f3733SSergio Gonzalez Monroy return -1; 783850f3733SSergio Gonzalez Monroy } 784850f3733SSergio Gonzalez Monroy 785850f3733SSergio Gonzalez Monroy print_stats(); 786850f3733SSergio Gonzalez Monroy return 0; 787850f3733SSergio Gonzalez Monroy } 788