examples/service_cores: fix lcore count check
[dpdk.git] / app / test-regex / main.c
index 2948d3e..8e665df 100644 (file)
@@ -35,6 +35,7 @@ enum app_args {
        ARG_NUM_OF_ITERATIONS,
        ARG_NUM_OF_QPS,
        ARG_NUM_OF_LCORES,
+       ARG_NUM_OF_MBUF_SEGS,
 };
 
 struct job_ctx {
@@ -48,6 +49,8 @@ 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 {
@@ -68,6 +71,7 @@ struct regex_conf {
        char *data_buf;
        long data_len;
        long job_len;
+       uint32_t nb_segs;
 };
 
 static void
@@ -80,14 +84,15 @@ usage(const char *prog_name)
                " --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_lcores N: number of lcores to use\n",
+               " --nb_lcores N: number of lcores to use\n"
+               " --nb_segs N: number of mbuf segments\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_lcores)
+          uint32_t *nb_qps, uint32_t *nb_lcores, uint32_t *nb_segs)
 {
        char **argvopt;
        int opt;
@@ -109,6 +114,8 @@ args_parse(int argc, char **argv, char *rules_file, char *data_file,
                { "nb_qps", 1, 0, ARG_NUM_OF_QPS},
                /* Number of lcores. */
                { "nb_lcores", 1, 0, ARG_NUM_OF_LCORES},
+               /* Number of mbuf segments. */
+               { "nb_segs", 1, 0, ARG_NUM_OF_MBUF_SEGS},
                /* End of options */
                { 0, 0, 0, 0 }
        };
@@ -148,13 +155,15 @@ args_parse(int argc, char **argv, char *rules_file, char *data_file,
                case ARG_NUM_OF_LCORES:
                        *nb_lcores = atoi(optarg);
                        break;
+               case ARG_NUM_OF_MBUF_SEGS:
+                       *nb_segs = atoi(optarg);
+                       break;
                case ARG_HELP:
-                       usage("RegEx test app");
+                       usage(argv[0]);
                        break;
                default:
-                       fprintf(stderr, "Invalid option: %s\n", argv[optind]);
-                       usage("RegEx test app");
-                       rte_exit(EXIT_FAILURE, "Invalid option\n");
+                       usage(argv[0]);
+                       rte_exit(EXIT_FAILURE, "Invalid option: %s\n", argv[optind]);
                        break;
                }
        }
@@ -300,11 +309,75 @@ extbuf_free_cb(void *addr __rte_unused, void *fcb_opaque __rte_unused)
 {
 }
 
+static inline struct rte_mbuf *
+regex_create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+               int nb_segs, void *buf) {
+
+       struct rte_mbuf *m = NULL, *mbuf = NULL;
+       uint8_t *dst;
+       char *src = buf;
+       int data_len = 0;
+       int i, size;
+       int t_len;
+
+       if (pkt_len < 1) {
+               printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+               return NULL;
+       }
+
+       if (nb_segs < 1) {
+               printf("Number of segments must be 1 or more (is %d)\n",
+                               nb_segs);
+               return NULL;
+       }
+
+       t_len = pkt_len >= nb_segs ? (pkt_len / nb_segs +
+                                    !!(pkt_len % nb_segs)) : 1;
+       size = pkt_len;
+
+       /* Create chained mbuf_src and fill it with buf data */
+       for (i = 0; size > 0; i++) {
+
+               m = rte_pktmbuf_alloc(mbuf_pool);
+               if (i == 0)
+                       mbuf = m;
+
+               if (m == NULL) {
+                       printf("Cannot create segment for source mbuf");
+                       goto fail;
+               }
+
+               data_len = size > t_len ? t_len : size;
+               memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+                               rte_pktmbuf_tailroom(m));
+               memcpy(rte_pktmbuf_mtod(m, uint8_t *), src, data_len);
+               dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+               if (dst == NULL) {
+                       printf("Cannot append %d bytes to the mbuf\n",
+                                       data_len);
+                       goto fail;
+               }
+
+               if (mbuf != m)
+                       rte_pktmbuf_chain(mbuf, m);
+               src += data_len;
+               size -= data_len;
+
+       }
+       return mbuf;
+
+fail:
+       if (mbuf)
+               rte_pktmbuf_free(mbuf);
+       return NULL;
+}
+
 static int
 run_regex(void *args)
 {
        struct regex_conf *rgxc = args;
        uint32_t nb_jobs = rgxc->nb_jobs;
+       uint32_t nb_segs = rgxc->nb_segs;
        uint32_t nb_iterations = rgxc->nb_iterations;
        uint8_t nb_max_matches = rgxc->nb_max_matches;
        uint32_t nb_qps = rgxc->nb_qps;
@@ -324,9 +397,7 @@ run_regex(void *args)
        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;
@@ -338,8 +409,12 @@ run_regex(void *args)
        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());
+       mbuf_mp = rte_pktmbuf_pool_create(mbuf_pool,
+                       rte_align32pow2(nb_jobs * nb_qps * nb_segs),
+                       0, 0, (nb_segs == 1) ? MBUF_SIZE :
+                       (rte_align32pow2(job_len) / nb_segs +
+                       RTE_PKTMBUF_HEADROOM),
+                       rte_socket_id());
        if (mbuf_mp == NULL) {
                printf("Error, can't create memory pool\n");
                return -ENOMEM;
@@ -375,8 +450,19 @@ run_regex(void *args)
                        goto end;
                }
 
+               if (clone_buf(data_buf, &buf, data_len)) {
+                       printf("Error, can't clone buf.\n");
+                       res = -EXIT_FAILURE;
+                       goto end;
+               }
+
+               /* Assign each mbuf with the data to handle. */
+               actual_jobs = 0;
+               pos = 0;
                /* Allocate the jobs and assign each job with an mbuf. */
-               for (i = 0; i < nb_jobs; i++) {
+               for (i = 0; (pos < data_len) && (i < nb_jobs) ; i++) {
+                       long act_job_len = RTE_MIN(job_len, data_len - pos);
+
                        ops[i] = rte_malloc(NULL, sizeof(*ops[0]) +
                                        nb_max_matches *
                                        sizeof(struct rte_regexdev_match), 0);
@@ -386,30 +472,26 @@ run_regex(void *args)
                                res = -ENOMEM;
                                goto end;
                        }
-                       ops[i]->mbuf = rte_pktmbuf_alloc(mbuf_mp);
+                       if (nb_segs > 1) {
+                               ops[i]->mbuf = regex_create_segmented_mbuf
+                                                       (mbuf_mp, act_job_len,
+                                                        nb_segs, &buf[pos]);
+                       } else {
+                               ops[i]->mbuf = rte_pktmbuf_alloc(mbuf_mp);
+                               if (ops[i]->mbuf) {
+                                       rte_pktmbuf_attach_extbuf(ops[i]->mbuf,
+                                       &buf[pos], 0, act_job_len, &shinfo);
+                                       ops[i]->mbuf->data_len = job_len;
+                                       ops[i]->mbuf->pkt_len = act_job_len;
+                               }
+                       }
                        if (!ops[i]->mbuf) {
-                               printf("Error, can't attach mbuf.\n");
+                               printf("Error, can't add mbuf.\n");
                                res = -ENOMEM;
                                goto end;
                        }
-               }
-
-               if (clone_buf(data_buf, &buf, data_len)) {
-                       printf("Error, can't clone buf.\n");
-                       res = -EXIT_FAILURE;
-                       goto end;
-               }
 
-               /* Assign each mbuf with the data to handle. */
-               actual_jobs = 0;
-               pos = 0;
-               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;
-                       ops[i]->mbuf->data_len = job_len;
-                       ops[i]->mbuf->pkt_len = act_job_len;
                        ops[i]->user_id = i;
                        ops[i]->group_id0 = 1;
                        pos += act_job_len;
@@ -418,9 +500,10 @@ run_regex(void *args)
 
                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];
@@ -432,6 +515,7 @@ run_regex(void *args)
                        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;
@@ -460,23 +544,28 @@ run_regex(void *args)
                                                        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);
+       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++) {
@@ -605,7 +694,7 @@ main(int argc, char **argv)
        char *data_buf;
        long data_len;
        long job_len;
-       uint32_t nb_lcores = 1;
+       uint32_t nb_lcores = 1, nb_segs = 1;
        struct regex_conf *rgxc;
        uint32_t i;
        struct qps_per_lcore *qps_per_lcore;
@@ -619,7 +708,7 @@ main(int argc, char **argv)
        if (argc > 1)
                args_parse(argc, argv, rules_file, data_file, &nb_jobs,
                                &perf_mode, &nb_iterations, &nb_qps,
-                               &nb_lcores);
+                               &nb_lcores, &nb_segs);
 
        if (nb_qps == 0)
                rte_exit(EXIT_FAILURE, "Number of QPs must be greater than 0\n");
@@ -649,6 +738,7 @@ main(int argc, char **argv)
        for (i = 0; i < nb_lcores; i++) {
                rgxc[i] = (struct regex_conf){
                        .nb_jobs = nb_jobs,
+                       .nb_segs = nb_segs,
                        .perf_mode = perf_mode,
                        .nb_iterations = nb_iterations,
                        .nb_max_matches = nb_max_matches,