main.c revision aa97dd1c
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		.max_rx_pkt_len = ETHER_MAX_VLAN_FRAME_LEN,
72		.hw_vlan_strip = 1,
73		.jumbo_frame = 1,
74	},
75};
76
77/* function pointers */
78static TLE_RX_BULK_FUNCTYPE tle_rx_bulk;
79static TLE_TX_BULK_FUNCTYPE tle_tx_bulk;
80static TLE_STREAM_RECV_FUNCTYPE tle_stream_recv;
81static TLE_STREAM_CLOSE_FUNCTYPE tle_stream_close;
82
83static LCORE_MAIN_FUNCTYPE lcore_main;
84
85#include "common.h"
86#include "parse.h"
87#include "lcore.h"
88#include "port.h"
89#include "tcp.h"
90#include "udp.h"
91
92int verbose = VERBOSE_NONE;
93
94static void
95netbe_lcore_fini(struct netbe_cfg *cfg)
96{
97	uint32_t i;
98
99	for (i = 0; i != cfg->cpu_num; i++) {
100		tle_ctx_destroy(cfg->cpu[i].ctx);
101		rte_ip_frag_table_destroy(cfg->cpu[i].ftbl);
102		rte_lpm_free(cfg->cpu[i].lpm4);
103		rte_lpm6_free(cfg->cpu[i].lpm6);
104
105		rte_free(cfg->cpu[i].prtq);
106		cfg->cpu[i].prtq_num = 0;
107	}
108
109	rte_free(cfg->cpu);
110	cfg->cpu_num = 0;
111	for (i = 0; i != cfg->prt_num; i++) {
112		rte_free(cfg->prt[i].lcore_id);
113		cfg->prt[i].nb_lcore = 0;
114	}
115	rte_free(cfg->prt);
116	cfg->prt_num = 0;
117}
118
119static int
120netbe_dest_init(const char *fname, struct netbe_cfg *cfg)
121{
122	int32_t rc;
123	uint32_t f, i, p;
124	uint32_t k, l, cnt;
125	struct netbe_lcore *lc;
126	struct netbe_dest_prm prm;
127
128	rc = netbe_parse_dest(fname, &prm);
129	if (rc != 0)
130		return rc;
131
132	rc = 0;
133	for (i = 0; i != prm.nb_dest; i++) {
134
135		p = prm.dest[i].port;
136		f = prm.dest[i].family;
137
138		cnt = 0;
139		for (k = 0; k != cfg->cpu_num; k++) {
140			lc = cfg->cpu + k;
141			for (l = 0; l != lc->prtq_num; l++)
142				if (lc->prtq[l].port.id == p) {
143					rc = netbe_add_dest(lc, l, f,
144							prm.dest + i, 1);
145					if (rc != 0) {
146						RTE_LOG(ERR, USER1,
147							"%s(lc=%u, family=%u) "
148							"could not add "
149							"destinations(%u)\n",
150							__func__, lc->id, f, i);
151						return -ENOSPC;
152					}
153					cnt++;
154				}
155		}
156
157		if (cnt == 0) {
158			RTE_LOG(ERR, USER1, "%s(%s) error at line %u: "
159				"port %u not managed by any lcore;\n",
160				__func__, fname, prm.dest[i].line, p);
161			break;
162		}
163	}
164
165	free(prm.dest);
166	return rc;
167}
168
169static void
170func_ptrs_init(uint32_t proto) {
171	if (proto == TLE_PROTO_TCP) {
172		tle_rx_bulk = tle_tcp_rx_bulk;
173		tle_tx_bulk = tle_tcp_tx_bulk;
174		tle_stream_recv = tle_tcp_stream_recv;
175		tle_stream_close = tle_tcp_stream_close;
176
177		lcore_main = lcore_main_tcp;
178
179	} else {
180		tle_rx_bulk = tle_udp_rx_bulk;
181		tle_tx_bulk = tle_udp_tx_bulk;
182		tle_stream_recv = tle_udp_stream_recv;
183		tle_stream_close = tle_udp_stream_close;
184
185		lcore_main = lcore_main_udp;
186	}
187}
188
189int
190main(int argc, char *argv[])
191{
192	int32_t rc;
193	uint32_t i;
194	struct tle_ctx_param ctx_prm;
195	struct netfe_lcore_prm feprm;
196	struct rte_eth_stats stats;
197	char fecfg_fname[PATH_MAX + 1];
198	char becfg_fname[PATH_MAX + 1];
199	struct lcore_prm prm[RTE_MAX_LCORE];
200	struct rte_eth_dev_info dev_info;
201
202	fecfg_fname[0] = 0;
203	becfg_fname[0] = 0;
204	memset(prm, 0, sizeof(prm));
205
206	rc = rte_eal_init(argc, argv);
207	if (rc < 0)
208		rte_exit(EXIT_FAILURE,
209			"%s: rte_eal_init failed with error code: %d\n",
210			__func__, rc);
211
212	memset(&ctx_prm, 0, sizeof(ctx_prm));
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