1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <unistd.h> 6 #include <stdint.h> 7 8 #include <rte_log.h> 9 #include <rte_mbuf.h> 10 #include <rte_malloc.h> 11 #include <rte_cycles.h> 12 #include <rte_ethdev.h> 13 #include <rte_memcpy.h> 14 #include <rte_byteorder.h> 15 #include <rte_branch_prediction.h> 16 17 #include <rte_sched.h> 18 19 #include "main.h" 20 21 #define APP_MODE_NONE 0 22 #define APP_RX_MODE 1 23 #define APP_WT_MODE 2 24 #define APP_TX_MODE 4 25 26 uint8_t interactive = APP_INTERACTIVE_DEFAULT; 27 uint32_t qavg_period = APP_QAVG_PERIOD; 28 uint32_t qavg_ntimes = APP_QAVG_NTIMES; 29 30 /* main processing loop */ 31 static int 32 app_main_loop(__attribute__((unused))void *dummy) 33 { 34 uint32_t lcore_id; 35 uint32_t i, mode; 36 uint32_t rx_idx = 0; 37 uint32_t wt_idx = 0; 38 uint32_t tx_idx = 0; 39 struct thread_conf *rx_confs[MAX_DATA_STREAMS]; 40 struct thread_conf *wt_confs[MAX_DATA_STREAMS]; 41 struct thread_conf *tx_confs[MAX_DATA_STREAMS]; 42 43 memset(rx_confs, 0, sizeof(rx_confs)); 44 memset(wt_confs, 0, sizeof(wt_confs)); 45 memset(tx_confs, 0, sizeof(tx_confs)); 46 47 48 mode = APP_MODE_NONE; 49 lcore_id = rte_lcore_id(); 50 51 for (i = 0; i < nb_pfc; i++) { 52 struct flow_conf *flow = &qos_conf[i]; 53 54 if (flow->rx_core == lcore_id) { 55 flow->rx_thread.rx_port = flow->rx_port; 56 flow->rx_thread.rx_ring = flow->rx_ring; 57 flow->rx_thread.rx_queue = flow->rx_queue; 58 59 rx_confs[rx_idx++] = &flow->rx_thread; 60 61 mode |= APP_RX_MODE; 62 } 63 if (flow->tx_core == lcore_id) { 64 flow->tx_thread.tx_port = flow->tx_port; 65 flow->tx_thread.tx_ring = flow->tx_ring; 66 flow->tx_thread.tx_queue = flow->tx_queue; 67 68 tx_confs[tx_idx++] = &flow->tx_thread; 69 70 mode |= APP_TX_MODE; 71 } 72 if (flow->wt_core == lcore_id) { 73 flow->wt_thread.rx_ring = flow->rx_ring; 74 flow->wt_thread.tx_ring = flow->tx_ring; 75 flow->wt_thread.tx_port = flow->tx_port; 76 flow->wt_thread.sched_port = flow->sched_port; 77 78 wt_confs[wt_idx++] = &flow->wt_thread; 79 80 mode |= APP_WT_MODE; 81 } 82 } 83 84 if (mode == APP_MODE_NONE) { 85 RTE_LOG(INFO, APP, "lcore %u has nothing to do\n", lcore_id); 86 return -1; 87 } 88 89 if (mode == (APP_RX_MODE | APP_WT_MODE)) { 90 RTE_LOG(INFO, APP, "lcore %u was configured for both RX and WT !!!\n", 91 lcore_id); 92 return -1; 93 } 94 95 RTE_LOG(INFO, APP, "entering main loop on lcore %u\n", lcore_id); 96 /* initialize mbuf memory */ 97 if (mode == APP_RX_MODE) { 98 for (i = 0; i < rx_idx; i++) { 99 RTE_LOG(INFO, APP, "flow%u lcoreid%u reading port%u\n", 100 i, lcore_id, rx_confs[i]->rx_port); 101 } 102 103 app_rx_thread(rx_confs); 104 } 105 else if (mode == (APP_TX_MODE | APP_WT_MODE)) { 106 for (i = 0; i < wt_idx; i++) { 107 wt_confs[i]->m_table = rte_malloc("table_wt", sizeof(struct rte_mbuf *) 108 * burst_conf.tx_burst, RTE_CACHE_LINE_SIZE); 109 110 if (wt_confs[i]->m_table == NULL) 111 rte_panic("flow %u unable to allocate memory buffer\n", i); 112 113 RTE_LOG(INFO, APP, 114 "flow %u lcoreid %u sched+write port %u\n", 115 i, lcore_id, wt_confs[i]->tx_port); 116 } 117 118 app_mixed_thread(wt_confs); 119 } 120 else if (mode == APP_TX_MODE) { 121 for (i = 0; i < tx_idx; i++) { 122 tx_confs[i]->m_table = rte_malloc("table_tx", sizeof(struct rte_mbuf *) 123 * burst_conf.tx_burst, RTE_CACHE_LINE_SIZE); 124 125 if (tx_confs[i]->m_table == NULL) 126 rte_panic("flow %u unable to allocate memory buffer\n", i); 127 128 RTE_LOG(INFO, APP, "flow%u lcoreid%u write port%u\n", 129 i, lcore_id, tx_confs[i]->tx_port); 130 } 131 132 app_tx_thread(tx_confs); 133 } 134 else if (mode == APP_WT_MODE){ 135 for (i = 0; i < wt_idx; i++) { 136 RTE_LOG(INFO, APP, "flow %u lcoreid %u scheduling \n", i, lcore_id); 137 } 138 139 app_worker_thread(wt_confs); 140 } 141 142 return 0; 143 } 144 145 void 146 app_stat(void) 147 { 148 uint32_t i; 149 struct rte_eth_stats stats; 150 static struct rte_eth_stats rx_stats[MAX_DATA_STREAMS]; 151 static struct rte_eth_stats tx_stats[MAX_DATA_STREAMS]; 152 153 /* print statistics */ 154 for(i = 0; i < nb_pfc; i++) { 155 struct flow_conf *flow = &qos_conf[i]; 156 157 rte_eth_stats_get(flow->rx_port, &stats); 158 printf("\nRX port %"PRIu16": rx: %"PRIu64 " err: %"PRIu64 159 " no_mbuf: %"PRIu64 "\n", 160 flow->rx_port, 161 stats.ipackets - rx_stats[i].ipackets, 162 stats.ierrors - rx_stats[i].ierrors, 163 stats.rx_nombuf - rx_stats[i].rx_nombuf); 164 memcpy(&rx_stats[i], &stats, sizeof(stats)); 165 166 rte_eth_stats_get(flow->tx_port, &stats); 167 printf("TX port %"PRIu16": tx: %" PRIu64 " err: %" PRIu64 "\n", 168 flow->tx_port, 169 stats.opackets - tx_stats[i].opackets, 170 stats.oerrors - tx_stats[i].oerrors); 171 memcpy(&tx_stats[i], &stats, sizeof(stats)); 172 173 #if APP_COLLECT_STAT 174 printf("-------+------------+------------+\n"); 175 printf(" | received | dropped |\n"); 176 printf("-------+------------+------------+\n"); 177 printf(" RX | %10" PRIu64 " | %10" PRIu64 " |\n", 178 flow->rx_thread.stat.nb_rx, 179 flow->rx_thread.stat.nb_drop); 180 printf("QOS+TX | %10" PRIu64 " | %10" PRIu64 " | pps: %"PRIu64 " \n", 181 flow->wt_thread.stat.nb_rx, 182 flow->wt_thread.stat.nb_drop, 183 flow->wt_thread.stat.nb_rx - flow->wt_thread.stat.nb_drop); 184 printf("-------+------------+------------+\n"); 185 186 memset(&flow->rx_thread.stat, 0, sizeof(struct thread_stat)); 187 memset(&flow->wt_thread.stat, 0, sizeof(struct thread_stat)); 188 #endif 189 } 190 } 191 192 int 193 main(int argc, char **argv) 194 { 195 int ret; 196 197 ret = app_parse_args(argc, argv); 198 if (ret < 0) 199 return -1; 200 201 ret = app_init(); 202 if (ret < 0) 203 return -1; 204 205 /* launch per-lcore init on every lcore */ 206 rte_eal_mp_remote_launch(app_main_loop, NULL, SKIP_MASTER); 207 208 if (interactive) { 209 sleep(1); 210 prompt(); 211 } 212 else { 213 /* print statistics every second */ 214 while(1) { 215 sleep(1); 216 app_stat(); 217 } 218 } 219 220 return 0; 221 } 222