LCOV - code coverage report
Current view: top level - app/test-regex - main.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 365 0.0 %
Date: 2025-01-02 22:41:34 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                 :            :         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                 :            : }

Generated by: LCOV version 1.14