xref: /dpdk/app/test-regex/main.c (revision b6aceada0824eec2a2247af8e61dc865dac66a15)
1de06137cSYuval Avnery /* SPDX-License-Identifier: BSD-3-Clause
2de06137cSYuval Avnery  * Copyright 2020 Mellanox Technologies, Ltd
3de06137cSYuval Avnery  */
4de06137cSYuval Avnery 
5de06137cSYuval Avnery #include <stdio.h>
6de06137cSYuval Avnery #include <stdlib.h>
7de06137cSYuval Avnery #include <string.h>
8de06137cSYuval Avnery #include <stdint.h>
9de06137cSYuval Avnery #include <stdbool.h>
10de06137cSYuval Avnery #include <stdarg.h>
11de06137cSYuval Avnery #include <ctype.h>
12de06137cSYuval Avnery #include <errno.h>
13de06137cSYuval Avnery #include <getopt.h>
14de06137cSYuval Avnery #include <signal.h>
15de06137cSYuval Avnery 
16de06137cSYuval Avnery #include <rte_eal.h>
17de06137cSYuval Avnery #include <rte_common.h>
18de06137cSYuval Avnery #include <rte_malloc.h>
19de06137cSYuval Avnery #include <rte_mempool.h>
20de06137cSYuval Avnery #include <rte_mbuf.h>
21de06137cSYuval Avnery #include <rte_cycles.h>
22de06137cSYuval Avnery #include <rte_regexdev.h>
23de06137cSYuval Avnery 
24de06137cSYuval Avnery #define MAX_FILE_NAME 255
25de06137cSYuval Avnery #define MBUF_CACHE_SIZE 256
26de06137cSYuval Avnery #define MBUF_SIZE (1 << 8)
27de06137cSYuval Avnery #define START_BURST_SIZE 32u
28*b6aceadaSGerry Gribbon #define MAX_MATCH_MODE 2
29de06137cSYuval Avnery 
30de06137cSYuval Avnery enum app_args {
31de06137cSYuval Avnery 	ARG_HELP,
32de06137cSYuval Avnery 	ARG_RULES_FILE_NAME,
33de06137cSYuval Avnery 	ARG_DATA_FILE_NAME,
34de06137cSYuval Avnery 	ARG_NUM_OF_JOBS,
35de06137cSYuval Avnery 	ARG_PERF_MODE,
36de06137cSYuval Avnery 	ARG_NUM_OF_ITERATIONS,
374545bd00SOphir Munk 	ARG_NUM_OF_QPS,
386b99ba8dSOphir Munk 	ARG_NUM_OF_LCORES,
39cace2d7eSSuanming Mou 	ARG_NUM_OF_MBUF_SEGS,
40*b6aceadaSGerry Gribbon 	ARG_NUM_OF_MATCH_MODE,
41de06137cSYuval Avnery };
42de06137cSYuval Avnery 
4330cf1713SGuy Kaneti struct job_ctx {
4430cf1713SGuy Kaneti 	struct rte_mbuf *mbuf;
4530cf1713SGuy Kaneti };
4630cf1713SGuy Kaneti 
474545bd00SOphir Munk struct qp_params {
484545bd00SOphir Munk 	uint32_t total_enqueue;
494545bd00SOphir Munk 	uint32_t total_dequeue;
504545bd00SOphir Munk 	uint32_t total_matches;
514545bd00SOphir Munk 	struct rte_regex_ops **ops;
524545bd00SOphir Munk 	struct job_ctx *jobs_ctx;
534545bd00SOphir Munk 	char *buf;
54e5e518edSOphir Munk 	uint64_t start;
55e5e518edSOphir Munk 	uint64_t cycles;
564545bd00SOphir Munk };
574545bd00SOphir Munk 
586b99ba8dSOphir Munk struct qps_per_lcore {
596b99ba8dSOphir Munk 	unsigned int lcore_id;
606b99ba8dSOphir Munk 	int socket;
616b99ba8dSOphir Munk 	uint16_t qp_id_base;
626b99ba8dSOphir Munk 	uint16_t nb_qps;
636b99ba8dSOphir Munk };
646b99ba8dSOphir Munk 
656b99ba8dSOphir Munk struct regex_conf {
666b99ba8dSOphir Munk 	uint32_t nb_jobs;
676b99ba8dSOphir Munk 	bool perf_mode;
686b99ba8dSOphir Munk 	uint32_t nb_iterations;
696b99ba8dSOphir Munk 	char *data_file;
706b99ba8dSOphir Munk 	uint8_t nb_max_matches;
716b99ba8dSOphir Munk 	uint32_t nb_qps;
726b99ba8dSOphir Munk 	uint16_t qp_id_base;
736b99ba8dSOphir Munk 	char *data_buf;
746b99ba8dSOphir Munk 	long data_len;
756b99ba8dSOphir Munk 	long job_len;
76cace2d7eSSuanming Mou 	uint32_t nb_segs;
77*b6aceadaSGerry Gribbon 	uint32_t match_mode;
786b99ba8dSOphir Munk };
796b99ba8dSOphir Munk 
80de06137cSYuval Avnery static void
usage(const char * prog_name)81de06137cSYuval Avnery usage(const char *prog_name)
82de06137cSYuval Avnery {
83de06137cSYuval Avnery 	printf("%s [EAL options] --\n"
84de06137cSYuval Avnery 		" --rules NAME: precompiled rules file\n"
85de06137cSYuval Avnery 		" --data NAME: data file to use\n"
86de06137cSYuval Avnery 		" --nb_jobs: number of jobs to use\n"
87de06137cSYuval Avnery 		" --perf N: only outputs the performance data\n"
884545bd00SOphir Munk 		" --nb_iter N: number of iteration to run\n"
896b99ba8dSOphir Munk 		" --nb_qps N: number of queues to use\n"
90cace2d7eSSuanming Mou 		" --nb_lcores N: number of lcores to use\n"
91*b6aceadaSGerry Gribbon 		" --nb_segs N: number of mbuf segments\n"
92*b6aceadaSGerry Gribbon 		" --match_mode N: match mode: 0 - None (default),"
93*b6aceadaSGerry Gribbon 		"   1 - Highest Priority, 2 - Stop On Any\n",
94de06137cSYuval Avnery 		prog_name);
95de06137cSYuval Avnery }
96de06137cSYuval Avnery 
97de06137cSYuval Avnery static void
args_parse(int argc,char ** argv,char * rules_file,char * data_file,uint32_t * nb_jobs,bool * perf_mode,uint32_t * nb_iterations,uint32_t * nb_qps,uint32_t * nb_lcores,uint32_t * nb_segs,uint32_t * match_mode)98de06137cSYuval Avnery args_parse(int argc, char **argv, char *rules_file, char *data_file,
994545bd00SOphir Munk 	   uint32_t *nb_jobs, bool *perf_mode, uint32_t *nb_iterations,
100*b6aceadaSGerry Gribbon 	   uint32_t *nb_qps, uint32_t *nb_lcores, uint32_t *nb_segs,
101*b6aceadaSGerry Gribbon 	   uint32_t *match_mode)
102de06137cSYuval Avnery {
103de06137cSYuval Avnery 	char **argvopt;
104de06137cSYuval Avnery 	int opt;
105de06137cSYuval Avnery 	int opt_idx;
106de06137cSYuval Avnery 	size_t len;
107de06137cSYuval Avnery 	static struct option lgopts[] = {
108de06137cSYuval Avnery 		{ "help",  0, 0, ARG_HELP},
109de06137cSYuval Avnery 		/* Rules database file to load. */
110de06137cSYuval Avnery 		{ "rules",  1, 0, ARG_RULES_FILE_NAME},
111de06137cSYuval Avnery 		/* Data file to load. */
112de06137cSYuval Avnery 		{ "data",  1, 0, ARG_DATA_FILE_NAME},
113de06137cSYuval Avnery 		/* Number of jobs to create. */
114de06137cSYuval Avnery 		{ "nb_jobs",  1, 0, ARG_NUM_OF_JOBS},
115de06137cSYuval Avnery 		/* Perf test only */
116de06137cSYuval Avnery 		{ "perf", 0, 0, ARG_PERF_MODE},
117de06137cSYuval Avnery 		/* Number of iterations to run with perf test */
11806ca0e4bSOphir Munk 		{ "nb_iter", 1, 0, ARG_NUM_OF_ITERATIONS},
1194545bd00SOphir Munk 		/* Number of QPs. */
1204545bd00SOphir Munk 		{ "nb_qps", 1, 0, ARG_NUM_OF_QPS},
1216b99ba8dSOphir Munk 		/* Number of lcores. */
1226b99ba8dSOphir Munk 		{ "nb_lcores", 1, 0, ARG_NUM_OF_LCORES},
123cace2d7eSSuanming Mou 		/* Number of mbuf segments. */
124cace2d7eSSuanming Mou 		{ "nb_segs", 1, 0, ARG_NUM_OF_MBUF_SEGS},
125*b6aceadaSGerry Gribbon 		/* Match mode. */
126*b6aceadaSGerry Gribbon 		{ "match_mode", 1, 0, ARG_NUM_OF_MATCH_MODE},
12706ca0e4bSOphir Munk 		/* End of options */
12806ca0e4bSOphir Munk 		{ 0, 0, 0, 0 }
129de06137cSYuval Avnery 	};
130de06137cSYuval Avnery 
131de06137cSYuval Avnery 	argvopt = argv;
132de06137cSYuval Avnery 	while ((opt = getopt_long(argc, argvopt, "",
133de06137cSYuval Avnery 				lgopts, &opt_idx)) != EOF) {
134de06137cSYuval Avnery 		switch (opt) {
135de06137cSYuval Avnery 		case ARG_RULES_FILE_NAME:
136de06137cSYuval Avnery 			len = strnlen(optarg, MAX_FILE_NAME - 1);
137de06137cSYuval Avnery 			if (len == MAX_FILE_NAME)
138de06137cSYuval Avnery 				rte_exit(EXIT_FAILURE,
139de06137cSYuval Avnery 					 "Rule file name to long max %d\n",
140de06137cSYuval Avnery 					 MAX_FILE_NAME - 1);
141de06137cSYuval Avnery 			strncpy(rules_file, optarg, MAX_FILE_NAME - 1);
142de06137cSYuval Avnery 			break;
143de06137cSYuval Avnery 		case ARG_DATA_FILE_NAME:
144de06137cSYuval Avnery 			len = strnlen(optarg, MAX_FILE_NAME - 1);
145de06137cSYuval Avnery 			if (len == MAX_FILE_NAME)
146de06137cSYuval Avnery 				rte_exit(EXIT_FAILURE,
147de06137cSYuval Avnery 					 "Data file name to long max %d\n",
148de06137cSYuval Avnery 					 MAX_FILE_NAME - 1);
149de06137cSYuval Avnery 			strncpy(data_file, optarg, MAX_FILE_NAME - 1);
150de06137cSYuval Avnery 			break;
151de06137cSYuval Avnery 		case ARG_NUM_OF_JOBS:
152de06137cSYuval Avnery 			*nb_jobs = atoi(optarg);
153de06137cSYuval Avnery 			break;
154de06137cSYuval Avnery 		case ARG_PERF_MODE:
155de06137cSYuval Avnery 			*perf_mode = true;
156de06137cSYuval Avnery 			break;
157de06137cSYuval Avnery 		case ARG_NUM_OF_ITERATIONS:
158de06137cSYuval Avnery 			*nb_iterations = atoi(optarg);
159de06137cSYuval Avnery 			break;
1604545bd00SOphir Munk 		case ARG_NUM_OF_QPS:
1614545bd00SOphir Munk 			*nb_qps = atoi(optarg);
1624545bd00SOphir Munk 			break;
1636b99ba8dSOphir Munk 		case ARG_NUM_OF_LCORES:
1646b99ba8dSOphir Munk 			*nb_lcores = atoi(optarg);
1656b99ba8dSOphir Munk 			break;
166cace2d7eSSuanming Mou 		case ARG_NUM_OF_MBUF_SEGS:
167cace2d7eSSuanming Mou 			*nb_segs = atoi(optarg);
168cace2d7eSSuanming Mou 			break;
169*b6aceadaSGerry Gribbon 		case ARG_NUM_OF_MATCH_MODE:
170*b6aceadaSGerry Gribbon 			*match_mode = atoi(optarg);
171*b6aceadaSGerry Gribbon 			if (*match_mode > MAX_MATCH_MODE)
172*b6aceadaSGerry Gribbon 				rte_exit(EXIT_FAILURE,
173*b6aceadaSGerry Gribbon 					 "Invalid match mode value\n");
174*b6aceadaSGerry Gribbon 			break;
175de06137cSYuval Avnery 		case ARG_HELP:
176e0512833SThomas Monjalon 			usage(argv[0]);
177de06137cSYuval Avnery 			break;
178de06137cSYuval Avnery 		default:
179e0512833SThomas Monjalon 			usage(argv[0]);
180487cfc24SThomas Monjalon 			rte_exit(EXIT_FAILURE, "Invalid option: %s\n", argv[optind]);
181de06137cSYuval Avnery 			break;
182de06137cSYuval Avnery 		}
183de06137cSYuval Avnery 	}
184de06137cSYuval Avnery 
185de06137cSYuval Avnery 	if (!perf_mode)
186de06137cSYuval Avnery 		*nb_iterations = 1;
187de06137cSYuval Avnery }
188de06137cSYuval Avnery 
189de06137cSYuval Avnery static long
read_file(char * file,char ** buf)190de06137cSYuval Avnery read_file(char *file, char **buf)
191de06137cSYuval Avnery {
192de06137cSYuval Avnery 	FILE *fp;
193de06137cSYuval Avnery 	long buf_len = 0;
194de06137cSYuval Avnery 	size_t read_len;
195de06137cSYuval Avnery 	int res = 0;
196de06137cSYuval Avnery 
197de06137cSYuval Avnery 	fp = fopen(file, "r");
198de06137cSYuval Avnery 	if (!fp)
199de06137cSYuval Avnery 		return -EIO;
200de06137cSYuval Avnery 	if (fseek(fp, 0L, SEEK_END) == 0) {
201de06137cSYuval Avnery 		buf_len = ftell(fp);
202de06137cSYuval Avnery 		if (buf_len == -1) {
203de06137cSYuval Avnery 			res = EIO;
204de06137cSYuval Avnery 			goto error;
205de06137cSYuval Avnery 		}
206de06137cSYuval Avnery 		*buf = rte_malloc(NULL, sizeof(char) * (buf_len + 1), 4096);
207de06137cSYuval Avnery 		if (!*buf) {
208de06137cSYuval Avnery 			res = ENOMEM;
209de06137cSYuval Avnery 			goto error;
210de06137cSYuval Avnery 		}
211de06137cSYuval Avnery 		if (fseek(fp, 0L, SEEK_SET) != 0) {
212de06137cSYuval Avnery 			res = EIO;
213de06137cSYuval Avnery 			goto error;
214de06137cSYuval Avnery 		}
215de06137cSYuval Avnery 		read_len = fread(*buf, sizeof(char), buf_len, fp);
216de06137cSYuval Avnery 		if (read_len != (unsigned long)buf_len) {
217de06137cSYuval Avnery 			res = EIO;
218de06137cSYuval Avnery 			goto error;
219de06137cSYuval Avnery 		}
220de06137cSYuval Avnery 	}
221de06137cSYuval Avnery 	fclose(fp);
222de06137cSYuval Avnery 	return buf_len;
223de06137cSYuval Avnery error:
224de06137cSYuval Avnery 	printf("Error, can't open file %s\n, err = %d", file, res);
225de06137cSYuval Avnery 	if (fp)
226de06137cSYuval Avnery 		fclose(fp);
227de06137cSYuval Avnery 	rte_free(*buf);
228de06137cSYuval Avnery 	return -res;
229de06137cSYuval Avnery }
230de06137cSYuval Avnery 
231de06137cSYuval Avnery static int
clone_buf(char * data_buf,char ** buf,long data_len)232f5cffb7eSOphir Munk clone_buf(char *data_buf, char **buf, long data_len)
233f5cffb7eSOphir Munk {
234f5cffb7eSOphir Munk 	char *dest_buf;
235f5cffb7eSOphir Munk 	dest_buf =
236f5cffb7eSOphir Munk 		rte_malloc(NULL, sizeof(char) * (data_len + 1), 4096);
237f5cffb7eSOphir Munk 	if (!dest_buf)
238f5cffb7eSOphir Munk 		return -ENOMEM;
239f5cffb7eSOphir Munk 	memcpy(dest_buf, data_buf, data_len + 1);
240f5cffb7eSOphir Munk 	*buf = dest_buf;
241f5cffb7eSOphir Munk 	return 0;
242f5cffb7eSOphir Munk }
243f5cffb7eSOphir Munk 
244f5cffb7eSOphir Munk static int
init_port(uint16_t * nb_max_payload,char * rules_file,uint8_t * nb_max_matches,uint32_t nb_qps)2454545bd00SOphir Munk init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches,
2464545bd00SOphir Munk 	  uint32_t nb_qps)
247de06137cSYuval Avnery {
248de06137cSYuval Avnery 	uint16_t id;
2494545bd00SOphir Munk 	uint16_t qp_id;
250de06137cSYuval Avnery 	uint16_t num_devs;
251de06137cSYuval Avnery 	char *rules = NULL;
252de06137cSYuval Avnery 	long rules_len;
253de06137cSYuval Avnery 	struct rte_regexdev_info info;
254de06137cSYuval Avnery 	struct rte_regexdev_config dev_conf = {
2554545bd00SOphir Munk 		.nb_queue_pairs = nb_qps,
256de06137cSYuval Avnery 		.nb_groups = 1,
257de06137cSYuval Avnery 	};
258de06137cSYuval Avnery 	struct rte_regexdev_qp_conf qp_conf = {
259de06137cSYuval Avnery 		.nb_desc = 1024,
260d96d0fa7SGuy Kaneti 		.qp_conf_flags = 0,
261de06137cSYuval Avnery 	};
262de06137cSYuval Avnery 	int res = 0;
263de06137cSYuval Avnery 
264de06137cSYuval Avnery 	num_devs = rte_regexdev_count();
265de06137cSYuval Avnery 	if (num_devs == 0) {
266de06137cSYuval Avnery 		printf("Error, no devices detected.\n");
267de06137cSYuval Avnery 		return -EINVAL;
268de06137cSYuval Avnery 	}
269de06137cSYuval Avnery 
270de06137cSYuval Avnery 	rules_len = read_file(rules_file, &rules);
271de06137cSYuval Avnery 	if (rules_len < 0) {
272de06137cSYuval Avnery 		printf("Error, can't read rules files.\n");
273de06137cSYuval Avnery 		res = -EIO;
274de06137cSYuval Avnery 		goto error;
275de06137cSYuval Avnery 	}
276de06137cSYuval Avnery 
277de06137cSYuval Avnery 	for (id = 0; id < num_devs; id++) {
278de06137cSYuval Avnery 		res = rte_regexdev_info_get(id, &info);
279de06137cSYuval Avnery 		if (res != 0) {
280de06137cSYuval Avnery 			printf("Error, can't get device info.\n");
281de06137cSYuval Avnery 			goto error;
282de06137cSYuval Avnery 		}
283de06137cSYuval Avnery 		printf(":: initializing dev: %d\n", id);
284de06137cSYuval Avnery 		*nb_max_matches = info.max_matches;
285de06137cSYuval Avnery 		*nb_max_payload = info.max_payload_size;
286de06137cSYuval Avnery 		if (info.regexdev_capa & RTE_REGEXDEV_SUPP_MATCH_AS_END_F)
2874545bd00SOphir Munk 			dev_conf.dev_cfg_flags |=
2884545bd00SOphir Munk 			RTE_REGEXDEV_CFG_MATCH_AS_END_F;
289de06137cSYuval Avnery 		dev_conf.nb_max_matches = info.max_matches;
290de06137cSYuval Avnery 		dev_conf.nb_rules_per_group = info.max_rules_per_group;
291de06137cSYuval Avnery 		dev_conf.rule_db_len = rules_len;
292de06137cSYuval Avnery 		dev_conf.rule_db = rules;
293de06137cSYuval Avnery 		res = rte_regexdev_configure(id, &dev_conf);
294de06137cSYuval Avnery 		if (res < 0) {
295de06137cSYuval Avnery 			printf("Error, can't configure device %d.\n", id);
296de06137cSYuval Avnery 			goto error;
297de06137cSYuval Avnery 		}
298d96d0fa7SGuy Kaneti 		if (info.regexdev_capa & RTE_REGEXDEV_CAPA_QUEUE_PAIR_OOS_F)
2994545bd00SOphir Munk 			qp_conf.qp_conf_flags |=
3004545bd00SOphir Munk 			RTE_REGEX_QUEUE_PAIR_CFG_OOS_F;
3014545bd00SOphir Munk 		for (qp_id = 0; qp_id < nb_qps; qp_id++) {
3024545bd00SOphir Munk 			res = rte_regexdev_queue_pair_setup(id, qp_id,
3034545bd00SOphir Munk 							    &qp_conf);
304de06137cSYuval Avnery 			if (res < 0) {
3054545bd00SOphir Munk 				printf("Error, can't setup queue pair %u for "
3064545bd00SOphir Munk 				       "device %d.\n", qp_id, id);
307de06137cSYuval Avnery 				goto error;
308de06137cSYuval Avnery 			}
3094545bd00SOphir Munk 		}
310de06137cSYuval Avnery 		printf(":: initializing device: %d done\n", id);
311de06137cSYuval Avnery 	}
312de06137cSYuval Avnery 	rte_free(rules);
313de06137cSYuval Avnery 	return 0;
314de06137cSYuval Avnery error:
315de06137cSYuval Avnery 	rte_free(rules);
316de06137cSYuval Avnery 	return res;
317de06137cSYuval Avnery }
318de06137cSYuval Avnery 
319de06137cSYuval Avnery static void
extbuf_free_cb(void * addr __rte_unused,void * fcb_opaque __rte_unused)320de06137cSYuval Avnery extbuf_free_cb(void *addr __rte_unused, void *fcb_opaque __rte_unused)
321de06137cSYuval Avnery {
322de06137cSYuval Avnery }
323de06137cSYuval Avnery 
324cace2d7eSSuanming Mou static inline struct rte_mbuf *
regex_create_segmented_mbuf(struct rte_mempool * mbuf_pool,int pkt_len,int nb_segs,void * buf)325cace2d7eSSuanming Mou regex_create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
326cace2d7eSSuanming Mou 		int nb_segs, void *buf) {
327cace2d7eSSuanming Mou 
328cace2d7eSSuanming Mou 	struct rte_mbuf *m = NULL, *mbuf = NULL;
329cace2d7eSSuanming Mou 	uint8_t *dst;
330cace2d7eSSuanming Mou 	char *src = buf;
331cace2d7eSSuanming Mou 	int data_len = 0;
332cace2d7eSSuanming Mou 	int i, size;
333cace2d7eSSuanming Mou 	int t_len;
334cace2d7eSSuanming Mou 
335cace2d7eSSuanming Mou 	if (pkt_len < 1) {
336cace2d7eSSuanming Mou 		printf("Packet size must be 1 or more (is %d)\n", pkt_len);
337cace2d7eSSuanming Mou 		return NULL;
338cace2d7eSSuanming Mou 	}
339cace2d7eSSuanming Mou 
340cace2d7eSSuanming Mou 	if (nb_segs < 1) {
341cace2d7eSSuanming Mou 		printf("Number of segments must be 1 or more (is %d)\n",
342cace2d7eSSuanming Mou 				nb_segs);
343cace2d7eSSuanming Mou 		return NULL;
344cace2d7eSSuanming Mou 	}
345cace2d7eSSuanming Mou 
346cace2d7eSSuanming Mou 	t_len = pkt_len >= nb_segs ? (pkt_len / nb_segs +
347cace2d7eSSuanming Mou 				     !!(pkt_len % nb_segs)) : 1;
348cace2d7eSSuanming Mou 	size = pkt_len;
349cace2d7eSSuanming Mou 
350cace2d7eSSuanming Mou 	/* Create chained mbuf_src and fill it with buf data */
351cace2d7eSSuanming Mou 	for (i = 0; size > 0; i++) {
352cace2d7eSSuanming Mou 
353cace2d7eSSuanming Mou 		m = rte_pktmbuf_alloc(mbuf_pool);
354cace2d7eSSuanming Mou 		if (i == 0)
355cace2d7eSSuanming Mou 			mbuf = m;
356cace2d7eSSuanming Mou 
357cace2d7eSSuanming Mou 		if (m == NULL) {
358cace2d7eSSuanming Mou 			printf("Cannot create segment for source mbuf");
359cace2d7eSSuanming Mou 			goto fail;
360cace2d7eSSuanming Mou 		}
361cace2d7eSSuanming Mou 
362cace2d7eSSuanming Mou 		data_len = size > t_len ? t_len : size;
363cace2d7eSSuanming Mou 		memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
364cace2d7eSSuanming Mou 				rte_pktmbuf_tailroom(m));
365cace2d7eSSuanming Mou 		memcpy(rte_pktmbuf_mtod(m, uint8_t *), src, data_len);
366cace2d7eSSuanming Mou 		dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
367cace2d7eSSuanming Mou 		if (dst == NULL) {
368cace2d7eSSuanming Mou 			printf("Cannot append %d bytes to the mbuf\n",
369cace2d7eSSuanming Mou 					data_len);
370cace2d7eSSuanming Mou 			goto fail;
371cace2d7eSSuanming Mou 		}
372cace2d7eSSuanming Mou 
373cace2d7eSSuanming Mou 		if (mbuf != m)
374cace2d7eSSuanming Mou 			rte_pktmbuf_chain(mbuf, m);
375cace2d7eSSuanming Mou 		src += data_len;
376cace2d7eSSuanming Mou 		size -= data_len;
377cace2d7eSSuanming Mou 
378cace2d7eSSuanming Mou 	}
379cace2d7eSSuanming Mou 	return mbuf;
380cace2d7eSSuanming Mou 
381cace2d7eSSuanming Mou fail:
382cace2d7eSSuanming Mou 	rte_pktmbuf_free(mbuf);
383cace2d7eSSuanming Mou 	return NULL;
384cace2d7eSSuanming Mou }
385cace2d7eSSuanming Mou 
386de06137cSYuval Avnery static int
run_regex(void * args)3876b99ba8dSOphir Munk run_regex(void *args)
388de06137cSYuval Avnery {
3896b99ba8dSOphir Munk 	struct regex_conf *rgxc = args;
3906b99ba8dSOphir Munk 	uint32_t nb_jobs = rgxc->nb_jobs;
391cace2d7eSSuanming Mou 	uint32_t nb_segs = rgxc->nb_segs;
3926b99ba8dSOphir Munk 	uint32_t nb_iterations = rgxc->nb_iterations;
3936b99ba8dSOphir Munk 	uint8_t nb_max_matches = rgxc->nb_max_matches;
3946b99ba8dSOphir Munk 	uint32_t nb_qps = rgxc->nb_qps;
3956b99ba8dSOphir Munk 	uint16_t qp_id_base  = rgxc->qp_id_base;
3966b99ba8dSOphir Munk 	char *data_buf = rgxc->data_buf;
3976b99ba8dSOphir Munk 	long data_len = rgxc->data_len;
3986b99ba8dSOphir Munk 	long job_len = rgxc->job_len;
399*b6aceadaSGerry Gribbon 	uint32_t match_mode = rgxc->match_mode;
400c1d1b94eSGerry Gribbon 	long remainder;
401c1d1b94eSGerry Gribbon 	long act_job_len = 0;
402c1d1b94eSGerry Gribbon 	bool last_job = false;
403de06137cSYuval Avnery 	char *buf = NULL;
404de06137cSYuval Avnery 	uint32_t actual_jobs = 0;
405de06137cSYuval Avnery 	uint32_t i;
406c1d1b94eSGerry Gribbon 	uint32_t job_id;
4074545bd00SOphir Munk 	uint16_t qp_id;
408de06137cSYuval Avnery 	uint16_t dev_id = 0;
409de06137cSYuval Avnery 	uint8_t nb_matches;
410392ac62bSGerry Gribbon 	uint16_t rsp_flags = 0;
411de06137cSYuval Avnery 	struct rte_regexdev_match *match;
4124545bd00SOphir Munk 	long pos;
413de06137cSYuval Avnery 	unsigned long d_ind = 0;
414de06137cSYuval Avnery 	struct rte_mbuf_ext_shared_info shinfo;
415de06137cSYuval Avnery 	int res = 0;
416e5e518edSOphir Munk 	long double time;
4172d1fb3f2SOphir Munk 	struct rte_mempool *mbuf_mp;
4184545bd00SOphir Munk 	struct qp_params *qp;
4194545bd00SOphir Munk 	struct qp_params *qps = NULL;
4204545bd00SOphir Munk 	bool update;
4214545bd00SOphir Munk 	uint16_t qps_used = 0;
4226b99ba8dSOphir Munk 	char mbuf_pool[16];
423de06137cSYuval Avnery 
424de06137cSYuval Avnery 	shinfo.free_cb = extbuf_free_cb;
4256b99ba8dSOphir Munk 	snprintf(mbuf_pool,
4266b99ba8dSOphir Munk 		 sizeof(mbuf_pool),
4276b99ba8dSOphir Munk 		 "mbuf_pool_%2u", qp_id_base);
428cace2d7eSSuanming Mou 	mbuf_mp = rte_pktmbuf_pool_create(mbuf_pool,
429cace2d7eSSuanming Mou 			rte_align32pow2(nb_jobs * nb_qps * nb_segs),
430cace2d7eSSuanming Mou 			0, 0, (nb_segs == 1) ? MBUF_SIZE :
431a442ca2dSRaslan Darawsheh 			(rte_align32pow2(job_len + (data_len % nb_jobs)) /
432a442ca2dSRaslan Darawsheh 			 nb_segs + RTE_PKTMBUF_HEADROOM),
433cace2d7eSSuanming Mou 			rte_socket_id());
4342d1fb3f2SOphir Munk 	if (mbuf_mp == NULL) {
4352d1fb3f2SOphir Munk 		printf("Error, can't create memory pool\n");
4362d1fb3f2SOphir Munk 		return -ENOMEM;
4372d1fb3f2SOphir Munk 	}
4382d1fb3f2SOphir Munk 
4394545bd00SOphir Munk 	qps = rte_malloc(NULL, sizeof(*qps) * nb_qps, 0);
4404545bd00SOphir Munk 	if (!qps) {
4414545bd00SOphir Munk 		printf("Error, can't allocate memory for QPs\n");
4424545bd00SOphir Munk 		res = -ENOMEM;
4434545bd00SOphir Munk 		goto end;
444de06137cSYuval Avnery 	}
445de06137cSYuval Avnery 
4464545bd00SOphir Munk 	for (qp_id = 0; qp_id < nb_qps; qp_id++) {
4474545bd00SOphir Munk 		struct rte_regex_ops **ops;
4484545bd00SOphir Munk 		struct job_ctx *jobs_ctx;
4494545bd00SOphir Munk 
4504545bd00SOphir Munk 		qps_used++;
4514545bd00SOphir Munk 		qp = &qps[qp_id];
4524545bd00SOphir Munk 		qp->jobs_ctx = NULL;
4534545bd00SOphir Munk 		qp->buf = NULL;
4544545bd00SOphir Munk 		qp->ops = ops = rte_malloc(NULL, sizeof(*ops) * nb_jobs, 0);
4554545bd00SOphir Munk 		if (!ops) {
4564545bd00SOphir Munk 			printf("Error, can't allocate memory for ops.\n");
4574545bd00SOphir Munk 			res = -ENOMEM;
4584545bd00SOphir Munk 			goto end;
4594545bd00SOphir Munk 		}
4604545bd00SOphir Munk 
4614545bd00SOphir Munk 		qp->jobs_ctx = jobs_ctx =
4624545bd00SOphir Munk 			rte_malloc(NULL, sizeof(*jobs_ctx) * nb_jobs, 0);
46330cf1713SGuy Kaneti 		if (!jobs_ctx) {
46430cf1713SGuy Kaneti 			printf("Error, can't allocate memory for jobs_ctx.\n");
4654545bd00SOphir Munk 			res = -ENOMEM;
4664545bd00SOphir Munk 			goto end;
46730cf1713SGuy Kaneti 		}
46830cf1713SGuy Kaneti 
469f5cffb7eSOphir Munk 		if (clone_buf(data_buf, &buf, data_len)) {
470f5cffb7eSOphir Munk 			printf("Error, can't clone buf.\n");
471de06137cSYuval Avnery 			res = -EXIT_FAILURE;
472de06137cSYuval Avnery 			goto end;
473de06137cSYuval Avnery 		}
474de06137cSYuval Avnery 
475de06137cSYuval Avnery 		/* Assign each mbuf with the data to handle. */
4764545bd00SOphir Munk 		actual_jobs = 0;
4774545bd00SOphir Munk 		pos = 0;
478c1d1b94eSGerry Gribbon 		remainder = data_len % nb_jobs;
479c1d1b94eSGerry Gribbon 
480cace2d7eSSuanming Mou 		/* Allocate the jobs and assign each job with an mbuf. */
481f5cffb7eSOphir Munk 		for (i = 0; (pos < data_len) && (i < nb_jobs) ; i++) {
482c1d1b94eSGerry Gribbon 			act_job_len = RTE_MIN(job_len, data_len - pos);
483c1d1b94eSGerry Gribbon 
484c1d1b94eSGerry Gribbon 			if (i == (nb_jobs - 1)) {
485c1d1b94eSGerry Gribbon 				last_job = true;
486c1d1b94eSGerry Gribbon 				act_job_len += remainder;
487c1d1b94eSGerry Gribbon 			}
488cace2d7eSSuanming Mou 
489cace2d7eSSuanming Mou 			ops[i] = rte_malloc(NULL, sizeof(*ops[0]) +
490cace2d7eSSuanming Mou 					nb_max_matches *
491cace2d7eSSuanming Mou 					sizeof(struct rte_regexdev_match), 0);
492cace2d7eSSuanming Mou 			if (!ops[i]) {
493cace2d7eSSuanming Mou 				printf("Error, can't allocate "
494cace2d7eSSuanming Mou 				       "memory for op.\n");
495cace2d7eSSuanming Mou 				res = -ENOMEM;
496cace2d7eSSuanming Mou 				goto end;
497cace2d7eSSuanming Mou 			}
498cace2d7eSSuanming Mou 			if (nb_segs > 1) {
499cace2d7eSSuanming Mou 				ops[i]->mbuf = regex_create_segmented_mbuf
500cace2d7eSSuanming Mou 							(mbuf_mp, act_job_len,
501cace2d7eSSuanming Mou 							 nb_segs, &buf[pos]);
502cace2d7eSSuanming Mou 			} else {
503cace2d7eSSuanming Mou 				ops[i]->mbuf = rte_pktmbuf_alloc(mbuf_mp);
504cace2d7eSSuanming Mou 				if (ops[i]->mbuf) {
505cace2d7eSSuanming Mou 					rte_pktmbuf_attach_extbuf(ops[i]->mbuf,
506cace2d7eSSuanming Mou 					&buf[pos], 0, act_job_len, &shinfo);
507c1d1b94eSGerry Gribbon 
508c1d1b94eSGerry Gribbon 					if (!last_job)
509de06137cSYuval Avnery 						ops[i]->mbuf->data_len = job_len;
510c1d1b94eSGerry Gribbon 					else
511c1d1b94eSGerry Gribbon 						ops[i]->mbuf->data_len = act_job_len;
512c1d1b94eSGerry Gribbon 
513de06137cSYuval Avnery 					ops[i]->mbuf->pkt_len = act_job_len;
514cace2d7eSSuanming Mou 				}
515cace2d7eSSuanming Mou 			}
516cace2d7eSSuanming Mou 			if (!ops[i]->mbuf) {
517cace2d7eSSuanming Mou 				printf("Error, can't add mbuf.\n");
518cace2d7eSSuanming Mou 				res = -ENOMEM;
519cace2d7eSSuanming Mou 				goto end;
520cace2d7eSSuanming Mou 			}
521cace2d7eSSuanming Mou 
522cace2d7eSSuanming Mou 			jobs_ctx[i].mbuf = ops[i]->mbuf;
523de06137cSYuval Avnery 			ops[i]->user_id = i;
524de06137cSYuval Avnery 			ops[i]->group_id0 = 1;
525*b6aceadaSGerry Gribbon 			switch (match_mode) {
526*b6aceadaSGerry Gribbon 			case 0:
527*b6aceadaSGerry Gribbon 				/* Nothing to set in req_flags */
528*b6aceadaSGerry Gribbon 				break;
529*b6aceadaSGerry Gribbon 			case 1:
530*b6aceadaSGerry Gribbon 				ops[i]->req_flags |= RTE_REGEX_OPS_REQ_MATCH_HIGH_PRIORITY_F;
531*b6aceadaSGerry Gribbon 				break;
532*b6aceadaSGerry Gribbon 			case 2:
533*b6aceadaSGerry Gribbon 				ops[i]->req_flags |= RTE_REGEX_OPS_REQ_STOP_ON_MATCH_F;
534*b6aceadaSGerry Gribbon 				break;
535*b6aceadaSGerry Gribbon 			default:
536*b6aceadaSGerry Gribbon 				rte_exit(EXIT_FAILURE,
537*b6aceadaSGerry Gribbon 					 "Invalid match mode value\n");
538*b6aceadaSGerry Gribbon 				break;
539*b6aceadaSGerry Gribbon 			}
540de06137cSYuval Avnery 			pos += act_job_len;
541de06137cSYuval Avnery 			actual_jobs++;
542de06137cSYuval Avnery 		}
543de06137cSYuval Avnery 
5444545bd00SOphir Munk 		qp->buf = buf;
5454545bd00SOphir Munk 		qp->total_matches = 0;
5466e3c6bd6SOphir Munk 		qp->start = 0;
547e5e518edSOphir Munk 		qp->cycles = 0;
5484545bd00SOphir Munk 	}
5494545bd00SOphir Munk 
550de06137cSYuval Avnery 	for (i = 0; i < nb_iterations; i++) {
5514545bd00SOphir Munk 		for (qp_id = 0; qp_id < nb_qps; qp_id++) {
5524545bd00SOphir Munk 			qp = &qps[qp_id];
5534545bd00SOphir Munk 			qp->total_enqueue = 0;
5544545bd00SOphir Munk 			qp->total_dequeue = 0;
555c1d1b94eSGerry Gribbon 			/* Re-set user id after dequeue to match data in mbuf. */
556c1d1b94eSGerry Gribbon 			for (job_id = 0 ; job_id < nb_jobs; job_id++)
557c1d1b94eSGerry Gribbon 				qp->ops[job_id]->user_id = job_id;
558de06137cSYuval Avnery 		}
5594545bd00SOphir Munk 		do {
5604545bd00SOphir Munk 			update = false;
5614545bd00SOphir Munk 			for (qp_id = 0; qp_id < nb_qps; qp_id++) {
5624545bd00SOphir Munk 				qp = &qps[qp_id];
5634545bd00SOphir Munk 				if (qp->total_dequeue < actual_jobs) {
564e5e518edSOphir Munk 					qp->start = rte_rdtsc_precise();
5654545bd00SOphir Munk 					struct rte_regex_ops **
5664545bd00SOphir Munk 						cur_ops_to_enqueue = qp->ops +
5674545bd00SOphir Munk 						qp->total_enqueue;
5684545bd00SOphir Munk 
5694545bd00SOphir Munk 					if (actual_jobs - qp->total_enqueue)
5704545bd00SOphir Munk 						qp->total_enqueue +=
5714545bd00SOphir Munk 						rte_regexdev_enqueue_burst
5724545bd00SOphir Munk 							(dev_id,
5736b99ba8dSOphir Munk 							qp_id_base + qp_id,
5744545bd00SOphir Munk 							cur_ops_to_enqueue,
5754545bd00SOphir Munk 							actual_jobs -
5764545bd00SOphir Munk 							qp->total_enqueue);
5774545bd00SOphir Munk 				}
5784545bd00SOphir Munk 			}
5794545bd00SOphir Munk 			for (qp_id = 0; qp_id < nb_qps; qp_id++) {
5804545bd00SOphir Munk 				qp = &qps[qp_id];
5814545bd00SOphir Munk 				if (qp->total_dequeue < actual_jobs) {
5824545bd00SOphir Munk 					struct rte_regex_ops **
5834545bd00SOphir Munk 						cur_ops_to_dequeue = qp->ops +
5844545bd00SOphir Munk 						qp->total_dequeue;
5854545bd00SOphir Munk 
5864545bd00SOphir Munk 					qp->total_dequeue +=
5874545bd00SOphir Munk 						rte_regexdev_dequeue_burst
5884545bd00SOphir Munk 							(dev_id,
5896b99ba8dSOphir Munk 							qp_id_base + qp_id,
5904545bd00SOphir Munk 							cur_ops_to_dequeue,
5914545bd00SOphir Munk 							qp->total_enqueue -
5924545bd00SOphir Munk 							qp->total_dequeue);
593e5e518edSOphir Munk 					qp->cycles +=
594e5e518edSOphir Munk 					     (rte_rdtsc_precise() - qp->start);
5954545bd00SOphir Munk 					update = true;
5964545bd00SOphir Munk 				}
5974545bd00SOphir Munk 			}
5984545bd00SOphir Munk 		} while (update);
599de06137cSYuval Avnery 	}
6006e3c6bd6SOphir Munk 	for (qp_id = 0; qp_id < nb_qps; qp_id++) {
6016e3c6bd6SOphir Munk 		qp = &qps[qp_id];
602e5e518edSOphir Munk 		time = (long double)qp->cycles / rte_get_timer_hz();
603c1d1b94eSGerry Gribbon 		printf("Core=%u QP=%u Job=%ld Bytes Last Job=%ld Bytes Time=%Lf sec Perf=%Lf "
604e5e518edSOphir Munk 		       "Gbps\n", rte_lcore_id(), qp_id + qp_id_base,
605c1d1b94eSGerry Gribbon 		       job_len, act_job_len, time,
606c1d1b94eSGerry Gribbon 		       (((double)data_len * nb_iterations * 8)
607e5e518edSOphir Munk 		       / time) / 1000000000.0);
6086e3c6bd6SOphir Munk 	}
609de06137cSYuval Avnery 
6106b99ba8dSOphir Munk 	if (rgxc->perf_mode)
6114545bd00SOphir Munk 		goto end;
6124545bd00SOphir Munk 	for (qp_id = 0; qp_id < nb_qps; qp_id++) {
6136e3c6bd6SOphir Munk 		printf("\n############ Core=%u QP=%u ############\n",
6146e3c6bd6SOphir Munk 		       rte_lcore_id(), qp_id + qp_id_base);
6154545bd00SOphir Munk 		qp = &qps[qp_id];
616de06137cSYuval Avnery 		/* Log results per job. */
6174545bd00SOphir Munk 		for (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {
6184545bd00SOphir Munk 			nb_matches = qp->ops[d_ind % actual_jobs]->nb_matches;
619392ac62bSGerry Gribbon 			rsp_flags = qp->ops[d_ind % actual_jobs]->rsp_flags;
620392ac62bSGerry Gribbon 			printf("Job id %"PRIu64" number of matches = %d, rsp flags = 0x%x\n",
621392ac62bSGerry Gribbon 					qp->ops[d_ind]->user_id, nb_matches, rsp_flags);
6224545bd00SOphir Munk 			qp->total_matches += nb_matches;
6234545bd00SOphir Munk 			match = qp->ops[d_ind % actual_jobs]->matches;
624de06137cSYuval Avnery 			for (i = 0; i < nb_matches; i++) {
6254545bd00SOphir Munk 				printf("match %d, rule = %d, "
6264545bd00SOphir Munk 				       "start = %d,len = %d\n",
627de06137cSYuval Avnery 				       i, match->rule_id, match->start_offset,
628de06137cSYuval Avnery 				       match->len);
629de06137cSYuval Avnery 				match++;
630de06137cSYuval Avnery 			}
631de06137cSYuval Avnery 		}
6324545bd00SOphir Munk 		printf("Total matches = %d\n", qp->total_matches);
633de06137cSYuval Avnery 		printf("All Matches:\n");
634de06137cSYuval Avnery 		/* Log absolute results. */
6354545bd00SOphir Munk 		for (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {
6364545bd00SOphir Munk 			nb_matches = qp->ops[d_ind % actual_jobs]->nb_matches;
6374545bd00SOphir Munk 			qp->total_matches += nb_matches;
6384545bd00SOphir Munk 			match = qp->ops[d_ind % actual_jobs]->matches;
639de06137cSYuval Avnery 			for (i = 0; i < nb_matches; i++) {
640c1d1b94eSGerry Gribbon 				printf("start = %d, len = %d, rule = %d\n",
6414545bd00SOphir Munk 					match->start_offset +
642c1d1b94eSGerry Gribbon 					(int)(qp->ops[d_ind % actual_jobs]->user_id * job_len),
643de06137cSYuval Avnery 					match->len, match->rule_id);
644de06137cSYuval Avnery 				match++;
645de06137cSYuval Avnery 			}
646de06137cSYuval Avnery 		}
647de06137cSYuval Avnery 	}
648de06137cSYuval Avnery end:
6494545bd00SOphir Munk 	for (qp_id = 0; qp_id < qps_used; qp_id++) {
6504545bd00SOphir Munk 		qp = &qps[qp_id];
6514545bd00SOphir Munk 		for (i = 0; i < actual_jobs && qp->ops; i++)
6524545bd00SOphir Munk 			rte_free(qp->ops[i]);
6534545bd00SOphir Munk 		rte_free(qp->ops);
6544545bd00SOphir Munk 		qp->ops = NULL;
6554545bd00SOphir Munk 		for (i = 0; i < actual_jobs && qp->jobs_ctx; i++)
6564545bd00SOphir Munk 			rte_pktmbuf_free(qp->jobs_ctx[i].mbuf);
6574545bd00SOphir Munk 		rte_free(qp->jobs_ctx);
6584545bd00SOphir Munk 		qp->jobs_ctx = NULL;
6594545bd00SOphir Munk 		rte_free(qp->buf);
6604545bd00SOphir Munk 		qp->buf = NULL;
661de06137cSYuval Avnery 	}
6622d1fb3f2SOphir Munk 	rte_mempool_free(mbuf_mp);
6634545bd00SOphir Munk 	rte_free(qps);
664de06137cSYuval Avnery 	return res;
665de06137cSYuval Avnery }
666de06137cSYuval Avnery 
6676b99ba8dSOphir Munk static int
distribute_qps_to_lcores(uint32_t nb_cores,uint32_t nb_qps,struct qps_per_lcore ** qpl)6686b99ba8dSOphir Munk distribute_qps_to_lcores(uint32_t nb_cores, uint32_t nb_qps,
6696b99ba8dSOphir Munk 			 struct qps_per_lcore **qpl)
6706b99ba8dSOphir Munk {
6716b99ba8dSOphir Munk 	int socket;
6726b99ba8dSOphir Munk 	unsigned lcore_id;
6736b99ba8dSOphir Munk 	uint32_t i;
6746b99ba8dSOphir Munk 	uint16_t min_qp_id;
6756b99ba8dSOphir Munk 	uint16_t max_qp_id;
6766b99ba8dSOphir Munk 	struct qps_per_lcore *qps_per_lcore;
6776b99ba8dSOphir Munk 	uint32_t detected_lcores;
6786b99ba8dSOphir Munk 
6796b99ba8dSOphir Munk 	if (nb_qps < nb_cores) {
6806b99ba8dSOphir Munk 		nb_cores = nb_qps;
6816b99ba8dSOphir Munk 		printf("Reducing number of cores to number of QPs (%u)\n",
6826b99ba8dSOphir Munk 		       nb_cores);
6836b99ba8dSOphir Munk 	}
6846b99ba8dSOphir Munk 	/* Allocate qps_per_lcore array */
6856b99ba8dSOphir Munk 	qps_per_lcore =
6866b99ba8dSOphir Munk 		rte_malloc(NULL, sizeof(*qps_per_lcore) * nb_cores, 0);
6876b99ba8dSOphir Munk 	if (!qps_per_lcore)
6886b99ba8dSOphir Munk 		rte_exit(EXIT_FAILURE, "Failed to create qps_per_lcore array\n");
6896b99ba8dSOphir Munk 	*qpl = qps_per_lcore;
6906b99ba8dSOphir Munk 	detected_lcores = 0;
6916b99ba8dSOphir Munk 	min_qp_id = 0;
6926b99ba8dSOphir Munk 
6936b99ba8dSOphir Munk 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
6946b99ba8dSOphir Munk 		if (detected_lcores >= nb_cores)
6956b99ba8dSOphir Munk 			break;
6966b99ba8dSOphir Munk 		qps_per_lcore[detected_lcores].lcore_id = lcore_id;
6976b99ba8dSOphir Munk 		socket = rte_lcore_to_socket_id(lcore_id);
6986b99ba8dSOphir Munk 		if (socket == SOCKET_ID_ANY)
6996b99ba8dSOphir Munk 			socket = 0;
7006b99ba8dSOphir Munk 		qps_per_lcore[detected_lcores].socket = socket;
7016b99ba8dSOphir Munk 		qps_per_lcore[detected_lcores].qp_id_base = min_qp_id;
7026b99ba8dSOphir Munk 		max_qp_id = min_qp_id + nb_qps / nb_cores - 1;
7036b99ba8dSOphir Munk 		if (nb_qps % nb_cores > detected_lcores)
7046b99ba8dSOphir Munk 			max_qp_id++;
7056b99ba8dSOphir Munk 		qps_per_lcore[detected_lcores].nb_qps = max_qp_id -
7066b99ba8dSOphir Munk 							min_qp_id + 1;
7076b99ba8dSOphir Munk 		min_qp_id = max_qp_id + 1;
7086b99ba8dSOphir Munk 		detected_lcores++;
7096b99ba8dSOphir Munk 	}
7106b99ba8dSOphir Munk 	if (detected_lcores != nb_cores)
7116b99ba8dSOphir Munk 		return -1;
7126b99ba8dSOphir Munk 
7136b99ba8dSOphir Munk 	for (i = 0; i < detected_lcores; i++) {
7146b99ba8dSOphir Munk 		printf("===> Core %d: allocated queues: ",
7156b99ba8dSOphir Munk 		       qps_per_lcore[i].lcore_id);
7166b99ba8dSOphir Munk 		min_qp_id = qps_per_lcore[i].qp_id_base;
7176b99ba8dSOphir Munk 		max_qp_id =
7186b99ba8dSOphir Munk 			qps_per_lcore[i].qp_id_base + qps_per_lcore[i].nb_qps;
7196b99ba8dSOphir Munk 		while (min_qp_id < max_qp_id) {
7206b99ba8dSOphir Munk 			printf("%u ", min_qp_id);
7216b99ba8dSOphir Munk 			min_qp_id++;
7226b99ba8dSOphir Munk 		}
7236b99ba8dSOphir Munk 		printf("\n");
7246b99ba8dSOphir Munk 	}
7256b99ba8dSOphir Munk 	return 0;
7266b99ba8dSOphir Munk }
7276b99ba8dSOphir Munk 
728de06137cSYuval Avnery int
main(int argc,char ** argv)729de06137cSYuval Avnery main(int argc, char **argv)
730de06137cSYuval Avnery {
731de06137cSYuval Avnery 	char rules_file[MAX_FILE_NAME];
732de06137cSYuval Avnery 	char data_file[MAX_FILE_NAME];
733de06137cSYuval Avnery 	uint32_t nb_jobs = 0;
734de06137cSYuval Avnery 	bool perf_mode = 0;
735de06137cSYuval Avnery 	uint32_t nb_iterations = 0;
736de06137cSYuval Avnery 	int ret;
7374545bd00SOphir Munk 	uint16_t nb_max_payload = 0;
7384545bd00SOphir Munk 	uint8_t nb_max_matches = 0;
7394545bd00SOphir Munk 	uint32_t nb_qps = 1;
740f5cffb7eSOphir Munk 	char *data_buf;
741f5cffb7eSOphir Munk 	long data_len;
742f5cffb7eSOphir Munk 	long job_len;
743cace2d7eSSuanming Mou 	uint32_t nb_lcores = 1, nb_segs = 1;
744*b6aceadaSGerry Gribbon 	uint32_t match_mode = 0;
7456b99ba8dSOphir Munk 	struct regex_conf *rgxc;
7466b99ba8dSOphir Munk 	uint32_t i;
7476b99ba8dSOphir Munk 	struct qps_per_lcore *qps_per_lcore;
748de06137cSYuval Avnery 
7494545bd00SOphir Munk 	/* Init EAL. */
750de06137cSYuval Avnery 	ret = rte_eal_init(argc, argv);
751de06137cSYuval Avnery 	if (ret < 0)
752de06137cSYuval Avnery 		rte_exit(EXIT_FAILURE, "EAL init failed\n");
753de06137cSYuval Avnery 	argc -= ret;
754de06137cSYuval Avnery 	argv += ret;
755de06137cSYuval Avnery 	if (argc > 1)
756de06137cSYuval Avnery 		args_parse(argc, argv, rules_file, data_file, &nb_jobs,
7576b99ba8dSOphir Munk 				&perf_mode, &nb_iterations, &nb_qps,
758*b6aceadaSGerry Gribbon 				&nb_lcores, &nb_segs, &match_mode);
759de06137cSYuval Avnery 
7604545bd00SOphir Munk 	if (nb_qps == 0)
7614545bd00SOphir Munk 		rte_exit(EXIT_FAILURE, "Number of QPs must be greater than 0\n");
7626b99ba8dSOphir Munk 	if (nb_lcores == 0)
7636b99ba8dSOphir Munk 		rte_exit(EXIT_FAILURE, "Number of lcores must be greater than 0\n");
7641afdf9edSThierry Herbelot 	if (nb_jobs == 0)
7651afdf9edSThierry Herbelot 		rte_exit(EXIT_FAILURE, "Number of jobs must be greater than 0\n");
7666b99ba8dSOphir Munk 	if (distribute_qps_to_lcores(nb_lcores, nb_qps, &qps_per_lcore) < 0)
7676b99ba8dSOphir Munk 		rte_exit(EXIT_FAILURE, "Failed to distribute queues to lcores!\n");
7684545bd00SOphir Munk 	ret = init_port(&nb_max_payload, rules_file,
7694545bd00SOphir Munk 			&nb_max_matches, nb_qps);
770de06137cSYuval Avnery 	if (ret < 0)
771de06137cSYuval Avnery 		rte_exit(EXIT_FAILURE, "init port failed\n");
772f5cffb7eSOphir Munk 
773f5cffb7eSOphir Munk 	data_len = read_file(data_file, &data_buf);
774f5cffb7eSOphir Munk 	if (data_len <= 0)
775f5cffb7eSOphir Munk 		rte_exit(EXIT_FAILURE, "Error, can't read file, or file is empty.\n");
776f5cffb7eSOphir Munk 
777f5cffb7eSOphir Munk 	job_len = data_len / nb_jobs;
778f5cffb7eSOphir Munk 	if (job_len == 0)
779f5cffb7eSOphir Munk 		rte_exit(EXIT_FAILURE, "Error, To many jobs, for the given input.\n");
780f5cffb7eSOphir Munk 
781f5cffb7eSOphir Munk 	if (job_len > nb_max_payload)
782f5cffb7eSOphir Munk 		rte_exit(EXIT_FAILURE, "Error, not enough jobs to cover input.\n");
783f5cffb7eSOphir Munk 
7846b99ba8dSOphir Munk 	rgxc = rte_malloc(NULL, sizeof(*rgxc) * nb_lcores, 0);
7856b99ba8dSOphir Munk 	if (!rgxc)
7866b99ba8dSOphir Munk 		rte_exit(EXIT_FAILURE, "Failed to create Regex Conf\n");
7876b99ba8dSOphir Munk 	for (i = 0; i < nb_lcores; i++) {
7886b99ba8dSOphir Munk 		rgxc[i] = (struct regex_conf){
7896b99ba8dSOphir Munk 			.nb_jobs = nb_jobs,
790cace2d7eSSuanming Mou 			.nb_segs = nb_segs,
7916b99ba8dSOphir Munk 			.perf_mode = perf_mode,
7926b99ba8dSOphir Munk 			.nb_iterations = nb_iterations,
7936b99ba8dSOphir Munk 			.nb_max_matches = nb_max_matches,
7946b99ba8dSOphir Munk 			.nb_qps = qps_per_lcore[i].nb_qps,
7956b99ba8dSOphir Munk 			.qp_id_base = qps_per_lcore[i].qp_id_base,
7966b99ba8dSOphir Munk 			.data_buf = data_buf,
7976b99ba8dSOphir Munk 			.data_len = data_len,
7986b99ba8dSOphir Munk 			.job_len = job_len,
799*b6aceadaSGerry Gribbon 			.match_mode = match_mode,
8006b99ba8dSOphir Munk 		};
8016b99ba8dSOphir Munk 		rte_eal_remote_launch(run_regex, &rgxc[i],
8026b99ba8dSOphir Munk 				      qps_per_lcore[i].lcore_id);
803de06137cSYuval Avnery 	}
8046b99ba8dSOphir Munk 	rte_eal_mp_wait_lcore();
805f5cffb7eSOphir Munk 	rte_free(data_buf);
8066b99ba8dSOphir Munk 	rte_free(rgxc);
8076b99ba8dSOphir Munk 	rte_free(qps_per_lcore);
808de06137cSYuval Avnery 	return EXIT_SUCCESS;
809de06137cSYuval Avnery }
810