main.c revision 7e18fa1b
1/*
2 * Copyright (c) 2016-2017  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	ctx_prm.timewait = TLE_TCP_TIMEWAIT_DEFAULT;
213
214	signal(SIGINT, sig_handle);
215
216	argc -= rc;
217	argv += rc;
218
219	rc = parse_app_options(argc, argv, &becfg, &ctx_prm,
220		fecfg_fname, becfg_fname);
221	if (rc != 0)
222		rte_exit(EXIT_FAILURE,
223			"%s: parse_app_options failed with error code: %d\n",
224			__func__, rc);
225
226	/* init all the function pointer */
227	func_ptrs_init(becfg.proto);
228
229	rc = netbe_port_init(&becfg);
230	if (rc != 0)
231		rte_exit(EXIT_FAILURE,
232			"%s: netbe_port_init failed with error code: %d\n",
233			__func__, rc);
234
235	rc = netbe_lcore_init(&becfg, &ctx_prm);
236	if (rc != 0)
237		sig_handle(SIGQUIT);
238
239	rc = netbe_dest_init(becfg_fname, &becfg);
240	if (rc != 0)
241		sig_handle(SIGQUIT);
242
243	for (i = 0; i != becfg.prt_num && rc == 0; i++) {
244		RTE_LOG(NOTICE, USER1, "%s: starting port %u\n",
245			__func__, becfg.prt[i].id);
246		rc = rte_eth_dev_start(becfg.prt[i].id);
247		if (rc != 0) {
248			RTE_LOG(ERR, USER1,
249				"%s: rte_eth_dev_start(%u) returned "
250				"error code: %d\n",
251				__func__, becfg.prt[i].id, rc);
252			sig_handle(SIGQUIT);
253		}
254		rte_eth_dev_info_get(becfg.prt[i].id, &dev_info);
255		rc = update_rss_reta(&becfg.prt[i], &dev_info);
256		if (rc != 0)
257			sig_handle(SIGQUIT);
258	}
259
260	feprm.max_streams = ctx_prm.max_streams * becfg.cpu_num;
261
262	rc = (rc != 0) ? rc : netfe_parse_cfg(fecfg_fname, &feprm);
263	if (rc != 0)
264		sig_handle(SIGQUIT);
265
266	for (i = 0; rc == 0 && i != becfg.cpu_num; i++)
267		prm[becfg.cpu[i].id].be.lc = becfg.cpu + i;
268
269	rc = (rc != 0) ? rc : netfe_lcore_fill(prm, &feprm);
270	if (rc != 0)
271		sig_handle(SIGQUIT);
272
273	/* launch all slave lcores. */
274	RTE_LCORE_FOREACH_SLAVE(i) {
275		if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0)
276			rte_eal_remote_launch(lcore_main, prm + i, i);
277	}
278
279	/* launch master lcore. */
280	i = rte_get_master_lcore();
281	if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0)
282		lcore_main(prm + i);
283
284	rte_eal_mp_wait_lcore();
285
286	for (i = 0; i != becfg.prt_num; i++) {
287		RTE_LOG(NOTICE, USER1, "%s: stoping port %u\n",
288			__func__, becfg.prt[i].id);
289		rte_eth_stats_get(becfg.prt[i].id, &stats);
290		RTE_LOG(NOTICE, USER1, "port %u stats={\n"
291			"ipackets=%" PRIu64 ";"
292			"ibytes=%" PRIu64 ";"
293			"ierrors=%" PRIu64 ";"
294			"imissed=%" PRIu64 ";\n"
295			"opackets=%" PRIu64 ";"
296			"obytes=%" PRIu64 ";"
297			"oerrors=%" PRIu64 ";\n"
298			"}\n",
299			becfg.prt[i].id,
300			stats.ipackets,
301			stats.ibytes,
302			stats.ierrors,
303			stats.imissed,
304			stats.opackets,
305			stats.obytes,
306			stats.oerrors);
307		rte_eth_dev_stop(becfg.prt[i].id);
308	}
309
310	netbe_lcore_fini(&becfg);
311
312	return 0;
313}
314