net/ice: clean input set macro definition
[dpdk.git] / app / test-regex / main.c
index d225267..aea4fa6 100644 (file)
@@ -34,6 +34,7 @@ enum app_args {
        ARG_PERF_MODE,
        ARG_NUM_OF_ITERATIONS,
        ARG_NUM_OF_QPS,
+       ARG_NUM_OF_LCORES,
 };
 
 struct job_ctx {
@@ -47,6 +48,28 @@ struct qp_params {
        struct rte_regex_ops **ops;
        struct job_ctx *jobs_ctx;
        char *buf;
+       uint64_t start;
+       uint64_t cycles;
+};
+
+struct qps_per_lcore {
+       unsigned int lcore_id;
+       int socket;
+       uint16_t qp_id_base;
+       uint16_t nb_qps;
+};
+
+struct regex_conf {
+       uint32_t nb_jobs;
+       bool perf_mode;
+       uint32_t nb_iterations;
+       char *data_file;
+       uint8_t nb_max_matches;
+       uint32_t nb_qps;
+       uint16_t qp_id_base;
+       char *data_buf;
+       long data_len;
+       long job_len;
 };
 
 static void
@@ -58,14 +81,15 @@ usage(const char *prog_name)
                " --nb_jobs: number of jobs to use\n"
                " --perf N: only outputs the performance data\n"
                " --nb_iter N: number of iteration to run\n"
-               " --nb_qps N: number of queues to use\n",
+               " --nb_qps N: number of queues to use\n"
+               " --nb_lcores N: number of lcores to use\n",
                prog_name);
 }
 
 static void
 args_parse(int argc, char **argv, char *rules_file, char *data_file,
           uint32_t *nb_jobs, bool *perf_mode, uint32_t *nb_iterations,
-          uint32_t *nb_qps)
+          uint32_t *nb_qps, uint32_t *nb_lcores)
 {
        char **argvopt;
        int opt;
@@ -85,6 +109,8 @@ args_parse(int argc, char **argv, char *rules_file, char *data_file,
                { "nb_iter", 1, 0, ARG_NUM_OF_ITERATIONS},
                /* Number of QPs. */
                { "nb_qps", 1, 0, ARG_NUM_OF_QPS},
+               /* Number of lcores. */
+               { "nb_lcores", 1, 0, ARG_NUM_OF_LCORES},
                /* End of options */
                { 0, 0, 0, 0 }
        };
@@ -121,6 +147,9 @@ args_parse(int argc, char **argv, char *rules_file, char *data_file,
                case ARG_NUM_OF_QPS:
                        *nb_qps = atoi(optarg);
                        break;
+               case ARG_NUM_OF_LCORES:
+                       *nb_lcores = atoi(optarg);
+                       break;
                case ARG_HELP:
                        usage("RegEx test app");
                        break;
@@ -179,6 +208,19 @@ error:
        return -res;
 }
 
+static int
+clone_buf(char *data_buf, char **buf, long data_len)
+{
+       char *dest_buf;
+       dest_buf =
+               rte_malloc(NULL, sizeof(char) * (data_len + 1), 4096);
+       if (!dest_buf)
+               return -ENOMEM;
+       memcpy(dest_buf, data_buf, data_len + 1);
+       *buf = dest_buf;
+       return 0;
+}
+
 static int
 init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches,
          uint32_t nb_qps)
@@ -261,13 +303,19 @@ extbuf_free_cb(void *addr __rte_unused, void *fcb_opaque __rte_unused)
 }
 
 static int
-run_regex(uint32_t nb_jobs,
-         uint16_t nb_max_payload, bool perf_mode, uint32_t nb_iterations,
-         char *data_file, uint8_t nb_max_matches, uint32_t nb_qps)
+run_regex(void *args)
 {
+       struct regex_conf *rgxc = args;
+       uint32_t nb_jobs = rgxc->nb_jobs;
+       uint32_t nb_iterations = rgxc->nb_iterations;
+       uint8_t nb_max_matches = rgxc->nb_max_matches;
+       uint32_t nb_qps = rgxc->nb_qps;
+       uint16_t qp_id_base  = rgxc->qp_id_base;
+       char *data_buf = rgxc->data_buf;
+       long data_len = rgxc->data_len;
+       long job_len = rgxc->job_len;
+
        char *buf = NULL;
-       long buf_len = 0;
-       long job_len = 0;
        uint32_t actual_jobs = 0;
        uint32_t i;
        uint16_t qp_id;
@@ -278,17 +326,19 @@ run_regex(uint32_t nb_jobs,
        unsigned long d_ind = 0;
        struct rte_mbuf_ext_shared_info shinfo;
        int res = 0;
-       time_t start;
-       time_t end;
-       double time;
+       long double time;
        struct rte_mempool *mbuf_mp;
        struct qp_params *qp;
        struct qp_params *qps = NULL;
        bool update;
        uint16_t qps_used = 0;
+       char mbuf_pool[16];
 
        shinfo.free_cb = extbuf_free_cb;
-       mbuf_mp = rte_pktmbuf_pool_create("mbuf_pool", nb_jobs * nb_qps, 0,
+       snprintf(mbuf_pool,
+                sizeof(mbuf_pool),
+                "mbuf_pool_%2u", qp_id_base);
+       mbuf_mp = rte_pktmbuf_pool_create(mbuf_pool, nb_jobs * nb_qps, 0,
                        0, MBUF_SIZE, rte_socket_id());
        if (mbuf_mp == NULL) {
                printf("Error, can't create memory pool\n");
@@ -344,22 +394,8 @@ run_regex(uint32_t nb_jobs,
                        }
                }
 
-               buf_len = read_file(data_file, &buf);
-               if (buf_len <= 0) {
-                       printf("Error, can't read file, or file is empty.\n");
-                       res = -EXIT_FAILURE;
-                       goto end;
-               }
-
-               job_len = buf_len / nb_jobs;
-               if (job_len == 0) {
-                       printf("Error, To many jobs, for the given input.\n");
-                       res = -EXIT_FAILURE;
-                       goto end;
-               }
-
-               if (job_len > nb_max_payload) {
-                       printf("Error, not enough jobs to cover input.\n");
+               if (clone_buf(data_buf, &buf, data_len)) {
+                       printf("Error, can't clone buf.\n");
                        res = -EXIT_FAILURE;
                        goto end;
                }
@@ -367,8 +403,8 @@ run_regex(uint32_t nb_jobs,
                /* Assign each mbuf with the data to handle. */
                actual_jobs = 0;
                pos = 0;
-               for (i = 0; (pos < buf_len) && (i < nb_jobs) ; i++) {
-                       long act_job_len = RTE_MIN(job_len, buf_len - pos);
+               for (i = 0; (pos < data_len) && (i < nb_jobs) ; i++) {
+                       long act_job_len = RTE_MIN(job_len, data_len - pos);
                        rte_pktmbuf_attach_extbuf(ops[i]->mbuf, &buf[pos], 0,
                                        act_job_len, &shinfo);
                        jobs_ctx[i].mbuf = ops[i]->mbuf;
@@ -382,9 +418,10 @@ run_regex(uint32_t nb_jobs,
 
                qp->buf = buf;
                qp->total_matches = 0;
+               qp->start = 0;
+               qp->cycles = 0;
        }
 
-       start = clock();
        for (i = 0; i < nb_iterations; i++) {
                for (qp_id = 0; qp_id < nb_qps; qp_id++) {
                        qp = &qps[qp_id];
@@ -396,6 +433,7 @@ run_regex(uint32_t nb_jobs,
                        for (qp_id = 0; qp_id < nb_qps; qp_id++) {
                                qp = &qps[qp_id];
                                if (qp->total_dequeue < actual_jobs) {
+                                       qp->start = rte_rdtsc_precise();
                                        struct rte_regex_ops **
                                                cur_ops_to_enqueue = qp->ops +
                                                qp->total_enqueue;
@@ -404,7 +442,7 @@ run_regex(uint32_t nb_jobs,
                                                qp->total_enqueue +=
                                                rte_regexdev_enqueue_burst
                                                        (dev_id,
-                                                       qp_id,
+                                                       qp_id_base + qp_id,
                                                        cur_ops_to_enqueue,
                                                        actual_jobs -
                                                        qp->total_enqueue);
@@ -420,27 +458,32 @@ run_regex(uint32_t nb_jobs,
                                        qp->total_dequeue +=
                                                rte_regexdev_dequeue_burst
                                                        (dev_id,
-                                                       qp_id,
+                                                       qp_id_base + qp_id,
                                                        cur_ops_to_dequeue,
                                                        qp->total_enqueue -
                                                        qp->total_dequeue);
+                                       qp->cycles +=
+                                            (rte_rdtsc_precise() - qp->start);
                                        update = true;
                                }
                        }
                } while (update);
        }
-       end = clock();
-       time = ((double)end - start) / CLOCKS_PER_SEC;
-       printf("Job len = %ld Bytes\n",  job_len);
-       printf("Time = %lf sec\n",  time);
-       printf("Perf = %lf Gbps\n",
-              (((double)actual_jobs * job_len * nb_iterations * 8) / time) /
-               1000000000.0);
-
-       if (perf_mode)
+       for (qp_id = 0; qp_id < nb_qps; qp_id++) {
+               qp = &qps[qp_id];
+               time = (long double)qp->cycles / rte_get_timer_hz();
+               printf("Core=%u QP=%u Job=%ld Bytes Time=%Lf sec Perf=%Lf "
+                      "Gbps\n", rte_lcore_id(), qp_id + qp_id_base,
+                      job_len, time,
+                      (((double)actual_jobs * job_len * nb_iterations * 8)
+                      / time) / 1000000000.0);
+       }
+
+       if (rgxc->perf_mode)
                goto end;
        for (qp_id = 0; qp_id < nb_qps; qp_id++) {
-               printf("\n############ QP id=%u ############\n", qp_id);
+               printf("\n############ Core=%u QP=%u ############\n",
+                      rte_lcore_id(), qp_id + qp_id_base);
                qp = &qps[qp_id];
                /* Log results per job. */
                for (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {
@@ -493,6 +536,67 @@ end:
        return res;
 }
 
+static int
+distribute_qps_to_lcores(uint32_t nb_cores, uint32_t nb_qps,
+                        struct qps_per_lcore **qpl)
+{
+       int socket;
+       unsigned lcore_id;
+       uint32_t i;
+       uint16_t min_qp_id;
+       uint16_t max_qp_id;
+       struct qps_per_lcore *qps_per_lcore;
+       uint32_t detected_lcores;
+
+       if (nb_qps < nb_cores) {
+               nb_cores = nb_qps;
+               printf("Reducing number of cores to number of QPs (%u)\n",
+                      nb_cores);
+       }
+       /* Allocate qps_per_lcore array */
+       qps_per_lcore =
+               rte_malloc(NULL, sizeof(*qps_per_lcore) * nb_cores, 0);
+       if (!qps_per_lcore)
+               rte_exit(EXIT_FAILURE, "Failed to create qps_per_lcore array\n");
+       *qpl = qps_per_lcore;
+       detected_lcores = 0;
+       min_qp_id = 0;
+
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
+               if (detected_lcores >= nb_cores)
+                       break;
+               qps_per_lcore[detected_lcores].lcore_id = lcore_id;
+               socket = rte_lcore_to_socket_id(lcore_id);
+               if (socket == SOCKET_ID_ANY)
+                       socket = 0;
+               qps_per_lcore[detected_lcores].socket = socket;
+               qps_per_lcore[detected_lcores].qp_id_base = min_qp_id;
+               max_qp_id = min_qp_id + nb_qps / nb_cores - 1;
+               if (nb_qps % nb_cores > detected_lcores)
+                       max_qp_id++;
+               qps_per_lcore[detected_lcores].nb_qps = max_qp_id -
+                                                       min_qp_id + 1;
+               min_qp_id = max_qp_id + 1;
+               detected_lcores++;
+       }
+       if (detected_lcores != nb_cores)
+               return -1;
+
+       for (i = 0; i < detected_lcores; i++) {
+               printf("===> Core %d: allocated queues: ",
+                      qps_per_lcore[i].lcore_id);
+               min_qp_id = qps_per_lcore[i].qp_id_base;
+               max_qp_id =
+                       qps_per_lcore[i].qp_id_base + qps_per_lcore[i].nb_qps;
+               while (min_qp_id < max_qp_id) {
+                       printf("%u ", min_qp_id);
+                       min_qp_id++;
+               }
+               printf("\n");
+       }
+       return 0;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -505,6 +609,13 @@ main(int argc, char **argv)
        uint16_t nb_max_payload = 0;
        uint8_t nb_max_matches = 0;
        uint32_t nb_qps = 1;
+       char *data_buf;
+       long data_len;
+       long job_len;
+       uint32_t nb_lcores = 1;
+       struct regex_conf *rgxc;
+       uint32_t i;
+       struct qps_per_lcore *qps_per_lcore;
 
        /* Init EAL. */
        ret = rte_eal_init(argc, argv);
@@ -514,18 +625,52 @@ main(int argc, char **argv)
        argv += ret;
        if (argc > 1)
                args_parse(argc, argv, rules_file, data_file, &nb_jobs,
-                               &perf_mode, &nb_iterations, &nb_qps);
+                               &perf_mode, &nb_iterations, &nb_qps,
+                               &nb_lcores);
 
        if (nb_qps == 0)
                rte_exit(EXIT_FAILURE, "Number of QPs must be greater than 0\n");
+       if (nb_lcores == 0)
+               rte_exit(EXIT_FAILURE, "Number of lcores must be greater than 0\n");
+       if (distribute_qps_to_lcores(nb_lcores, nb_qps, &qps_per_lcore) < 0)
+               rte_exit(EXIT_FAILURE, "Failed to distribute queues to lcores!\n");
        ret = init_port(&nb_max_payload, rules_file,
                        &nb_max_matches, nb_qps);
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "init port failed\n");
-       ret = run_regex(nb_jobs, nb_max_payload, perf_mode,
-                       nb_iterations, data_file, nb_max_matches, nb_qps);
-       if (ret < 0) {
-               rte_exit(EXIT_FAILURE, "RegEx function failed\n");
+
+       data_len = read_file(data_file, &data_buf);
+       if (data_len <= 0)
+               rte_exit(EXIT_FAILURE, "Error, can't read file, or file is empty.\n");
+
+       job_len = data_len / nb_jobs;
+       if (job_len == 0)
+               rte_exit(EXIT_FAILURE, "Error, To many jobs, for the given input.\n");
+
+       if (job_len > nb_max_payload)
+               rte_exit(EXIT_FAILURE, "Error, not enough jobs to cover input.\n");
+
+       rgxc = rte_malloc(NULL, sizeof(*rgxc) * nb_lcores, 0);
+       if (!rgxc)
+               rte_exit(EXIT_FAILURE, "Failed to create Regex Conf\n");
+       for (i = 0; i < nb_lcores; i++) {
+               rgxc[i] = (struct regex_conf){
+                       .nb_jobs = nb_jobs,
+                       .perf_mode = perf_mode,
+                       .nb_iterations = nb_iterations,
+                       .nb_max_matches = nb_max_matches,
+                       .nb_qps = qps_per_lcore[i].nb_qps,
+                       .qp_id_base = qps_per_lcore[i].qp_id_base,
+                       .data_buf = data_buf,
+                       .data_len = data_len,
+                       .job_len = job_len,
+               };
+               rte_eal_remote_launch(run_regex, &rgxc[i],
+                                     qps_per_lcore[i].lcore_id);
        }
+       rte_eal_mp_wait_lcore();
+       rte_free(data_buf);
+       rte_free(rgxc);
+       rte_free(qps_per_lcore);
        return EXIT_SUCCESS;
 }