main.c revision 36d90e3a
1/*
2 * Copyright (c) 2016  Intel Corporation.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <time.h>
17
18#include "netbe.h"
19#include "parse.h"
20
21#define	MAX_RULES	0x100
22#define	MAX_TBL8	0x800
23
24#define	RX_RING_SIZE	0x400
25#define	TX_RING_SIZE	0x800
26
27#define	MPOOL_CACHE_SIZE	0x100
28#define	MPOOL_NB_BUF		0x20000
29
30#define FRAG_MBUF_BUF_SIZE	(RTE_PKTMBUF_HEADROOM + TLE_DST_MAX_HDR)
31#define FRAG_TTL		MS_PER_S
32#define	FRAG_TBL_BUCKET_ENTRIES	16
33
34#define	FIRST_PORT	0x8000
35
36#define RX_CSUM_OFFLOAD	(DEV_RX_OFFLOAD_IPV4_CKSUM | DEV_RX_OFFLOAD_UDP_CKSUM)
37#define TX_CSUM_OFFLOAD	(DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM)
38
39RTE_DEFINE_PER_LCORE(struct netbe_lcore *, _be);
40RTE_DEFINE_PER_LCORE(struct netfe_lcore *, _fe);
41
42#include "fwdtbl.h"
43
44/**
45 * Location to be modified to create the IPv4 hash key which helps
46 * to distribute packets based on the destination TCP/UDP port.
47 */
48#define RSS_HASH_KEY_DEST_PORT_LOC_IPV4 15
49
50/**
51 * Location to be modified to create the IPv6 hash key which helps
52 * to distribute packets based on the destination TCP/UDP port.
53 */
54#define RSS_HASH_KEY_DEST_PORT_LOC_IPV6 39
55
56/**
57 * Size of the rte_eth_rss_reta_entry64 array to update through
58 * rte_eth_dev_rss_reta_update.
59 */
60#define RSS_RETA_CONF_ARRAY_SIZE (ETH_RSS_RETA_SIZE_512/RTE_RETA_GROUP_SIZE)
61
62static volatile int force_quit;
63
64static struct netbe_cfg becfg;
65static struct rte_mempool *mpool[RTE_MAX_NUMA_NODES + 1];
66static struct rte_mempool *frag_mpool[RTE_MAX_NUMA_NODES + 1];
67static char proto_name[3][10] = {"udp", "tcp", ""};
68
69static const struct rte_eth_conf port_conf_default = {
70	.rxmode = {
71		.hw_vlan_strip = 1,
72		.jumbo_frame = 0,
73	},
74};
75
76/* function pointers */
77static TLE_RX_BULK_FUNCTYPE tle_rx_bulk;
78static TLE_TX_BULK_FUNCTYPE tle_tx_bulk;
79static TLE_STREAM_RECV_FUNCTYPE tle_stream_recv;
80static TLE_STREAM_CLOSE_FUNCTYPE tle_stream_close;
81
82static LCORE_MAIN_FUNCTYPE lcore_main;
83
84#include "common.h"
85#include "parse.h"
86#include "lcore.h"
87#include "port.h"
88#include "tcp.h"
89#include "udp.h"
90
91int verbose = VERBOSE_NONE;
92
93static void
94netbe_lcore_fini(struct netbe_cfg *cfg)
95{
96	uint32_t i;
97
98	for (i = 0; i != cfg->cpu_num; i++) {
99		tle_ctx_destroy(cfg->cpu[i].ctx);
100		rte_ip_frag_table_destroy(cfg->cpu[i].ftbl);
101		rte_lpm_free(cfg->cpu[i].lpm4);
102		rte_lpm6_free(cfg->cpu[i].lpm6);
103
104		rte_free(cfg->cpu[i].prtq);
105		cfg->cpu[i].prtq_num = 0;
106	}
107
108	rte_free(cfg->cpu);
109	cfg->cpu_num = 0;
110	for (i = 0; i != cfg->prt_num; i++) {
111		rte_free(cfg->prt[i].lcore_id);
112		cfg->prt[i].nb_lcore = 0;
113	}
114	rte_free(cfg->prt);
115	cfg->prt_num = 0;
116}
117
118static int
119netbe_dest_init(const char *fname, struct netbe_cfg *cfg)
120{
121	int32_t rc;
122	uint32_t f, i, p;
123	uint32_t k, l, cnt;
124	struct netbe_lcore *lc;
125	struct netbe_dest_prm prm;
126
127	rc = netbe_parse_dest(fname, &prm);
128	if (rc != 0)
129		return rc;
130
131	rc = 0;
132	for (i = 0; i != prm.nb_dest; i++) {
133
134		p = prm.dest[i].port;
135		f = prm.dest[i].family;
136
137		cnt = 0;
138		for (k = 0; k != cfg->cpu_num; k++) {
139			lc = cfg->cpu + k;
140			for (l = 0; l != lc->prtq_num; l++)
141				if (lc->prtq[l].port.id == p) {
142					rc = netbe_add_dest(lc, l, f,
143							prm.dest + i, 1);
144					if (rc != 0) {
145						RTE_LOG(ERR, USER1,
146							"%s(lc=%u, family=%u) "
147							"could not add "
148							"destinations(%u)\n",
149							__func__, lc->id, f, i);
150						return -ENOSPC;
151					}
152					cnt++;
153				}
154		}
155
156		if (cnt == 0) {
157			RTE_LOG(ERR, USER1, "%s(%s) error at line %u: "
158				"port %u not managed by any lcore;\n",
159				__func__, fname, prm.dest[i].line, p);
160			break;
161		}
162	}
163
164	free(prm.dest);
165	return rc;
166}
167
168static void
169func_ptrs_init(uint32_t proto) {
170	if (proto == TLE_PROTO_TCP) {
171		tle_rx_bulk = tle_tcp_rx_bulk;
172		tle_tx_bulk = tle_tcp_tx_bulk;
173		tle_stream_recv = tle_tcp_stream_recv;
174		tle_stream_close = tle_tcp_stream_close;
175
176		lcore_main = lcore_main_tcp;
177
178	} else {
179		tle_rx_bulk = tle_udp_rx_bulk;
180		tle_tx_bulk = tle_udp_tx_bulk;
181		tle_stream_recv = tle_udp_stream_recv;
182		tle_stream_close = tle_udp_stream_close;
183
184		lcore_main = lcore_main_udp;
185	}
186}
187
188int
189main(int argc, char *argv[])
190{
191	int32_t rc;
192	uint32_t i;
193	struct tle_ctx_param ctx_prm;
194	struct netfe_lcore_prm feprm;
195	struct rte_eth_stats stats;
196	char fecfg_fname[PATH_MAX + 1];
197	char becfg_fname[PATH_MAX + 1];
198	struct lcore_prm prm[RTE_MAX_LCORE];
199	struct rte_eth_dev_info dev_info;
200
201	fecfg_fname[0] = 0;
202	becfg_fname[0] = 0;
203	memset(prm, 0, sizeof(prm));
204
205	rc = rte_eal_init(argc, argv);
206	if (rc < 0)
207		rte_exit(EXIT_FAILURE,
208			"%s: rte_eal_init failed with error code: %d\n",
209			__func__, rc);
210
211	memset(&ctx_prm, 0, sizeof(ctx_prm));
212
213	signal(SIGINT, sig_handle);
214
215	argc -= rc;
216	argv += rc;
217
218	rc = parse_app_options(argc, argv, &becfg, &ctx_prm,
219		fecfg_fname, becfg_fname);
220	if (rc != 0)
221		rte_exit(EXIT_FAILURE,
222			"%s: parse_app_options failed with error code: %d\n",
223			__func__, rc);
224
225	/* init all the function pointer */
226	func_ptrs_init(becfg.proto);
227
228	rc = netbe_port_init(&becfg);
229	if (rc != 0)
230		rte_exit(EXIT_FAILURE,
231			"%s: netbe_port_init failed with error code: %d\n",
232			__func__, rc);
233
234	rc = netbe_lcore_init(&becfg, &ctx_prm);
235	if (rc != 0)
236		sig_handle(SIGQUIT);
237
238	rc = netbe_dest_init(becfg_fname, &becfg);
239	if (rc != 0)
240		sig_handle(SIGQUIT);
241
242	for (i = 0; i != becfg.prt_num && rc == 0; i++) {
243		RTE_LOG(NOTICE, USER1, "%s: starting port %u\n",
244			__func__, becfg.prt[i].id);
245		rc = rte_eth_dev_start(becfg.prt[i].id);
246		if (rc != 0) {
247			RTE_LOG(ERR, USER1,
248				"%s: rte_eth_dev_start(%u) returned "
249				"error code: %d\n",
250				__func__, becfg.prt[i].id, rc);
251			sig_handle(SIGQUIT);
252		}
253		rte_eth_dev_info_get(becfg.prt[i].id, &dev_info);
254		rc = update_rss_reta(&becfg.prt[i], &dev_info);
255		if (rc != 0)
256			sig_handle(SIGQUIT);
257	}
258
259	feprm.max_streams = ctx_prm.max_streams * becfg.cpu_num;
260
261	rc = (rc != 0) ? rc : netfe_parse_cfg(fecfg_fname, &feprm);
262	if (rc != 0)
263		sig_handle(SIGQUIT);
264
265	for (i = 0; rc == 0 && i != becfg.cpu_num; i++)
266		prm[becfg.cpu[i].id].be.lc = becfg.cpu + i;
267
268	rc = (rc != 0) ? rc : netfe_lcore_fill(prm, &feprm);
269	if (rc != 0)
270		sig_handle(SIGQUIT);
271
272	/* launch all slave lcores. */
273	RTE_LCORE_FOREACH_SLAVE(i) {
274		if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0)
275			rte_eal_remote_launch(lcore_main, prm + i, i);
276	}
277
278	/* launch master lcore. */
279	i = rte_get_master_lcore();
280	if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0)
281		lcore_main(prm + i);
282
283	rte_eal_mp_wait_lcore();
284
285	for (i = 0; i != becfg.prt_num; i++) {
286		RTE_LOG(NOTICE, USER1, "%s: stoping port %u\n",
287			__func__, becfg.prt[i].id);
288		rte_eth_stats_get(becfg.prt[i].id, &stats);
289		RTE_LOG(NOTICE, USER1, "port %u stats={\n"
290			"ipackets=%" PRIu64 ";"
291			"ibytes=%" PRIu64 ";"
292			"ierrors=%" PRIu64 ";"
293			"imissed=%" PRIu64 ";\n"
294			"opackets=%" PRIu64 ";"
295			"obytes=%" PRIu64 ";"
296			"oerrors=%" PRIu64 ";\n"
297			"}\n",
298			becfg.prt[i].id,
299			stats.ipackets,
300			stats.ibytes,
301			stats.ierrors,
302			stats.imissed,
303			stats.opackets,
304			stats.obytes,
305			stats.oerrors);
306		rte_eth_dev_stop(becfg.prt[i].id);
307	}
308
309	netbe_lcore_fini(&becfg);
310
311	return 0;
312}
313