xref: /dpdk/examples/qos_sched/main.c (revision de3cfa2c9823a7e0391d4f4a355e2d78b83eec62)
1*de3cfa2cSIntel /*-
2*de3cfa2cSIntel  *   BSD LICENSE
3*de3cfa2cSIntel  *
4*de3cfa2cSIntel  *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
5*de3cfa2cSIntel  *   All rights reserved.
6*de3cfa2cSIntel  *
7*de3cfa2cSIntel  *   Redistribution and use in source and binary forms, with or without
8*de3cfa2cSIntel  *   modification, are permitted provided that the following conditions
9*de3cfa2cSIntel  *   are met:
10*de3cfa2cSIntel  *
11*de3cfa2cSIntel  *     * Redistributions of source code must retain the above copyright
12*de3cfa2cSIntel  *       notice, this list of conditions and the following disclaimer.
13*de3cfa2cSIntel  *     * Redistributions in binary form must reproduce the above copyright
14*de3cfa2cSIntel  *       notice, this list of conditions and the following disclaimer in
15*de3cfa2cSIntel  *       the documentation and/or other materials provided with the
16*de3cfa2cSIntel  *       distribution.
17*de3cfa2cSIntel  *     * Neither the name of Intel Corporation nor the names of its
18*de3cfa2cSIntel  *       contributors may be used to endorse or promote products derived
19*de3cfa2cSIntel  *       from this software without specific prior written permission.
20*de3cfa2cSIntel  *
21*de3cfa2cSIntel  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*de3cfa2cSIntel  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*de3cfa2cSIntel  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*de3cfa2cSIntel  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*de3cfa2cSIntel  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*de3cfa2cSIntel  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*de3cfa2cSIntel  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*de3cfa2cSIntel  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*de3cfa2cSIntel  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*de3cfa2cSIntel  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*de3cfa2cSIntel  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*de3cfa2cSIntel  *
33*de3cfa2cSIntel  */
34*de3cfa2cSIntel 
35*de3cfa2cSIntel #include <unistd.h>
36*de3cfa2cSIntel #include <stdint.h>
37*de3cfa2cSIntel 
38*de3cfa2cSIntel #include <rte_log.h>
39*de3cfa2cSIntel #include <rte_mbuf.h>
40*de3cfa2cSIntel #include <rte_malloc.h>
41*de3cfa2cSIntel #include <rte_cycles.h>
42*de3cfa2cSIntel #include <rte_ethdev.h>
43*de3cfa2cSIntel #include <rte_memcpy.h>
44*de3cfa2cSIntel #include <rte_byteorder.h>
45*de3cfa2cSIntel #include <rte_branch_prediction.h>
46*de3cfa2cSIntel 
47*de3cfa2cSIntel #include <rte_sched.h>
48*de3cfa2cSIntel 
49*de3cfa2cSIntel #include "main.h"
50*de3cfa2cSIntel 
51*de3cfa2cSIntel #define APP_MODE_NONE 0
52*de3cfa2cSIntel #define APP_RX_MODE   1
53*de3cfa2cSIntel #define APP_WT_MODE   2
54*de3cfa2cSIntel #define APP_TX_MODE   4
55*de3cfa2cSIntel 
56*de3cfa2cSIntel 
57*de3cfa2cSIntel /* main processing loop */
58*de3cfa2cSIntel static int
59*de3cfa2cSIntel app_main_loop(__attribute__((unused))void *dummy)
60*de3cfa2cSIntel {
61*de3cfa2cSIntel 	uint32_t lcore_id;
62*de3cfa2cSIntel 	uint32_t i, mode;
63*de3cfa2cSIntel 	uint32_t rx_idx = 0;
64*de3cfa2cSIntel 	uint32_t wt_idx = 0;
65*de3cfa2cSIntel 	uint32_t tx_idx = 0;
66*de3cfa2cSIntel 	struct thread_conf *rx_confs[MAX_DATA_STREAMS];
67*de3cfa2cSIntel 	struct thread_conf *wt_confs[MAX_DATA_STREAMS];
68*de3cfa2cSIntel 	struct thread_conf *tx_confs[MAX_DATA_STREAMS];
69*de3cfa2cSIntel 
70*de3cfa2cSIntel 	memset(rx_confs, 0, sizeof(rx_confs));
71*de3cfa2cSIntel 	memset(wt_confs, 0, sizeof(wt_confs));
72*de3cfa2cSIntel 	memset(tx_confs, 0, sizeof(tx_confs));
73*de3cfa2cSIntel 
74*de3cfa2cSIntel 
75*de3cfa2cSIntel 	mode = APP_MODE_NONE;
76*de3cfa2cSIntel 	lcore_id = rte_lcore_id();
77*de3cfa2cSIntel 
78*de3cfa2cSIntel 	for (i = 0; i < nb_pfc; i++) {
79*de3cfa2cSIntel 		struct flow_conf *flow = &qos_conf[i];
80*de3cfa2cSIntel 
81*de3cfa2cSIntel 		if (flow->rx_core == lcore_id) {
82*de3cfa2cSIntel 			flow->rx_thread.rx_port = flow->rx_port;
83*de3cfa2cSIntel 			flow->rx_thread.rx_ring =  flow->rx_ring;
84*de3cfa2cSIntel 			flow->rx_thread.rx_queue = flow->rx_queue;
85*de3cfa2cSIntel 
86*de3cfa2cSIntel 			rx_confs[rx_idx++] = &flow->rx_thread;
87*de3cfa2cSIntel 
88*de3cfa2cSIntel 			mode |= APP_RX_MODE;
89*de3cfa2cSIntel 		}
90*de3cfa2cSIntel 		if (flow->tx_core == lcore_id) {
91*de3cfa2cSIntel 			flow->tx_thread.tx_port = flow->tx_port;
92*de3cfa2cSIntel 			flow->tx_thread.tx_ring =  flow->tx_ring;
93*de3cfa2cSIntel 			flow->tx_thread.tx_queue = flow->tx_queue;
94*de3cfa2cSIntel 
95*de3cfa2cSIntel 			tx_confs[tx_idx++] = &flow->tx_thread;
96*de3cfa2cSIntel 
97*de3cfa2cSIntel 			mode |= APP_TX_MODE;
98*de3cfa2cSIntel 		}
99*de3cfa2cSIntel 		if (flow->wt_core == lcore_id) {
100*de3cfa2cSIntel 			flow->wt_thread.rx_ring =  flow->rx_ring;
101*de3cfa2cSIntel 			flow->wt_thread.tx_ring =  flow->tx_ring;
102*de3cfa2cSIntel 			flow->wt_thread.tx_port =  flow->tx_port;
103*de3cfa2cSIntel 			flow->wt_thread.sched_port =  flow->sched_port;
104*de3cfa2cSIntel 
105*de3cfa2cSIntel 			wt_confs[wt_idx++] = &flow->wt_thread;
106*de3cfa2cSIntel 
107*de3cfa2cSIntel 			mode |= APP_WT_MODE;
108*de3cfa2cSIntel 		}
109*de3cfa2cSIntel 	}
110*de3cfa2cSIntel 
111*de3cfa2cSIntel 	if (mode == APP_MODE_NONE) {
112*de3cfa2cSIntel 		RTE_LOG(INFO, APP, "lcore %u has nothing to do\n", lcore_id);
113*de3cfa2cSIntel 		return -1;
114*de3cfa2cSIntel 	}
115*de3cfa2cSIntel 
116*de3cfa2cSIntel 	if (mode == (APP_RX_MODE | APP_WT_MODE)) {
117*de3cfa2cSIntel 		RTE_LOG(INFO, APP, "lcore %u was configured for both RX and WT !!!\n",
118*de3cfa2cSIntel 				 lcore_id);
119*de3cfa2cSIntel 		return -1;
120*de3cfa2cSIntel 	}
121*de3cfa2cSIntel 
122*de3cfa2cSIntel 	RTE_LOG(INFO, APP, "entering main loop on lcore %u\n", lcore_id);
123*de3cfa2cSIntel 	/* initialize mbuf memory */
124*de3cfa2cSIntel 	if (mode == APP_RX_MODE) {
125*de3cfa2cSIntel 		for (i = 0; i < rx_idx; i++) {
126*de3cfa2cSIntel 			RTE_LOG(INFO, APP, "flow %u lcoreid %u reading port %hu\n",
127*de3cfa2cSIntel 				i, lcore_id, rx_confs[i]->rx_port);
128*de3cfa2cSIntel 		}
129*de3cfa2cSIntel 
130*de3cfa2cSIntel 		app_rx_thread(rx_confs);
131*de3cfa2cSIntel 	}
132*de3cfa2cSIntel 	else if (mode == (APP_TX_MODE | APP_WT_MODE)) {
133*de3cfa2cSIntel 		for (i = 0; i < wt_idx; i++) {
134*de3cfa2cSIntel 			wt_confs[i]->m_table = rte_malloc("table_wt", sizeof(struct rte_mbuf *)
135*de3cfa2cSIntel 					* burst_conf.tx_burst, CACHE_LINE_SIZE);
136*de3cfa2cSIntel 
137*de3cfa2cSIntel 			if (wt_confs[i]->m_table == NULL)
138*de3cfa2cSIntel 				rte_panic("flow %u unable to allocate memory buffer\n", i);
139*de3cfa2cSIntel 
140*de3cfa2cSIntel 			RTE_LOG(INFO, APP, "flow %u lcoreid %u sched+write port %hu\n",
141*de3cfa2cSIntel 				i, lcore_id, wt_confs[i]->tx_port);
142*de3cfa2cSIntel 		}
143*de3cfa2cSIntel 
144*de3cfa2cSIntel 		app_mixed_thread(wt_confs);
145*de3cfa2cSIntel 	}
146*de3cfa2cSIntel 	else if (mode == APP_TX_MODE) {
147*de3cfa2cSIntel 		for (i = 0; i < tx_idx; i++) {
148*de3cfa2cSIntel 			tx_confs[i]->m_table = rte_malloc("table_tx", sizeof(struct rte_mbuf *)
149*de3cfa2cSIntel 					* burst_conf.tx_burst, CACHE_LINE_SIZE);
150*de3cfa2cSIntel 
151*de3cfa2cSIntel 			if (tx_confs[i]->m_table == NULL)
152*de3cfa2cSIntel 				rte_panic("flow %u unable to allocate memory buffer\n", i);
153*de3cfa2cSIntel 
154*de3cfa2cSIntel 			RTE_LOG(INFO, APP, "flow %u lcoreid %u writing port %hu\n",
155*de3cfa2cSIntel 				i, lcore_id, tx_confs[i]->tx_port);
156*de3cfa2cSIntel 		}
157*de3cfa2cSIntel 
158*de3cfa2cSIntel 		app_tx_thread(tx_confs);
159*de3cfa2cSIntel 	}
160*de3cfa2cSIntel 	else if (mode == APP_WT_MODE){
161*de3cfa2cSIntel 		for (i = 0; i < wt_idx; i++) {
162*de3cfa2cSIntel 			RTE_LOG(INFO, APP, "flow %u lcoreid %u scheduling \n", i, lcore_id);
163*de3cfa2cSIntel 		}
164*de3cfa2cSIntel 
165*de3cfa2cSIntel 		app_worker_thread(wt_confs);
166*de3cfa2cSIntel 	}
167*de3cfa2cSIntel 
168*de3cfa2cSIntel 	return 0;
169*de3cfa2cSIntel }
170*de3cfa2cSIntel 
171*de3cfa2cSIntel static void
172*de3cfa2cSIntel app_stat(void)
173*de3cfa2cSIntel {
174*de3cfa2cSIntel 	uint32_t i;
175*de3cfa2cSIntel 	struct rte_eth_stats stats;
176*de3cfa2cSIntel 	static struct rte_eth_stats rx_stats[MAX_DATA_STREAMS];
177*de3cfa2cSIntel 	static struct rte_eth_stats tx_stats[MAX_DATA_STREAMS];
178*de3cfa2cSIntel 
179*de3cfa2cSIntel 	/* print statistics */
180*de3cfa2cSIntel 	for(i = 0; i < nb_pfc; i++) {
181*de3cfa2cSIntel 		struct flow_conf *flow = &qos_conf[i];
182*de3cfa2cSIntel 
183*de3cfa2cSIntel 		rte_eth_stats_get(flow->rx_port, &stats);
184*de3cfa2cSIntel 		printf("\nRX port %hu: rx: %"PRIu64 " err: %"PRIu64 " no_mbuf: %"PRIu64 "\n",
185*de3cfa2cSIntel 			flow->rx_port,
186*de3cfa2cSIntel 			stats.ipackets - rx_stats[i].ipackets,
187*de3cfa2cSIntel 			stats.ierrors - rx_stats[i].ierrors,
188*de3cfa2cSIntel 			stats.rx_nombuf - rx_stats[i].rx_nombuf);
189*de3cfa2cSIntel 		memcpy(&rx_stats[i], &stats, sizeof(stats));
190*de3cfa2cSIntel 
191*de3cfa2cSIntel 		rte_eth_stats_get(flow->tx_port, &stats);
192*de3cfa2cSIntel 		printf("TX port %hu: tx: %" PRIu64 " err: %" PRIu64 "\n",
193*de3cfa2cSIntel 			flow->tx_port,
194*de3cfa2cSIntel 			stats.opackets - tx_stats[i].opackets,
195*de3cfa2cSIntel 			stats.oerrors - tx_stats[i].oerrors);
196*de3cfa2cSIntel 		memcpy(&tx_stats[i], &stats, sizeof(stats));
197*de3cfa2cSIntel 
198*de3cfa2cSIntel 		//printf("MP = %d\n", rte_mempool_count(conf->app_pktmbuf_pool));
199*de3cfa2cSIntel 
200*de3cfa2cSIntel #if APP_COLLECT_STAT
201*de3cfa2cSIntel 		printf("-------+------------+------------+\n");
202*de3cfa2cSIntel 		printf("       |  received  |   dropped  |\n");
203*de3cfa2cSIntel 		printf("-------+------------+------------+\n");
204*de3cfa2cSIntel 		printf("  RX   | %10" PRIu64 " | %10" PRIu64 " |\n",
205*de3cfa2cSIntel 			flow->rx_thread.stat.nb_rx,
206*de3cfa2cSIntel 			flow->rx_thread.stat.nb_drop);
207*de3cfa2cSIntel 		printf("QOS+TX | %10" PRIu64 " | %10" PRIu64 " |   pps: %"PRIu64 " \n",
208*de3cfa2cSIntel 			flow->wt_thread.stat.nb_rx,
209*de3cfa2cSIntel 			flow->wt_thread.stat.nb_drop,
210*de3cfa2cSIntel 			flow->wt_thread.stat.nb_rx - flow->wt_thread.stat.nb_drop);
211*de3cfa2cSIntel 		printf("-------+------------+------------+\n");
212*de3cfa2cSIntel 
213*de3cfa2cSIntel 		memset(&flow->rx_thread.stat, 0, sizeof(struct thread_stat));
214*de3cfa2cSIntel 		memset(&flow->wt_thread.stat, 0, sizeof(struct thread_stat));
215*de3cfa2cSIntel #endif
216*de3cfa2cSIntel 	}
217*de3cfa2cSIntel }
218*de3cfa2cSIntel 
219*de3cfa2cSIntel 
220*de3cfa2cSIntel 
221*de3cfa2cSIntel int
222*de3cfa2cSIntel MAIN(int argc, char **argv)
223*de3cfa2cSIntel {
224*de3cfa2cSIntel 	int ret;
225*de3cfa2cSIntel 
226*de3cfa2cSIntel 	ret = app_parse_args(argc, argv);
227*de3cfa2cSIntel 	if (ret < 0)
228*de3cfa2cSIntel 		return -1;
229*de3cfa2cSIntel 
230*de3cfa2cSIntel 	ret = app_init();
231*de3cfa2cSIntel 	if (ret < 0)
232*de3cfa2cSIntel 		return -1;
233*de3cfa2cSIntel 
234*de3cfa2cSIntel 
235*de3cfa2cSIntel 	/* launch per-lcore init on every lcore */
236*de3cfa2cSIntel 	rte_eal_mp_remote_launch(app_main_loop, NULL, SKIP_MASTER);
237*de3cfa2cSIntel 
238*de3cfa2cSIntel 	/* print statistics every second */
239*de3cfa2cSIntel 	while(1) {
240*de3cfa2cSIntel 		sleep(1);
241*de3cfa2cSIntel 		app_stat();
242*de3cfa2cSIntel 	}
243*de3cfa2cSIntel }
244*de3cfa2cSIntel 
245*de3cfa2cSIntel 
246*de3cfa2cSIntel 
247