xref: /dpdk/app/test-sad/main.c (revision 9ac91e2f7339e66658ef55b756a06b328e336fde)
1908be065SVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause
2908be065SVladimir Medvedkin  * Copyright(c) 2019 Intel Corporation
3908be065SVladimir Medvedkin  */
4908be065SVladimir Medvedkin 
5908be065SVladimir Medvedkin #include <rte_string_fns.h>
6908be065SVladimir Medvedkin #include <rte_ipsec_sad.h>
7908be065SVladimir Medvedkin #include <getopt.h>
8908be065SVladimir Medvedkin #include <string.h>
9908be065SVladimir Medvedkin #include <stdio.h>
1072b452c5SDmitry Kozlyuk #include <stdlib.h>
11908be065SVladimir Medvedkin #include <sys/types.h>
12908be065SVladimir Medvedkin #include <sys/socket.h>
13908be065SVladimir Medvedkin #include <netinet/in.h>
14908be065SVladimir Medvedkin #include <arpa/inet.h>
15908be065SVladimir Medvedkin 
16908be065SVladimir Medvedkin #include <rte_cycles.h>
17908be065SVladimir Medvedkin #include <rte_errno.h>
18908be065SVladimir Medvedkin #include <rte_ip.h>
19908be065SVladimir Medvedkin #include <rte_random.h>
20908be065SVladimir Medvedkin #include <rte_malloc.h>
21908be065SVladimir Medvedkin 
22908be065SVladimir Medvedkin #define	PRINT_USAGE_START	"%s [EAL options] --\n"
23908be065SVladimir Medvedkin 
24908be065SVladimir Medvedkin #define GET_CB_FIELD(in, fd, base, lim, dlm)	do {		\
25908be065SVladimir Medvedkin 	unsigned long val;					\
26908be065SVladimir Medvedkin 	char *end_fld;						\
27908be065SVladimir Medvedkin 	errno = 0;						\
28908be065SVladimir Medvedkin 	val = strtoul((in), &end_fld, (base));			\
29908be065SVladimir Medvedkin 	if (errno != 0 || end_fld[0] != (dlm) || val > (lim))	\
30908be065SVladimir Medvedkin 		return -EINVAL;					\
31908be065SVladimir Medvedkin 	(fd) = (typeof(fd))val;					\
32908be065SVladimir Medvedkin 	(in) = end_fld + 1;					\
33908be065SVladimir Medvedkin } while (0)
34908be065SVladimir Medvedkin 
35908be065SVladimir Medvedkin #define	DEF_RULE_NUM		0x10000
36908be065SVladimir Medvedkin #define	DEF_TUPLES_NUM	0x100000
37908be065SVladimir Medvedkin #define BURST_SZ_MAX	64
38908be065SVladimir Medvedkin 
39908be065SVladimir Medvedkin static struct {
40908be065SVladimir Medvedkin 	const char	*prgname;
41908be065SVladimir Medvedkin 	const char	*rules_file;
42908be065SVladimir Medvedkin 	const char	*tuples_file;
43908be065SVladimir Medvedkin 	uint32_t	nb_rules;
44908be065SVladimir Medvedkin 	uint32_t	nb_tuples;
45908be065SVladimir Medvedkin 	uint32_t	nb_rules_32;
46908be065SVladimir Medvedkin 	uint32_t	nb_rules_64;
47908be065SVladimir Medvedkin 	uint32_t	nb_rules_96;
48908be065SVladimir Medvedkin 	uint32_t	nb_tuples_rnd;
49908be065SVladimir Medvedkin 	uint32_t	burst_sz;
50908be065SVladimir Medvedkin 	uint8_t		fract_32;
51908be065SVladimir Medvedkin 	uint8_t		fract_64;
52908be065SVladimir Medvedkin 	uint8_t		fract_96;
53908be065SVladimir Medvedkin 	uint8_t		fract_rnd_tuples;
54908be065SVladimir Medvedkin 	int		ipv6;
55908be065SVladimir Medvedkin 	int		verbose;
56908be065SVladimir Medvedkin 	int		parallel_lookup;
57908be065SVladimir Medvedkin 	int		concurrent_rw;
58908be065SVladimir Medvedkin } config = {
59908be065SVladimir Medvedkin 	.rules_file = NULL,
60908be065SVladimir Medvedkin 	.tuples_file = NULL,
61908be065SVladimir Medvedkin 	.nb_rules = DEF_RULE_NUM,
62908be065SVladimir Medvedkin 	.nb_tuples = DEF_TUPLES_NUM,
63908be065SVladimir Medvedkin 	.nb_rules_32 = 0,
64908be065SVladimir Medvedkin 	.nb_rules_64 = 0,
65908be065SVladimir Medvedkin 	.nb_rules_96 = 0,
66908be065SVladimir Medvedkin 	.nb_tuples_rnd = 0,
67908be065SVladimir Medvedkin 	.burst_sz = BURST_SZ_MAX,
68908be065SVladimir Medvedkin 	.fract_32 = 90,
69908be065SVladimir Medvedkin 	.fract_64 = 9,
70908be065SVladimir Medvedkin 	.fract_96 = 1,
71908be065SVladimir Medvedkin 	.fract_rnd_tuples = 0,
72908be065SVladimir Medvedkin 	.ipv6 = 0,
73908be065SVladimir Medvedkin 	.verbose = 0,
74908be065SVladimir Medvedkin 	.parallel_lookup = 0,
75908be065SVladimir Medvedkin 	.concurrent_rw = 0
76908be065SVladimir Medvedkin };
77908be065SVladimir Medvedkin 
78908be065SVladimir Medvedkin enum {
79908be065SVladimir Medvedkin 	CB_RULE_SPI,
80908be065SVladimir Medvedkin 	CB_RULE_DIP,
81908be065SVladimir Medvedkin 	CB_RULE_SIP,
82908be065SVladimir Medvedkin 	CB_RULE_LEN,
83908be065SVladimir Medvedkin 	CB_RULE_NUM,
84908be065SVladimir Medvedkin };
85908be065SVladimir Medvedkin 
86908be065SVladimir Medvedkin static char line[LINE_MAX];
87908be065SVladimir Medvedkin struct rule {
88908be065SVladimir Medvedkin 	union rte_ipsec_sad_key	tuple;
89908be065SVladimir Medvedkin 	int rule_type;
90908be065SVladimir Medvedkin };
91908be065SVladimir Medvedkin 
92908be065SVladimir Medvedkin static struct rule *rules_tbl;
93908be065SVladimir Medvedkin static struct rule *tuples_tbl;
94908be065SVladimir Medvedkin 
95908be065SVladimir Medvedkin static int
96908be065SVladimir Medvedkin parse_distrib(const char *in)
97908be065SVladimir Medvedkin {
98908be065SVladimir Medvedkin 	int a, b, c;
99908be065SVladimir Medvedkin 
100908be065SVladimir Medvedkin 	GET_CB_FIELD(in, a, 0, UINT8_MAX, '/');
101908be065SVladimir Medvedkin 	GET_CB_FIELD(in, b, 0, UINT8_MAX, '/');
102908be065SVladimir Medvedkin 	GET_CB_FIELD(in, c, 0, UINT8_MAX, 0);
103908be065SVladimir Medvedkin 
104908be065SVladimir Medvedkin 	if ((a + b + c) != 100)
105908be065SVladimir Medvedkin 		return -EINVAL;
106908be065SVladimir Medvedkin 
107908be065SVladimir Medvedkin 	config.fract_32 = a;
108908be065SVladimir Medvedkin 	config.fract_64 = b;
109908be065SVladimir Medvedkin 	config.fract_96 = c;
110908be065SVladimir Medvedkin 
111908be065SVladimir Medvedkin 	return 0;
112908be065SVladimir Medvedkin }
113908be065SVladimir Medvedkin 
114908be065SVladimir Medvedkin static void
115908be065SVladimir Medvedkin print_config(void)
116908be065SVladimir Medvedkin {
117908be065SVladimir Medvedkin 	fprintf(stdout,
118908be065SVladimir Medvedkin 		"Rules total: %u\n"
119908be065SVladimir Medvedkin 		"Configured rules distribution SPI/SPI_DIP/SIP_DIP_SIP:"
120908be065SVladimir Medvedkin 		"%u/%u/%u\n"
121908be065SVladimir Medvedkin 		"SPI only rules: %u\n"
122908be065SVladimir Medvedkin 		"SPI_DIP  rules: %u\n"
123908be065SVladimir Medvedkin 		"SPI_DIP_SIP rules: %u\n"
124908be065SVladimir Medvedkin 		"Lookup tuples: %u\n"
125908be065SVladimir Medvedkin 		"Lookup burst size %u\n"
126908be065SVladimir Medvedkin 		"Configured fraction of random tuples: %u\n"
127908be065SVladimir Medvedkin 		"Random lookup tuples: %u\n",
128908be065SVladimir Medvedkin 		config.nb_rules, config.fract_32, config.fract_64,
129908be065SVladimir Medvedkin 		config.fract_96, config.nb_rules_32, config.nb_rules_64,
130908be065SVladimir Medvedkin 		config.nb_rules_96, config.nb_tuples, config.burst_sz,
131908be065SVladimir Medvedkin 		config.fract_rnd_tuples, config.nb_tuples_rnd);
132908be065SVladimir Medvedkin }
133908be065SVladimir Medvedkin 
134908be065SVladimir Medvedkin static void
135908be065SVladimir Medvedkin print_usage(void)
136908be065SVladimir Medvedkin {
137908be065SVladimir Medvedkin 	fprintf(stdout,
138908be065SVladimir Medvedkin 		PRINT_USAGE_START
139908be065SVladimir Medvedkin 		"[-f <rules file>]\n"
140908be065SVladimir Medvedkin 		"[-t <tuples file for lookup>]\n"
141908be065SVladimir Medvedkin 		"[-n <rules number (if -f is not specified)>]\n"
142908be065SVladimir Medvedkin 		"[-l <lookup tuples number (if -t is not specified)>]\n"
143908be065SVladimir Medvedkin 		"[-6 <ipv6 tests>]\n"
144908be065SVladimir Medvedkin 		"[-d <\"/\" separated rules length distribution"
145908be065SVladimir Medvedkin 		"(if -f is not specified)>]\n"
146908be065SVladimir Medvedkin 		"[-r <random tuples fraction to lookup"
147908be065SVladimir Medvedkin 		"(if -t is not specified)>]\n"
148908be065SVladimir Medvedkin 		"[-b <lookup burst size: 1-64 >]\n"
149908be065SVladimir Medvedkin 		"[-v <verbose, print results on lookup>]\n"
150908be065SVladimir Medvedkin 		"[-p <parallel lookup on all available cores>]\n"
151908be065SVladimir Medvedkin 		"[-c <init sad supporting read/write concurrency>]\n",
152908be065SVladimir Medvedkin 		config.prgname);
153908be065SVladimir Medvedkin 
154908be065SVladimir Medvedkin }
155908be065SVladimir Medvedkin 
156908be065SVladimir Medvedkin static int
157908be065SVladimir Medvedkin get_str_num(FILE *f, int num)
158908be065SVladimir Medvedkin {
159908be065SVladimir Medvedkin 	int n_lines = 0;
160908be065SVladimir Medvedkin 
161908be065SVladimir Medvedkin 	if (f != NULL) {
162908be065SVladimir Medvedkin 		while (fgets(line, sizeof(line), f) != NULL)
163908be065SVladimir Medvedkin 			n_lines++;
164908be065SVladimir Medvedkin 		rewind(f);
165908be065SVladimir Medvedkin 	} else {
166908be065SVladimir Medvedkin 		n_lines = num;
167908be065SVladimir Medvedkin 	}
168908be065SVladimir Medvedkin 	return n_lines;
169908be065SVladimir Medvedkin }
170908be065SVladimir Medvedkin 
171908be065SVladimir Medvedkin static int
172908be065SVladimir Medvedkin parse_file(FILE *f, struct rule *tbl, int rule_tbl)
173908be065SVladimir Medvedkin {
174908be065SVladimir Medvedkin 	int ret, i, j = 0;
175908be065SVladimir Medvedkin 	char *s, *sp, *in[CB_RULE_NUM];
176908be065SVladimir Medvedkin 	static const char *dlm = " \t\n";
177908be065SVladimir Medvedkin 	int string_tok_nb = RTE_DIM(in);
178908be065SVladimir Medvedkin 
179908be065SVladimir Medvedkin 	string_tok_nb -= (rule_tbl == 0) ? 1 : 0;
180908be065SVladimir Medvedkin 	while (fgets(line, sizeof(line), f) != NULL) {
181908be065SVladimir Medvedkin 		s = line;
182908be065SVladimir Medvedkin 		for (i = 0; i != string_tok_nb; i++) {
183908be065SVladimir Medvedkin 			in[i] = strtok_r(s, dlm, &sp);
184908be065SVladimir Medvedkin 			if (in[i] == NULL)
185908be065SVladimir Medvedkin 				return -EINVAL;
186908be065SVladimir Medvedkin 			s = NULL;
187908be065SVladimir Medvedkin 		}
188908be065SVladimir Medvedkin 		GET_CB_FIELD(in[CB_RULE_SPI], tbl[j].tuple.v4.spi, 0,
189908be065SVladimir Medvedkin 				UINT32_MAX, 0);
190908be065SVladimir Medvedkin 
191908be065SVladimir Medvedkin 		if (config.ipv6)
192908be065SVladimir Medvedkin 			ret = inet_pton(AF_INET6, in[CB_RULE_DIP],
193908be065SVladimir Medvedkin 				&tbl[j].tuple.v6.dip);
194908be065SVladimir Medvedkin 		else
195908be065SVladimir Medvedkin 			ret = inet_pton(AF_INET, in[CB_RULE_DIP],
196908be065SVladimir Medvedkin 				&tbl[j].tuple.v4.dip);
197908be065SVladimir Medvedkin 		if (ret != 1)
198908be065SVladimir Medvedkin 			return -EINVAL;
199908be065SVladimir Medvedkin 		if (config.ipv6)
200908be065SVladimir Medvedkin 			ret = inet_pton(AF_INET6, in[CB_RULE_SIP],
201908be065SVladimir Medvedkin 				&tbl[j].tuple.v6.sip);
202908be065SVladimir Medvedkin 		else
203908be065SVladimir Medvedkin 			ret = inet_pton(AF_INET, in[CB_RULE_SIP],
204908be065SVladimir Medvedkin 				&tbl[j].tuple.v4.sip);
205908be065SVladimir Medvedkin 		if (ret != 1)
206908be065SVladimir Medvedkin 			return -EINVAL;
207908be065SVladimir Medvedkin 		if ((rule_tbl) && (in[CB_RULE_LEN] != NULL)) {
208908be065SVladimir Medvedkin 			if (strcmp(in[CB_RULE_LEN], "SPI_DIP_SIP") == 0) {
209908be065SVladimir Medvedkin 				tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP;
210908be065SVladimir Medvedkin 				config.nb_rules_96++;
211908be065SVladimir Medvedkin 			} else if (strcmp(in[CB_RULE_LEN], "SPI_DIP") == 0) {
212908be065SVladimir Medvedkin 				tbl[j].rule_type = RTE_IPSEC_SAD_SPI_DIP;
213908be065SVladimir Medvedkin 				config.nb_rules_64++;
214908be065SVladimir Medvedkin 			} else if (strcmp(in[CB_RULE_LEN], "SPI") == 0) {
215908be065SVladimir Medvedkin 				tbl[j].rule_type = RTE_IPSEC_SAD_SPI_ONLY;
216908be065SVladimir Medvedkin 				config.nb_rules_32++;
217908be065SVladimir Medvedkin 			} else {
218908be065SVladimir Medvedkin 				return -EINVAL;
219908be065SVladimir Medvedkin 			}
220908be065SVladimir Medvedkin 		}
221908be065SVladimir Medvedkin 		j++;
222908be065SVladimir Medvedkin 	}
223908be065SVladimir Medvedkin 	return 0;
224908be065SVladimir Medvedkin }
225908be065SVladimir Medvedkin 
226908be065SVladimir Medvedkin static uint64_t
227908be065SVladimir Medvedkin get_rnd_rng(uint64_t l, uint64_t u)
228908be065SVladimir Medvedkin {
229908be065SVladimir Medvedkin 	if (l == u)
230908be065SVladimir Medvedkin 		return l;
231908be065SVladimir Medvedkin 	else
232908be065SVladimir Medvedkin 		return (rte_rand() % (u - l) + l);
233908be065SVladimir Medvedkin }
234908be065SVladimir Medvedkin 
235908be065SVladimir Medvedkin static void
236908be065SVladimir Medvedkin get_random_rules(struct rule *tbl, uint32_t nb_rules, int rule_tbl)
237908be065SVladimir Medvedkin {
238908be065SVladimir Medvedkin 	unsigned int i, j, rnd;
239908be065SVladimir Medvedkin 	int rule_type;
240908be065SVladimir Medvedkin 	double edge = 0;
241908be065SVladimir Medvedkin 	double step;
242908be065SVladimir Medvedkin 
243908be065SVladimir Medvedkin 	step = (double)UINT32_MAX / nb_rules;
244908be065SVladimir Medvedkin 	for (i = 0; i < nb_rules; i++, edge += step) {
245908be065SVladimir Medvedkin 		rnd = rte_rand() % 100;
246908be065SVladimir Medvedkin 		if (rule_tbl) {
247908be065SVladimir Medvedkin 			tbl[i].tuple.v4.spi = get_rnd_rng((uint64_t)edge,
248908be065SVladimir Medvedkin 						(uint64_t)(edge + step));
249908be065SVladimir Medvedkin 			if (config.ipv6) {
250908be065SVladimir Medvedkin 				for (j = 0; j < 16; j++) {
251*9ac91e2fSRobin Jarry 					tbl[i].tuple.v6.dip.a[j] = rte_rand();
252*9ac91e2fSRobin Jarry 					tbl[i].tuple.v6.sip.a[j] = rte_rand();
253908be065SVladimir Medvedkin 				}
254908be065SVladimir Medvedkin 			} else {
255908be065SVladimir Medvedkin 				tbl[i].tuple.v4.dip = rte_rand();
256908be065SVladimir Medvedkin 				tbl[i].tuple.v4.sip = rte_rand();
257908be065SVladimir Medvedkin 			}
258908be065SVladimir Medvedkin 			if (rnd >= (100UL - config.fract_32)) {
259908be065SVladimir Medvedkin 				rule_type = RTE_IPSEC_SAD_SPI_ONLY;
260908be065SVladimir Medvedkin 				config.nb_rules_32++;
261908be065SVladimir Medvedkin 			} else if (rnd >= (100UL - (config.fract_32 +
262908be065SVladimir Medvedkin 					config.fract_64))) {
263908be065SVladimir Medvedkin 				rule_type = RTE_IPSEC_SAD_SPI_DIP;
264908be065SVladimir Medvedkin 				config.nb_rules_64++;
265908be065SVladimir Medvedkin 			} else {
266908be065SVladimir Medvedkin 				rule_type = RTE_IPSEC_SAD_SPI_DIP_SIP;
267908be065SVladimir Medvedkin 				config.nb_rules_96++;
268908be065SVladimir Medvedkin 			}
269908be065SVladimir Medvedkin 			tbl[i].rule_type = rule_type;
270908be065SVladimir Medvedkin 		} else {
271908be065SVladimir Medvedkin 			if (rnd >= 100UL - config.fract_rnd_tuples) {
272908be065SVladimir Medvedkin 				tbl[i].tuple.v4.spi =
273908be065SVladimir Medvedkin 					get_rnd_rng((uint64_t)edge,
274908be065SVladimir Medvedkin 					(uint64_t)(edge + step));
275908be065SVladimir Medvedkin 				if (config.ipv6) {
276908be065SVladimir Medvedkin 					for (j = 0; j < 16; j++) {
277*9ac91e2fSRobin Jarry 						tbl[i].tuple.v6.dip.a[j] =
278908be065SVladimir Medvedkin 								rte_rand();
279*9ac91e2fSRobin Jarry 						tbl[i].tuple.v6.sip.a[j] =
280908be065SVladimir Medvedkin 								rte_rand();
281908be065SVladimir Medvedkin 					}
282908be065SVladimir Medvedkin 				} else {
283908be065SVladimir Medvedkin 					tbl[i].tuple.v4.dip = rte_rand();
284908be065SVladimir Medvedkin 					tbl[i].tuple.v4.sip = rte_rand();
285908be065SVladimir Medvedkin 				}
286908be065SVladimir Medvedkin 				config.nb_tuples_rnd++;
287908be065SVladimir Medvedkin 			} else {
288908be065SVladimir Medvedkin 				tbl[i].tuple.v4.spi = rules_tbl[i %
289908be065SVladimir Medvedkin 					config.nb_rules].tuple.v4.spi;
290908be065SVladimir Medvedkin 				if (config.ipv6) {
291908be065SVladimir Medvedkin 					int r_idx = i % config.nb_rules;
292*9ac91e2fSRobin Jarry 					tbl[i].tuple.v6.dip = rules_tbl[r_idx].tuple.v6.dip;
293*9ac91e2fSRobin Jarry 					tbl[i].tuple.v6.sip = rules_tbl[r_idx].tuple.v6.sip;
294908be065SVladimir Medvedkin 				} else {
295908be065SVladimir Medvedkin 					tbl[i].tuple.v4.dip = rules_tbl[i %
296908be065SVladimir Medvedkin 						config.nb_rules].tuple.v4.dip;
297908be065SVladimir Medvedkin 					tbl[i].tuple.v4.sip = rules_tbl[i %
298908be065SVladimir Medvedkin 						config.nb_rules].tuple.v4.sip;
299908be065SVladimir Medvedkin 				}
300908be065SVladimir Medvedkin 			}
301908be065SVladimir Medvedkin 		}
302908be065SVladimir Medvedkin 	}
303908be065SVladimir Medvedkin }
304908be065SVladimir Medvedkin 
305908be065SVladimir Medvedkin static void
306908be065SVladimir Medvedkin tbl_init(struct rule **tbl, uint32_t *n_entries,
307908be065SVladimir Medvedkin 	const char *file_name, int rule_tbl)
308908be065SVladimir Medvedkin {
309908be065SVladimir Medvedkin 	FILE *f = NULL;
310908be065SVladimir Medvedkin 	int ret;
311908be065SVladimir Medvedkin 	const char *rules = "rules";
312908be065SVladimir Medvedkin 	const char *tuples = "tuples";
313908be065SVladimir Medvedkin 
314908be065SVladimir Medvedkin 	if (file_name != NULL) {
315908be065SVladimir Medvedkin 		f = fopen(file_name, "r");
316908be065SVladimir Medvedkin 		if (f == NULL)
317908be065SVladimir Medvedkin 			rte_exit(-EINVAL, "failed to open file: %s\n",
318908be065SVladimir Medvedkin 				file_name);
319908be065SVladimir Medvedkin 	}
320908be065SVladimir Medvedkin 
321908be065SVladimir Medvedkin 	printf("init %s table...", (rule_tbl) ? rules : tuples);
322908be065SVladimir Medvedkin 	*n_entries = get_str_num(f, *n_entries);
323908be065SVladimir Medvedkin 	printf("%d entries\n", *n_entries);
324908be065SVladimir Medvedkin 	*tbl = rte_zmalloc(NULL, sizeof(struct rule) * *n_entries,
325908be065SVladimir Medvedkin 		RTE_CACHE_LINE_SIZE);
326908be065SVladimir Medvedkin 	if (*tbl == NULL)
327908be065SVladimir Medvedkin 		rte_exit(-ENOMEM, "failed to allocate tbl\n");
328908be065SVladimir Medvedkin 
329908be065SVladimir Medvedkin 	if (f != NULL) {
330908be065SVladimir Medvedkin 		printf("parse file %s\n", file_name);
331908be065SVladimir Medvedkin 		ret = parse_file(f, *tbl, rule_tbl);
332908be065SVladimir Medvedkin 		if (ret != 0)
333908be065SVladimir Medvedkin 			rte_exit(-EINVAL, "failed to parse file %s\n"
334908be065SVladimir Medvedkin 				"rules file must be: "
335908be065SVladimir Medvedkin 				"<uint32_t: spi> <space> "
336908be065SVladimir Medvedkin 				"<ip_addr: dip> <space> "
337908be065SVladimir Medvedkin 				"<ip_addr: sip> <space> "
338908be065SVladimir Medvedkin 				"<string: SPI|SPI_DIP|SIP_DIP_SIP>\n"
339908be065SVladimir Medvedkin 				"tuples file must be: "
340908be065SVladimir Medvedkin 				"<uint32_t: spi> <space> "
341908be065SVladimir Medvedkin 				"<ip_addr: dip> <space> "
342908be065SVladimir Medvedkin 				"<ip_addr: sip>\n",
343908be065SVladimir Medvedkin 				file_name);
344908be065SVladimir Medvedkin 	} else {
345908be065SVladimir Medvedkin 		printf("generate random values in %s table\n",
346908be065SVladimir Medvedkin 			(rule_tbl) ? rules : tuples);
347908be065SVladimir Medvedkin 		get_random_rules(*tbl, *n_entries, rule_tbl);
348908be065SVladimir Medvedkin 	}
349908be065SVladimir Medvedkin 	if (f != NULL)
350908be065SVladimir Medvedkin 		fclose(f);
351908be065SVladimir Medvedkin }
352908be065SVladimir Medvedkin 
353908be065SVladimir Medvedkin static void
354908be065SVladimir Medvedkin parse_opts(int argc, char **argv)
355908be065SVladimir Medvedkin {
356908be065SVladimir Medvedkin 	int opt, ret;
357908be065SVladimir Medvedkin 	char *endptr;
358908be065SVladimir Medvedkin 
359908be065SVladimir Medvedkin 	while ((opt = getopt(argc, argv, "f:t:n:d:l:r:6b:vpc")) != -1) {
360908be065SVladimir Medvedkin 		switch (opt) {
361908be065SVladimir Medvedkin 		case 'f':
362908be065SVladimir Medvedkin 			config.rules_file = optarg;
363908be065SVladimir Medvedkin 			break;
364908be065SVladimir Medvedkin 		case 't':
365908be065SVladimir Medvedkin 			config.tuples_file = optarg;
366908be065SVladimir Medvedkin 			break;
367908be065SVladimir Medvedkin 		case 'n':
368908be065SVladimir Medvedkin 			errno = 0;
369908be065SVladimir Medvedkin 			config.nb_rules = strtoul(optarg, &endptr, 10);
370908be065SVladimir Medvedkin 			if ((errno != 0) || (config.nb_rules == 0) ||
371908be065SVladimir Medvedkin 					(endptr[0] != 0)) {
372908be065SVladimir Medvedkin 				print_usage();
373908be065SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -n\n");
374908be065SVladimir Medvedkin 			}
375908be065SVladimir Medvedkin 			break;
376908be065SVladimir Medvedkin 		case 'd':
377908be065SVladimir Medvedkin 			ret = parse_distrib(optarg);
378908be065SVladimir Medvedkin 			if (ret != 0) {
379908be065SVladimir Medvedkin 				print_usage();
380908be065SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -d\n");
381908be065SVladimir Medvedkin 			}
382908be065SVladimir Medvedkin 			break;
383908be065SVladimir Medvedkin 		case 'b':
384908be065SVladimir Medvedkin 			errno = 0;
385908be065SVladimir Medvedkin 			config.burst_sz = strtoul(optarg, &endptr, 10);
386908be065SVladimir Medvedkin 			if ((errno != 0) || (config.burst_sz == 0) ||
387908be065SVladimir Medvedkin 					(config.burst_sz > BURST_SZ_MAX) ||
388908be065SVladimir Medvedkin 					(endptr[0] != 0)) {
389908be065SVladimir Medvedkin 				print_usage();
390908be065SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -b\n");
391908be065SVladimir Medvedkin 			}
392908be065SVladimir Medvedkin 			break;
393908be065SVladimir Medvedkin 		case 'l':
394908be065SVladimir Medvedkin 			errno = 0;
395908be065SVladimir Medvedkin 			config.nb_tuples = strtoul(optarg, &endptr, 10);
396908be065SVladimir Medvedkin 			if ((errno != 0) || (config.nb_tuples == 0) ||
397908be065SVladimir Medvedkin 					(endptr[0] != 0)) {
398908be065SVladimir Medvedkin 				print_usage();
399908be065SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -l\n");
400908be065SVladimir Medvedkin 			}
401908be065SVladimir Medvedkin 			break;
402908be065SVladimir Medvedkin 		case 'r':
403908be065SVladimir Medvedkin 			errno = 0;
404908be065SVladimir Medvedkin 			config.fract_rnd_tuples = strtoul(optarg, &endptr, 10);
405908be065SVladimir Medvedkin 			if ((errno != 0) || (config.fract_rnd_tuples == 0) ||
406908be065SVladimir Medvedkin 					(config.fract_rnd_tuples >= 100) ||
407908be065SVladimir Medvedkin 					(endptr[0] != 0)) {
408908be065SVladimir Medvedkin 				print_usage();
409908be065SVladimir Medvedkin 				rte_exit(-EINVAL, "Invalid option -r\n");
410908be065SVladimir Medvedkin 			}
411908be065SVladimir Medvedkin 			break;
412908be065SVladimir Medvedkin 		case '6':
413908be065SVladimir Medvedkin 			config.ipv6 = 1;
414908be065SVladimir Medvedkin 			break;
415908be065SVladimir Medvedkin 		case 'v':
416908be065SVladimir Medvedkin 			config.verbose = 1;
417908be065SVladimir Medvedkin 			break;
418908be065SVladimir Medvedkin 		case 'p':
419908be065SVladimir Medvedkin 			config.parallel_lookup = 1;
420908be065SVladimir Medvedkin 			break;
421908be065SVladimir Medvedkin 		case 'c':
422908be065SVladimir Medvedkin 			config.concurrent_rw = 1;
423908be065SVladimir Medvedkin 			break;
424908be065SVladimir Medvedkin 		default:
425908be065SVladimir Medvedkin 			print_usage();
426908be065SVladimir Medvedkin 			rte_exit(-EINVAL, "Invalid options\n");
427908be065SVladimir Medvedkin 		}
428908be065SVladimir Medvedkin 	}
429908be065SVladimir Medvedkin }
430908be065SVladimir Medvedkin 
431908be065SVladimir Medvedkin static void
432908be065SVladimir Medvedkin print_addr(int af, const void *addr)
433908be065SVladimir Medvedkin {
434908be065SVladimir Medvedkin 	char str[INET6_ADDRSTRLEN];
435908be065SVladimir Medvedkin 	const char *ret;
436908be065SVladimir Medvedkin 
437908be065SVladimir Medvedkin 	ret = inet_ntop(af, addr, str, sizeof(str));
438908be065SVladimir Medvedkin 	if (ret != NULL)
439908be065SVladimir Medvedkin 		printf("%s", str);
440908be065SVladimir Medvedkin }
441908be065SVladimir Medvedkin 
442908be065SVladimir Medvedkin static void
443908be065SVladimir Medvedkin print_tuple(int af, uint32_t spi, const void *dip, const void *sip)
444908be065SVladimir Medvedkin {
445908be065SVladimir Medvedkin 
446908be065SVladimir Medvedkin 	printf("<SPI: %u DIP: ", spi);
447908be065SVladimir Medvedkin 	print_addr(af, dip);
448908be065SVladimir Medvedkin 	printf(" SIP: ");
449908be065SVladimir Medvedkin 	print_addr(af, sip);
450908be065SVladimir Medvedkin 	printf(">");
451908be065SVladimir Medvedkin }
452908be065SVladimir Medvedkin 
453908be065SVladimir Medvedkin static void
454908be065SVladimir Medvedkin print_result(const union rte_ipsec_sad_key *key, void *res)
455908be065SVladimir Medvedkin {
456908be065SVladimir Medvedkin 	struct rule *rule = res;
457908be065SVladimir Medvedkin 	const struct rte_ipsec_sadv4_key *v4;
458908be065SVladimir Medvedkin 	const struct rte_ipsec_sadv6_key *v6;
459908be065SVladimir Medvedkin 	const char *spi_only = "SPI_ONLY";
460908be065SVladimir Medvedkin 	const char *spi_dip = "SPI_DIP";
461908be065SVladimir Medvedkin 	const char *spi_dip_sip = "SPI_DIP_SIP";
462908be065SVladimir Medvedkin 	const char *rule_type;
463908be065SVladimir Medvedkin 	const void *dip, *sip;
464908be065SVladimir Medvedkin 	uint32_t spi;
465908be065SVladimir Medvedkin 	int af;
466908be065SVladimir Medvedkin 
467908be065SVladimir Medvedkin 	af = (config.ipv6) ? AF_INET6 : AF_INET;
468908be065SVladimir Medvedkin 	v4 = &key->v4;
469908be065SVladimir Medvedkin 	v6 = &key->v6;
470908be065SVladimir Medvedkin 	spi = (config.ipv6 == 0) ? v4->spi : v6->spi;
471*9ac91e2fSRobin Jarry 	dip = (config.ipv6 == 0) ? &v4->dip : (const void *)&v6->dip;
472*9ac91e2fSRobin Jarry 	sip = (config.ipv6 == 0) ? &v4->sip : (const void *)&v6->sip;
473908be065SVladimir Medvedkin 
474908be065SVladimir Medvedkin 	if (res == NULL) {
475908be065SVladimir Medvedkin 		printf("TUPLE: ");
476908be065SVladimir Medvedkin 		print_tuple(af, spi, dip, sip);
477908be065SVladimir Medvedkin 		printf(" not found\n");
478908be065SVladimir Medvedkin 		return;
479908be065SVladimir Medvedkin 	}
480908be065SVladimir Medvedkin 
481908be065SVladimir Medvedkin 	switch (rule->rule_type) {
482908be065SVladimir Medvedkin 	case RTE_IPSEC_SAD_SPI_ONLY:
483908be065SVladimir Medvedkin 		rule_type = spi_only;
484908be065SVladimir Medvedkin 		break;
485908be065SVladimir Medvedkin 	case RTE_IPSEC_SAD_SPI_DIP:
486908be065SVladimir Medvedkin 		rule_type = spi_dip;
487908be065SVladimir Medvedkin 		break;
488908be065SVladimir Medvedkin 	case RTE_IPSEC_SAD_SPI_DIP_SIP:
489908be065SVladimir Medvedkin 		rule_type = spi_dip_sip;
490908be065SVladimir Medvedkin 		break;
491908be065SVladimir Medvedkin 	default:
492908be065SVladimir Medvedkin 		return;
493908be065SVladimir Medvedkin 	}
494908be065SVladimir Medvedkin 
495908be065SVladimir Medvedkin 	print_tuple(af, spi, dip, sip);
496908be065SVladimir Medvedkin 	v4 = &rule->tuple.v4;
497908be065SVladimir Medvedkin 	v6 = &rule->tuple.v6;
498908be065SVladimir Medvedkin 	spi = (config.ipv6 == 0) ? v4->spi : v6->spi;
499*9ac91e2fSRobin Jarry 	dip = (config.ipv6 == 0) ? &v4->dip : (const void *)&v6->dip;
500*9ac91e2fSRobin Jarry 	sip = (config.ipv6 == 0) ? &v4->sip : (const void *)&v6->sip;
501908be065SVladimir Medvedkin 	printf("\n\tpoints to RULE ID %zu ",
502908be065SVladimir Medvedkin 		RTE_PTR_DIFF(res, rules_tbl)/sizeof(struct rule));
503908be065SVladimir Medvedkin 	print_tuple(af, spi, dip, sip);
504908be065SVladimir Medvedkin 	printf(" %s\n", rule_type);
505908be065SVladimir Medvedkin }
506908be065SVladimir Medvedkin 
507908be065SVladimir Medvedkin static int
508908be065SVladimir Medvedkin lookup(void *arg)
509908be065SVladimir Medvedkin {
510908be065SVladimir Medvedkin 	int ret;
511908be065SVladimir Medvedkin 	unsigned int i, j;
512908be065SVladimir Medvedkin 	const union rte_ipsec_sad_key *keys[BURST_SZ_MAX];
513908be065SVladimir Medvedkin 	void *vals[BURST_SZ_MAX];
514908be065SVladimir Medvedkin 	uint64_t start, acc = 0;
515908be065SVladimir Medvedkin 	uint32_t burst_sz;
516908be065SVladimir Medvedkin 	struct rte_ipsec_sad *sad = arg;
517908be065SVladimir Medvedkin 
5183e43647cSVladimir Medvedkin 	if (config.nb_tuples == 0)
5193e43647cSVladimir Medvedkin 		return 0;
5203e43647cSVladimir Medvedkin 
521908be065SVladimir Medvedkin 	burst_sz = RTE_MIN(config.burst_sz, config.nb_tuples);
522908be065SVladimir Medvedkin 	for (i = 0; i < config.nb_tuples; i += burst_sz) {
523908be065SVladimir Medvedkin 		for (j = 0; j < burst_sz; j++)
524908be065SVladimir Medvedkin 			keys[j] = (union rte_ipsec_sad_key *)
525908be065SVladimir Medvedkin 				(&tuples_tbl[i + j].tuple);
526908be065SVladimir Medvedkin 		start = rte_rdtsc_precise();
527908be065SVladimir Medvedkin 		ret = rte_ipsec_sad_lookup(sad, keys, vals, burst_sz);
528908be065SVladimir Medvedkin 		acc += rte_rdtsc_precise() - start;
529908be065SVladimir Medvedkin 		if (ret < 0)
530908be065SVladimir Medvedkin 			rte_exit(-EINVAL, "Lookup failed\n");
531908be065SVladimir Medvedkin 		if (config.verbose) {
532908be065SVladimir Medvedkin 			for (j = 0; j < burst_sz; j++)
533908be065SVladimir Medvedkin 				print_result(keys[j], vals[j]);
534908be065SVladimir Medvedkin 		}
535908be065SVladimir Medvedkin 	}
5363e43647cSVladimir Medvedkin 	acc = (acc == 0) ? UINT64_MAX : acc;
537908be065SVladimir Medvedkin 	printf("Average lookup cycles %.2Lf, lookups/sec: %.2Lf\n",
538908be065SVladimir Medvedkin 		(long double)acc / config.nb_tuples,
539908be065SVladimir Medvedkin 		(long double)config.nb_tuples * rte_get_tsc_hz() / acc);
540908be065SVladimir Medvedkin 
541908be065SVladimir Medvedkin 	return 0;
542908be065SVladimir Medvedkin }
543908be065SVladimir Medvedkin 
544908be065SVladimir Medvedkin static void
545908be065SVladimir Medvedkin add_rules(struct rte_ipsec_sad *sad, uint32_t fract)
546908be065SVladimir Medvedkin {
547908be065SVladimir Medvedkin 	int32_t ret;
548908be065SVladimir Medvedkin 	uint32_t i, j, f, fn, n;
549908be065SVladimir Medvedkin 	uint64_t start, tm[fract + 1];
550908be065SVladimir Medvedkin 	uint32_t nm[fract + 1];
551908be065SVladimir Medvedkin 
552908be065SVladimir Medvedkin 	f = (config.nb_rules > fract) ? config.nb_rules / fract : 1;
553908be065SVladimir Medvedkin 
554908be065SVladimir Medvedkin 	for (n = 0, j = 0; n != config.nb_rules; n = fn, j++) {
555908be065SVladimir Medvedkin 
556908be065SVladimir Medvedkin 		fn = n + f;
557908be065SVladimir Medvedkin 		fn = fn > config.nb_rules ? config.nb_rules : fn;
558908be065SVladimir Medvedkin 
559908be065SVladimir Medvedkin 		start = rte_rdtsc_precise();
560908be065SVladimir Medvedkin 		for (i = n; i != fn; i++) {
561908be065SVladimir Medvedkin 			ret = rte_ipsec_sad_add(sad,
562908be065SVladimir Medvedkin 				&rules_tbl[i].tuple,
563908be065SVladimir Medvedkin 				rules_tbl[i].rule_type, &rules_tbl[i]);
564908be065SVladimir Medvedkin 			if (ret != 0)
565908be065SVladimir Medvedkin 				rte_exit(ret, "%s failed @ %u-th rule\n",
566908be065SVladimir Medvedkin 					__func__, i);
567908be065SVladimir Medvedkin 		}
568908be065SVladimir Medvedkin 		tm[j] = rte_rdtsc_precise() - start;
569908be065SVladimir Medvedkin 		nm[j] = fn - n;
570908be065SVladimir Medvedkin 	}
571908be065SVladimir Medvedkin 
572908be065SVladimir Medvedkin 	for (i = 0; i != j; i++)
573908be065SVladimir Medvedkin 		printf("ADD %u rules, %.2Lf cycles/rule, %.2Lf ADD/sec\n",
574908be065SVladimir Medvedkin 			nm[i], (long double)tm[i] / nm[i],
575908be065SVladimir Medvedkin 			(long double)nm[i] * rte_get_tsc_hz() / tm[i]);
576908be065SVladimir Medvedkin }
577908be065SVladimir Medvedkin 
578908be065SVladimir Medvedkin static void
579908be065SVladimir Medvedkin del_rules(struct rte_ipsec_sad *sad, uint32_t fract)
580908be065SVladimir Medvedkin {
581908be065SVladimir Medvedkin 	int32_t ret;
582908be065SVladimir Medvedkin 	uint32_t i, j, f, fn, n;
583908be065SVladimir Medvedkin 	uint64_t start, tm[fract + 1];
584908be065SVladimir Medvedkin 	uint32_t nm[fract + 1];
585908be065SVladimir Medvedkin 
586908be065SVladimir Medvedkin 	f = (config.nb_rules > fract) ? config.nb_rules / fract : 1;
587908be065SVladimir Medvedkin 
588908be065SVladimir Medvedkin 	for (n = 0, j = 0; n != config.nb_rules; n = fn, j++) {
589908be065SVladimir Medvedkin 
590908be065SVladimir Medvedkin 		fn = n + f;
591908be065SVladimir Medvedkin 		fn = fn > config.nb_rules ? config.nb_rules : fn;
592908be065SVladimir Medvedkin 
593908be065SVladimir Medvedkin 		start = rte_rdtsc_precise();
594908be065SVladimir Medvedkin 		for (i = n; i != fn; i++) {
595908be065SVladimir Medvedkin 			ret = rte_ipsec_sad_del(sad,
596908be065SVladimir Medvedkin 				&rules_tbl[i].tuple,
597908be065SVladimir Medvedkin 				rules_tbl[i].rule_type);
598908be065SVladimir Medvedkin 			if (ret != 0 && ret != -ENOENT)
599908be065SVladimir Medvedkin 				rte_exit(ret, "%s failed @ %u-th rule\n",
600908be065SVladimir Medvedkin 					__func__, i);
601908be065SVladimir Medvedkin 		}
602908be065SVladimir Medvedkin 		tm[j] = rte_rdtsc_precise() - start;
603908be065SVladimir Medvedkin 		nm[j] = fn - n;
604908be065SVladimir Medvedkin 	}
605908be065SVladimir Medvedkin 
606908be065SVladimir Medvedkin 	for (i = 0; i != j; i++)
607908be065SVladimir Medvedkin 		printf("DEL %u rules, %.2Lf cycles/rule, %.2Lf DEL/sec\n",
608908be065SVladimir Medvedkin 			nm[i], (long double)tm[i] / nm[i],
609908be065SVladimir Medvedkin 			(long double)nm[i] * rte_get_tsc_hz() / tm[i]);
610908be065SVladimir Medvedkin }
611908be065SVladimir Medvedkin 
612908be065SVladimir Medvedkin int
613908be065SVladimir Medvedkin main(int argc, char **argv)
614908be065SVladimir Medvedkin {
615908be065SVladimir Medvedkin 	int ret;
616908be065SVladimir Medvedkin 	struct rte_ipsec_sad *sad;
617d26ec0d9SVladimir Medvedkin 	struct rte_ipsec_sad_conf conf = {0};
618908be065SVladimir Medvedkin 	unsigned int lcore_id;
619908be065SVladimir Medvedkin 
620908be065SVladimir Medvedkin 	ret = rte_eal_init(argc, argv);
621908be065SVladimir Medvedkin 	if (ret < 0)
622908be065SVladimir Medvedkin 		rte_panic("Cannot init EAL\n");
623908be065SVladimir Medvedkin 
624908be065SVladimir Medvedkin 	argc -= ret;
625908be065SVladimir Medvedkin 	argv += ret;
626908be065SVladimir Medvedkin 
627908be065SVladimir Medvedkin 	config.prgname = argv[0];
628908be065SVladimir Medvedkin 
629908be065SVladimir Medvedkin 	parse_opts(argc, argv);
630908be065SVladimir Medvedkin 	tbl_init(&rules_tbl, &config.nb_rules, config.rules_file, 1);
631908be065SVladimir Medvedkin 	tbl_init(&tuples_tbl, &config.nb_tuples, config.tuples_file, 0);
632908be065SVladimir Medvedkin 	if (config.rules_file != NULL) {
633908be065SVladimir Medvedkin 		config.fract_32 = (100 * config.nb_rules_32) / config.nb_rules;
634908be065SVladimir Medvedkin 		config.fract_64 = (100 * config.nb_rules_64) / config.nb_rules;
635908be065SVladimir Medvedkin 		config.fract_96 = (100 * config.nb_rules_96) / config.nb_rules;
636908be065SVladimir Medvedkin 	}
637908be065SVladimir Medvedkin 	if (config.tuples_file != NULL) {
638908be065SVladimir Medvedkin 		config.fract_rnd_tuples = 0;
639908be065SVladimir Medvedkin 		config.nb_tuples_rnd = 0;
640908be065SVladimir Medvedkin 	}
641908be065SVladimir Medvedkin 	conf.socket_id = -1;
642908be065SVladimir Medvedkin 	conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = config.nb_rules_32 * 5 / 4;
643908be065SVladimir Medvedkin 	conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = config.nb_rules_64 * 5 / 4;
644908be065SVladimir Medvedkin 	conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = config.nb_rules_96 * 5 / 4;
645908be065SVladimir Medvedkin 	if (config.ipv6)
646908be065SVladimir Medvedkin 		conf.flags |= RTE_IPSEC_SAD_FLAG_IPV6;
647908be065SVladimir Medvedkin 	if (config.concurrent_rw)
648908be065SVladimir Medvedkin 		conf.flags |= RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY;
649908be065SVladimir Medvedkin 	sad = rte_ipsec_sad_create("test", &conf);
650908be065SVladimir Medvedkin 	if (sad == NULL)
651908be065SVladimir Medvedkin 		rte_exit(-rte_errno, "can not allocate SAD table\n");
652908be065SVladimir Medvedkin 
653908be065SVladimir Medvedkin 	print_config();
654908be065SVladimir Medvedkin 
655908be065SVladimir Medvedkin 	add_rules(sad, 10);
656908be065SVladimir Medvedkin 	if (config.parallel_lookup)
657cb056611SStephen Hemminger 		rte_eal_mp_remote_launch(lookup, sad, SKIP_MAIN);
658908be065SVladimir Medvedkin 
659908be065SVladimir Medvedkin 	lookup(sad);
660908be065SVladimir Medvedkin 	if (config.parallel_lookup)
661cb056611SStephen Hemminger 		RTE_LCORE_FOREACH_WORKER(lcore_id)
662908be065SVladimir Medvedkin 			if (rte_eal_wait_lcore(lcore_id) < 0)
663908be065SVladimir Medvedkin 				return -1;
664908be065SVladimir Medvedkin 
665908be065SVladimir Medvedkin 	del_rules(sad, 10);
666908be065SVladimir Medvedkin 
667908be065SVladimir Medvedkin 	return 0;
668908be065SVladimir Medvedkin }
669