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')) 146*ce6b8c31SSarosh Arif return 0; 147850f3733SSergio Gonzalez Monroy 148850f3733SSergio Gonzalez Monroy return pm; 149850f3733SSergio Gonzalez Monroy } 150850f3733SSergio Gonzalez Monroy 151850f3733SSergio Gonzalez Monroy /* Parse the argument given in the command line of the application */ 152850f3733SSergio Gonzalez Monroy static int 153850f3733SSergio Gonzalez Monroy parse_args(int argc, char **argv) 154850f3733SSergio Gonzalez Monroy { 155850f3733SSergio Gonzalez Monroy int opt; 156850f3733SSergio Gonzalez Monroy int option_index; 157850f3733SSergio Gonzalez Monroy char **argvopt; 158850f3733SSergio Gonzalez Monroy char *prgname = argv[0]; 159850f3733SSergio Gonzalez Monroy static struct option lgopts[] = { 160850f3733SSergio Gonzalez Monroy {"disable-reorder", 0, 0, 0}, 16101649330SPhil Yang {"insight-worker", 0, 0, 0}, 162850f3733SSergio Gonzalez Monroy {NULL, 0, 0, 0} 163850f3733SSergio Gonzalez Monroy }; 164850f3733SSergio Gonzalez Monroy 165850f3733SSergio Gonzalez Monroy argvopt = argv; 166850f3733SSergio Gonzalez Monroy 167850f3733SSergio Gonzalez Monroy while ((opt = getopt_long(argc, argvopt, "p:", 168850f3733SSergio Gonzalez Monroy lgopts, &option_index)) != EOF) { 169850f3733SSergio Gonzalez Monroy switch (opt) { 170850f3733SSergio Gonzalez Monroy /* portmask */ 171850f3733SSergio Gonzalez Monroy case 'p': 172850f3733SSergio Gonzalez Monroy portmask = parse_portmask(optarg); 173850f3733SSergio Gonzalez Monroy if (portmask == 0) { 174850f3733SSergio Gonzalez Monroy printf("invalid portmask\n"); 175850f3733SSergio Gonzalez Monroy print_usage(prgname); 176850f3733SSergio Gonzalez Monroy return -1; 177850f3733SSergio Gonzalez Monroy } 178850f3733SSergio Gonzalez Monroy break; 179850f3733SSergio Gonzalez Monroy /* long options */ 180850f3733SSergio Gonzalez Monroy case 0: 181850f3733SSergio Gonzalez Monroy if (!strcmp(lgopts[option_index].name, "disable-reorder")) { 182850f3733SSergio Gonzalez Monroy printf("reorder disabled\n"); 183850f3733SSergio Gonzalez Monroy disable_reorder = 1; 184850f3733SSergio Gonzalez Monroy } 18501649330SPhil Yang if (!strcmp(lgopts[option_index].name, 18601649330SPhil Yang "insight-worker")) { 18701649330SPhil Yang printf("print all worker statistics\n"); 18801649330SPhil Yang insight_worker = 1; 18901649330SPhil Yang } 190850f3733SSergio Gonzalez Monroy break; 191850f3733SSergio Gonzalez Monroy default: 192850f3733SSergio Gonzalez Monroy print_usage(prgname); 193850f3733SSergio Gonzalez Monroy return -1; 194850f3733SSergio Gonzalez Monroy } 195850f3733SSergio Gonzalez Monroy } 196850f3733SSergio Gonzalez Monroy if (optind <= 1) { 197850f3733SSergio Gonzalez Monroy print_usage(prgname); 198850f3733SSergio Gonzalez Monroy return -1; 199850f3733SSergio Gonzalez Monroy } 200850f3733SSergio Gonzalez Monroy 201850f3733SSergio Gonzalez Monroy argv[optind-1] = prgname; 2029d5ca532SKeith Wiles optind = 1; /* reset getopt lib */ 203850f3733SSergio Gonzalez Monroy return 0; 204850f3733SSergio Gonzalez Monroy } 205850f3733SSergio Gonzalez Monroy 206e2366e74STomasz Kulasek /* 207e2366e74STomasz Kulasek * Tx buffer error callback 208e2366e74STomasz Kulasek */ 209e2366e74STomasz Kulasek static void 210e2366e74STomasz Kulasek flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count, 211e2366e74STomasz Kulasek void *userdata __rte_unused) { 212e2366e74STomasz Kulasek 213e2366e74STomasz Kulasek /* free the mbufs which failed from transmit */ 214e2366e74STomasz Kulasek app_stats.tx.ro_tx_failed_pkts += count; 2155d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, "%s:Packet loss with tx_burst\n", __func__); 216e2366e74STomasz Kulasek pktmbuf_free_bulk(unsent, count); 217e2366e74STomasz Kulasek 218e2366e74STomasz Kulasek } 219e2366e74STomasz Kulasek 220e2366e74STomasz Kulasek static inline int 221e2366e74STomasz Kulasek free_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) { 2228728ccf3SThomas Monjalon uint16_t port_id; 223e2366e74STomasz Kulasek 224e2366e74STomasz Kulasek /* initialize buffers for all ports */ 2258728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 226e2366e74STomasz Kulasek /* skip ports that are not enabled */ 227e2366e74STomasz Kulasek if ((portmask & (1 << port_id)) == 0) 228e2366e74STomasz Kulasek continue; 229e2366e74STomasz Kulasek 230e2366e74STomasz Kulasek rte_free(tx_buffer[port_id]); 231e2366e74STomasz Kulasek } 232e2366e74STomasz Kulasek return 0; 233e2366e74STomasz Kulasek } 234e2366e74STomasz Kulasek 235e2366e74STomasz Kulasek static inline int 236e2366e74STomasz Kulasek configure_tx_buffers(struct rte_eth_dev_tx_buffer *tx_buffer[]) 237e2366e74STomasz Kulasek { 2388728ccf3SThomas Monjalon uint16_t port_id; 239e2366e74STomasz Kulasek int ret; 240e2366e74STomasz Kulasek 241e2366e74STomasz Kulasek /* initialize buffers for all ports */ 2428728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 243e2366e74STomasz Kulasek /* skip ports that are not enabled */ 244e2366e74STomasz Kulasek if ((portmask & (1 << port_id)) == 0) 245e2366e74STomasz Kulasek continue; 246e2366e74STomasz Kulasek 247e2366e74STomasz Kulasek /* Initialize TX buffers */ 248e2366e74STomasz Kulasek tx_buffer[port_id] = rte_zmalloc_socket("tx_buffer", 249e2366e74STomasz Kulasek RTE_ETH_TX_BUFFER_SIZE(MAX_PKTS_BURST), 0, 250e2366e74STomasz Kulasek rte_eth_dev_socket_id(port_id)); 251e2366e74STomasz Kulasek if (tx_buffer[port_id] == NULL) 252e2366e74STomasz Kulasek rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", 253f8244c63SZhiyong Yang port_id); 254e2366e74STomasz Kulasek 255e2366e74STomasz Kulasek rte_eth_tx_buffer_init(tx_buffer[port_id], MAX_PKTS_BURST); 256e2366e74STomasz Kulasek 257e2366e74STomasz Kulasek ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[port_id], 258e2366e74STomasz Kulasek flush_tx_error_callback, NULL); 259e2366e74STomasz Kulasek if (ret < 0) 260f8244c63SZhiyong Yang rte_exit(EXIT_FAILURE, 261f8244c63SZhiyong Yang "Cannot set error callback for tx buffer on port %u\n", 262f8244c63SZhiyong Yang port_id); 263e2366e74STomasz Kulasek } 264e2366e74STomasz Kulasek return 0; 265e2366e74STomasz Kulasek } 266e2366e74STomasz Kulasek 267850f3733SSergio Gonzalez Monroy static inline int 268f8244c63SZhiyong Yang configure_eth_port(uint16_t port_id) 269850f3733SSergio Gonzalez Monroy { 2706d13ea8eSOlivier Matz struct rte_ether_addr addr; 271850f3733SSergio Gonzalez Monroy const uint16_t rxRings = 1, txRings = 1; 272850f3733SSergio Gonzalez Monroy int ret; 273850f3733SSergio Gonzalez Monroy uint16_t q; 27460efb44fSRoman Zhukov uint16_t nb_rxd = RX_DESC_PER_QUEUE; 27560efb44fSRoman Zhukov uint16_t nb_txd = TX_DESC_PER_QUEUE; 2766833f919SShahaf Shuler struct rte_eth_dev_info dev_info; 2776833f919SShahaf Shuler struct rte_eth_txconf txconf; 2786833f919SShahaf Shuler struct rte_eth_conf port_conf = port_conf_default; 279850f3733SSergio Gonzalez Monroy 280a9dbe180SThomas Monjalon if (!rte_eth_dev_is_valid_port(port_id)) 281850f3733SSergio Gonzalez Monroy return -1; 282850f3733SSergio Gonzalez Monroy 283089e5ed7SIvan Ilchenko ret = rte_eth_dev_info_get(port_id, &dev_info); 284089e5ed7SIvan Ilchenko if (ret != 0) { 285089e5ed7SIvan Ilchenko printf("Error during getting device (port %u) info: %s\n", 286089e5ed7SIvan Ilchenko port_id, strerror(-ret)); 287089e5ed7SIvan Ilchenko return ret; 288089e5ed7SIvan Ilchenko } 289089e5ed7SIvan Ilchenko 2906833f919SShahaf Shuler if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) 2916833f919SShahaf Shuler port_conf.txmode.offloads |= 2926833f919SShahaf Shuler DEV_TX_OFFLOAD_MBUF_FAST_FREE; 293850f3733SSergio Gonzalez Monroy ret = rte_eth_dev_configure(port_id, rxRings, txRings, &port_conf_default); 294850f3733SSergio Gonzalez Monroy if (ret != 0) 295850f3733SSergio Gonzalez Monroy return ret; 296850f3733SSergio Gonzalez Monroy 29760efb44fSRoman Zhukov ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd); 29860efb44fSRoman Zhukov if (ret != 0) 29960efb44fSRoman Zhukov return ret; 30060efb44fSRoman Zhukov 301850f3733SSergio Gonzalez Monroy for (q = 0; q < rxRings; q++) { 30260efb44fSRoman Zhukov ret = rte_eth_rx_queue_setup(port_id, q, nb_rxd, 303850f3733SSergio Gonzalez Monroy rte_eth_dev_socket_id(port_id), NULL, 304850f3733SSergio Gonzalez Monroy mbuf_pool); 305850f3733SSergio Gonzalez Monroy if (ret < 0) 306850f3733SSergio Gonzalez Monroy return ret; 307850f3733SSergio Gonzalez Monroy } 308850f3733SSergio Gonzalez Monroy 3096833f919SShahaf Shuler txconf = dev_info.default_txconf; 3106833f919SShahaf Shuler txconf.offloads = port_conf.txmode.offloads; 311850f3733SSergio Gonzalez Monroy for (q = 0; q < txRings; q++) { 31260efb44fSRoman Zhukov ret = rte_eth_tx_queue_setup(port_id, q, nb_txd, 3136833f919SShahaf Shuler rte_eth_dev_socket_id(port_id), &txconf); 314850f3733SSergio Gonzalez Monroy if (ret < 0) 315850f3733SSergio Gonzalez Monroy return ret; 316850f3733SSergio Gonzalez Monroy } 317850f3733SSergio Gonzalez Monroy 318850f3733SSergio Gonzalez Monroy ret = rte_eth_dev_start(port_id); 319850f3733SSergio Gonzalez Monroy if (ret < 0) 320850f3733SSergio Gonzalez Monroy return ret; 321850f3733SSergio Gonzalez Monroy 32270febdcfSIgor Romanov ret = rte_eth_macaddr_get(port_id, &addr); 32370febdcfSIgor Romanov if (ret != 0) { 32470febdcfSIgor Romanov printf("Failed to get MAC address (port %u): %s\n", 32570febdcfSIgor Romanov port_id, rte_strerror(-ret)); 32670febdcfSIgor Romanov return ret; 32770febdcfSIgor Romanov } 32870febdcfSIgor Romanov 329850f3733SSergio Gonzalez Monroy printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8 330850f3733SSergio Gonzalez Monroy " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", 331f8244c63SZhiyong Yang port_id, 332850f3733SSergio Gonzalez Monroy addr.addr_bytes[0], addr.addr_bytes[1], 333850f3733SSergio Gonzalez Monroy addr.addr_bytes[2], addr.addr_bytes[3], 334850f3733SSergio Gonzalez Monroy addr.addr_bytes[4], addr.addr_bytes[5]); 335850f3733SSergio Gonzalez Monroy 336f430bbceSIvan Ilchenko ret = rte_eth_promiscuous_enable(port_id); 337f430bbceSIvan Ilchenko if (ret != 0) 338f430bbceSIvan Ilchenko return ret; 339850f3733SSergio Gonzalez Monroy 340850f3733SSergio Gonzalez Monroy return 0; 341850f3733SSergio Gonzalez Monroy } 342850f3733SSergio Gonzalez Monroy 343850f3733SSergio Gonzalez Monroy static void 344850f3733SSergio Gonzalez Monroy print_stats(void) 345850f3733SSergio Gonzalez Monroy { 3468728ccf3SThomas Monjalon uint16_t i; 347850f3733SSergio Gonzalez Monroy struct rte_eth_stats eth_stats; 34801649330SPhil Yang unsigned int lcore_id, last_lcore_id, master_lcore_id, end_w_lcore_id; 34901649330SPhil Yang 35001649330SPhil Yang last_lcore_id = get_last_lcore_id(); 35101649330SPhil Yang master_lcore_id = rte_get_master_lcore(); 35201649330SPhil Yang end_w_lcore_id = get_previous_lcore_id(last_lcore_id); 353850f3733SSergio Gonzalez Monroy 354850f3733SSergio Gonzalez Monroy printf("\nRX thread stats:\n"); 355850f3733SSergio Gonzalez Monroy printf(" - Pkts rxd: %"PRIu64"\n", 356850f3733SSergio Gonzalez Monroy app_stats.rx.rx_pkts); 357850f3733SSergio Gonzalez Monroy printf(" - Pkts enqd to workers ring: %"PRIu64"\n", 358850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_pkts); 359850f3733SSergio Gonzalez Monroy 36001649330SPhil Yang for (lcore_id = 0; lcore_id <= end_w_lcore_id; lcore_id++) { 36101649330SPhil Yang if (insight_worker 36201649330SPhil Yang && rte_lcore_is_enabled(lcore_id) 36301649330SPhil Yang && lcore_id != master_lcore_id) { 36401649330SPhil Yang printf("\nWorker thread stats on core [%u]:\n", 36501649330SPhil Yang lcore_id); 36601649330SPhil Yang printf(" - Pkts deqd from workers ring: %"PRIu64"\n", 36701649330SPhil Yang wkr_stats[lcore_id].deq_pkts); 36801649330SPhil Yang printf(" - Pkts enqd to tx ring: %"PRIu64"\n", 36901649330SPhil Yang wkr_stats[lcore_id].enq_pkts); 37001649330SPhil Yang printf(" - Pkts enq to tx failed: %"PRIu64"\n", 37101649330SPhil Yang wkr_stats[lcore_id].enq_failed_pkts); 37201649330SPhil Yang } 37301649330SPhil Yang 37401649330SPhil Yang app_stats.wkr.dequeue_pkts += wkr_stats[lcore_id].deq_pkts; 37501649330SPhil Yang app_stats.wkr.enqueue_pkts += wkr_stats[lcore_id].enq_pkts; 37601649330SPhil Yang app_stats.wkr.enqueue_failed_pkts += 37701649330SPhil Yang wkr_stats[lcore_id].enq_failed_pkts; 37801649330SPhil Yang } 37901649330SPhil Yang 380850f3733SSergio Gonzalez Monroy printf("\nWorker thread stats:\n"); 381850f3733SSergio Gonzalez Monroy printf(" - Pkts deqd from workers ring: %"PRIu64"\n", 382850f3733SSergio Gonzalez Monroy app_stats.wkr.dequeue_pkts); 383850f3733SSergio Gonzalez Monroy printf(" - Pkts enqd to tx ring: %"PRIu64"\n", 384850f3733SSergio Gonzalez Monroy app_stats.wkr.enqueue_pkts); 385850f3733SSergio Gonzalez Monroy printf(" - Pkts enq to tx failed: %"PRIu64"\n", 386850f3733SSergio Gonzalez Monroy app_stats.wkr.enqueue_failed_pkts); 387850f3733SSergio Gonzalez Monroy 388850f3733SSergio Gonzalez Monroy printf("\nTX stats:\n"); 389850f3733SSergio Gonzalez Monroy printf(" - Pkts deqd from tx ring: %"PRIu64"\n", 390850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts); 391850f3733SSergio Gonzalez Monroy printf(" - Ro Pkts transmitted: %"PRIu64"\n", 392850f3733SSergio Gonzalez Monroy app_stats.tx.ro_tx_pkts); 393850f3733SSergio Gonzalez Monroy printf(" - Ro Pkts tx failed: %"PRIu64"\n", 394850f3733SSergio Gonzalez Monroy app_stats.tx.ro_tx_failed_pkts); 395850f3733SSergio Gonzalez Monroy printf(" - Pkts transmitted w/o reorder: %"PRIu64"\n", 396850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_txtd_woro); 397850f3733SSergio Gonzalez Monroy printf(" - Pkts tx failed w/o reorder: %"PRIu64"\n", 398850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_tx_failed_woro); 399850f3733SSergio Gonzalez Monroy 4008728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(i) { 401850f3733SSergio Gonzalez Monroy rte_eth_stats_get(i, ð_stats); 402850f3733SSergio Gonzalez Monroy printf("\nPort %u stats:\n", i); 403850f3733SSergio Gonzalez Monroy printf(" - Pkts in: %"PRIu64"\n", eth_stats.ipackets); 404850f3733SSergio Gonzalez Monroy printf(" - Pkts out: %"PRIu64"\n", eth_stats.opackets); 405850f3733SSergio Gonzalez Monroy printf(" - In Errs: %"PRIu64"\n", eth_stats.ierrors); 406850f3733SSergio Gonzalez Monroy printf(" - Out Errs: %"PRIu64"\n", eth_stats.oerrors); 407850f3733SSergio Gonzalez Monroy printf(" - Mbuf Errs: %"PRIu64"\n", eth_stats.rx_nombuf); 408850f3733SSergio Gonzalez Monroy } 409850f3733SSergio Gonzalez Monroy } 410850f3733SSergio Gonzalez Monroy 411850f3733SSergio Gonzalez Monroy static void 412850f3733SSergio Gonzalez Monroy int_handler(int sig_num) 413850f3733SSergio Gonzalez Monroy { 414850f3733SSergio Gonzalez Monroy printf("Exiting on signal %d\n", sig_num); 415850f3733SSergio Gonzalez Monroy quit_signal = 1; 416850f3733SSergio Gonzalez Monroy } 417850f3733SSergio Gonzalez Monroy 418850f3733SSergio Gonzalez Monroy /** 419850f3733SSergio Gonzalez Monroy * This thread receives mbufs from the port and affects them an internal 420850f3733SSergio Gonzalez Monroy * sequence number to keep track of their order of arrival through an 421850f3733SSergio Gonzalez Monroy * mbuf structure. 422850f3733SSergio Gonzalez Monroy * The mbufs are then passed to the worker threads via the rx_to_workers 423850f3733SSergio Gonzalez Monroy * ring. 424850f3733SSergio Gonzalez Monroy */ 425850f3733SSergio Gonzalez Monroy static int 426850f3733SSergio Gonzalez Monroy rx_thread(struct rte_ring *ring_out) 427850f3733SSergio Gonzalez Monroy { 428850f3733SSergio Gonzalez Monroy uint32_t seqn = 0; 429850f3733SSergio Gonzalez Monroy uint16_t i, ret = 0; 430850f3733SSergio Gonzalez Monroy uint16_t nb_rx_pkts; 431f8244c63SZhiyong Yang uint16_t port_id; 432850f3733SSergio Gonzalez Monroy struct rte_mbuf *pkts[MAX_PKTS_BURST]; 433850f3733SSergio Gonzalez Monroy 434850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 435850f3733SSergio Gonzalez Monroy rte_lcore_id()); 436850f3733SSergio Gonzalez Monroy 437850f3733SSergio Gonzalez Monroy while (!quit_signal) { 438850f3733SSergio Gonzalez Monroy 4398728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 440850f3733SSergio Gonzalez Monroy if ((portmask & (1 << port_id)) != 0) { 441850f3733SSergio Gonzalez Monroy 442850f3733SSergio Gonzalez Monroy /* receive packets */ 443850f3733SSergio Gonzalez Monroy nb_rx_pkts = rte_eth_rx_burst(port_id, 0, 444850f3733SSergio Gonzalez Monroy pkts, MAX_PKTS_BURST); 445850f3733SSergio Gonzalez Monroy if (nb_rx_pkts == 0) { 4465d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, 447850f3733SSergio Gonzalez Monroy "%s():Received zero packets\n", __func__); 448850f3733SSergio Gonzalez Monroy continue; 449850f3733SSergio Gonzalez Monroy } 450850f3733SSergio Gonzalez Monroy app_stats.rx.rx_pkts += nb_rx_pkts; 451850f3733SSergio Gonzalez Monroy 452850f3733SSergio Gonzalez Monroy /* mark sequence number */ 453850f3733SSergio Gonzalez Monroy for (i = 0; i < nb_rx_pkts; ) 454850f3733SSergio Gonzalez Monroy pkts[i++]->seqn = seqn++; 455850f3733SSergio Gonzalez Monroy 456850f3733SSergio Gonzalez Monroy /* enqueue to rx_to_workers ring */ 45714fbffb0SBruce Richardson ret = rte_ring_enqueue_burst(ring_out, 45814fbffb0SBruce Richardson (void *)pkts, nb_rx_pkts, NULL); 459850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_pkts += ret; 460850f3733SSergio Gonzalez Monroy if (unlikely(ret < nb_rx_pkts)) { 461850f3733SSergio Gonzalez Monroy app_stats.rx.enqueue_failed_pkts += 462850f3733SSergio Gonzalez Monroy (nb_rx_pkts-ret); 463850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(&pkts[ret], nb_rx_pkts - ret); 464850f3733SSergio Gonzalez Monroy } 465850f3733SSergio Gonzalez Monroy } 466850f3733SSergio Gonzalez Monroy } 467850f3733SSergio Gonzalez Monroy } 468850f3733SSergio Gonzalez Monroy return 0; 469850f3733SSergio Gonzalez Monroy } 470850f3733SSergio Gonzalez Monroy 471850f3733SSergio Gonzalez Monroy /** 472850f3733SSergio Gonzalez Monroy * This thread takes bursts of packets from the rx_to_workers ring and 473850f3733SSergio Gonzalez Monroy * Changes the input port value to output port value. And feds it to 474850f3733SSergio Gonzalez Monroy * workers_to_tx 475850f3733SSergio Gonzalez Monroy */ 476850f3733SSergio Gonzalez Monroy static int 477850f3733SSergio Gonzalez Monroy worker_thread(void *args_ptr) 478850f3733SSergio Gonzalez Monroy { 479d9a42a69SThomas Monjalon const uint16_t nb_ports = rte_eth_dev_count_avail(); 480850f3733SSergio Gonzalez Monroy uint16_t i, ret = 0; 481850f3733SSergio Gonzalez Monroy uint16_t burst_size = 0; 482850f3733SSergio Gonzalez Monroy struct worker_thread_args *args; 483850f3733SSergio Gonzalez Monroy struct rte_mbuf *burst_buffer[MAX_PKTS_BURST] = { NULL }; 484850f3733SSergio Gonzalez Monroy struct rte_ring *ring_in, *ring_out; 485850f3733SSergio Gonzalez Monroy const unsigned xor_val = (nb_ports > 1); 48601649330SPhil Yang unsigned int core_id = rte_lcore_id(); 487850f3733SSergio Gonzalez Monroy 488850f3733SSergio Gonzalez Monroy args = (struct worker_thread_args *) args_ptr; 489850f3733SSergio Gonzalez Monroy ring_in = args->ring_in; 490850f3733SSergio Gonzalez Monroy ring_out = args->ring_out; 491850f3733SSergio Gonzalez Monroy 492850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 49301649330SPhil Yang core_id); 494850f3733SSergio Gonzalez Monroy 495850f3733SSergio Gonzalez Monroy while (!quit_signal) { 496850f3733SSergio Gonzalez Monroy 497850f3733SSergio Gonzalez Monroy /* dequeue the mbufs from rx_to_workers ring */ 498850f3733SSergio Gonzalez Monroy burst_size = rte_ring_dequeue_burst(ring_in, 499ecaed092SBruce Richardson (void *)burst_buffer, MAX_PKTS_BURST, NULL); 500850f3733SSergio Gonzalez Monroy if (unlikely(burst_size == 0)) 501850f3733SSergio Gonzalez Monroy continue; 502850f3733SSergio Gonzalez Monroy 50301649330SPhil Yang wkr_stats[core_id].deq_pkts += burst_size; 504850f3733SSergio Gonzalez Monroy 505850f3733SSergio Gonzalez Monroy /* just do some operation on mbuf */ 506850f3733SSergio Gonzalez Monroy for (i = 0; i < burst_size;) 507850f3733SSergio Gonzalez Monroy burst_buffer[i++]->port ^= xor_val; 508850f3733SSergio Gonzalez Monroy 509850f3733SSergio Gonzalez Monroy /* enqueue the modified mbufs to workers_to_tx ring */ 51014fbffb0SBruce Richardson ret = rte_ring_enqueue_burst(ring_out, (void *)burst_buffer, 51114fbffb0SBruce Richardson burst_size, NULL); 51201649330SPhil Yang wkr_stats[core_id].enq_pkts += ret; 513850f3733SSergio Gonzalez Monroy if (unlikely(ret < burst_size)) { 514850f3733SSergio Gonzalez Monroy /* Return the mbufs to their respective pool, dropping packets */ 51501649330SPhil Yang wkr_stats[core_id].enq_failed_pkts += burst_size - ret; 516850f3733SSergio Gonzalez Monroy pktmbuf_free_bulk(&burst_buffer[ret], burst_size - ret); 517850f3733SSergio Gonzalez Monroy } 518850f3733SSergio Gonzalez Monroy } 519850f3733SSergio Gonzalez Monroy return 0; 520850f3733SSergio Gonzalez Monroy } 521850f3733SSergio Gonzalez Monroy 522850f3733SSergio Gonzalez Monroy /** 523850f3733SSergio Gonzalez Monroy * Dequeue mbufs from the workers_to_tx ring and reorder them before 524850f3733SSergio Gonzalez Monroy * transmitting. 525850f3733SSergio Gonzalez Monroy */ 526850f3733SSergio Gonzalez Monroy static int 5276ebc23d8SSergio Gonzalez Monroy send_thread(struct send_thread_args *args) 528850f3733SSergio Gonzalez Monroy { 529850f3733SSergio Gonzalez Monroy int ret; 530850f3733SSergio Gonzalez Monroy unsigned int i, dret; 531850f3733SSergio Gonzalez Monroy uint16_t nb_dq_mbufs; 532850f3733SSergio Gonzalez Monroy uint8_t outp; 533e2366e74STomasz Kulasek unsigned sent; 534850f3733SSergio Gonzalez Monroy struct rte_mbuf *mbufs[MAX_PKTS_BURST]; 535850f3733SSergio Gonzalez Monroy struct rte_mbuf *rombufs[MAX_PKTS_BURST] = {NULL}; 536e2366e74STomasz Kulasek static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 537850f3733SSergio Gonzalez Monroy 5386ebc23d8SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, rte_lcore_id()); 5396ebc23d8SSergio Gonzalez Monroy 540e2366e74STomasz Kulasek configure_tx_buffers(tx_buffer); 541e2366e74STomasz Kulasek 542850f3733SSergio Gonzalez Monroy while (!quit_signal) { 543850f3733SSergio Gonzalez Monroy 544850f3733SSergio Gonzalez Monroy /* deque the mbufs from workers_to_tx ring */ 5456ebc23d8SSergio Gonzalez Monroy nb_dq_mbufs = rte_ring_dequeue_burst(args->ring_in, 546ecaed092SBruce Richardson (void *)mbufs, MAX_PKTS_BURST, NULL); 547850f3733SSergio Gonzalez Monroy 548850f3733SSergio Gonzalez Monroy if (unlikely(nb_dq_mbufs == 0)) 549850f3733SSergio Gonzalez Monroy continue; 550850f3733SSergio Gonzalez Monroy 551850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts += nb_dq_mbufs; 552850f3733SSergio Gonzalez Monroy 553850f3733SSergio Gonzalez Monroy for (i = 0; i < nb_dq_mbufs; i++) { 554850f3733SSergio Gonzalez Monroy /* send dequeued mbufs for reordering */ 5556ebc23d8SSergio Gonzalez Monroy ret = rte_reorder_insert(args->buffer, mbufs[i]); 556850f3733SSergio Gonzalez Monroy 557850f3733SSergio Gonzalez Monroy if (ret == -1 && rte_errno == ERANGE) { 558850f3733SSergio Gonzalez Monroy /* Too early pkts should be transmitted out directly */ 5595d8f0bafSOlivier Matz RTE_LOG_DP(DEBUG, REORDERAPP, 5601f49ec15SThomas Monjalon "%s():Cannot reorder early packet " 561850f3733SSergio Gonzalez Monroy "direct enqueuing to TX\n", __func__); 562850f3733SSergio Gonzalez Monroy outp = mbufs[i]->port; 563850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp)) == 0) { 564850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 565850f3733SSergio Gonzalez Monroy continue; 566850f3733SSergio Gonzalez Monroy } 567850f3733SSergio Gonzalez Monroy if (rte_eth_tx_burst(outp, 0, (void *)mbufs[i], 1) != 1) { 568850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 569850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_tx_failed_woro++; 570850f3733SSergio Gonzalez Monroy } else 571850f3733SSergio Gonzalez Monroy app_stats.tx.early_pkts_txtd_woro++; 572850f3733SSergio Gonzalez Monroy } else if (ret == -1 && rte_errno == ENOSPC) { 573850f3733SSergio Gonzalez Monroy /** 574850f3733SSergio Gonzalez Monroy * Early pkts just outside of window should be dropped 575850f3733SSergio Gonzalez Monroy */ 576850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 577850f3733SSergio Gonzalez Monroy } 578850f3733SSergio Gonzalez Monroy } 579850f3733SSergio Gonzalez Monroy 580850f3733SSergio Gonzalez Monroy /* 581850f3733SSergio Gonzalez Monroy * drain MAX_PKTS_BURST of reordered 582850f3733SSergio Gonzalez Monroy * mbufs for transmit 583850f3733SSergio Gonzalez Monroy */ 5846ebc23d8SSergio Gonzalez Monroy dret = rte_reorder_drain(args->buffer, rombufs, MAX_PKTS_BURST); 585850f3733SSergio Gonzalez Monroy for (i = 0; i < dret; i++) { 586850f3733SSergio Gonzalez Monroy 587e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *outbuf; 588850f3733SSergio Gonzalez Monroy uint8_t outp1; 589850f3733SSergio Gonzalez Monroy 590850f3733SSergio Gonzalez Monroy outp1 = rombufs[i]->port; 591850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 592850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp1)) == 0) { 593850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(rombufs[i]); 594850f3733SSergio Gonzalez Monroy continue; 595850f3733SSergio Gonzalez Monroy } 596850f3733SSergio Gonzalez Monroy 597e2366e74STomasz Kulasek outbuf = tx_buffer[outp1]; 598e2366e74STomasz Kulasek sent = rte_eth_tx_buffer(outp1, 0, outbuf, rombufs[i]); 599e2366e74STomasz Kulasek if (sent) 600e2366e74STomasz Kulasek app_stats.tx.ro_tx_pkts += sent; 601850f3733SSergio Gonzalez Monroy } 602850f3733SSergio Gonzalez Monroy } 603e2366e74STomasz Kulasek 604e2366e74STomasz Kulasek free_tx_buffers(tx_buffer); 605e2366e74STomasz Kulasek 606850f3733SSergio Gonzalez Monroy return 0; 607850f3733SSergio Gonzalez Monroy } 608850f3733SSergio Gonzalez Monroy 609850f3733SSergio Gonzalez Monroy /** 610850f3733SSergio Gonzalez Monroy * Dequeue mbufs from the workers_to_tx ring and transmit them 611850f3733SSergio Gonzalez Monroy */ 612850f3733SSergio Gonzalez Monroy static int 613850f3733SSergio Gonzalez Monroy tx_thread(struct rte_ring *ring_in) 614850f3733SSergio Gonzalez Monroy { 615850f3733SSergio Gonzalez Monroy uint32_t i, dqnum; 616850f3733SSergio Gonzalez Monroy uint8_t outp; 617e2366e74STomasz Kulasek unsigned sent; 618850f3733SSergio Gonzalez Monroy struct rte_mbuf *mbufs[MAX_PKTS_BURST]; 619e2366e74STomasz Kulasek struct rte_eth_dev_tx_buffer *outbuf; 620e2366e74STomasz Kulasek static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; 621850f3733SSergio Gonzalez Monroy 622850f3733SSergio Gonzalez Monroy RTE_LOG(INFO, REORDERAPP, "%s() started on lcore %u\n", __func__, 623850f3733SSergio Gonzalez Monroy rte_lcore_id()); 624e2366e74STomasz Kulasek 625e2366e74STomasz Kulasek configure_tx_buffers(tx_buffer); 626e2366e74STomasz Kulasek 627850f3733SSergio Gonzalez Monroy while (!quit_signal) { 628850f3733SSergio Gonzalez Monroy 629850f3733SSergio Gonzalez Monroy /* deque the mbufs from workers_to_tx ring */ 630850f3733SSergio Gonzalez Monroy dqnum = rte_ring_dequeue_burst(ring_in, 631ecaed092SBruce Richardson (void *)mbufs, MAX_PKTS_BURST, NULL); 632850f3733SSergio Gonzalez Monroy 633850f3733SSergio Gonzalez Monroy if (unlikely(dqnum == 0)) 634850f3733SSergio Gonzalez Monroy continue; 635850f3733SSergio Gonzalez Monroy 636850f3733SSergio Gonzalez Monroy app_stats.tx.dequeue_pkts += dqnum; 637850f3733SSergio Gonzalez Monroy 638850f3733SSergio Gonzalez Monroy for (i = 0; i < dqnum; i++) { 639850f3733SSergio Gonzalez Monroy outp = mbufs[i]->port; 640850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 641850f3733SSergio Gonzalez Monroy if ((portmask & (1 << outp)) == 0) { 642850f3733SSergio Gonzalez Monroy rte_pktmbuf_free(mbufs[i]); 643850f3733SSergio Gonzalez Monroy continue; 644850f3733SSergio Gonzalez Monroy } 645850f3733SSergio Gonzalez Monroy 646e2366e74STomasz Kulasek outbuf = tx_buffer[outp]; 647e2366e74STomasz Kulasek sent = rte_eth_tx_buffer(outp, 0, outbuf, mbufs[i]); 648e2366e74STomasz Kulasek if (sent) 649e2366e74STomasz Kulasek app_stats.tx.ro_tx_pkts += sent; 650850f3733SSergio Gonzalez Monroy } 651850f3733SSergio Gonzalez Monroy } 652850f3733SSergio Gonzalez Monroy 653850f3733SSergio Gonzalez Monroy return 0; 654850f3733SSergio Gonzalez Monroy } 655850f3733SSergio Gonzalez Monroy 656850f3733SSergio Gonzalez Monroy int 657850f3733SSergio Gonzalez Monroy main(int argc, char **argv) 658850f3733SSergio Gonzalez Monroy { 659850f3733SSergio Gonzalez Monroy int ret; 660850f3733SSergio Gonzalez Monroy unsigned nb_ports; 661850f3733SSergio Gonzalez Monroy unsigned int lcore_id, last_lcore_id, master_lcore_id; 662f8244c63SZhiyong Yang uint16_t port_id; 663f8244c63SZhiyong Yang uint16_t nb_ports_available; 664850f3733SSergio Gonzalez Monroy struct worker_thread_args worker_args = {NULL, NULL}; 6656ebc23d8SSergio Gonzalez Monroy struct send_thread_args send_args = {NULL, NULL}; 666850f3733SSergio Gonzalez Monroy struct rte_ring *rx_to_workers; 667850f3733SSergio Gonzalez Monroy struct rte_ring *workers_to_tx; 668850f3733SSergio Gonzalez Monroy 669850f3733SSergio Gonzalez Monroy /* catch ctrl-c so we can print on exit */ 670850f3733SSergio Gonzalez Monroy signal(SIGINT, int_handler); 671850f3733SSergio Gonzalez Monroy 672850f3733SSergio Gonzalez Monroy /* Initialize EAL */ 673850f3733SSergio Gonzalez Monroy ret = rte_eal_init(argc, argv); 674850f3733SSergio Gonzalez Monroy if (ret < 0) 675850f3733SSergio Gonzalez Monroy return -1; 676850f3733SSergio Gonzalez Monroy 677850f3733SSergio Gonzalez Monroy argc -= ret; 678850f3733SSergio Gonzalez Monroy argv += ret; 679850f3733SSergio Gonzalez Monroy 680850f3733SSergio Gonzalez Monroy /* Parse the application specific arguments */ 681850f3733SSergio Gonzalez Monroy ret = parse_args(argc, argv); 682850f3733SSergio Gonzalez Monroy if (ret < 0) 683850f3733SSergio Gonzalez Monroy return -1; 684850f3733SSergio Gonzalez Monroy 685850f3733SSergio Gonzalez Monroy /* Check if we have enought cores */ 686850f3733SSergio Gonzalez Monroy if (rte_lcore_count() < 3) 687850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error, This application needs at " 688850f3733SSergio Gonzalez Monroy "least 3 logical cores to run:\n" 689850f3733SSergio Gonzalez Monroy "1 lcore for packet RX\n" 690850f3733SSergio Gonzalez Monroy "1 lcore for packet TX\n" 691850f3733SSergio Gonzalez Monroy "and at least 1 lcore for worker threads\n"); 692850f3733SSergio Gonzalez Monroy 693d9a42a69SThomas Monjalon nb_ports = rte_eth_dev_count_avail(); 694850f3733SSergio Gonzalez Monroy if (nb_ports == 0) 695850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n"); 696850f3733SSergio Gonzalez Monroy if (nb_ports != 1 && (nb_ports & 1)) 697850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Error: number of ports must be even, except " 698850f3733SSergio Gonzalez Monroy "when using a single port\n"); 699850f3733SSergio Gonzalez Monroy 700ea0c20eaSOlivier Matz mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 701824cb29cSKonstantin Ananyev MBUF_POOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, 702ea0c20eaSOlivier Matz rte_socket_id()); 703850f3733SSergio Gonzalez Monroy if (mbuf_pool == NULL) 704850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 705850f3733SSergio Gonzalez Monroy 706850f3733SSergio Gonzalez Monroy nb_ports_available = nb_ports; 707850f3733SSergio Gonzalez Monroy 708850f3733SSergio Gonzalez Monroy /* initialize all ports */ 7098728ccf3SThomas Monjalon RTE_ETH_FOREACH_DEV(port_id) { 710850f3733SSergio Gonzalez Monroy /* skip ports that are not enabled */ 711850f3733SSergio Gonzalez Monroy if ((portmask & (1 << port_id)) == 0) { 712850f3733SSergio Gonzalez Monroy printf("\nSkipping disabled port %d\n", port_id); 713850f3733SSergio Gonzalez Monroy nb_ports_available--; 714850f3733SSergio Gonzalez Monroy continue; 715850f3733SSergio Gonzalez Monroy } 716850f3733SSergio Gonzalez Monroy /* init port */ 717f8244c63SZhiyong Yang printf("Initializing port %u... done\n", port_id); 718850f3733SSergio Gonzalez Monroy 719850f3733SSergio Gonzalez Monroy if (configure_eth_port(port_id) != 0) 720850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "Cannot initialize port %"PRIu8"\n", 721850f3733SSergio Gonzalez Monroy port_id); 722850f3733SSergio Gonzalez Monroy } 723850f3733SSergio Gonzalez Monroy 724850f3733SSergio Gonzalez Monroy if (!nb_ports_available) { 725850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, 726850f3733SSergio Gonzalez Monroy "All available ports are disabled. Please set portmask.\n"); 727850f3733SSergio Gonzalez Monroy } 728850f3733SSergio Gonzalez Monroy 729850f3733SSergio Gonzalez Monroy /* Create rings for inter core communication */ 730850f3733SSergio Gonzalez Monroy rx_to_workers = rte_ring_create("rx_to_workers", RING_SIZE, rte_socket_id(), 731850f3733SSergio Gonzalez Monroy RING_F_SP_ENQ); 732850f3733SSergio Gonzalez Monroy if (rx_to_workers == NULL) 733850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 734850f3733SSergio Gonzalez Monroy 735850f3733SSergio Gonzalez Monroy workers_to_tx = rte_ring_create("workers_to_tx", RING_SIZE, rte_socket_id(), 736850f3733SSergio Gonzalez Monroy RING_F_SC_DEQ); 737850f3733SSergio Gonzalez Monroy if (workers_to_tx == NULL) 738850f3733SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 739850f3733SSergio Gonzalez Monroy 7406ebc23d8SSergio Gonzalez Monroy if (!disable_reorder) { 7416ebc23d8SSergio Gonzalez Monroy send_args.buffer = rte_reorder_create("PKT_RO", rte_socket_id(), 7426ebc23d8SSergio Gonzalez Monroy REORDER_BUFFER_SIZE); 7436ebc23d8SSergio Gonzalez Monroy if (send_args.buffer == NULL) 7446ebc23d8SSergio Gonzalez Monroy rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); 7456ebc23d8SSergio Gonzalez Monroy } 7466ebc23d8SSergio Gonzalez Monroy 747850f3733SSergio Gonzalez Monroy last_lcore_id = get_last_lcore_id(); 748850f3733SSergio Gonzalez Monroy master_lcore_id = rte_get_master_lcore(); 749850f3733SSergio Gonzalez Monroy 750850f3733SSergio Gonzalez Monroy worker_args.ring_in = rx_to_workers; 751850f3733SSergio Gonzalez Monroy worker_args.ring_out = workers_to_tx; 752850f3733SSergio Gonzalez Monroy 753850f3733SSergio Gonzalez Monroy /* Start worker_thread() on all the available slave cores but the last 1 */ 754850f3733SSergio Gonzalez Monroy for (lcore_id = 0; lcore_id <= get_previous_lcore_id(last_lcore_id); lcore_id++) 755850f3733SSergio Gonzalez Monroy if (rte_lcore_is_enabled(lcore_id) && lcore_id != master_lcore_id) 756850f3733SSergio Gonzalez Monroy rte_eal_remote_launch(worker_thread, (void *)&worker_args, 757850f3733SSergio Gonzalez Monroy lcore_id); 758850f3733SSergio Gonzalez Monroy 7596ebc23d8SSergio Gonzalez Monroy if (disable_reorder) { 760850f3733SSergio Gonzalez Monroy /* Start tx_thread() on the last slave core */ 761850f3733SSergio Gonzalez Monroy rte_eal_remote_launch((lcore_function_t *)tx_thread, workers_to_tx, 762850f3733SSergio Gonzalez Monroy last_lcore_id); 7636ebc23d8SSergio Gonzalez Monroy } else { 7646ebc23d8SSergio Gonzalez Monroy send_args.ring_in = workers_to_tx; 765850f3733SSergio Gonzalez Monroy /* Start send_thread() on the last slave core */ 7666ebc23d8SSergio Gonzalez Monroy rte_eal_remote_launch((lcore_function_t *)send_thread, 7676ebc23d8SSergio Gonzalez Monroy (void *)&send_args, last_lcore_id); 7686ebc23d8SSergio Gonzalez Monroy } 769850f3733SSergio Gonzalez Monroy 770850f3733SSergio Gonzalez Monroy /* Start rx_thread() on the master core */ 771850f3733SSergio Gonzalez Monroy rx_thread(rx_to_workers); 772850f3733SSergio Gonzalez Monroy 773850f3733SSergio Gonzalez Monroy RTE_LCORE_FOREACH_SLAVE(lcore_id) { 774850f3733SSergio Gonzalez Monroy if (rte_eal_wait_lcore(lcore_id) < 0) 775850f3733SSergio Gonzalez Monroy return -1; 776850f3733SSergio Gonzalez Monroy } 777850f3733SSergio Gonzalez Monroy 778850f3733SSergio Gonzalez Monroy print_stats(); 779850f3733SSergio Gonzalez Monroy return 0; 780850f3733SSergio Gonzalez Monroy } 781