LCOV - code coverage report
Current view: top level - app/test-regex - main.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 363 0.0 %
Date: 2026-08-01 17:54:00 Functions: 0 9 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.14