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