Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2020 Mellanox Technologies, Ltd
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : : #include <stdint.h>
9 : : #include <stdbool.h>
10 : : #include <stdarg.h>
11 : : #include <ctype.h>
12 : : #include <errno.h>
13 : : #include <getopt.h>
14 : : #include <signal.h>
15 : :
16 : : #include <rte_eal.h>
17 : : #include <rte_common.h>
18 : : #include <rte_malloc.h>
19 : : #include <rte_mempool.h>
20 : : #include <rte_mbuf.h>
21 : : #include <rte_cycles.h>
22 : : #include <rte_regexdev.h>
23 : :
24 : : #define MAX_FILE_NAME 255
25 : : #define MBUF_CACHE_SIZE 256
26 : : #define MBUF_SIZE (1 << 8)
27 : : #define START_BURST_SIZE 32u
28 : : #define MAX_MATCH_MODE 2
29 : :
30 : : enum app_args {
31 : : ARG_HELP,
32 : : ARG_RULES_FILE_NAME,
33 : : ARG_DATA_FILE_NAME,
34 : : ARG_NUM_OF_JOBS,
35 : : ARG_PERF_MODE,
36 : : ARG_NUM_OF_ITERATIONS,
37 : : ARG_NUM_OF_QPS,
38 : : ARG_NUM_OF_LCORES,
39 : : ARG_NUM_OF_MBUF_SEGS,
40 : : ARG_NUM_OF_MATCH_MODE,
41 : : };
42 : :
43 : : struct job_ctx {
44 : : struct rte_mbuf *mbuf;
45 : : };
46 : :
47 : : struct qp_params {
48 : : uint32_t total_enqueue;
49 : : uint32_t total_dequeue;
50 : : uint32_t total_matches;
51 : : struct rte_regex_ops **ops;
52 : : struct job_ctx *jobs_ctx;
53 : : char *buf;
54 : : uint64_t start;
55 : : uint64_t cycles;
56 : : };
57 : :
58 : : struct qps_per_lcore {
59 : : unsigned int lcore_id;
60 : : int socket;
61 : : uint16_t qp_id_base;
62 : : uint16_t nb_qps;
63 : : };
64 : :
65 : : struct regex_conf {
66 : : uint32_t nb_jobs;
67 : : bool perf_mode;
68 : : uint32_t nb_iterations;
69 : : char *data_file;
70 : : uint8_t nb_max_matches;
71 : : uint32_t nb_qps;
72 : : uint16_t qp_id_base;
73 : : char *data_buf;
74 : : long data_len;
75 : : long job_len;
76 : : uint32_t nb_segs;
77 : : uint32_t match_mode;
78 : : };
79 : :
80 : : static void
81 : : usage(const char *prog_name)
82 : : {
83 : : printf("%s [EAL options] --\n"
84 : : " --rules NAME: precompiled rules file\n"
85 : : " --data NAME: data file to use\n"
86 : : " --nb_jobs: number of jobs to use\n"
87 : : " --perf N: only outputs the performance data\n"
88 : : " --nb_iter N: number of iteration to run\n"
89 : : " --nb_qps N: number of queues to use\n"
90 : : " --nb_lcores N: number of lcores to use\n"
91 : : " --nb_segs N: number of mbuf segments\n"
92 : : " --match_mode N: match mode: 0 - None (default),"
93 : : " 1 - Highest Priority, 2 - Stop On Any\n",
94 : : prog_name);
95 : 0 : }
96 : :
97 : : static void
98 : 0 : args_parse(int argc, char **argv, char *rules_file, char *data_file,
99 : : uint32_t *nb_jobs, bool *perf_mode, uint32_t *nb_iterations,
100 : : uint32_t *nb_qps, uint32_t *nb_lcores, uint32_t *nb_segs,
101 : : uint32_t *match_mode)
102 : : {
103 : : char **argvopt;
104 : : int opt;
105 : : int opt_idx;
106 : : size_t len;
107 : : static struct option lgopts[] = {
108 : : { "help", 0, 0, ARG_HELP},
109 : : /* Rules database file to load. */
110 : : { "rules", 1, 0, ARG_RULES_FILE_NAME},
111 : : /* Data file to load. */
112 : : { "data", 1, 0, ARG_DATA_FILE_NAME},
113 : : /* Number of jobs to create. */
114 : : { "nb_jobs", 1, 0, ARG_NUM_OF_JOBS},
115 : : /* Perf test only */
116 : : { "perf", 0, 0, ARG_PERF_MODE},
117 : : /* Number of iterations to run with perf test */
118 : : { "nb_iter", 1, 0, ARG_NUM_OF_ITERATIONS},
119 : : /* Number of QPs. */
120 : : { "nb_qps", 1, 0, ARG_NUM_OF_QPS},
121 : : /* Number of lcores. */
122 : : { "nb_lcores", 1, 0, ARG_NUM_OF_LCORES},
123 : : /* Number of mbuf segments. */
124 : : { "nb_segs", 1, 0, ARG_NUM_OF_MBUF_SEGS},
125 : : /* Match mode. */
126 : : { "match_mode", 1, 0, ARG_NUM_OF_MATCH_MODE},
127 : : /* End of options */
128 : : { 0, 0, 0, 0 }
129 : : };
130 : :
131 : : argvopt = argv;
132 : 0 : while ((opt = getopt_long(argc, argvopt, "",
133 : 0 : lgopts, &opt_idx)) != EOF) {
134 : 0 : switch (opt) {
135 : 0 : case ARG_RULES_FILE_NAME:
136 : 0 : len = strnlen(optarg, MAX_FILE_NAME - 1);
137 : 0 : if (len == MAX_FILE_NAME)
138 : 0 : rte_exit(EXIT_FAILURE,
139 : : "Rule file name to long max %d\n",
140 : : MAX_FILE_NAME - 1);
141 : : strncpy(rules_file, optarg, MAX_FILE_NAME - 1);
142 : : break;
143 : 0 : case ARG_DATA_FILE_NAME:
144 : 0 : len = strnlen(optarg, MAX_FILE_NAME - 1);
145 : 0 : if (len == MAX_FILE_NAME)
146 : 0 : rte_exit(EXIT_FAILURE,
147 : : "Data file name to long max %d\n",
148 : : MAX_FILE_NAME - 1);
149 : : strncpy(data_file, optarg, MAX_FILE_NAME - 1);
150 : : break;
151 : 0 : case ARG_NUM_OF_JOBS:
152 : 0 : *nb_jobs = atoi(optarg);
153 : 0 : break;
154 : 0 : case ARG_PERF_MODE:
155 : 0 : *perf_mode = true;
156 : 0 : break;
157 : 0 : case ARG_NUM_OF_ITERATIONS:
158 : 0 : *nb_iterations = atoi(optarg);
159 : 0 : break;
160 : 0 : case ARG_NUM_OF_QPS:
161 : 0 : *nb_qps = atoi(optarg);
162 : 0 : break;
163 : 0 : case ARG_NUM_OF_LCORES:
164 : 0 : *nb_lcores = atoi(optarg);
165 : 0 : break;
166 : 0 : case ARG_NUM_OF_MBUF_SEGS:
167 : 0 : *nb_segs = atoi(optarg);
168 : 0 : break;
169 : 0 : case ARG_NUM_OF_MATCH_MODE:
170 : 0 : *match_mode = atoi(optarg);
171 : 0 : if (*match_mode > MAX_MATCH_MODE)
172 : 0 : rte_exit(EXIT_FAILURE,
173 : : "Invalid match mode value\n");
174 : : break;
175 : 0 : case ARG_HELP:
176 : 0 : usage(argv[0]);
177 : : break;
178 : 0 : default:
179 : 0 : usage(argv[0]);
180 : 0 : rte_exit(EXIT_FAILURE, "Invalid option: %s\n", argv[optind]);
181 : : break;
182 : : }
183 : : }
184 : :
185 : 0 : if (!perf_mode)
186 : 0 : *nb_iterations = 1;
187 : 0 : }
188 : :
189 : : static long
190 : 0 : read_file(char *file, char **buf)
191 : : {
192 : : FILE *fp;
193 : : long buf_len = 0;
194 : : size_t read_len;
195 : : int res = 0;
196 : :
197 : 0 : fp = fopen(file, "r");
198 : 0 : if (!fp)
199 : : return -EIO;
200 : 0 : if (fseek(fp, 0L, SEEK_END) == 0) {
201 : 0 : buf_len = ftell(fp);
202 : 0 : if (buf_len == -1) {
203 : : res = EIO;
204 : 0 : goto error;
205 : : }
206 : 0 : *buf = rte_malloc(NULL, sizeof(char) * (buf_len + 1), 4096);
207 : 0 : if (!*buf) {
208 : : res = ENOMEM;
209 : 0 : goto error;
210 : : }
211 : 0 : if (fseek(fp, 0L, SEEK_SET) != 0) {
212 : : res = EIO;
213 : 0 : goto error;
214 : : }
215 : 0 : read_len = fread(*buf, sizeof(char), buf_len, fp);
216 : 0 : if (read_len != (unsigned long)buf_len) {
217 : : res = EIO;
218 : 0 : goto error;
219 : : }
220 : : }
221 : 0 : fclose(fp);
222 : 0 : return buf_len;
223 : 0 : error:
224 : : printf("Error, can't open file %s\n, err = %d", file, res);
225 : : if (fp)
226 : 0 : fclose(fp);
227 : 0 : rte_free(*buf);
228 : 0 : return -res;
229 : : }
230 : :
231 : : static int
232 : 0 : clone_buf(char *data_buf, char **buf, long data_len)
233 : : {
234 : : char *dest_buf;
235 : : dest_buf =
236 : 0 : rte_malloc(NULL, sizeof(char) * (data_len + 1), 4096);
237 : 0 : if (!dest_buf)
238 : : return -ENOMEM;
239 : : memcpy(dest_buf, data_buf, data_len + 1);
240 : 0 : *buf = dest_buf;
241 : 0 : return 0;
242 : : }
243 : :
244 : : static int
245 : 0 : init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches,
246 : : uint32_t nb_qps)
247 : : {
248 : : uint16_t id;
249 : : uint16_t qp_id;
250 : : uint16_t num_devs;
251 : 0 : char *rules = NULL;
252 : : long rules_len;
253 : : struct rte_regexdev_info info;
254 : 0 : struct rte_regexdev_config dev_conf = {
255 : : .nb_queue_pairs = nb_qps,
256 : : .nb_groups = 1,
257 : : };
258 : 0 : struct rte_regexdev_qp_conf qp_conf = {
259 : : .nb_desc = 1024,
260 : : .qp_conf_flags = 0,
261 : : };
262 : : int res = 0;
263 : :
264 : 0 : num_devs = rte_regexdev_count();
265 : 0 : if (num_devs == 0) {
266 : : printf("Error, no devices detected.\n");
267 : 0 : return -EINVAL;
268 : : }
269 : :
270 : 0 : rules_len = read_file(rules_file, &rules);
271 : 0 : if (rules_len < 0) {
272 : : printf("Error, can't read rules files.\n");
273 : : res = -EIO;
274 : 0 : goto error;
275 : : }
276 : :
277 : 0 : for (id = 0; id < num_devs; id++) {
278 : 0 : res = rte_regexdev_info_get(id, &info);
279 : 0 : if (res != 0) {
280 : : printf("Error, can't get device info.\n");
281 : 0 : goto error;
282 : : }
283 : 0 : printf(":: initializing dev: %d\n", id);
284 : 0 : *nb_max_matches = info.max_matches;
285 : 0 : *nb_max_payload = info.max_payload_size;
286 : 0 : if (info.regexdev_capa & RTE_REGEXDEV_SUPP_MATCH_AS_END_F)
287 : 0 : dev_conf.dev_cfg_flags |=
288 : : RTE_REGEXDEV_CFG_MATCH_AS_END_F;
289 : 0 : dev_conf.nb_max_matches = info.max_matches;
290 : 0 : dev_conf.nb_rules_per_group = info.max_rules_per_group;
291 : 0 : dev_conf.rule_db_len = rules_len;
292 : 0 : dev_conf.rule_db = rules;
293 : 0 : res = rte_regexdev_configure(id, &dev_conf);
294 : 0 : if (res < 0) {
295 : : printf("Error, can't configure device %d.\n", id);
296 : 0 : goto error;
297 : : }
298 : 0 : if (info.regexdev_capa & RTE_REGEXDEV_CAPA_QUEUE_PAIR_OOS_F)
299 : 0 : qp_conf.qp_conf_flags |=
300 : : RTE_REGEX_QUEUE_PAIR_CFG_OOS_F;
301 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
302 : 0 : res = rte_regexdev_queue_pair_setup(id, qp_id,
303 : : &qp_conf);
304 : 0 : if (res < 0) {
305 : : printf("Error, can't setup queue pair %u for "
306 : : "device %d.\n", qp_id, id);
307 : 0 : goto error;
308 : : }
309 : : }
310 : : printf(":: initializing device: %d done\n", id);
311 : : }
312 : 0 : rte_free(rules);
313 : 0 : return 0;
314 : 0 : error:
315 : 0 : rte_free(rules);
316 : 0 : return res;
317 : : }
318 : :
319 : : static void
320 : 0 : extbuf_free_cb(void *addr __rte_unused, void *fcb_opaque __rte_unused)
321 : : {
322 : 0 : }
323 : :
324 : : static inline struct rte_mbuf *
325 : 0 : regex_create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
326 : : int nb_segs, void *buf) {
327 : :
328 : : struct rte_mbuf *m = NULL, *mbuf = NULL;
329 : : uint8_t *dst;
330 : : char *src = buf;
331 : : int data_len = 0;
332 : : int i, size;
333 : : int t_len;
334 : :
335 : 0 : if (pkt_len < 1) {
336 : : printf("Packet size must be 1 or more (is %d)\n", pkt_len);
337 : 0 : return NULL;
338 : : }
339 : :
340 : 0 : if (nb_segs < 1) {
341 : : printf("Number of segments must be 1 or more (is %d)\n",
342 : : nb_segs);
343 : 0 : return NULL;
344 : : }
345 : :
346 : 0 : t_len = pkt_len >= nb_segs ? (pkt_len / nb_segs +
347 : 0 : !!(pkt_len % nb_segs)) : 1;
348 : : size = pkt_len;
349 : :
350 : : /* Create chained mbuf_src and fill it with buf data */
351 : 0 : for (i = 0; size > 0; i++) {
352 : :
353 : 0 : m = rte_pktmbuf_alloc(mbuf_pool);
354 : 0 : if (i == 0)
355 : : mbuf = m;
356 : :
357 : 0 : if (m == NULL) {
358 : : printf("Cannot create segment for source mbuf");
359 : 0 : goto fail;
360 : : }
361 : :
362 : 0 : data_len = size > t_len ? t_len : size;
363 : 0 : memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
364 : : rte_pktmbuf_tailroom(m));
365 : 0 : memcpy(rte_pktmbuf_mtod(m, uint8_t *), src, data_len);
366 : 0 : dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
367 : 0 : if (dst == NULL) {
368 : : printf("Cannot append %d bytes to the mbuf\n",
369 : : data_len);
370 : 0 : goto fail;
371 : : }
372 : :
373 : 0 : if (mbuf != m)
374 : : rte_pktmbuf_chain(mbuf, m);
375 : 0 : src += data_len;
376 : 0 : size -= data_len;
377 : :
378 : : }
379 : : return mbuf;
380 : :
381 : 0 : fail:
382 : 0 : rte_pktmbuf_free(mbuf);
383 : 0 : return NULL;
384 : : }
385 : :
386 : : static int
387 : 0 : run_regex(void *args)
388 : : {
389 : : struct regex_conf *rgxc = args;
390 : 0 : uint32_t nb_jobs = rgxc->nb_jobs;
391 : 0 : uint32_t nb_segs = rgxc->nb_segs;
392 : 0 : uint32_t nb_iterations = rgxc->nb_iterations;
393 : 0 : uint8_t nb_max_matches = rgxc->nb_max_matches;
394 : 0 : uint32_t nb_qps = rgxc->nb_qps;
395 : 0 : uint16_t qp_id_base = rgxc->qp_id_base;
396 : 0 : char *data_buf = rgxc->data_buf;
397 : 0 : long data_len = rgxc->data_len;
398 : 0 : long job_len = rgxc->job_len;
399 : 0 : uint32_t match_mode = rgxc->match_mode;
400 : : long remainder;
401 : : long act_job_len = 0;
402 : : bool last_job = false;
403 : 0 : char *buf = NULL;
404 : : uint32_t actual_jobs = 0;
405 : : uint32_t i;
406 : : uint32_t job_id;
407 : : uint16_t qp_id;
408 : : uint16_t dev_id = 0;
409 : : uint8_t nb_matches;
410 : : uint16_t rsp_flags = 0;
411 : : struct rte_regexdev_match *match;
412 : : long pos;
413 : : unsigned long d_ind = 0;
414 : : struct rte_mbuf_ext_shared_info shinfo;
415 : : int res = 0;
416 : : long double time;
417 : : struct rte_mempool *mbuf_mp;
418 : : struct qp_params *qp;
419 : : struct qp_params *qps = NULL;
420 : : bool update;
421 : : uint16_t qps_used = 0;
422 : : char mbuf_pool[16];
423 : :
424 : 0 : shinfo.free_cb = extbuf_free_cb;
425 : 0 : snprintf(mbuf_pool,
426 : : sizeof(mbuf_pool),
427 : : "mbuf_pool_%2u", qp_id_base);
428 : 0 : mbuf_mp = rte_pktmbuf_pool_create(mbuf_pool,
429 : 0 : rte_align32pow2(nb_jobs * nb_qps * nb_segs),
430 : : 0, 0, (nb_segs == 1) ? MBUF_SIZE :
431 : 0 : (rte_align32pow2(job_len + (data_len % nb_jobs)) /
432 : 0 : nb_segs + RTE_PKTMBUF_HEADROOM),
433 : 0 : rte_socket_id());
434 : 0 : if (mbuf_mp == NULL) {
435 : : printf("Error, can't create memory pool\n");
436 : 0 : return -ENOMEM;
437 : : }
438 : :
439 : 0 : qps = rte_malloc(NULL, sizeof(*qps) * nb_qps, 0);
440 : 0 : if (!qps) {
441 : : printf("Error, can't allocate memory for QPs\n");
442 : : res = -ENOMEM;
443 : 0 : goto end;
444 : : }
445 : :
446 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
447 : : struct rte_regex_ops **ops;
448 : : struct job_ctx *jobs_ctx;
449 : :
450 : 0 : qps_used++;
451 : 0 : qp = &qps[qp_id];
452 : 0 : qp->jobs_ctx = NULL;
453 : 0 : qp->buf = NULL;
454 : 0 : qp->ops = ops = rte_malloc(NULL, sizeof(*ops) * nb_jobs, 0);
455 : 0 : if (!ops) {
456 : : printf("Error, can't allocate memory for ops.\n");
457 : : res = -ENOMEM;
458 : 0 : goto end;
459 : : }
460 : :
461 : 0 : qp->jobs_ctx = jobs_ctx =
462 : 0 : rte_malloc(NULL, sizeof(*jobs_ctx) * nb_jobs, 0);
463 : 0 : if (!jobs_ctx) {
464 : : printf("Error, can't allocate memory for jobs_ctx.\n");
465 : : res = -ENOMEM;
466 : 0 : goto end;
467 : : }
468 : :
469 : 0 : if (clone_buf(data_buf, &buf, data_len)) {
470 : : printf("Error, can't clone buf.\n");
471 : : res = -EXIT_FAILURE;
472 : 0 : goto end;
473 : : }
474 : :
475 : : /* Assign each mbuf with the data to handle. */
476 : : actual_jobs = 0;
477 : : pos = 0;
478 : 0 : remainder = data_len % nb_jobs;
479 : :
480 : : /* Allocate the jobs and assign each job with an mbuf. */
481 : 0 : for (i = 0; (pos < data_len) && (i < nb_jobs) ; i++) {
482 : 0 : act_job_len = RTE_MIN(job_len, data_len - pos);
483 : :
484 : 0 : if (i == (nb_jobs - 1)) {
485 : : last_job = true;
486 : 0 : act_job_len += remainder;
487 : : }
488 : :
489 : 0 : ops[i] = rte_malloc(NULL, sizeof(*ops[0]) +
490 : : nb_max_matches *
491 : : sizeof(struct rte_regexdev_match), 0);
492 : 0 : if (!ops[i]) {
493 : : printf("Error, can't allocate "
494 : : "memory for op.\n");
495 : : res = -ENOMEM;
496 : 0 : goto end;
497 : : }
498 : 0 : if (nb_segs > 1) {
499 : 0 : ops[i]->mbuf = regex_create_segmented_mbuf
500 : : (mbuf_mp, act_job_len,
501 : 0 : nb_segs, &buf[pos]);
502 : : } else {
503 : 0 : ops[i]->mbuf = rte_pktmbuf_alloc(mbuf_mp);
504 : 0 : if (ops[i]->mbuf) {
505 : 0 : rte_pktmbuf_attach_extbuf(ops[i]->mbuf,
506 : 0 : &buf[pos], 0, act_job_len, &shinfo);
507 : :
508 : 0 : if (!last_job)
509 : 0 : ops[i]->mbuf->data_len = job_len;
510 : : else
511 : 0 : ops[i]->mbuf->data_len = act_job_len;
512 : :
513 : 0 : ops[i]->mbuf->pkt_len = act_job_len;
514 : : }
515 : : }
516 : 0 : if (!ops[i]->mbuf) {
517 : : printf("Error, can't add mbuf.\n");
518 : : res = -ENOMEM;
519 : 0 : goto end;
520 : : }
521 : :
522 : 0 : jobs_ctx[i].mbuf = ops[i]->mbuf;
523 : 0 : ops[i]->user_id = i;
524 : 0 : ops[i]->group_id0 = 1;
525 : 0 : switch (match_mode) {
526 : : case 0:
527 : : /* Nothing to set in req_flags */
528 : : break;
529 : 0 : case 1:
530 : 0 : ops[i]->req_flags |= RTE_REGEX_OPS_REQ_MATCH_HIGH_PRIORITY_F;
531 : 0 : break;
532 : 0 : case 2:
533 : 0 : ops[i]->req_flags |= RTE_REGEX_OPS_REQ_STOP_ON_MATCH_F;
534 : 0 : break;
535 : 0 : default:
536 : 0 : rte_exit(EXIT_FAILURE,
537 : : "Invalid match mode value\n");
538 : : break;
539 : : }
540 : 0 : pos += act_job_len;
541 : 0 : actual_jobs++;
542 : : }
543 : :
544 : 0 : qp->buf = buf;
545 : 0 : qp->total_matches = 0;
546 : 0 : qp->start = 0;
547 : 0 : qp->cycles = 0;
548 : : }
549 : :
550 : 0 : for (i = 0; i < nb_iterations; i++) {
551 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
552 : 0 : qp = &qps[qp_id];
553 : 0 : qp->total_enqueue = 0;
554 : 0 : qp->total_dequeue = 0;
555 : : /* Re-set user id after dequeue to match data in mbuf. */
556 : 0 : for (job_id = 0 ; job_id < nb_jobs; job_id++)
557 : 0 : qp->ops[job_id]->user_id = job_id;
558 : : }
559 : : do {
560 : : update = false;
561 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
562 : 0 : qp = &qps[qp_id];
563 : 0 : if (qp->total_dequeue < actual_jobs) {
564 : 0 : qp->start = rte_rdtsc_precise();
565 : : struct rte_regex_ops **
566 : 0 : cur_ops_to_enqueue = qp->ops +
567 : 0 : qp->total_enqueue;
568 : :
569 : 0 : if (actual_jobs - qp->total_enqueue)
570 : 0 : qp->total_enqueue +=
571 : 0 : rte_regexdev_enqueue_burst
572 : : (dev_id,
573 : 0 : qp_id_base + qp_id,
574 : : cur_ops_to_enqueue,
575 : 0 : actual_jobs -
576 : : qp->total_enqueue);
577 : : }
578 : : }
579 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
580 : 0 : qp = &qps[qp_id];
581 : 0 : if (qp->total_dequeue < actual_jobs) {
582 : : struct rte_regex_ops **
583 : 0 : cur_ops_to_dequeue = qp->ops +
584 : 0 : qp->total_dequeue;
585 : :
586 : 0 : qp->total_dequeue +=
587 : 0 : rte_regexdev_dequeue_burst
588 : : (dev_id,
589 : 0 : qp_id_base + qp_id,
590 : : cur_ops_to_dequeue,
591 : 0 : qp->total_enqueue -
592 : : qp->total_dequeue);
593 : 0 : qp->cycles +=
594 : 0 : (rte_rdtsc_precise() - qp->start);
595 : : update = true;
596 : : }
597 : : }
598 : 0 : } while (update);
599 : : }
600 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
601 : 0 : qp = &qps[qp_id];
602 : 0 : time = (long double)qp->cycles / rte_get_timer_hz();
603 : 0 : printf("Core=%u QP=%u Job=%ld Bytes Last Job=%ld Bytes Time=%Lf sec Perf=%Lf "
604 : : "Gbps\n", rte_lcore_id(), qp_id + qp_id_base,
605 : : job_len, act_job_len, time,
606 : 0 : (((double)data_len * nb_iterations * 8)
607 : 0 : / time) / 1000000000.0);
608 : : }
609 : :
610 : 0 : if (rgxc->perf_mode)
611 : 0 : goto end;
612 : 0 : for (qp_id = 0; qp_id < nb_qps; qp_id++) {
613 : 0 : printf("\n############ Core=%u QP=%u ############\n",
614 : : rte_lcore_id(), qp_id + qp_id_base);
615 : 0 : qp = &qps[qp_id];
616 : : /* Log results per job. */
617 : 0 : for (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {
618 : 0 : nb_matches = qp->ops[d_ind % actual_jobs]->nb_matches;
619 : 0 : rsp_flags = qp->ops[d_ind % actual_jobs]->rsp_flags;
620 : 0 : printf("Job id %"PRIu64" number of matches = %d, rsp flags = 0x%x\n",
621 : 0 : qp->ops[d_ind]->user_id, nb_matches, rsp_flags);
622 : 0 : qp->total_matches += nb_matches;
623 : 0 : match = qp->ops[d_ind % actual_jobs]->matches;
624 : 0 : for (i = 0; i < nb_matches; i++) {
625 : 0 : printf("match %d, rule = %d, "
626 : : "start = %d,len = %d\n",
627 : 0 : i, match->rule_id, match->start_offset,
628 : 0 : match->len);
629 : 0 : match++;
630 : : }
631 : : }
632 : 0 : printf("Total matches = %d\n", qp->total_matches);
633 : : printf("All Matches:\n");
634 : : /* Log absolute results. */
635 : 0 : for (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {
636 : 0 : nb_matches = qp->ops[d_ind % actual_jobs]->nb_matches;
637 : 0 : qp->total_matches += nb_matches;
638 : 0 : match = qp->ops[d_ind % actual_jobs]->matches;
639 : 0 : for (i = 0; i < nb_matches; i++) {
640 : 0 : printf("start = %d, len = %d, rule = %d\n",
641 : 0 : match->start_offset +
642 : 0 : (int)(qp->ops[d_ind % actual_jobs]->user_id * job_len),
643 : 0 : match->len, match->rule_id);
644 : 0 : match++;
645 : : }
646 : : }
647 : : }
648 : 0 : end:
649 : 0 : for (qp_id = 0; qp_id < qps_used; qp_id++) {
650 : 0 : qp = &qps[qp_id];
651 : 0 : for (i = 0; i < actual_jobs && qp->ops; i++)
652 : 0 : rte_free(qp->ops[i]);
653 : 0 : rte_free(qp->ops);
654 : 0 : qp->ops = NULL;
655 : 0 : for (i = 0; i < actual_jobs && qp->jobs_ctx; i++)
656 : 0 : rte_pktmbuf_free(qp->jobs_ctx[i].mbuf);
657 : 0 : rte_free(qp->jobs_ctx);
658 : 0 : qp->jobs_ctx = NULL;
659 : 0 : rte_free(qp->buf);
660 : 0 : qp->buf = NULL;
661 : : }
662 : 0 : rte_mempool_free(mbuf_mp);
663 : 0 : rte_free(qps);
664 : 0 : return res;
665 : : }
666 : :
667 : : static int
668 : 0 : distribute_qps_to_lcores(uint32_t nb_cores, uint32_t nb_qps,
669 : : struct qps_per_lcore **qpl)
670 : : {
671 : : int socket;
672 : : unsigned lcore_id;
673 : : uint32_t i;
674 : : uint16_t min_qp_id;
675 : : uint16_t max_qp_id;
676 : : struct qps_per_lcore *qps_per_lcore;
677 : : uint32_t detected_lcores;
678 : :
679 : 0 : if (nb_qps < nb_cores) {
680 : : nb_cores = nb_qps;
681 : : printf("Reducing number of cores to number of QPs (%u)\n",
682 : : nb_cores);
683 : : }
684 : : /* Allocate qps_per_lcore array */
685 : : qps_per_lcore =
686 : 0 : rte_malloc(NULL, sizeof(*qps_per_lcore) * nb_cores, 0);
687 : 0 : if (!qps_per_lcore)
688 : 0 : rte_exit(EXIT_FAILURE, "Failed to create qps_per_lcore array\n");
689 : 0 : *qpl = qps_per_lcore;
690 : : detected_lcores = 0;
691 : : min_qp_id = 0;
692 : :
693 : 0 : RTE_LCORE_FOREACH_WORKER(lcore_id) {
694 : 0 : if (detected_lcores >= nb_cores)
695 : : break;
696 : 0 : qps_per_lcore[detected_lcores].lcore_id = lcore_id;
697 : 0 : socket = rte_lcore_to_socket_id(lcore_id);
698 : 0 : if (socket == SOCKET_ID_ANY)
699 : : socket = 0;
700 : 0 : qps_per_lcore[detected_lcores].socket = socket;
701 : 0 : qps_per_lcore[detected_lcores].qp_id_base = min_qp_id;
702 : 0 : max_qp_id = min_qp_id + nb_qps / nb_cores - 1;
703 : 0 : if (nb_qps % nb_cores > detected_lcores)
704 : : max_qp_id++;
705 : 0 : qps_per_lcore[detected_lcores].nb_qps = max_qp_id -
706 : 0 : min_qp_id + 1;
707 : 0 : min_qp_id = max_qp_id + 1;
708 : 0 : detected_lcores++;
709 : : }
710 : 0 : if (detected_lcores != nb_cores)
711 : : return -1;
712 : :
713 : 0 : for (i = 0; i < detected_lcores; i++) {
714 : 0 : printf("===> Core %d: allocated queues: ",
715 : 0 : qps_per_lcore[i].lcore_id);
716 : 0 : min_qp_id = qps_per_lcore[i].qp_id_base;
717 : 0 : max_qp_id =
718 : 0 : qps_per_lcore[i].qp_id_base + qps_per_lcore[i].nb_qps;
719 : 0 : while (min_qp_id < max_qp_id) {
720 : 0 : printf("%u ", min_qp_id);
721 : 0 : min_qp_id++;
722 : : }
723 : : printf("\n");
724 : : }
725 : : return 0;
726 : : }
727 : :
728 : : int
729 : 0 : main(int argc, char **argv)
730 : : {
731 : : char rules_file[MAX_FILE_NAME];
732 : : char data_file[MAX_FILE_NAME];
733 : 0 : uint32_t nb_jobs = 0;
734 : 0 : bool perf_mode = 0;
735 : 0 : uint32_t nb_iterations = 0;
736 : : int ret;
737 : 0 : uint16_t nb_max_payload = 0;
738 : 0 : uint8_t nb_max_matches = 0;
739 : 0 : uint32_t nb_qps = 1;
740 : : char *data_buf;
741 : : long data_len;
742 : : long job_len;
743 : 0 : uint32_t nb_lcores = 1, nb_segs = 1;
744 : 0 : uint32_t match_mode = 0;
745 : : struct regex_conf *rgxc;
746 : : uint32_t i;
747 : : struct qps_per_lcore *qps_per_lcore;
748 : :
749 : : /* Init EAL. */
750 : 0 : ret = rte_eal_init(argc, argv);
751 : 0 : if (ret < 0)
752 : 0 : rte_exit(EXIT_FAILURE, "EAL init failed\n");
753 : 0 : argc -= ret;
754 : 0 : argv += ret;
755 : 0 : if (argc > 1)
756 : 0 : args_parse(argc, argv, rules_file, data_file, &nb_jobs,
757 : : &perf_mode, &nb_iterations, &nb_qps,
758 : : &nb_lcores, &nb_segs, &match_mode);
759 : :
760 : 0 : if (nb_qps == 0)
761 : 0 : rte_exit(EXIT_FAILURE, "Number of QPs must be greater than 0\n");
762 : 0 : if (nb_lcores == 0)
763 : 0 : rte_exit(EXIT_FAILURE, "Number of lcores must be greater than 0\n");
764 : 0 : if (nb_jobs == 0)
765 : 0 : rte_exit(EXIT_FAILURE, "Number of jobs must be greater than 0\n");
766 : 0 : if (distribute_qps_to_lcores(nb_lcores, nb_qps, &qps_per_lcore) < 0)
767 : 0 : rte_exit(EXIT_FAILURE, "Failed to distribute queues to lcores!\n");
768 : 0 : ret = init_port(&nb_max_payload, rules_file,
769 : : &nb_max_matches, nb_qps);
770 : 0 : if (ret < 0)
771 : 0 : rte_exit(EXIT_FAILURE, "init port failed\n");
772 : :
773 : 0 : data_len = read_file(data_file, &data_buf);
774 : 0 : if (data_len <= 0)
775 : 0 : rte_exit(EXIT_FAILURE, "Error, can't read file, or file is empty.\n");
776 : :
777 : 0 : job_len = data_len / nb_jobs;
778 : 0 : if (job_len == 0)
779 : 0 : rte_exit(EXIT_FAILURE, "Error, To many jobs, for the given input.\n");
780 : :
781 : 0 : if (job_len > nb_max_payload)
782 : 0 : rte_exit(EXIT_FAILURE, "Error, not enough jobs to cover input.\n");
783 : :
784 : 0 : rgxc = rte_malloc(NULL, sizeof(*rgxc) * nb_lcores, 0);
785 : 0 : if (!rgxc)
786 : 0 : rte_exit(EXIT_FAILURE, "Failed to create Regex Conf\n");
787 : 0 : for (i = 0; i < nb_lcores; i++) {
788 : 0 : rgxc[i] = (struct regex_conf){
789 : : .nb_jobs = nb_jobs,
790 : : .nb_segs = nb_segs,
791 : : .perf_mode = perf_mode,
792 : : .nb_iterations = nb_iterations,
793 : : .nb_max_matches = nb_max_matches,
794 : 0 : .nb_qps = qps_per_lcore[i].nb_qps,
795 : 0 : .qp_id_base = qps_per_lcore[i].qp_id_base,
796 : : .data_buf = data_buf,
797 : : .data_len = data_len,
798 : : .job_len = job_len,
799 : : .match_mode = match_mode,
800 : : };
801 : 0 : rte_eal_remote_launch(run_regex, &rgxc[i],
802 : : qps_per_lcore[i].lcore_id);
803 : : }
804 : 0 : rte_eal_mp_wait_lcore();
805 : 0 : rte_free(data_buf);
806 : 0 : rte_free(rgxc);
807 : 0 : rte_free(qps_per_lcore);
808 : : return EXIT_SUCCESS;
809 : : }
|