xref: /dpdk/app/test-fib/main.c (revision 6cb10a9bdb6d2d0253e4d022f230371d703d8ac2)
1103809d0SVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause
2103809d0SVladimir Medvedkin  * Copyright(c) 2019 Intel Corporation
3103809d0SVladimir Medvedkin  */
4103809d0SVladimir Medvedkin 
5103809d0SVladimir Medvedkin #include <getopt.h>
672b452c5SDmitry Kozlyuk #include <stdlib.h>
7103809d0SVladimir Medvedkin #include <string.h>
8103809d0SVladimir Medvedkin #include <arpa/inet.h>
98cd3ef56SVladimir Medvedkin #include <sys/socket.h>
10103809d0SVladimir Medvedkin 
11103809d0SVladimir Medvedkin #include <rte_cycles.h>
12103809d0SVladimir Medvedkin #include <rte_errno.h>
13103809d0SVladimir Medvedkin #include <rte_ip.h>
14103809d0SVladimir Medvedkin #include <rte_random.h>
15103809d0SVladimir Medvedkin #include <rte_malloc.h>
16103809d0SVladimir Medvedkin #include <rte_lpm.h>
17103809d0SVladimir Medvedkin #include <rte_lpm6.h>
18103809d0SVladimir Medvedkin #include <rte_fib.h>
19103809d0SVladimir Medvedkin #include <rte_fib6.h>
20103809d0SVladimir Medvedkin 
21103809d0SVladimir Medvedkin #define	PRINT_USAGE_START	"%s [EAL options] --\n"
22103809d0SVladimir Medvedkin 
23103809d0SVladimir Medvedkin #define GET_CB_FIELD(in, fd, base, lim, dlm)	do {		\
24103809d0SVladimir Medvedkin 	unsigned long val;					\
25103809d0SVladimir Medvedkin 	char *end_fld;						\
26103809d0SVladimir Medvedkin 	errno = 0;						\
27103809d0SVladimir Medvedkin 	val = strtoul((in), &end_fld, (base));			\
28103809d0SVladimir Medvedkin 	if (errno != 0 || end_fld[0] != (dlm) || val > (lim))	\
29103809d0SVladimir Medvedkin 		return -EINVAL;					\
30103809d0SVladimir Medvedkin 	(fd) = (typeof(fd))val;					\
31103809d0SVladimir Medvedkin 	(in) = end_fld + 1;					\
32103809d0SVladimir Medvedkin } while (0)
33103809d0SVladimir Medvedkin 
34103809d0SVladimir Medvedkin #define	DEF_ROUTES_NUM		0x10000
35103809d0SVladimir Medvedkin #define	DEF_LOOKUP_IPS_NUM	0x100000
36103809d0SVladimir Medvedkin #define BURST_SZ		64
37103809d0SVladimir Medvedkin #define DEFAULT_LPM_TBL8	100000U
38103809d0SVladimir Medvedkin 
39103809d0SVladimir Medvedkin #define CMP_FLAG		(1 << 0)
40103809d0SVladimir Medvedkin #define CMP_ALL_FLAG		(1 << 1)
41103809d0SVladimir Medvedkin #define IPV6_FLAG		(1 << 2)
42103809d0SVladimir Medvedkin #define FIB_RIB_TYPE		(1 << 3)
43103809d0SVladimir Medvedkin #define FIB_V4_DIR_TYPE		(1 << 4)
44103809d0SVladimir Medvedkin #define FIB_V6_TRIE_TYPE	(1 << 4)
45103809d0SVladimir Medvedkin #define FIB_TYPE_MASK		(FIB_RIB_TYPE|FIB_V4_DIR_TYPE|FIB_V6_TRIE_TYPE)
46103809d0SVladimir Medvedkin #define SHUFFLE_FLAG		(1 << 7)
47103809d0SVladimir Medvedkin #define DRY_RUN_FLAG		(1 << 8)
48103809d0SVladimir Medvedkin 
49103809d0SVladimir Medvedkin static char *distrib_string;
50103809d0SVladimir Medvedkin static char line[LINE_MAX];
51103809d0SVladimir Medvedkin 
52103809d0SVladimir Medvedkin enum {
53103809d0SVladimir Medvedkin 	RT_PREFIX,
54103809d0SVladimir Medvedkin 	RT_NEXTHOP,
55103809d0SVladimir Medvedkin 	RT_NUM
56103809d0SVladimir Medvedkin };
57103809d0SVladimir Medvedkin 
58103809d0SVladimir Medvedkin #ifndef NIPQUAD
59103809d0SVladimir Medvedkin #define NIPQUAD_FMT "%u.%u.%u.%u"
60103809d0SVladimir Medvedkin #define NIPQUAD(addr)				\
61103809d0SVladimir Medvedkin 	(unsigned)((unsigned char *)&addr)[3],	\
62103809d0SVladimir Medvedkin 	(unsigned)((unsigned char *)&addr)[2],	\
63103809d0SVladimir Medvedkin 	(unsigned)((unsigned char *)&addr)[1],	\
64103809d0SVladimir Medvedkin 	(unsigned)((unsigned char *)&addr)[0]
65103809d0SVladimir Medvedkin #endif
66103809d0SVladimir Medvedkin 
67103809d0SVladimir Medvedkin static struct {
68103809d0SVladimir Medvedkin 	const char	*prgname;
69103809d0SVladimir Medvedkin 	const char	*routes_file;
70103809d0SVladimir Medvedkin 	const char	*lookup_ips_file;
71103809d0SVladimir Medvedkin 	const char	*routes_file_s;
72103809d0SVladimir Medvedkin 	const char	*lookup_ips_file_s;
73103809d0SVladimir Medvedkin 	void		*rt;
74103809d0SVladimir Medvedkin 	void		*lookup_tbl;
75103809d0SVladimir Medvedkin 	uint32_t	nb_routes;
76103809d0SVladimir Medvedkin 	uint32_t	nb_lookup_ips;
77103809d0SVladimir Medvedkin 	uint32_t	nb_lookup_ips_rnd;
78103809d0SVladimir Medvedkin 	uint32_t	nb_routes_per_depth[128 + 1];
79103809d0SVladimir Medvedkin 	uint32_t	flags;
80103809d0SVladimir Medvedkin 	uint32_t	tbl8;
81103809d0SVladimir Medvedkin 	uint8_t		ent_sz;
82103809d0SVladimir Medvedkin 	uint8_t		rnd_lookup_ips_ratio;
83103809d0SVladimir Medvedkin 	uint8_t		print_fract;
84eda44cedSVladimir Medvedkin 	uint8_t		lookup_fn;
85103809d0SVladimir Medvedkin } config = {
86103809d0SVladimir Medvedkin 	.routes_file = NULL,
87103809d0SVladimir Medvedkin 	.lookup_ips_file = NULL,
88103809d0SVladimir Medvedkin 	.nb_routes = DEF_ROUTES_NUM,
89103809d0SVladimir Medvedkin 	.nb_lookup_ips = DEF_LOOKUP_IPS_NUM,
90103809d0SVladimir Medvedkin 	.nb_lookup_ips_rnd = 0,
91103809d0SVladimir Medvedkin 	.nb_routes_per_depth = {0},
92103809d0SVladimir Medvedkin 	.flags = FIB_V4_DIR_TYPE,
93103809d0SVladimir Medvedkin 	.tbl8 = DEFAULT_LPM_TBL8,
94103809d0SVladimir Medvedkin 	.ent_sz = 4,
95103809d0SVladimir Medvedkin 	.rnd_lookup_ips_ratio = 0,
96eda44cedSVladimir Medvedkin 	.print_fract = 10,
97eda44cedSVladimir Medvedkin 	.lookup_fn = 0
98103809d0SVladimir Medvedkin };
99103809d0SVladimir Medvedkin 
100103809d0SVladimir Medvedkin struct rt_rule_4 {
101103809d0SVladimir Medvedkin 	uint32_t	addr;
102103809d0SVladimir Medvedkin 	uint8_t		depth;
103103809d0SVladimir Medvedkin 	uint64_t	nh;
104103809d0SVladimir Medvedkin };
105103809d0SVladimir Medvedkin 
106103809d0SVladimir Medvedkin struct rt_rule_6 {
107e1a06e39SRobin Jarry 	struct rte_ipv6_addr addr;
108103809d0SVladimir Medvedkin 	uint8_t		depth;
109103809d0SVladimir Medvedkin 	uint64_t	nh;
110103809d0SVladimir Medvedkin };
111103809d0SVladimir Medvedkin 
112103809d0SVladimir Medvedkin static uint64_t
113103809d0SVladimir Medvedkin get_rnd_rng(uint64_t l, uint64_t u)
114103809d0SVladimir Medvedkin {
115103809d0SVladimir Medvedkin 	if (l == u)
116103809d0SVladimir Medvedkin 		return l;
117103809d0SVladimir Medvedkin 	else
118103809d0SVladimir Medvedkin 		return (rte_rand() % (u - l) + l);
119103809d0SVladimir Medvedkin }
120103809d0SVladimir Medvedkin 
121ff933786STyler Retzlaff static __rte_always_inline __rte_pure uint8_t
122103809d0SVladimir Medvedkin bits_in_nh(uint8_t nh_sz)
123103809d0SVladimir Medvedkin {
124103809d0SVladimir Medvedkin 	return 8 * (1 << nh_sz);
125103809d0SVladimir Medvedkin }
126103809d0SVladimir Medvedkin 
127ff933786STyler Retzlaff static  __rte_always_inline __rte_pure uint64_t
128103809d0SVladimir Medvedkin get_max_nh(uint8_t nh_sz)
129103809d0SVladimir Medvedkin {
130103809d0SVladimir Medvedkin 	/* min between fib and lpm6 which is 21 bits */
131103809d0SVladimir Medvedkin 	return RTE_MIN(((1ULL << (bits_in_nh(nh_sz) - 1)) - 1),
132103809d0SVladimir Medvedkin 			(1ULL << 21) - 1);
133103809d0SVladimir Medvedkin }
134103809d0SVladimir Medvedkin 
135103809d0SVladimir Medvedkin static int
136103809d0SVladimir Medvedkin get_fib_type(void)
137103809d0SVladimir Medvedkin {
138103809d0SVladimir Medvedkin 	if (config.flags & IPV6_FLAG) {
139103809d0SVladimir Medvedkin 		if ((config.flags & FIB_TYPE_MASK) == FIB_V6_TRIE_TYPE)
140103809d0SVladimir Medvedkin 			return RTE_FIB6_TRIE;
141103809d0SVladimir Medvedkin 		else
142103809d0SVladimir Medvedkin 			return RTE_FIB6_DUMMY;
143103809d0SVladimir Medvedkin 	} else {
144103809d0SVladimir Medvedkin 		if ((config.flags & FIB_TYPE_MASK) == FIB_V4_DIR_TYPE)
145103809d0SVladimir Medvedkin 			return RTE_FIB_DIR24_8;
146103809d0SVladimir Medvedkin 		if ((config.flags & FIB_TYPE_MASK) == FIB_RIB_TYPE)
147103809d0SVladimir Medvedkin 			return RTE_FIB_DUMMY;
148103809d0SVladimir Medvedkin 	}
149103809d0SVladimir Medvedkin 	return -1;
150103809d0SVladimir Medvedkin }
151103809d0SVladimir Medvedkin 
152103809d0SVladimir Medvedkin static int
153103809d0SVladimir Medvedkin complete_distrib(uint8_t depth_lim, const uint32_t n, uint8_t rpd[],
154103809d0SVladimir Medvedkin 	uint32_t nrpd[])
155103809d0SVladimir Medvedkin {
156103809d0SVladimir Medvedkin 	uint8_t depth;
157103809d0SVladimir Medvedkin 	uint32_t nr = 0;
158103809d0SVladimir Medvedkin 	uint8_t m = 0;
159103809d0SVladimir Medvedkin 
160103809d0SVladimir Medvedkin 	/*
161103809d0SVladimir Medvedkin 	 * complete number of routes for every depth
162103809d0SVladimir Medvedkin 	 * that was configured with ratio
163103809d0SVladimir Medvedkin 	 */
164103809d0SVladimir Medvedkin 	for (depth = 0; depth <= depth_lim; depth++) {
165103809d0SVladimir Medvedkin 		if (rpd[depth] != 0) {
166103809d0SVladimir Medvedkin 			if (rpd[depth] == UINT8_MAX)
167103809d0SVladimir Medvedkin 				config.nb_routes_per_depth[depth] =
168103809d0SVladimir Medvedkin 					nrpd[depth];
169103809d0SVladimir Medvedkin 			else
170103809d0SVladimir Medvedkin 				config.nb_routes_per_depth[depth] =
171103809d0SVladimir Medvedkin 					(n * rpd[depth]) / 100;
172103809d0SVladimir Medvedkin 
173103809d0SVladimir Medvedkin 			nr += config.nb_routes_per_depth[depth];
174103809d0SVladimir Medvedkin 			m++;
175103809d0SVladimir Medvedkin 		}
176103809d0SVladimir Medvedkin 	}
177103809d0SVladimir Medvedkin 
178103809d0SVladimir Medvedkin 	if (nr > n) {
179103809d0SVladimir Medvedkin 		printf("Too much configured routes\n");
180103809d0SVladimir Medvedkin 		return -1;
181103809d0SVladimir Medvedkin 	}
182103809d0SVladimir Medvedkin 
183103809d0SVladimir Medvedkin 	/*complete number of routes for every unspecified depths*/
184103809d0SVladimir Medvedkin 	for (depth = 0; depth <= depth_lim; depth++) {
185103809d0SVladimir Medvedkin 		if (rpd[depth] == 0) {
186103809d0SVladimir Medvedkin 			/*we don't need more than two /1 routes*/
187103809d0SVladimir Medvedkin 			uint64_t max_routes_per_depth =
188103809d0SVladimir Medvedkin 				1ULL << RTE_MIN(depth, 63);
189103809d0SVladimir Medvedkin 			uint32_t avg_routes_left = (n - nr) /
190103809d0SVladimir Medvedkin 				(depth_lim + 1 - m++);
191103809d0SVladimir Medvedkin 			config.nb_routes_per_depth[depth] =
192103809d0SVladimir Medvedkin 				RTE_MIN(max_routes_per_depth, avg_routes_left);
193103809d0SVladimir Medvedkin 			nr += config.nb_routes_per_depth[depth];
194103809d0SVladimir Medvedkin 		}
195103809d0SVladimir Medvedkin 	}
196103809d0SVladimir Medvedkin 
197103809d0SVladimir Medvedkin 	return 0;
198103809d0SVladimir Medvedkin }
199103809d0SVladimir Medvedkin 
200103809d0SVladimir Medvedkin static int
201103809d0SVladimir Medvedkin parse_distrib(uint8_t depth_lim, const uint32_t n)
202103809d0SVladimir Medvedkin {
203103809d0SVladimir Medvedkin 	uint8_t	rpd[128 + 1] = {0}; /*routes ratios per depth including /0 */
204103809d0SVladimir Medvedkin 	uint32_t nrpd[128 + 1] = {0}; /* number of routes per depth */
205103809d0SVladimir Medvedkin 	uint32_t n_routes;
206103809d0SVladimir Medvedkin 	uint8_t depth, ratio, ratio_acc = 0;
207103809d0SVladimir Medvedkin 	char *in;
208103809d0SVladimir Medvedkin 
209103809d0SVladimir Medvedkin 	in = strtok(distrib_string, ",");
210103809d0SVladimir Medvedkin 
211103809d0SVladimir Medvedkin 	/*parse configures routes percentage ratios*/
212103809d0SVladimir Medvedkin 	while (in != NULL) {
213103809d0SVladimir Medvedkin 		GET_CB_FIELD(in, depth, 0, UINT8_MAX, ':');
214103809d0SVladimir Medvedkin 		if (in[strlen(in) - 1] == '%') {
215103809d0SVladimir Medvedkin 			in[strlen(in) - 1] = 0;
216103809d0SVladimir Medvedkin 			GET_CB_FIELD(in, ratio, 0, UINT8_MAX, '\0');
217103809d0SVladimir Medvedkin 			if (depth > depth_lim) {
218103809d0SVladimir Medvedkin 				printf("Depth /%d is bigger than maximum "
219103809d0SVladimir Medvedkin 					"allowed depth /%d for this AF\n",
220103809d0SVladimir Medvedkin 					depth, depth_lim);
221103809d0SVladimir Medvedkin 				return -EINVAL;
222103809d0SVladimir Medvedkin 			}
223103809d0SVladimir Medvedkin 			if (ratio > 100) {
224103809d0SVladimir Medvedkin 				printf("Ratio for depth /%d is bigger "
225103809d0SVladimir Medvedkin 					"than 100%%\n", depth);
226103809d0SVladimir Medvedkin 				return -EINVAL;
227103809d0SVladimir Medvedkin 			}
228103809d0SVladimir Medvedkin 			if ((depth < 64) && ((n * ratio) / 100) >
229103809d0SVladimir Medvedkin 					(1ULL << depth)) {
230103809d0SVladimir Medvedkin 				printf("Configured ratio %d%% for depth /%d "
231103809d0SVladimir Medvedkin 					"has %d different routes, but maximum "
232103809d0SVladimir Medvedkin 					"is %lu\n", ratio, depth,
233103809d0SVladimir Medvedkin 					((n * ratio) / 100), (1UL << depth));
234103809d0SVladimir Medvedkin 				return -EINVAL;
235103809d0SVladimir Medvedkin 			}
236103809d0SVladimir Medvedkin 			rpd[depth] = ratio;
237103809d0SVladimir Medvedkin 			/*configured zero routes for a given depth*/
238103809d0SVladimir Medvedkin 			if (ratio == 0)
239103809d0SVladimir Medvedkin 				rpd[depth] = UINT8_MAX;
240103809d0SVladimir Medvedkin 			/*sum of all percentage ratios*/
241103809d0SVladimir Medvedkin 			ratio_acc += ratio;
242103809d0SVladimir Medvedkin 		} else {
243103809d0SVladimir Medvedkin 			GET_CB_FIELD(in, n_routes, 0, UINT32_MAX, '\0');
244103809d0SVladimir Medvedkin 			rpd[depth] = UINT8_MAX;
245103809d0SVladimir Medvedkin 			nrpd[depth] = n_routes;
246103809d0SVladimir Medvedkin 		}
247103809d0SVladimir Medvedkin 
248103809d0SVladimir Medvedkin 		/*number of configured depths in*/
249103809d0SVladimir Medvedkin 		in = strtok(NULL, ",");
250103809d0SVladimir Medvedkin 	}
251103809d0SVladimir Medvedkin 
252103809d0SVladimir Medvedkin 	if (ratio_acc > 100) {
253103809d0SVladimir Medvedkin 		printf("Total ratio's sum is bigger than 100%%\n");
254103809d0SVladimir Medvedkin 		return -EINVAL;
255103809d0SVladimir Medvedkin 	}
256103809d0SVladimir Medvedkin 
257103809d0SVladimir Medvedkin 	return complete_distrib(depth_lim, n, rpd, nrpd);
258103809d0SVladimir Medvedkin }
259103809d0SVladimir Medvedkin 
260103809d0SVladimir Medvedkin static void
261103809d0SVladimir Medvedkin shuffle_rt_4(struct rt_rule_4 *rt, int n)
262103809d0SVladimir Medvedkin {
263103809d0SVladimir Medvedkin 	struct rt_rule_4 tmp;
264103809d0SVladimir Medvedkin 	int i, j;
265103809d0SVladimir Medvedkin 
266103809d0SVladimir Medvedkin 	for (i = 0; i < n; i++) {
267103809d0SVladimir Medvedkin 		j = rte_rand() % n;
268103809d0SVladimir Medvedkin 		tmp.addr = rt[i].addr;
269103809d0SVladimir Medvedkin 		tmp.depth = rt[i].depth;
270103809d0SVladimir Medvedkin 		tmp.nh = rt[i].nh;
271103809d0SVladimir Medvedkin 
272103809d0SVladimir Medvedkin 		rt[i].addr = rt[j].addr;
273103809d0SVladimir Medvedkin 		rt[i].depth = rt[j].depth;
274103809d0SVladimir Medvedkin 		rt[i].nh = rt[j].nh;
275103809d0SVladimir Medvedkin 
276103809d0SVladimir Medvedkin 		rt[j].addr = tmp.addr;
277103809d0SVladimir Medvedkin 		rt[j].depth = tmp.depth;
278103809d0SVladimir Medvedkin 		rt[j].nh = tmp.nh;
279103809d0SVladimir Medvedkin 	}
280103809d0SVladimir Medvedkin }
281103809d0SVladimir Medvedkin 
282103809d0SVladimir Medvedkin static void
283103809d0SVladimir Medvedkin shuffle_rt_6(struct rt_rule_6 *rt, int n)
284103809d0SVladimir Medvedkin {
285103809d0SVladimir Medvedkin 	struct rt_rule_6 tmp;
286103809d0SVladimir Medvedkin 	int i, j;
287103809d0SVladimir Medvedkin 
288103809d0SVladimir Medvedkin 	for (i = 0; i < n; i++) {
289103809d0SVladimir Medvedkin 		j = rte_rand() % n;
290e1a06e39SRobin Jarry 		tmp.addr = rt[i].addr;
291103809d0SVladimir Medvedkin 		tmp.depth = rt[i].depth;
292103809d0SVladimir Medvedkin 		tmp.nh = rt[i].nh;
293103809d0SVladimir Medvedkin 
294e1a06e39SRobin Jarry 		rt[i].addr = rt[j].addr;
295103809d0SVladimir Medvedkin 		rt[i].depth = rt[j].depth;
296103809d0SVladimir Medvedkin 		rt[i].nh = rt[j].nh;
297103809d0SVladimir Medvedkin 
298e1a06e39SRobin Jarry 		rt[j].addr = tmp.addr;
299103809d0SVladimir Medvedkin 		rt[j].depth = tmp.depth;
300103809d0SVladimir Medvedkin 		rt[j].nh = tmp.nh;
301103809d0SVladimir Medvedkin 	}
302103809d0SVladimir Medvedkin }
303103809d0SVladimir Medvedkin 
304103809d0SVladimir Medvedkin static void
305103809d0SVladimir Medvedkin gen_random_rt_4(struct rt_rule_4 *rt, int nh_sz)
306103809d0SVladimir Medvedkin {
307103809d0SVladimir Medvedkin 	uint32_t i, j, k = 0;
308103809d0SVladimir Medvedkin 
309103809d0SVladimir Medvedkin 	if (config.nb_routes_per_depth[0] != 0) {
310103809d0SVladimir Medvedkin 		rt[k].addr = 0;
311103809d0SVladimir Medvedkin 		rt[k].depth = 0;
312103809d0SVladimir Medvedkin 		rt[k++].nh = rte_rand() & get_max_nh(nh_sz);
313103809d0SVladimir Medvedkin 	}
314103809d0SVladimir Medvedkin 
315103809d0SVladimir Medvedkin 	for (i = 1; i <= 32; i++) {
316103809d0SVladimir Medvedkin 		double edge = 0;
317103809d0SVladimir Medvedkin 		double step;
318103809d0SVladimir Medvedkin 		step = (double)(1ULL << i) / config.nb_routes_per_depth[i];
319103809d0SVladimir Medvedkin 		for (j = 0; j < config.nb_routes_per_depth[i];
320103809d0SVladimir Medvedkin 				j++, k++, edge += step) {
321103809d0SVladimir Medvedkin 			uint64_t rnd_val = get_rnd_rng((uint64_t)edge,
322103809d0SVladimir Medvedkin 				(uint64_t)(edge + step));
323103809d0SVladimir Medvedkin 			rt[k].addr = rnd_val << (32 - i);
324103809d0SVladimir Medvedkin 			rt[k].depth = i;
325103809d0SVladimir Medvedkin 			rt[k].nh = rte_rand() & get_max_nh(nh_sz);
326103809d0SVladimir Medvedkin 		}
327103809d0SVladimir Medvedkin 	}
328103809d0SVladimir Medvedkin }
329103809d0SVladimir Medvedkin 
330103809d0SVladimir Medvedkin static void
331103809d0SVladimir Medvedkin complete_v6_addr(uint32_t *addr, uint32_t rnd, int n)
332103809d0SVladimir Medvedkin {
333103809d0SVladimir Medvedkin 	int i;
334103809d0SVladimir Medvedkin 
335103809d0SVladimir Medvedkin 	for (i = 0; i < n; i++)
336103809d0SVladimir Medvedkin 		addr[i] = rte_rand();
337103809d0SVladimir Medvedkin 	addr[i++] = rnd;
338103809d0SVladimir Medvedkin 	for (; i < 4; i++)
339103809d0SVladimir Medvedkin 		addr[i] = 0;
340103809d0SVladimir Medvedkin }
341103809d0SVladimir Medvedkin 
342103809d0SVladimir Medvedkin static void
343103809d0SVladimir Medvedkin gen_random_rt_6(struct rt_rule_6 *rt, int nh_sz)
344103809d0SVladimir Medvedkin {
345f1caf7f8SVladimir Medvedkin 	uint32_t a, i, j, k = 0;
346103809d0SVladimir Medvedkin 
347103809d0SVladimir Medvedkin 	if (config.nb_routes_per_depth[0] != 0) {
348e1a06e39SRobin Jarry 		memset(&rt[k].addr, 0, 16);
349103809d0SVladimir Medvedkin 		rt[k].depth = 0;
350103809d0SVladimir Medvedkin 		rt[k++].nh = rte_rand() & get_max_nh(nh_sz);
351103809d0SVladimir Medvedkin 	}
352103809d0SVladimir Medvedkin 
353f1caf7f8SVladimir Medvedkin 	for (a = 0; a < 4; a++) {
354103809d0SVladimir Medvedkin 		for (i = 1; i <= 32; i++) {
355103809d0SVladimir Medvedkin 			uint32_t rnd;
356103809d0SVladimir Medvedkin 			double edge = 0;
357103809d0SVladimir Medvedkin 			double step = (double)(1ULL << i) /
358103809d0SVladimir Medvedkin 				config.nb_routes_per_depth[(a * 32) + i];
359103809d0SVladimir Medvedkin 			for (j = 0; j < config.nb_routes_per_depth[a * 32 + i];
360103809d0SVladimir Medvedkin 					j++, k++, edge += step) {
361103809d0SVladimir Medvedkin 				uint64_t rnd_val = get_rnd_rng((uint64_t)edge,
362103809d0SVladimir Medvedkin 					(uint64_t)(edge + step));
363103809d0SVladimir Medvedkin 				rnd = rte_cpu_to_be_32(rnd_val << (32 - i));
364e1a06e39SRobin Jarry 				complete_v6_addr((uint32_t *)&rt[k].addr,
365103809d0SVladimir Medvedkin 					rnd, a);
366103809d0SVladimir Medvedkin 				rt[k].depth = (a * 32) + i;
367103809d0SVladimir Medvedkin 				rt[k].nh = rte_rand() & get_max_nh(nh_sz);
368103809d0SVladimir Medvedkin 			}
369103809d0SVladimir Medvedkin 		}
370103809d0SVladimir Medvedkin 	}
371103809d0SVladimir Medvedkin }
372103809d0SVladimir Medvedkin 
373103809d0SVladimir Medvedkin static inline void
374e1a06e39SRobin Jarry set_rnd_ipv6(struct rte_ipv6_addr *addr, struct rte_ipv6_addr *route, int depth)
375103809d0SVladimir Medvedkin {
376103809d0SVladimir Medvedkin 	int i;
377103809d0SVladimir Medvedkin 
378103809d0SVladimir Medvedkin 	for (i = 0; i < 16; i++)
379e1a06e39SRobin Jarry 		addr->a[i] = rte_rand();
380103809d0SVladimir Medvedkin 
381103809d0SVladimir Medvedkin 	for (i = 0; i < 16; i++) {
382103809d0SVladimir Medvedkin 		if (depth >= 8)
383e1a06e39SRobin Jarry 			addr->a[i] = route->a[i];
384103809d0SVladimir Medvedkin 		else if (depth > 0) {
385e1a06e39SRobin Jarry 			addr->a[i] &= (uint16_t)UINT8_MAX >> depth;
386e1a06e39SRobin Jarry 			addr->a[i] |= route->a[i] & UINT8_MAX << (8 - depth);
387103809d0SVladimir Medvedkin 		} else
388103809d0SVladimir Medvedkin 			return;
389103809d0SVladimir Medvedkin 		depth -= 8;
390103809d0SVladimir Medvedkin 	}
391103809d0SVladimir Medvedkin }
392103809d0SVladimir Medvedkin 
393103809d0SVladimir Medvedkin static void
394103809d0SVladimir Medvedkin gen_rnd_lookup_tbl(int af)
395103809d0SVladimir Medvedkin {
396103809d0SVladimir Medvedkin 	uint32_t *tbl4 = config.lookup_tbl;
397e1a06e39SRobin Jarry 	struct rte_ipv6_addr *tbl6 = config.lookup_tbl;
398103809d0SVladimir Medvedkin 	struct rt_rule_4 *rt4 = (struct rt_rule_4 *)config.rt;
399103809d0SVladimir Medvedkin 	struct rt_rule_6 *rt6 = (struct rt_rule_6 *)config.rt;
400103809d0SVladimir Medvedkin 	uint32_t i, j;
401103809d0SVladimir Medvedkin 
402103809d0SVladimir Medvedkin 	if (af == AF_INET) {
403103809d0SVladimir Medvedkin 		for (i = 0, j = 0; i < config.nb_lookup_ips;
404103809d0SVladimir Medvedkin 				i++, j = (j + 1) % config.nb_routes) {
405103809d0SVladimir Medvedkin 			if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) {
406103809d0SVladimir Medvedkin 				tbl4[i] = rte_rand();
407103809d0SVladimir Medvedkin 				config.nb_lookup_ips_rnd++;
408103809d0SVladimir Medvedkin 			} else
409103809d0SVladimir Medvedkin 				tbl4[i] = rt4[j].addr | (rte_rand() &
410103809d0SVladimir Medvedkin 					((1ULL << (32 - rt4[j].depth)) - 1));
411103809d0SVladimir Medvedkin 		}
412103809d0SVladimir Medvedkin 	} else {
413103809d0SVladimir Medvedkin 		for (i = 0, j = 0; i < config.nb_lookup_ips;
414103809d0SVladimir Medvedkin 				i++, j = (j + 1) % config.nb_routes) {
415103809d0SVladimir Medvedkin 			if ((rte_rand() % 100) < config.rnd_lookup_ips_ratio) {
416e1a06e39SRobin Jarry 				set_rnd_ipv6(&tbl6[i], &rt6[j].addr, 0);
417103809d0SVladimir Medvedkin 				config.nb_lookup_ips_rnd++;
418103809d0SVladimir Medvedkin 			} else {
419e1a06e39SRobin Jarry 				set_rnd_ipv6(&tbl6[i], &rt6[j].addr, rt6[j].depth);
420103809d0SVladimir Medvedkin 			}
421103809d0SVladimir Medvedkin 		}
422103809d0SVladimir Medvedkin 	}
423103809d0SVladimir Medvedkin }
424103809d0SVladimir Medvedkin 
425103809d0SVladimir Medvedkin static int
4268cd3ef56SVladimir Medvedkin _inet_net_pton(int af, char *prefix, void *addr)
4278cd3ef56SVladimir Medvedkin {
4288cd3ef56SVladimir Medvedkin 	const char *dlm = "/";
4298cd3ef56SVladimir Medvedkin 	char *s, *sp;
4308cd3ef56SVladimir Medvedkin 	int ret, depth;
4318cd3ef56SVladimir Medvedkin 	unsigned int max_depth;
4328cd3ef56SVladimir Medvedkin 
4338cd3ef56SVladimir Medvedkin 	if ((prefix == NULL) || (addr == NULL))
4348cd3ef56SVladimir Medvedkin 		return -EINVAL;
4358cd3ef56SVladimir Medvedkin 
4368cd3ef56SVladimir Medvedkin 	s = strtok_r(prefix, dlm, &sp);
4378cd3ef56SVladimir Medvedkin 	if (s == NULL)
4388cd3ef56SVladimir Medvedkin 		return -EINVAL;
4398cd3ef56SVladimir Medvedkin 
4408cd3ef56SVladimir Medvedkin 	ret = inet_pton(af, s, addr);
4418cd3ef56SVladimir Medvedkin 	if (ret != 1)
4428cd3ef56SVladimir Medvedkin 		return -errno;
4438cd3ef56SVladimir Medvedkin 
4448cd3ef56SVladimir Medvedkin 	s = strtok_r(NULL, dlm, &sp);
4458cd3ef56SVladimir Medvedkin 	max_depth = (af == AF_INET) ? 32 : 128;
4468cd3ef56SVladimir Medvedkin 	GET_CB_FIELD(s, depth, 0, max_depth, 0);
4478cd3ef56SVladimir Medvedkin 
4488cd3ef56SVladimir Medvedkin 	return depth;
4498cd3ef56SVladimir Medvedkin }
4508cd3ef56SVladimir Medvedkin 
4518cd3ef56SVladimir Medvedkin static int
452103809d0SVladimir Medvedkin parse_rt_4(FILE *f)
453103809d0SVladimir Medvedkin {
454103809d0SVladimir Medvedkin 	int ret, i, j = 0;
455103809d0SVladimir Medvedkin 	char *s, *sp, *in[RT_NUM];
456103809d0SVladimir Medvedkin 	static const char *dlm = " \t\n";
457103809d0SVladimir Medvedkin 	int string_tok_nb = RTE_DIM(in);
458103809d0SVladimir Medvedkin 	struct rt_rule_4 *rt;
459103809d0SVladimir Medvedkin 
460103809d0SVladimir Medvedkin 	rt = (struct rt_rule_4 *)config.rt;
461103809d0SVladimir Medvedkin 
462103809d0SVladimir Medvedkin 	while (fgets(line, sizeof(line), f) != NULL) {
463103809d0SVladimir Medvedkin 		s = line;
464103809d0SVladimir Medvedkin 		for (i = 0; i != string_tok_nb; i++) {
465103809d0SVladimir Medvedkin 			in[i] = strtok_r(s, dlm, &sp);
466103809d0SVladimir Medvedkin 			if (in[i] == NULL)
467103809d0SVladimir Medvedkin 				return -EINVAL;
468103809d0SVladimir Medvedkin 			s = NULL;
469103809d0SVladimir Medvedkin 		}
470103809d0SVladimir Medvedkin 
4718cd3ef56SVladimir Medvedkin 		ret = _inet_net_pton(AF_INET, in[RT_PREFIX], &rt[j].addr);
472103809d0SVladimir Medvedkin 		if (ret == -1)
473103809d0SVladimir Medvedkin 			return -errno;
474103809d0SVladimir Medvedkin 
475103809d0SVladimir Medvedkin 		rt[j].addr = rte_be_to_cpu_32(rt[j].addr);
476103809d0SVladimir Medvedkin 		rt[j].depth = ret;
477103809d0SVladimir Medvedkin 		config.nb_routes_per_depth[ret]++;
478103809d0SVladimir Medvedkin 		GET_CB_FIELD(in[RT_NEXTHOP], rt[j].nh, 0,
479103809d0SVladimir Medvedkin 				UINT32_MAX, 0);
480103809d0SVladimir Medvedkin 		j++;
481103809d0SVladimir Medvedkin 	}
482103809d0SVladimir Medvedkin 	return 0;
483103809d0SVladimir Medvedkin }
484103809d0SVladimir Medvedkin 
485103809d0SVladimir Medvedkin static int
486103809d0SVladimir Medvedkin parse_rt_6(FILE *f)
487103809d0SVladimir Medvedkin {
488103809d0SVladimir Medvedkin 	int ret, i, j = 0;
489103809d0SVladimir Medvedkin 	char *s, *sp, *in[RT_NUM];
490103809d0SVladimir Medvedkin 	static const char *dlm = " \t\n";
491103809d0SVladimir Medvedkin 	int string_tok_nb = RTE_DIM(in);
492103809d0SVladimir Medvedkin 	struct rt_rule_6 *rt;
493103809d0SVladimir Medvedkin 
494103809d0SVladimir Medvedkin 	rt = (struct rt_rule_6 *)config.rt;
495103809d0SVladimir Medvedkin 
496103809d0SVladimir Medvedkin 	while (fgets(line, sizeof(line), f) != NULL) {
497103809d0SVladimir Medvedkin 		s = line;
498103809d0SVladimir Medvedkin 		for (i = 0; i != string_tok_nb; i++) {
499103809d0SVladimir Medvedkin 			in[i] = strtok_r(s, dlm, &sp);
500103809d0SVladimir Medvedkin 			if (in[i] == NULL)
501103809d0SVladimir Medvedkin 				return -EINVAL;
502103809d0SVladimir Medvedkin 			s = NULL;
503103809d0SVladimir Medvedkin 		}
504103809d0SVladimir Medvedkin 
505e1a06e39SRobin Jarry 		ret = _inet_net_pton(AF_INET6, in[RT_PREFIX], &rt[j].addr);
506103809d0SVladimir Medvedkin 		if (ret < 0)
507103809d0SVladimir Medvedkin 			return ret;
508103809d0SVladimir Medvedkin 
509103809d0SVladimir Medvedkin 		rt[j].depth = ret;
510103809d0SVladimir Medvedkin 		config.nb_routes_per_depth[ret]++;
511103809d0SVladimir Medvedkin 		GET_CB_FIELD(in[RT_NEXTHOP], rt[j].nh, 0,
512103809d0SVladimir Medvedkin 				UINT32_MAX, 0);
513103809d0SVladimir Medvedkin 		j++;
514103809d0SVladimir Medvedkin 	}
515103809d0SVladimir Medvedkin 
516103809d0SVladimir Medvedkin 	return 0;
517103809d0SVladimir Medvedkin }
518103809d0SVladimir Medvedkin 
519103809d0SVladimir Medvedkin static int
520103809d0SVladimir Medvedkin parse_lookup(FILE *f, int af)
521103809d0SVladimir Medvedkin {
522103809d0SVladimir Medvedkin 	int ret, i = 0;
523103809d0SVladimir Medvedkin 	uint8_t *tbl = (uint8_t *)config.lookup_tbl;
524103809d0SVladimir Medvedkin 	int step = (af == AF_INET) ? 4 : 16;
525103809d0SVladimir Medvedkin 	char *s;
526103809d0SVladimir Medvedkin 
527103809d0SVladimir Medvedkin 	while (fgets(line, sizeof(line), f) != NULL) {
528103809d0SVladimir Medvedkin 		s = strtok(line, " \t\n");
5295876077aSVladimir Medvedkin 		if (s == NULL)
5305876077aSVladimir Medvedkin 			return -EINVAL;
531103809d0SVladimir Medvedkin 		ret = inet_pton(af, s, &tbl[i]);
532103809d0SVladimir Medvedkin 		if (ret != 1)
533103809d0SVladimir Medvedkin 			return -EINVAL;
534103809d0SVladimir Medvedkin 		i += step;
535103809d0SVladimir Medvedkin 	}
536103809d0SVladimir Medvedkin 	return 0;
537103809d0SVladimir Medvedkin }
538103809d0SVladimir Medvedkin 
539103809d0SVladimir Medvedkin static int
540103809d0SVladimir Medvedkin dump_lookup(int af)
541103809d0SVladimir Medvedkin {
542103809d0SVladimir Medvedkin 	FILE *f;
543103809d0SVladimir Medvedkin 	uint32_t *tbl4 = config.lookup_tbl;
544e1a06e39SRobin Jarry 	struct rte_ipv6_addr *tbl6 = config.lookup_tbl;
545103809d0SVladimir Medvedkin 	uint32_t i;
546103809d0SVladimir Medvedkin 
547103809d0SVladimir Medvedkin 	f = fopen(config.lookup_ips_file_s, "w");
548103809d0SVladimir Medvedkin 	if (f == NULL) {
549103809d0SVladimir Medvedkin 		printf("Can not open file %s\n", config.lookup_ips_file_s);
550103809d0SVladimir Medvedkin 		return -1;
551103809d0SVladimir Medvedkin 	}
552103809d0SVladimir Medvedkin 
553103809d0SVladimir Medvedkin 	if (af == AF_INET) {
554103809d0SVladimir Medvedkin 		for (i = 0; i < config.nb_lookup_ips; i++)
555103809d0SVladimir Medvedkin 			fprintf(f, NIPQUAD_FMT"\n", NIPQUAD(tbl4[i]));
556103809d0SVladimir Medvedkin 	} else {
557103809d0SVladimir Medvedkin 		for (i = 0; i < config.nb_lookup_ips; i++)
558e1a06e39SRobin Jarry 			fprintf(f, RTE_IPV6_ADDR_FMT"\n", RTE_IPV6_ADDR_SPLIT(&tbl6[i * 16]));
559103809d0SVladimir Medvedkin 	}
560103809d0SVladimir Medvedkin 	fclose(f);
561103809d0SVladimir Medvedkin 	return 0;
562103809d0SVladimir Medvedkin }
563103809d0SVladimir Medvedkin 
564103809d0SVladimir Medvedkin static void
565103809d0SVladimir Medvedkin print_config(void)
566103809d0SVladimir Medvedkin {
567103809d0SVladimir Medvedkin 	uint8_t depth_lim;
568103809d0SVladimir Medvedkin 	char dlm;
569103809d0SVladimir Medvedkin 	int i;
570103809d0SVladimir Medvedkin 
571103809d0SVladimir Medvedkin 	depth_lim = ((config.flags & IPV6_FLAG) == IPV6_FLAG) ? 128 : 32;
572103809d0SVladimir Medvedkin 
573103809d0SVladimir Medvedkin 	fprintf(stdout,
574103809d0SVladimir Medvedkin 		"Routes total: %u\n"
575103809d0SVladimir Medvedkin 		"Routes distribution:\n", config.nb_routes);
576103809d0SVladimir Medvedkin 
577103809d0SVladimir Medvedkin 	for (i = 1; i <= depth_lim; i++) {
578103809d0SVladimir Medvedkin 		fprintf(stdout,
579103809d0SVladimir Medvedkin 			"depth /%d:%u", i, config.nb_routes_per_depth[i]);
580103809d0SVladimir Medvedkin 		if (i % 4 == 0)
581103809d0SVladimir Medvedkin 			dlm = '\n';
582103809d0SVladimir Medvedkin 		else
583103809d0SVladimir Medvedkin 			dlm = '\t';
584103809d0SVladimir Medvedkin 		fprintf(stdout, "%c", dlm);
585103809d0SVladimir Medvedkin 	}
586103809d0SVladimir Medvedkin 
587103809d0SVladimir Medvedkin 	fprintf(stdout,
588103809d0SVladimir Medvedkin 		"Lookup tuples: %u\n"
589103809d0SVladimir Medvedkin 		"Configured ratios of random ips for lookup: %u\n"
590103809d0SVladimir Medvedkin 		"Random lookup ips: %u\n",
591103809d0SVladimir Medvedkin 		config.nb_lookup_ips, config.rnd_lookup_ips_ratio,
592103809d0SVladimir Medvedkin 		config.nb_lookup_ips_rnd);
593103809d0SVladimir Medvedkin }
594103809d0SVladimir Medvedkin 
595103809d0SVladimir Medvedkin static void
596103809d0SVladimir Medvedkin print_usage(void)
597103809d0SVladimir Medvedkin {
598103809d0SVladimir Medvedkin 	fprintf(stdout,
599103809d0SVladimir Medvedkin 		PRINT_USAGE_START
600103809d0SVladimir Medvedkin 		"[-f <routes file>]\n"
601103809d0SVladimir Medvedkin 		"[-t <ip's file for lookup>]\n"
602103809d0SVladimir Medvedkin 		"[-n <number of routes (if -f is not specified)>]\n"
603103809d0SVladimir Medvedkin 		"[-l <number of ip's for lookup (if -t is not specified)>]\n"
604103809d0SVladimir Medvedkin 		"[-d <\",\" separated \"depth:n%%\"routes depth distribution"
605103809d0SVladimir Medvedkin 		"(if -f is not specified)>]\n"
606103809d0SVladimir Medvedkin 		"[-r <percentage ratio of random ip's to lookup"
607103809d0SVladimir Medvedkin 		"(if -t is not specified)>]\n"
6087be78d02SJosh Soref 		"[-c <do comparison with LPM library>]\n"
609103809d0SVladimir Medvedkin 		"[-6 <do tests with ipv6 (default ipv4)>]\n"
610103809d0SVladimir Medvedkin 		"[-s <shuffle randomly generated routes>]\n"
611103809d0SVladimir Medvedkin 		"[-a <check nexthops for all ipv4 address space"
612103809d0SVladimir Medvedkin 		"(only valid with -c)>]\n"
613e8cff614SLuca Boccassi 		"[-b <fib algorithm>]\n\tavailable options for ipv4\n"
614103809d0SVladimir Medvedkin 		"\t\trib - RIB based FIB\n"
615103809d0SVladimir Medvedkin 		"\t\tdir - DIR24_8 based FIB\n"
616e8cff614SLuca Boccassi 		"\tavailable options for ipv6:\n"
617103809d0SVladimir Medvedkin 		"\t\trib - RIB based FIB\n"
618103809d0SVladimir Medvedkin 		"\t\ttrie - TRIE based FIB\n"
619103809d0SVladimir Medvedkin 		"defaults are: dir for ipv4 and trie for ipv6\n"
620103809d0SVladimir Medvedkin 		"[-e <entry size (valid only for dir and trie fib types): "
621103809d0SVladimir Medvedkin 		"1/2/4/8 (default 4)>]\n"
622103809d0SVladimir Medvedkin 		"[-g <number of tbl8's for dir24_8 or trie FIBs>]\n"
623103809d0SVladimir Medvedkin 		"[-w <path to the file to dump routing table>]\n"
624eda44cedSVladimir Medvedkin 		"[-u <path to the file to dump ip's for lookup>]\n"
6257be78d02SJosh Soref 		"[-v <type of lookup function:"
626eda44cedSVladimir Medvedkin 		"\ts1, s2, s3 (3 types of scalar), v (vector) -"
627eda44cedSVladimir Medvedkin 		" for DIR24_8 based FIB\n"
628eda44cedSVladimir Medvedkin 		"\ts, v - for TRIE based ipv6 FIB>]\n",
629103809d0SVladimir Medvedkin 		config.prgname);
630103809d0SVladimir Medvedkin }
631103809d0SVladimir Medvedkin 
632103809d0SVladimir Medvedkin static int
633103809d0SVladimir Medvedkin check_config(void)
634103809d0SVladimir Medvedkin {
635103809d0SVladimir Medvedkin 	if ((config.routes_file == NULL) && (config.lookup_ips_file != NULL)) {
636103809d0SVladimir Medvedkin 		printf("-t option only valid with -f option\n");
637103809d0SVladimir Medvedkin 		return -1;
638103809d0SVladimir Medvedkin 	}
639103809d0SVladimir Medvedkin 
640103809d0SVladimir Medvedkin 	if ((config.flags & CMP_ALL_FLAG) && (config.flags & IPV6_FLAG)) {
641103809d0SVladimir Medvedkin 		printf("-a flag is only valid for ipv4\n");
642103809d0SVladimir Medvedkin 		return -1;
643103809d0SVladimir Medvedkin 	}
644103809d0SVladimir Medvedkin 
645103809d0SVladimir Medvedkin 	if ((config.flags & CMP_ALL_FLAG) &&
646103809d0SVladimir Medvedkin 			((config.flags & CMP_FLAG) != CMP_FLAG)) {
647103809d0SVladimir Medvedkin 		printf("-a flag is valid only with -c flag\n");
648103809d0SVladimir Medvedkin 		return -1;
649103809d0SVladimir Medvedkin 	}
650103809d0SVladimir Medvedkin 
651103809d0SVladimir Medvedkin 	if (!((config.ent_sz == 1) || (config.ent_sz == 2) ||
652103809d0SVladimir Medvedkin 			(config.ent_sz == 4) || (config.ent_sz == 8))) {
653103809d0SVladimir Medvedkin 		printf("wrong -e option %d, can be 1 or 2 or 4 or 8\n",
654103809d0SVladimir Medvedkin 			config.ent_sz);
655103809d0SVladimir Medvedkin 		return -1;
656103809d0SVladimir Medvedkin 	}
657103809d0SVladimir Medvedkin 
658103809d0SVladimir Medvedkin 	if ((config.ent_sz == 1) && (config.flags & IPV6_FLAG)) {
659103809d0SVladimir Medvedkin 		printf("-e 1 is valid only for ipv4\n");
660103809d0SVladimir Medvedkin 		return -1;
661103809d0SVladimir Medvedkin 	}
662103809d0SVladimir Medvedkin 	return 0;
663103809d0SVladimir Medvedkin }
664103809d0SVladimir Medvedkin 
665103809d0SVladimir Medvedkin static void
666103809d0SVladimir Medvedkin parse_opts(int argc, char **argv)
667103809d0SVladimir Medvedkin {
668103809d0SVladimir Medvedkin 	int opt;
669103809d0SVladimir Medvedkin 	char *endptr;
670103809d0SVladimir Medvedkin 
671eda44cedSVladimir Medvedkin 	while ((opt = getopt(argc, argv, "f:t:n:d:l:r:c6ab:e:g:w:u:sv:")) !=
672103809d0SVladimir Medvedkin 			-1) {
673103809d0SVladimir Medvedkin 		switch (opt) {
674103809d0SVladimir Medvedkin 		case 'f':
675103809d0SVladimir Medvedkin 			config.routes_file = optarg;
676103809d0SVladimir Medvedkin 			break;
677103809d0SVladimir Medvedkin 		case 't':
678103809d0SVladimir Medvedkin 			config.lookup_ips_file = optarg;
679103809d0SVladimir Medvedkin 			break;
680103809d0SVladimir Medvedkin 		case 'w':
681103809d0SVladimir Medvedkin 			config.routes_file_s = optarg;
682103809d0SVladimir Medvedkin 			config.flags |= DRY_RUN_FLAG;
683103809d0SVladimir Medvedkin 			break;
684103809d0SVladimir Medvedkin 		case 'u':
685103809d0SVladimir Medvedkin 			config.lookup_ips_file_s = optarg;
686103809d0SVladimir Medvedkin 			config.flags |= DRY_RUN_FLAG;
687103809d0SVladimir Medvedkin 			break;
688103809d0SVladimir Medvedkin 		case 'n':
689103809d0SVladimir Medvedkin 			errno = 0;
690103809d0SVladimir Medvedkin 			config.nb_routes = strtoul(optarg, &endptr, 10);
691103809d0SVladimir Medvedkin 			if ((errno != 0) || (config.nb_routes == 0)) {
692103809d0SVladimir Medvedkin 				print_usage();
693103809d0SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -n\n");
694103809d0SVladimir Medvedkin 			}
695a01070daSVladimir Medvedkin 
696a01070daSVladimir Medvedkin 			if (config.nb_routes < config.print_fract)
697a01070daSVladimir Medvedkin 				config.print_fract = config.nb_routes;
698a01070daSVladimir Medvedkin 
699103809d0SVladimir Medvedkin 			break;
700103809d0SVladimir Medvedkin 		case 'd':
701103809d0SVladimir Medvedkin 			distrib_string = optarg;
702103809d0SVladimir Medvedkin 			break;
703103809d0SVladimir Medvedkin 		case 'l':
704103809d0SVladimir Medvedkin 			errno = 0;
705103809d0SVladimir Medvedkin 			config.nb_lookup_ips = strtoul(optarg, &endptr, 10);
706103809d0SVladimir Medvedkin 			if ((errno != 0) || (config.nb_lookup_ips == 0)) {
707103809d0SVladimir Medvedkin 				print_usage();
708103809d0SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -l\n");
709103809d0SVladimir Medvedkin 			}
710103809d0SVladimir Medvedkin 			break;
711103809d0SVladimir Medvedkin 		case 'r':
712103809d0SVladimir Medvedkin 			errno = 0;
713103809d0SVladimir Medvedkin 			config.rnd_lookup_ips_ratio =
714103809d0SVladimir Medvedkin 				strtoul(optarg, &endptr, 10);
715103809d0SVladimir Medvedkin 			if ((errno != 0) ||
716103809d0SVladimir Medvedkin 					(config.rnd_lookup_ips_ratio == 0) ||
717103809d0SVladimir Medvedkin 					(config.rnd_lookup_ips_ratio >= 100)) {
718103809d0SVladimir Medvedkin 				print_usage();
719103809d0SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -r\n");
720103809d0SVladimir Medvedkin 			}
721103809d0SVladimir Medvedkin 			break;
722103809d0SVladimir Medvedkin 		case 's':
723103809d0SVladimir Medvedkin 			config.flags |= SHUFFLE_FLAG;
724103809d0SVladimir Medvedkin 			break;
725103809d0SVladimir Medvedkin 		case 'c':
726103809d0SVladimir Medvedkin 			config.flags |= CMP_FLAG;
727103809d0SVladimir Medvedkin 			break;
728103809d0SVladimir Medvedkin 		case '6':
729103809d0SVladimir Medvedkin 			config.flags |= IPV6_FLAG;
730103809d0SVladimir Medvedkin 			break;
731103809d0SVladimir Medvedkin 		case 'a':
732103809d0SVladimir Medvedkin 			config.flags |= CMP_ALL_FLAG;
733103809d0SVladimir Medvedkin 			break;
734103809d0SVladimir Medvedkin 		case 'b':
735103809d0SVladimir Medvedkin 			if (strcmp(optarg, "rib") == 0) {
736103809d0SVladimir Medvedkin 				config.flags &= ~FIB_TYPE_MASK;
737103809d0SVladimir Medvedkin 				config.flags |= FIB_RIB_TYPE;
738103809d0SVladimir Medvedkin 			} else if (strcmp(optarg, "dir") == 0) {
739103809d0SVladimir Medvedkin 				config.flags &= ~FIB_TYPE_MASK;
740103809d0SVladimir Medvedkin 				config.flags |= FIB_V4_DIR_TYPE;
741103809d0SVladimir Medvedkin 			} else if (strcmp(optarg, "trie") == 0) {
742103809d0SVladimir Medvedkin 				config.flags &= ~FIB_TYPE_MASK;
743103809d0SVladimir Medvedkin 				config.flags |= FIB_V6_TRIE_TYPE;
744103809d0SVladimir Medvedkin 			} else
745103809d0SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -b\n");
746103809d0SVladimir Medvedkin 			break;
747103809d0SVladimir Medvedkin 		case 'e':
748103809d0SVladimir Medvedkin 			errno = 0;
749103809d0SVladimir Medvedkin 			config.ent_sz = strtoul(optarg, &endptr, 10);
750103809d0SVladimir Medvedkin 			if (errno != 0) {
751103809d0SVladimir Medvedkin 				print_usage();
752103809d0SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -e\n");
753103809d0SVladimir Medvedkin 			}
754103809d0SVladimir Medvedkin 			break;
755103809d0SVladimir Medvedkin 		case 'g':
756103809d0SVladimir Medvedkin 			errno = 0;
757103809d0SVladimir Medvedkin 			config.tbl8 = strtoul(optarg, &endptr, 10);
758103809d0SVladimir Medvedkin 			if ((errno != 0) || (config.tbl8 == 0)) {
759103809d0SVladimir Medvedkin 				print_usage();
760103809d0SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -g\n");
761103809d0SVladimir Medvedkin 			}
762103809d0SVladimir Medvedkin 			break;
763eda44cedSVladimir Medvedkin 		case 'v':
764eda44cedSVladimir Medvedkin 			if ((strcmp(optarg, "s1") == 0) ||
765eda44cedSVladimir Medvedkin 					(strcmp(optarg, "s") == 0)) {
766eda44cedSVladimir Medvedkin 				config.lookup_fn = 1;
767eda44cedSVladimir Medvedkin 				break;
768eda44cedSVladimir Medvedkin 			} else if (strcmp(optarg, "v") == 0) {
769eda44cedSVladimir Medvedkin 				config.lookup_fn = 2;
770eda44cedSVladimir Medvedkin 				break;
771eda44cedSVladimir Medvedkin 			} else if (strcmp(optarg, "s2") == 0) {
772eda44cedSVladimir Medvedkin 				config.lookup_fn = 3;
773eda44cedSVladimir Medvedkin 				break;
774eda44cedSVladimir Medvedkin 			} else if (strcmp(optarg, "s3") == 0) {
775eda44cedSVladimir Medvedkin 				config.lookup_fn = 4;
776eda44cedSVladimir Medvedkin 				break;
777eda44cedSVladimir Medvedkin 			}
778eda44cedSVladimir Medvedkin 			print_usage();
779eda44cedSVladimir Medvedkin 			rte_exit(-EINVAL, "Invalid option -v %s\n", optarg);
780103809d0SVladimir Medvedkin 		default:
781103809d0SVladimir Medvedkin 			print_usage();
782103809d0SVladimir Medvedkin 			rte_exit(-EINVAL, "Invalid options\n");
783103809d0SVladimir Medvedkin 		}
784103809d0SVladimir Medvedkin 	}
785103809d0SVladimir Medvedkin }
786103809d0SVladimir Medvedkin 
787103809d0SVladimir Medvedkin static int
788103809d0SVladimir Medvedkin dump_rt_4(struct rt_rule_4 *rt)
789103809d0SVladimir Medvedkin {
790103809d0SVladimir Medvedkin 	FILE *f;
791103809d0SVladimir Medvedkin 	uint32_t i;
792103809d0SVladimir Medvedkin 
793103809d0SVladimir Medvedkin 	f = fopen(config.routes_file_s, "w");
794103809d0SVladimir Medvedkin 	if (f == NULL) {
795103809d0SVladimir Medvedkin 		printf("Can not open file %s\n", config.routes_file_s);
796103809d0SVladimir Medvedkin 		return -1;
797103809d0SVladimir Medvedkin 	}
798103809d0SVladimir Medvedkin 
799103809d0SVladimir Medvedkin 	for (i = 0; i < config.nb_routes; i++)
800d19034aeSVladimir Medvedkin 		fprintf(f, NIPQUAD_FMT"/%d %"PRIu64"\n", NIPQUAD(rt[i].addr),
801103809d0SVladimir Medvedkin 			rt[i].depth, rt[i].nh);
802103809d0SVladimir Medvedkin 
803103809d0SVladimir Medvedkin 	fclose(f);
804103809d0SVladimir Medvedkin 	return 0;
805103809d0SVladimir Medvedkin }
806103809d0SVladimir Medvedkin 
807103809d0SVladimir Medvedkin static inline void
808103809d0SVladimir Medvedkin print_depth_err(void)
809103809d0SVladimir Medvedkin {
810103809d0SVladimir Medvedkin 	printf("LPM does not support /0 prefix length (default route), use "
811103809d0SVladimir Medvedkin 		"-d 0:0 option or remove /0 prefix from routes file\n");
812103809d0SVladimir Medvedkin }
813103809d0SVladimir Medvedkin 
814103809d0SVladimir Medvedkin static int
815103809d0SVladimir Medvedkin run_v4(void)
816103809d0SVladimir Medvedkin {
817103809d0SVladimir Medvedkin 	uint64_t start, acc;
818103809d0SVladimir Medvedkin 	uint64_t def_nh = 0;
819103809d0SVladimir Medvedkin 	struct rte_fib *fib;
820103809d0SVladimir Medvedkin 	struct rte_fib_conf conf = {0};
821103809d0SVladimir Medvedkin 	struct rt_rule_4 *rt;
822103809d0SVladimir Medvedkin 	uint32_t i, j, k;
823103809d0SVladimir Medvedkin 	int ret = 0;
824103809d0SVladimir Medvedkin 	struct rte_lpm	*lpm = NULL;
825103809d0SVladimir Medvedkin 	struct rte_lpm_config lpm_conf;
826103809d0SVladimir Medvedkin 	uint32_t *tbl4 = config.lookup_tbl;
827103809d0SVladimir Medvedkin 	uint64_t fib_nh[BURST_SZ];
828103809d0SVladimir Medvedkin 	uint32_t lpm_nh[BURST_SZ];
829103809d0SVladimir Medvedkin 
830103809d0SVladimir Medvedkin 	rt = (struct rt_rule_4 *)config.rt;
831103809d0SVladimir Medvedkin 
832103809d0SVladimir Medvedkin 	if (config.flags & DRY_RUN_FLAG) {
833103809d0SVladimir Medvedkin 		if (config.routes_file_s != NULL)
834103809d0SVladimir Medvedkin 			ret = dump_rt_4(rt);
835103809d0SVladimir Medvedkin 		if (ret != 0)
836103809d0SVladimir Medvedkin 			return ret;
837103809d0SVladimir Medvedkin 		if (config.lookup_ips_file_s != NULL)
838103809d0SVladimir Medvedkin 			ret = dump_lookup(AF_INET);
839103809d0SVladimir Medvedkin 		return ret;
840103809d0SVladimir Medvedkin 	}
841103809d0SVladimir Medvedkin 
842103809d0SVladimir Medvedkin 	conf.type = get_fib_type();
843103809d0SVladimir Medvedkin 	conf.default_nh = def_nh;
844103809d0SVladimir Medvedkin 	conf.max_routes = config.nb_routes * 2;
84511c5b9b5SVladimir Medvedkin 	conf.rib_ext_sz = 0;
846103809d0SVladimir Medvedkin 	if (conf.type == RTE_FIB_DIR24_8) {
8473d4e27fdSDavid Marchand 		conf.dir24_8.nh_sz = rte_ctz32(config.ent_sz);
848103809d0SVladimir Medvedkin 		conf.dir24_8.num_tbl8 = RTE_MIN(config.tbl8,
849103809d0SVladimir Medvedkin 			get_max_nh(conf.dir24_8.nh_sz));
850103809d0SVladimir Medvedkin 	}
851103809d0SVladimir Medvedkin 
852103809d0SVladimir Medvedkin 	fib = rte_fib_create("test", -1, &conf);
853103809d0SVladimir Medvedkin 	if (fib == NULL) {
854103809d0SVladimir Medvedkin 		printf("Can not alloc FIB, err %d\n", rte_errno);
855103809d0SVladimir Medvedkin 		return -rte_errno;
856103809d0SVladimir Medvedkin 	}
857103809d0SVladimir Medvedkin 
858eda44cedSVladimir Medvedkin 	if (config.lookup_fn != 0) {
859eda44cedSVladimir Medvedkin 		if (config.lookup_fn == 1)
860eda44cedSVladimir Medvedkin 			ret = rte_fib_select_lookup(fib,
861eda44cedSVladimir Medvedkin 				RTE_FIB_LOOKUP_DIR24_8_SCALAR_MACRO);
862eda44cedSVladimir Medvedkin 		else if (config.lookup_fn == 2)
863eda44cedSVladimir Medvedkin 			ret = rte_fib_select_lookup(fib,
864eda44cedSVladimir Medvedkin 				RTE_FIB_LOOKUP_DIR24_8_VECTOR_AVX512);
865eda44cedSVladimir Medvedkin 		else if (config.lookup_fn == 3)
866eda44cedSVladimir Medvedkin 			ret = rte_fib_select_lookup(fib,
867eda44cedSVladimir Medvedkin 				RTE_FIB_LOOKUP_DIR24_8_SCALAR_INLINE);
868eda44cedSVladimir Medvedkin 		else if (config.lookup_fn == 4)
869eda44cedSVladimir Medvedkin 			ret = rte_fib_select_lookup(fib,
870eda44cedSVladimir Medvedkin 				RTE_FIB_LOOKUP_DIR24_8_SCALAR_UNI);
871eda44cedSVladimir Medvedkin 		else
872eda44cedSVladimir Medvedkin 			ret = -EINVAL;
873eda44cedSVladimir Medvedkin 		if (ret != 0) {
874eda44cedSVladimir Medvedkin 			printf("Can not init lookup function\n");
875eda44cedSVladimir Medvedkin 			return ret;
876eda44cedSVladimir Medvedkin 		}
877eda44cedSVladimir Medvedkin 	}
878eda44cedSVladimir Medvedkin 
879103809d0SVladimir Medvedkin 	for (k = config.print_fract, i = 0; k > 0; k--) {
880103809d0SVladimir Medvedkin 		start = rte_rdtsc_precise();
881103809d0SVladimir Medvedkin 		for (j = 0; j < (config.nb_routes - i) / k; j++) {
882103809d0SVladimir Medvedkin 			ret = rte_fib_add(fib, rt[i + j].addr, rt[i + j].depth,
883103809d0SVladimir Medvedkin 				rt[i + j].nh);
884103809d0SVladimir Medvedkin 			if (unlikely(ret != 0)) {
885103809d0SVladimir Medvedkin 				printf("Can not add a route to FIB, err %d\n",
886103809d0SVladimir Medvedkin 					ret);
887103809d0SVladimir Medvedkin 				return -ret;
888103809d0SVladimir Medvedkin 			}
889103809d0SVladimir Medvedkin 		}
890d19034aeSVladimir Medvedkin 		printf("AVG FIB add %"PRIu64"\n",
891d19034aeSVladimir Medvedkin 			(rte_rdtsc_precise() - start) / j);
892103809d0SVladimir Medvedkin 		i += j;
893103809d0SVladimir Medvedkin 	}
894103809d0SVladimir Medvedkin 
895103809d0SVladimir Medvedkin 	if (config.flags & CMP_FLAG) {
896103809d0SVladimir Medvedkin 		lpm_conf.max_rules = config.nb_routes * 2;
897103809d0SVladimir Medvedkin 		lpm_conf.number_tbl8s = RTE_MAX(conf.dir24_8.num_tbl8,
898103809d0SVladimir Medvedkin 			config.tbl8);
899103809d0SVladimir Medvedkin 
900103809d0SVladimir Medvedkin 		lpm = rte_lpm_create("test_lpm", -1, &lpm_conf);
901103809d0SVladimir Medvedkin 		if (lpm == NULL) {
902103809d0SVladimir Medvedkin 			printf("Can not alloc LPM, err %d\n", rte_errno);
903103809d0SVladimir Medvedkin 			return -rte_errno;
904103809d0SVladimir Medvedkin 		}
905103809d0SVladimir Medvedkin 		for (k = config.print_fract, i = 0; k > 0; k--) {
906103809d0SVladimir Medvedkin 			start = rte_rdtsc_precise();
907103809d0SVladimir Medvedkin 			for (j = 0; j < (config.nb_routes - i) / k; j++) {
908103809d0SVladimir Medvedkin 				ret = rte_lpm_add(lpm, rt[i + j].addr,
909103809d0SVladimir Medvedkin 					rt[i + j].depth, rt[i + j].nh);
910103809d0SVladimir Medvedkin 				if (ret != 0) {
911103809d0SVladimir Medvedkin 					if (rt[i + j].depth == 0)
912103809d0SVladimir Medvedkin 						print_depth_err();
913103809d0SVladimir Medvedkin 					printf("Can not add a route to LPM, "
914103809d0SVladimir Medvedkin 						"err %d\n", ret);
915103809d0SVladimir Medvedkin 					return -ret;
916103809d0SVladimir Medvedkin 				}
917103809d0SVladimir Medvedkin 			}
918d19034aeSVladimir Medvedkin 			printf("AVG LPM add %"PRIu64"\n",
919103809d0SVladimir Medvedkin 				(rte_rdtsc_precise() - start) / j);
920103809d0SVladimir Medvedkin 			i += j;
921103809d0SVladimir Medvedkin 		}
922103809d0SVladimir Medvedkin 	}
923103809d0SVladimir Medvedkin 
924103809d0SVladimir Medvedkin 	acc = 0;
925103809d0SVladimir Medvedkin 	for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
926103809d0SVladimir Medvedkin 		start = rte_rdtsc_precise();
927103809d0SVladimir Medvedkin 		ret = rte_fib_lookup_bulk(fib, tbl4 + i, fib_nh, BURST_SZ);
928103809d0SVladimir Medvedkin 		acc += rte_rdtsc_precise() - start;
929103809d0SVladimir Medvedkin 		if (ret != 0) {
930103809d0SVladimir Medvedkin 			printf("FIB lookup fails, err %d\n", ret);
931103809d0SVladimir Medvedkin 			return -ret;
932103809d0SVladimir Medvedkin 		}
933103809d0SVladimir Medvedkin 	}
934103809d0SVladimir Medvedkin 	printf("AVG FIB lookup %.1f\n", (double)acc / (double)i);
935103809d0SVladimir Medvedkin 
936103809d0SVladimir Medvedkin 	if (config.flags & CMP_FLAG) {
937103809d0SVladimir Medvedkin 		acc = 0;
938103809d0SVladimir Medvedkin 		for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
939103809d0SVladimir Medvedkin 			start = rte_rdtsc_precise();
940103809d0SVladimir Medvedkin 			ret = rte_lpm_lookup_bulk(lpm, tbl4 + i, lpm_nh,
941103809d0SVladimir Medvedkin 				BURST_SZ);
942103809d0SVladimir Medvedkin 			acc += rte_rdtsc_precise() - start;
943103809d0SVladimir Medvedkin 			if (ret != 0) {
944103809d0SVladimir Medvedkin 				printf("LPM lookup fails, err %d\n", ret);
945103809d0SVladimir Medvedkin 				return -ret;
946103809d0SVladimir Medvedkin 			}
947103809d0SVladimir Medvedkin 		}
948103809d0SVladimir Medvedkin 		printf("AVG LPM lookup %.1f\n", (double)acc / (double)i);
949103809d0SVladimir Medvedkin 
950103809d0SVladimir Medvedkin 		for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
951103809d0SVladimir Medvedkin 			rte_fib_lookup_bulk(fib, tbl4 + i, fib_nh, BURST_SZ);
952103809d0SVladimir Medvedkin 			rte_lpm_lookup_bulk(lpm, tbl4 + i, lpm_nh, BURST_SZ);
953103809d0SVladimir Medvedkin 			for (j = 0; j < BURST_SZ; j++) {
954103809d0SVladimir Medvedkin 				struct rte_lpm_tbl_entry *tbl;
955103809d0SVladimir Medvedkin 				tbl = (struct rte_lpm_tbl_entry *)&lpm_nh[j];
956103809d0SVladimir Medvedkin 				if ((fib_nh[j] != tbl->next_hop) &&
957103809d0SVladimir Medvedkin 						!((tbl->valid == 0) &&
958103809d0SVladimir Medvedkin 						(fib_nh[j] == def_nh))) {
959103809d0SVladimir Medvedkin 					printf("FAIL\n");
960103809d0SVladimir Medvedkin 					return -1;
961103809d0SVladimir Medvedkin 				}
962103809d0SVladimir Medvedkin 			}
963103809d0SVladimir Medvedkin 		}
964103809d0SVladimir Medvedkin 		printf("FIB and LPM lookup returns same values\n");
965103809d0SVladimir Medvedkin 	}
966103809d0SVladimir Medvedkin 
967103809d0SVladimir Medvedkin 	for (k = config.print_fract, i = 0; k > 0; k--) {
968103809d0SVladimir Medvedkin 		start = rte_rdtsc_precise();
969103809d0SVladimir Medvedkin 		for (j = 0; j < (config.nb_routes - i) / k; j++)
970103809d0SVladimir Medvedkin 			rte_fib_delete(fib, rt[i + j].addr, rt[i + j].depth);
971103809d0SVladimir Medvedkin 
972d19034aeSVladimir Medvedkin 		printf("AVG FIB delete %"PRIu64"\n",
973103809d0SVladimir Medvedkin 			(rte_rdtsc_precise() - start) / j);
974103809d0SVladimir Medvedkin 		i += j;
975103809d0SVladimir Medvedkin 	}
976103809d0SVladimir Medvedkin 
977103809d0SVladimir Medvedkin 	if (config.flags & CMP_FLAG) {
978103809d0SVladimir Medvedkin 		for (k = config.print_fract, i = 0; k > 0; k--) {
979103809d0SVladimir Medvedkin 			start = rte_rdtsc_precise();
980103809d0SVladimir Medvedkin 			for (j = 0; j < (config.nb_routes - i) / k; j++)
981103809d0SVladimir Medvedkin 				rte_lpm_delete(lpm, rt[i + j].addr,
982103809d0SVladimir Medvedkin 					rt[i + j].depth);
983103809d0SVladimir Medvedkin 
984d19034aeSVladimir Medvedkin 			printf("AVG LPM delete %"PRIu64"\n",
985103809d0SVladimir Medvedkin 				(rte_rdtsc_precise() - start) / j);
986103809d0SVladimir Medvedkin 			i += j;
987103809d0SVladimir Medvedkin 		}
988103809d0SVladimir Medvedkin 	}
989103809d0SVladimir Medvedkin 
990103809d0SVladimir Medvedkin 	return 0;
991103809d0SVladimir Medvedkin }
992103809d0SVladimir Medvedkin 
993103809d0SVladimir Medvedkin static int
994103809d0SVladimir Medvedkin dump_rt_6(struct rt_rule_6 *rt)
995103809d0SVladimir Medvedkin {
996103809d0SVladimir Medvedkin 	FILE *f;
997103809d0SVladimir Medvedkin 	uint32_t i;
998103809d0SVladimir Medvedkin 
999103809d0SVladimir Medvedkin 	f = fopen(config.routes_file_s, "w");
1000103809d0SVladimir Medvedkin 	if (f == NULL) {
1001103809d0SVladimir Medvedkin 		printf("Can not open file %s\n", config.routes_file_s);
1002103809d0SVladimir Medvedkin 		return -1;
1003103809d0SVladimir Medvedkin 	}
1004103809d0SVladimir Medvedkin 
1005103809d0SVladimir Medvedkin 	for (i = 0; i < config.nb_routes; i++) {
1006e1a06e39SRobin Jarry 		fprintf(f, RTE_IPV6_ADDR_FMT"/%d %"PRIu64"\n", RTE_IPV6_ADDR_SPLIT(&rt[i].addr),
1007103809d0SVladimir Medvedkin 			rt[i].depth, rt[i].nh);
1008103809d0SVladimir Medvedkin 
1009103809d0SVladimir Medvedkin 	}
1010103809d0SVladimir Medvedkin 	fclose(f);
1011103809d0SVladimir Medvedkin 	return 0;
1012103809d0SVladimir Medvedkin }
1013103809d0SVladimir Medvedkin 
1014103809d0SVladimir Medvedkin static int
1015103809d0SVladimir Medvedkin run_v6(void)
1016103809d0SVladimir Medvedkin {
1017103809d0SVladimir Medvedkin 	uint64_t start, acc;
1018103809d0SVladimir Medvedkin 	uint64_t def_nh = 0;
1019103809d0SVladimir Medvedkin 	struct rte_fib6 *fib;
1020103809d0SVladimir Medvedkin 	struct rte_fib6_conf conf = {0};
1021103809d0SVladimir Medvedkin 	struct rt_rule_6 *rt;
1022103809d0SVladimir Medvedkin 	uint32_t i, j, k;
1023103809d0SVladimir Medvedkin 	int ret = 0;
1024103809d0SVladimir Medvedkin 	struct rte_lpm6	*lpm = NULL;
1025103809d0SVladimir Medvedkin 	struct rte_lpm6_config lpm_conf;
1026e1a06e39SRobin Jarry 	struct rte_ipv6_addr *tbl6;
1027103809d0SVladimir Medvedkin 	uint64_t fib_nh[BURST_SZ];
1028103809d0SVladimir Medvedkin 	int32_t lpm_nh[BURST_SZ];
1029103809d0SVladimir Medvedkin 
1030103809d0SVladimir Medvedkin 	rt = (struct rt_rule_6 *)config.rt;
1031103809d0SVladimir Medvedkin 	tbl6 = config.lookup_tbl;
1032103809d0SVladimir Medvedkin 
1033103809d0SVladimir Medvedkin 	if (config.flags & DRY_RUN_FLAG) {
1034103809d0SVladimir Medvedkin 		if (config.routes_file_s != NULL)
1035103809d0SVladimir Medvedkin 			ret =  dump_rt_6(rt);
1036103809d0SVladimir Medvedkin 		if (ret != 0)
1037103809d0SVladimir Medvedkin 			return ret;
1038103809d0SVladimir Medvedkin 		if (config.lookup_ips_file_s != NULL)
1039103809d0SVladimir Medvedkin 			ret = dump_lookup(AF_INET6);
1040103809d0SVladimir Medvedkin 		return ret;
1041103809d0SVladimir Medvedkin 	}
1042103809d0SVladimir Medvedkin 
1043103809d0SVladimir Medvedkin 	conf.type = get_fib_type();
1044103809d0SVladimir Medvedkin 	conf.default_nh = def_nh;
1045103809d0SVladimir Medvedkin 	conf.max_routes = config.nb_routes * 2;
104611c5b9b5SVladimir Medvedkin 	conf.rib_ext_sz = 0;
1047103809d0SVladimir Medvedkin 	if (conf.type == RTE_FIB6_TRIE) {
10483d4e27fdSDavid Marchand 		conf.trie.nh_sz = rte_ctz32(config.ent_sz);
1049103809d0SVladimir Medvedkin 		conf.trie.num_tbl8 = RTE_MIN(config.tbl8,
1050103809d0SVladimir Medvedkin 			get_max_nh(conf.trie.nh_sz));
1051103809d0SVladimir Medvedkin 	}
1052103809d0SVladimir Medvedkin 
1053103809d0SVladimir Medvedkin 	fib = rte_fib6_create("test", -1, &conf);
1054103809d0SVladimir Medvedkin 	if (fib == NULL) {
1055103809d0SVladimir Medvedkin 		printf("Can not alloc FIB, err %d\n", rte_errno);
1056103809d0SVladimir Medvedkin 		return -rte_errno;
1057103809d0SVladimir Medvedkin 	}
1058103809d0SVladimir Medvedkin 
1059eda44cedSVladimir Medvedkin 	if (config.lookup_fn != 0) {
1060eda44cedSVladimir Medvedkin 		if (config.lookup_fn == 1)
1061eda44cedSVladimir Medvedkin 			ret = rte_fib6_select_lookup(fib,
1062eda44cedSVladimir Medvedkin 				RTE_FIB6_LOOKUP_TRIE_SCALAR);
1063eda44cedSVladimir Medvedkin 		else if (config.lookup_fn == 2)
1064eda44cedSVladimir Medvedkin 			ret = rte_fib6_select_lookup(fib,
1065eda44cedSVladimir Medvedkin 				RTE_FIB6_LOOKUP_TRIE_VECTOR_AVX512);
1066eda44cedSVladimir Medvedkin 		else
1067eda44cedSVladimir Medvedkin 			ret = -EINVAL;
1068eda44cedSVladimir Medvedkin 		if (ret != 0) {
1069eda44cedSVladimir Medvedkin 			printf("Can not init lookup function\n");
1070eda44cedSVladimir Medvedkin 			return ret;
1071eda44cedSVladimir Medvedkin 		}
1072eda44cedSVladimir Medvedkin 	}
1073eda44cedSVladimir Medvedkin 
1074103809d0SVladimir Medvedkin 	for (k = config.print_fract, i = 0; k > 0; k--) {
1075103809d0SVladimir Medvedkin 		start = rte_rdtsc_precise();
1076103809d0SVladimir Medvedkin 		for (j = 0; j < (config.nb_routes - i) / k; j++) {
1077*6cb10a9bSRobin Jarry 			ret = rte_fib6_add(fib, &rt[i + j].addr,
1078103809d0SVladimir Medvedkin 				rt[i + j].depth, rt[i + j].nh);
1079103809d0SVladimir Medvedkin 			if (unlikely(ret != 0)) {
1080103809d0SVladimir Medvedkin 				printf("Can not add a route to FIB, err %d\n",
1081103809d0SVladimir Medvedkin 					ret);
1082103809d0SVladimir Medvedkin 				return -ret;
1083103809d0SVladimir Medvedkin 			}
1084103809d0SVladimir Medvedkin 		}
1085d19034aeSVladimir Medvedkin 		printf("AVG FIB add %"PRIu64"\n",
1086d19034aeSVladimir Medvedkin 			(rte_rdtsc_precise() - start) / j);
1087103809d0SVladimir Medvedkin 		i += j;
1088103809d0SVladimir Medvedkin 	}
1089103809d0SVladimir Medvedkin 
1090103809d0SVladimir Medvedkin 	if (config.flags & CMP_FLAG) {
1091103809d0SVladimir Medvedkin 		lpm_conf.max_rules = config.nb_routes * 2;
1092103809d0SVladimir Medvedkin 		lpm_conf.number_tbl8s = RTE_MAX(conf.trie.num_tbl8,
1093103809d0SVladimir Medvedkin 			config.tbl8);
1094103809d0SVladimir Medvedkin 
1095103809d0SVladimir Medvedkin 		lpm = rte_lpm6_create("test_lpm", -1, &lpm_conf);
1096103809d0SVladimir Medvedkin 		if (lpm == NULL) {
1097103809d0SVladimir Medvedkin 			printf("Can not alloc LPM, err %d\n", rte_errno);
1098103809d0SVladimir Medvedkin 			return -rte_errno;
1099103809d0SVladimir Medvedkin 		}
1100103809d0SVladimir Medvedkin 		for (k = config.print_fract, i = 0; k > 0; k--) {
1101103809d0SVladimir Medvedkin 			start = rte_rdtsc_precise();
1102103809d0SVladimir Medvedkin 			for (j = 0; j < (config.nb_routes - i) / k; j++) {
1103e1a06e39SRobin Jarry 				ret = rte_lpm6_add(lpm, &rt[i + j].addr,
1104103809d0SVladimir Medvedkin 					rt[i + j].depth, rt[i + j].nh);
1105103809d0SVladimir Medvedkin 				if (ret != 0) {
1106103809d0SVladimir Medvedkin 					if (rt[i + j].depth == 0)
1107103809d0SVladimir Medvedkin 						print_depth_err();
1108103809d0SVladimir Medvedkin 					printf("Can not add a route to LPM, "
1109103809d0SVladimir Medvedkin 						"err %d\n", ret);
1110103809d0SVladimir Medvedkin 					return -ret;
1111103809d0SVladimir Medvedkin 				}
1112103809d0SVladimir Medvedkin 			}
1113d19034aeSVladimir Medvedkin 			printf("AVG LPM add %"PRIu64"\n",
1114103809d0SVladimir Medvedkin 				(rte_rdtsc_precise() - start) / j);
1115103809d0SVladimir Medvedkin 			i += j;
1116103809d0SVladimir Medvedkin 		}
1117103809d0SVladimir Medvedkin 	}
1118103809d0SVladimir Medvedkin 
1119103809d0SVladimir Medvedkin 	acc = 0;
1120103809d0SVladimir Medvedkin 	for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
1121103809d0SVladimir Medvedkin 		start = rte_rdtsc_precise();
1122*6cb10a9bSRobin Jarry 		ret = rte_fib6_lookup_bulk(fib, &tbl6[i],
1123103809d0SVladimir Medvedkin 			fib_nh, BURST_SZ);
1124103809d0SVladimir Medvedkin 		acc += rte_rdtsc_precise() - start;
1125103809d0SVladimir Medvedkin 		if (ret != 0) {
1126103809d0SVladimir Medvedkin 			printf("FIB lookup fails, err %d\n", ret);
1127103809d0SVladimir Medvedkin 			return -ret;
1128103809d0SVladimir Medvedkin 		}
1129103809d0SVladimir Medvedkin 	}
1130103809d0SVladimir Medvedkin 	printf("AVG FIB lookup %.1f\n", (double)acc / (double)i);
1131103809d0SVladimir Medvedkin 
1132103809d0SVladimir Medvedkin 	if (config.flags & CMP_FLAG) {
1133103809d0SVladimir Medvedkin 		acc = 0;
1134103809d0SVladimir Medvedkin 		for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
1135103809d0SVladimir Medvedkin 			start = rte_rdtsc_precise();
1136103809d0SVladimir Medvedkin 			ret = rte_lpm6_lookup_bulk_func(lpm,
1137e1a06e39SRobin Jarry 				&tbl6[i],
1138103809d0SVladimir Medvedkin 				lpm_nh, BURST_SZ);
1139103809d0SVladimir Medvedkin 			acc += rte_rdtsc_precise() - start;
1140103809d0SVladimir Medvedkin 			if (ret != 0) {
1141103809d0SVladimir Medvedkin 				printf("LPM lookup fails, err %d\n", ret);
1142103809d0SVladimir Medvedkin 				return -ret;
1143103809d0SVladimir Medvedkin 			}
1144103809d0SVladimir Medvedkin 		}
1145103809d0SVladimir Medvedkin 		printf("AVG LPM lookup %.1f\n", (double)acc / (double)i);
1146103809d0SVladimir Medvedkin 
1147103809d0SVladimir Medvedkin 		for (i = 0; i < config.nb_lookup_ips; i += BURST_SZ) {
1148103809d0SVladimir Medvedkin 			rte_fib6_lookup_bulk(fib,
1149*6cb10a9bSRobin Jarry 				&tbl6[i],
1150103809d0SVladimir Medvedkin 				fib_nh, BURST_SZ);
1151103809d0SVladimir Medvedkin 			rte_lpm6_lookup_bulk_func(lpm,
1152e1a06e39SRobin Jarry 				&tbl6[i],
1153103809d0SVladimir Medvedkin 				lpm_nh, BURST_SZ);
1154103809d0SVladimir Medvedkin 			for (j = 0; j < BURST_SZ; j++) {
1155103809d0SVladimir Medvedkin 				if ((fib_nh[j] != (uint32_t)lpm_nh[j]) &&
1156103809d0SVladimir Medvedkin 						!((lpm_nh[j] == -1) &&
1157103809d0SVladimir Medvedkin 						(fib_nh[j] == def_nh))) {
1158103809d0SVladimir Medvedkin 					printf("FAIL\n");
1159103809d0SVladimir Medvedkin 					return -1;
1160103809d0SVladimir Medvedkin 				}
1161103809d0SVladimir Medvedkin 			}
1162103809d0SVladimir Medvedkin 		}
1163103809d0SVladimir Medvedkin 		printf("FIB and LPM lookup returns same values\n");
1164103809d0SVladimir Medvedkin 	}
1165103809d0SVladimir Medvedkin 
1166103809d0SVladimir Medvedkin 	for (k = config.print_fract, i = 0; k > 0; k--) {
1167103809d0SVladimir Medvedkin 		start = rte_rdtsc_precise();
1168103809d0SVladimir Medvedkin 		for (j = 0; j < (config.nb_routes - i) / k; j++)
1169*6cb10a9bSRobin Jarry 			rte_fib6_delete(fib, &rt[i + j].addr, rt[i + j].depth);
1170103809d0SVladimir Medvedkin 
1171d19034aeSVladimir Medvedkin 		printf("AVG FIB delete %"PRIu64"\n",
1172103809d0SVladimir Medvedkin 			(rte_rdtsc_precise() - start) / j);
1173103809d0SVladimir Medvedkin 		i += j;
1174103809d0SVladimir Medvedkin 	}
1175103809d0SVladimir Medvedkin 
1176103809d0SVladimir Medvedkin 	if (config.flags & CMP_FLAG) {
1177103809d0SVladimir Medvedkin 		for (k = config.print_fract, i = 0; k > 0; k--) {
1178103809d0SVladimir Medvedkin 			start = rte_rdtsc_precise();
1179103809d0SVladimir Medvedkin 			for (j = 0; j < (config.nb_routes - i) / k; j++)
1180e1a06e39SRobin Jarry 				rte_lpm6_delete(lpm, &rt[i + j].addr,
1181103809d0SVladimir Medvedkin 					rt[i + j].depth);
1182103809d0SVladimir Medvedkin 
1183d19034aeSVladimir Medvedkin 			printf("AVG LPM delete %"PRIu64"\n",
1184103809d0SVladimir Medvedkin 				(rte_rdtsc_precise() - start) / j);
1185103809d0SVladimir Medvedkin 			i += j;
1186103809d0SVladimir Medvedkin 		}
1187103809d0SVladimir Medvedkin 	}
1188103809d0SVladimir Medvedkin 	return 0;
1189103809d0SVladimir Medvedkin }
1190103809d0SVladimir Medvedkin 
1191103809d0SVladimir Medvedkin int
1192103809d0SVladimir Medvedkin main(int argc, char **argv)
1193103809d0SVladimir Medvedkin {
1194103809d0SVladimir Medvedkin 	int ret, af, rt_ent_sz, lookup_ent_sz;
1195f1caf7f8SVladimir Medvedkin 	FILE *fr = NULL;
1196f1caf7f8SVladimir Medvedkin 	FILE *fl = NULL;
1197103809d0SVladimir Medvedkin 	uint8_t depth_lim;
1198103809d0SVladimir Medvedkin 
1199103809d0SVladimir Medvedkin 	ret = rte_eal_init(argc, argv);
1200103809d0SVladimir Medvedkin 	if (ret < 0)
1201103809d0SVladimir Medvedkin 		rte_panic("Cannot init EAL\n");
1202103809d0SVladimir Medvedkin 
1203103809d0SVladimir Medvedkin 	argc -= ret;
1204103809d0SVladimir Medvedkin 	argv += ret;
1205103809d0SVladimir Medvedkin 
1206103809d0SVladimir Medvedkin 	config.prgname = argv[0];
1207103809d0SVladimir Medvedkin 
1208103809d0SVladimir Medvedkin 	parse_opts(argc, argv);
1209103809d0SVladimir Medvedkin 
1210103809d0SVladimir Medvedkin 	ret = check_config();
1211103809d0SVladimir Medvedkin 	if (ret != 0)
1212103809d0SVladimir Medvedkin 		rte_exit(-ret, "Bad configuration\n");
1213103809d0SVladimir Medvedkin 
1214103809d0SVladimir Medvedkin 	af = ((config.flags & IPV6_FLAG) == 0) ? AF_INET : AF_INET6;
1215103809d0SVladimir Medvedkin 	depth_lim = (af == AF_INET) ? 32 : 128;
1216103809d0SVladimir Medvedkin 	rt_ent_sz = (af == AF_INET) ? sizeof(struct rt_rule_4) :
1217103809d0SVladimir Medvedkin 		sizeof(struct rt_rule_6);
1218103809d0SVladimir Medvedkin 	lookup_ent_sz = (af == AF_INET) ? 4 : 16;
1219103809d0SVladimir Medvedkin 
1220103809d0SVladimir Medvedkin 	/* Count number of rules in file*/
1221103809d0SVladimir Medvedkin 	if (config.routes_file != NULL) {
1222103809d0SVladimir Medvedkin 		fr = fopen(config.routes_file, "r");
1223103809d0SVladimir Medvedkin 		if (fr == NULL)
1224103809d0SVladimir Medvedkin 			rte_exit(-errno, "Can not open file with routes %s\n",
1225103809d0SVladimir Medvedkin 				config.routes_file);
1226103809d0SVladimir Medvedkin 
1227103809d0SVladimir Medvedkin 		config.nb_routes = 0;
1228103809d0SVladimir Medvedkin 		while (fgets(line, sizeof(line), fr) != NULL)
1229103809d0SVladimir Medvedkin 			config.nb_routes++;
1230a01070daSVladimir Medvedkin 
1231a01070daSVladimir Medvedkin 		if (config.nb_routes < config.print_fract)
1232a01070daSVladimir Medvedkin 			config.print_fract = config.nb_routes;
1233a01070daSVladimir Medvedkin 
1234103809d0SVladimir Medvedkin 		rewind(fr);
1235103809d0SVladimir Medvedkin 	}
1236103809d0SVladimir Medvedkin 
1237103809d0SVladimir Medvedkin 	/* Count number of ip's in file*/
1238103809d0SVladimir Medvedkin 	if (config.lookup_ips_file != NULL) {
1239103809d0SVladimir Medvedkin 		fl = fopen(config.lookup_ips_file, "r");
1240103809d0SVladimir Medvedkin 		if (fl == NULL)
1241103809d0SVladimir Medvedkin 			rte_exit(-errno, "Can not open file with ip's %s\n",
1242103809d0SVladimir Medvedkin 				config.lookup_ips_file);
1243103809d0SVladimir Medvedkin 
1244103809d0SVladimir Medvedkin 		config.nb_lookup_ips = 0;
1245103809d0SVladimir Medvedkin 		while (fgets(line, sizeof(line), fl) != NULL)
1246103809d0SVladimir Medvedkin 			config.nb_lookup_ips++;
1247103809d0SVladimir Medvedkin 		rewind(fl);
1248103809d0SVladimir Medvedkin 	}
1249103809d0SVladimir Medvedkin 
1250103809d0SVladimir Medvedkin 	/* Alloc routes table*/
1251103809d0SVladimir Medvedkin 	config.rt  = rte_malloc(NULL, rt_ent_sz * config.nb_routes, 0);
1252103809d0SVladimir Medvedkin 	if (config.rt == NULL)
1253103809d0SVladimir Medvedkin 		rte_exit(-ENOMEM, "Can not alloc rt\n");
1254103809d0SVladimir Medvedkin 
1255103809d0SVladimir Medvedkin 	/* Alloc table with ip's for lookup*/
1256103809d0SVladimir Medvedkin 	config.lookup_tbl  = rte_malloc(NULL, lookup_ent_sz *
1257103809d0SVladimir Medvedkin 		config.nb_lookup_ips, 0);
1258103809d0SVladimir Medvedkin 	if (config.lookup_tbl == NULL)
1259103809d0SVladimir Medvedkin 		rte_exit(-ENOMEM, "Can not alloc lookup table\n");
1260103809d0SVladimir Medvedkin 
1261103809d0SVladimir Medvedkin 	/* Fill routes table */
1262f1caf7f8SVladimir Medvedkin 	if (fr == NULL) {
1263103809d0SVladimir Medvedkin 		if (distrib_string != NULL)
1264103809d0SVladimir Medvedkin 			ret = parse_distrib(depth_lim, config.nb_routes);
1265103809d0SVladimir Medvedkin 		else {
1266103809d0SVladimir Medvedkin 			uint8_t rpd[129] = {0};
1267103809d0SVladimir Medvedkin 			uint32_t nrpd[129] = {0};
1268103809d0SVladimir Medvedkin 			ret = complete_distrib(depth_lim, config.nb_routes,
1269103809d0SVladimir Medvedkin 				rpd, nrpd);
1270103809d0SVladimir Medvedkin 		}
1271103809d0SVladimir Medvedkin 		if (ret != 0)
1272103809d0SVladimir Medvedkin 			rte_exit(-ret,
1273103809d0SVladimir Medvedkin 				"Bad routes distribution configuration\n");
1274103809d0SVladimir Medvedkin 		if (af == AF_INET) {
1275103809d0SVladimir Medvedkin 			gen_random_rt_4(config.rt,
12763d4e27fdSDavid Marchand 				rte_ctz32(config.ent_sz));
1277103809d0SVladimir Medvedkin 			if (config.flags & SHUFFLE_FLAG)
1278103809d0SVladimir Medvedkin 				shuffle_rt_4(config.rt, config.nb_routes);
1279103809d0SVladimir Medvedkin 		} else {
1280103809d0SVladimir Medvedkin 			gen_random_rt_6(config.rt,
12813d4e27fdSDavid Marchand 				rte_ctz32(config.ent_sz));
1282103809d0SVladimir Medvedkin 			if (config.flags & SHUFFLE_FLAG)
1283103809d0SVladimir Medvedkin 				shuffle_rt_6(config.rt, config.nb_routes);
1284103809d0SVladimir Medvedkin 		}
1285103809d0SVladimir Medvedkin 	} else {
1286103809d0SVladimir Medvedkin 		if (af == AF_INET)
1287103809d0SVladimir Medvedkin 			ret = parse_rt_4(fr);
1288103809d0SVladimir Medvedkin 		else
1289103809d0SVladimir Medvedkin 			ret = parse_rt_6(fr);
1290103809d0SVladimir Medvedkin 
1291103809d0SVladimir Medvedkin 		if (ret != 0) {
1292103809d0SVladimir Medvedkin 			rte_exit(-ret, "failed to parse routes file %s\n",
1293103809d0SVladimir Medvedkin 				config.routes_file);
1294103809d0SVladimir Medvedkin 		}
1295103809d0SVladimir Medvedkin 	}
1296103809d0SVladimir Medvedkin 
1297103809d0SVladimir Medvedkin 	/* Fill lookup table with ip's*/
1298f1caf7f8SVladimir Medvedkin 	if (fl == NULL)
1299103809d0SVladimir Medvedkin 		gen_rnd_lookup_tbl(af);
1300103809d0SVladimir Medvedkin 	else {
1301103809d0SVladimir Medvedkin 		ret = parse_lookup(fl, af);
1302103809d0SVladimir Medvedkin 		if (ret != 0)
1303103809d0SVladimir Medvedkin 			rte_exit(-ret, "failed to parse lookup file\n");
1304103809d0SVladimir Medvedkin 	}
1305103809d0SVladimir Medvedkin 
1306103809d0SVladimir Medvedkin 	print_config();
1307103809d0SVladimir Medvedkin 
1308103809d0SVladimir Medvedkin 	if (af == AF_INET)
1309103809d0SVladimir Medvedkin 		ret = run_v4();
1310103809d0SVladimir Medvedkin 	else
1311103809d0SVladimir Medvedkin 		ret = run_v6();
1312103809d0SVladimir Medvedkin 
1313103809d0SVladimir Medvedkin 	return ret;
1314103809d0SVladimir Medvedkin }
1315