main.c revision 3726dc50
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
76struct tx_content tx_content = {
77	.sz = 0,
78	.data = NULL,
79};
80
81/* function pointers */
82static TLE_RX_BULK_FUNCTYPE tle_rx_bulk;
83static TLE_TX_BULK_FUNCTYPE tle_tx_bulk;
84static TLE_STREAM_RECV_FUNCTYPE tle_stream_recv;
85static TLE_STREAM_CLOSE_FUNCTYPE tle_stream_close;
86
87static LCORE_MAIN_FUNCTYPE lcore_main;
88
89#include "common.h"
90#include "parse.h"
91#include "lcore.h"
92#include "port.h"
93#include "tcp.h"
94#include "udp.h"
95
96int verbose = VERBOSE_NONE;
97
98static void
99netbe_lcore_fini(struct netbe_cfg *cfg)
100{
101	uint32_t i;
102
103	for (i = 0; i != cfg->cpu_num; i++) {
104		tle_ctx_destroy(cfg->cpu[i].ctx);
105		rte_ip_frag_table_destroy(cfg->cpu[i].ftbl);
106		rte_lpm_free(cfg->cpu[i].lpm4);
107		rte_lpm6_free(cfg->cpu[i].lpm6);
108
109		rte_free(cfg->cpu[i].prtq);
110		cfg->cpu[i].prtq_num = 0;
111	}
112
113	rte_free(cfg->cpu);
114	cfg->cpu_num = 0;
115	for (i = 0; i != cfg->prt_num; i++) {
116		rte_free(cfg->prt[i].lcore_id);
117		cfg->prt[i].nb_lcore = 0;
118	}
119	rte_free(cfg->prt);
120	cfg->prt_num = 0;
121}
122
123static int
124netbe_dest_init(const char *fname, struct netbe_cfg *cfg)
125{
126	int32_t rc;
127	uint32_t f, i, p;
128	uint32_t k, l, cnt;
129	struct netbe_lcore *lc;
130	struct netbe_dest_prm prm;
131
132	rc = netbe_parse_dest(fname, &prm);
133	if (rc != 0)
134		return rc;
135
136	rc = 0;
137	for (i = 0; i != prm.nb_dest; i++) {
138
139		p = prm.dest[i].port;
140		f = prm.dest[i].family;
141
142		cnt = 0;
143		for (k = 0; k != cfg->cpu_num; k++) {
144			lc = cfg->cpu + k;
145			for (l = 0; l != lc->prtq_num; l++)
146				if (lc->prtq[l].port.id == p) {
147					rc = netbe_add_dest(lc, l, f,
148							prm.dest + i, 1);
149					if (rc != 0) {
150						RTE_LOG(ERR, USER1,
151							"%s(lc=%u, family=%u) "
152							"could not add "
153							"destinations(%u)\n",
154							__func__, lc->id, f, i);
155						return -ENOSPC;
156					}
157					cnt++;
158				}
159		}
160
161		if (cnt == 0) {
162			RTE_LOG(ERR, USER1, "%s(%s) error at line %u: "
163				"port %u not managed by any lcore;\n",
164				__func__, fname, prm.dest[i].line, p);
165			break;
166		}
167	}
168
169	free(prm.dest);
170	return rc;
171}
172
173static void
174func_ptrs_init(uint32_t proto) {
175	if (proto == TLE_PROTO_TCP) {
176		tle_rx_bulk = tle_tcp_rx_bulk;
177		tle_tx_bulk = tle_tcp_tx_bulk;
178		tle_stream_recv = tle_tcp_stream_recv;
179		tle_stream_close = tle_tcp_stream_close;
180
181		lcore_main = lcore_main_tcp;
182
183	} else {
184		tle_rx_bulk = tle_udp_rx_bulk;
185		tle_tx_bulk = tle_udp_tx_bulk;
186		tle_stream_recv = tle_udp_stream_recv;
187		tle_stream_close = tle_udp_stream_close;
188
189		lcore_main = lcore_main_udp;
190	}
191}
192
193int
194main(int argc, char *argv[])
195{
196	int32_t rc;
197	uint32_t i;
198	struct tle_ctx_param ctx_prm;
199	struct netfe_lcore_prm feprm;
200	struct rte_eth_stats stats;
201	char fecfg_fname[PATH_MAX + 1];
202	char becfg_fname[PATH_MAX + 1];
203	struct lcore_prm prm[RTE_MAX_LCORE];
204	struct rte_eth_dev_info dev_info;
205
206	fecfg_fname[0] = 0;
207	becfg_fname[0] = 0;
208	memset(prm, 0, sizeof(prm));
209
210	rc = rte_eal_init(argc, argv);
211	if (rc < 0)
212		rte_exit(EXIT_FAILURE,
213			"%s: rte_eal_init failed with error code: %d\n",
214			__func__, rc);
215
216	memset(&ctx_prm, 0, sizeof(ctx_prm));
217	ctx_prm.timewait = TLE_TCP_TIMEWAIT_DEFAULT;
218
219	signal(SIGINT, sig_handle);
220
221	argc -= rc;
222	argv += rc;
223
224	rc = parse_app_options(argc, argv, &becfg, &ctx_prm,
225		fecfg_fname, becfg_fname);
226	if (rc != 0)
227		rte_exit(EXIT_FAILURE,
228			"%s: parse_app_options failed with error code: %d\n",
229			__func__, rc);
230
231	/* init all the function pointer */
232	func_ptrs_init(becfg.proto);
233
234	rc = netbe_port_init(&becfg);
235	if (rc != 0)
236		rte_exit(EXIT_FAILURE,
237			"%s: netbe_port_init failed with error code: %d\n",
238			__func__, rc);
239
240	rc = netbe_lcore_init(&becfg, &ctx_prm);
241	if (rc != 0)
242		sig_handle(SIGQUIT);
243
244	rc = netbe_dest_init(becfg_fname, &becfg);
245	if (rc != 0)
246		sig_handle(SIGQUIT);
247
248	for (i = 0; i != becfg.prt_num && rc == 0; i++) {
249		RTE_LOG(NOTICE, USER1, "%s: starting port %u\n",
250			__func__, becfg.prt[i].id);
251		rc = rte_eth_dev_start(becfg.prt[i].id);
252		if (rc != 0) {
253			RTE_LOG(ERR, USER1,
254				"%s: rte_eth_dev_start(%u) returned "
255				"error code: %d\n",
256				__func__, becfg.prt[i].id, rc);
257			sig_handle(SIGQUIT);
258		}
259		rte_eth_dev_info_get(becfg.prt[i].id, &dev_info);
260		rc = update_rss_reta(&becfg.prt[i], &dev_info);
261		if (rc != 0)
262			sig_handle(SIGQUIT);
263	}
264
265	feprm.max_streams = ctx_prm.max_streams * becfg.cpu_num;
266
267	rc = (rc != 0) ? rc : netfe_parse_cfg(fecfg_fname, &feprm);
268	if (rc != 0)
269		sig_handle(SIGQUIT);
270
271	for (i = 0; rc == 0 && i != becfg.cpu_num; i++)
272		prm[becfg.cpu[i].id].be.lc = becfg.cpu + i;
273
274	rc = (rc != 0) ? rc : netfe_lcore_fill(prm, &feprm);
275	if (rc != 0)
276		sig_handle(SIGQUIT);
277
278	/* launch all slave lcores. */
279	RTE_LCORE_FOREACH_SLAVE(i) {
280		if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0)
281			rte_eal_remote_launch(lcore_main, prm + i, i);
282	}
283
284	/* launch master lcore. */
285	i = rte_get_master_lcore();
286	if (prm[i].be.lc != NULL || prm[i].fe.max_streams != 0)
287		lcore_main(prm + i);
288
289	rte_eal_mp_wait_lcore();
290
291	for (i = 0; i != becfg.prt_num; i++) {
292		RTE_LOG(NOTICE, USER1, "%s: stoping port %u\n",
293			__func__, becfg.prt[i].id);
294		rte_eth_stats_get(becfg.prt[i].id, &stats);
295		RTE_LOG(NOTICE, USER1, "port %u stats={\n"
296			"ipackets=%" PRIu64 ";"
297			"ibytes=%" PRIu64 ";"
298			"ierrors=%" PRIu64 ";"
299			"imissed=%" PRIu64 ";\n"
300			"opackets=%" PRIu64 ";"
301			"obytes=%" PRIu64 ";"
302			"oerrors=%" PRIu64 ";\n"
303			"}\n",
304			becfg.prt[i].id,
305			stats.ipackets,
306			stats.ibytes,
307			stats.ierrors,
308			stats.imissed,
309			stats.opackets,
310			stats.obytes,
311			stats.oerrors);
312		rte_eth_dev_stop(becfg.prt[i].id);
313	}
314
315	netbe_lcore_fini(&becfg);
316
317	return 0;
318}
319