get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/85253/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 85253,
    "url": "http://patches.dpdk.org/api/patches/85253/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201216164931.1517-3-ophirmu@nvidia.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20201216164931.1517-3-ophirmu@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201216164931.1517-3-ophirmu@nvidia.com",
    "date": "2020-12-16T16:49:27",
    "name": "[v1,2/6] app/regex: support multi QPs",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2ddbf2fa8b7d3638a2742669acb29fab45f94bda",
    "submitter": {
        "id": 1908,
        "url": "http://patches.dpdk.org/api/people/1908/?format=api",
        "name": "Ophir Munk",
        "email": "ophirmu@nvidia.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20201216164931.1517-3-ophirmu@nvidia.com/mbox/",
    "series": [
        {
            "id": 14334,
            "url": "http://patches.dpdk.org/api/series/14334/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=14334",
            "date": "2020-12-16T16:49:28",
            "name": "regex multi Q with multi cores support",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/14334/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/85253/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/85253/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 72911A09F0;\n\tWed, 16 Dec 2020 17:50:21 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id D8C96C9D4;\n\tWed, 16 Dec 2020 17:50:05 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id 9D7D0C9D2\n for <dev@dpdk.org>; Wed, 16 Dec 2020 17:50:04 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n ophirmu@nvidia.com) with SMTP; 16 Dec 2020 18:49:58 +0200",
            "from nvidia.com (pegasus05.mtr.labs.mlnx [10.210.16.100])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 0BGGnvct005924;\n Wed, 16 Dec 2020 18:49:57 +0200"
        ],
        "From": "Ophir Munk <ophirmu@nvidia.com>",
        "To": "Ori Kam <orika@nvidia.com>, dev@dpdk.org,\n Raslan Darawsheh <rasland@nvidia.com>",
        "Cc": "Ophir Munk <ophirmu@nvidia.com>, Thomas Monjalon <thomas@monjalon.net>",
        "Date": "Wed, 16 Dec 2020 16:49:27 +0000",
        "Message-Id": "<20201216164931.1517-3-ophirmu@nvidia.com>",
        "X-Mailer": "git-send-email 2.8.4",
        "In-Reply-To": "<20201216164931.1517-1-ophirmu@nvidia.com>",
        "References": "<20201216164931.1517-1-ophirmu@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v1 2/6] app/regex: support multi QPs",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Up to this commit the regex application used one QP which was assigned a\nnumber of jobs, each with a different segment of a file to parse.  This\ncommit adds support for multiple QPs assignments. All QPs will be\nassigned the same number of jobs, with the same segments of file to\nparse. It will enable comparing functionality with different numbers of\nQPs. All queues are managed on one core with one thread. This commit\nfocuses on changing routines API to support multi QPs, mainly, QP scalar\nvariables are replaced by per-QP struct instance.  The enque/deque\noperations are interleaved as follows:\n enque(QP #1)\n enque(QP #2)\n ...\n enque(QP #n)\n deque(QP #1)\n deque(QP #2)\n ...\n deque(QP #n)\n\nA new parameter 'nb_qps' was added to configure the number of QPs:\n --nb_qps <num of qps>.\nIf not configured, nb_qps is set to 1 by defalut.\n\nSigned-off-by: Ophir Munk <ophirmu@nvidia.com>\n---\n app/test-regex/main.c | 322 ++++++++++++++++++++++++++++++++------------------\n 1 file changed, 204 insertions(+), 118 deletions(-)",
    "diff": "diff --git a/app/test-regex/main.c b/app/test-regex/main.c\nindex cb2a065..d225267 100644\n--- a/app/test-regex/main.c\n+++ b/app/test-regex/main.c\n@@ -33,12 +33,22 @@ enum app_args {\n \tARG_NUM_OF_JOBS,\n \tARG_PERF_MODE,\n \tARG_NUM_OF_ITERATIONS,\n+\tARG_NUM_OF_QPS,\n };\n \n struct job_ctx {\n \tstruct rte_mbuf *mbuf;\n };\n \n+struct qp_params {\n+\tuint32_t total_enqueue;\n+\tuint32_t total_dequeue;\n+\tuint32_t total_matches;\n+\tstruct rte_regex_ops **ops;\n+\tstruct job_ctx *jobs_ctx;\n+\tchar *buf;\n+};\n+\n static void\n usage(const char *prog_name)\n {\n@@ -47,13 +57,15 @@ usage(const char *prog_name)\n \t\t\" --data NAME: data file to use\\n\"\n \t\t\" --nb_jobs: number of jobs to use\\n\"\n \t\t\" --perf N: only outputs the performance data\\n\"\n-\t\t\" --nb_iter N: number of iteration to run\\n\",\n+\t\t\" --nb_iter N: number of iteration to run\\n\"\n+\t\t\" --nb_qps N: number of queues to use\\n\",\n \t\tprog_name);\n }\n \n static void\n args_parse(int argc, char **argv, char *rules_file, char *data_file,\n-\t   uint32_t *nb_jobs, bool *perf_mode, uint32_t *nb_iterations)\n+\t   uint32_t *nb_jobs, bool *perf_mode, uint32_t *nb_iterations,\n+\t   uint32_t *nb_qps)\n {\n \tchar **argvopt;\n \tint opt;\n@@ -71,6 +83,8 @@ args_parse(int argc, char **argv, char *rules_file, char *data_file,\n \t\t{ \"perf\", 0, 0, ARG_PERF_MODE},\n \t\t/* Number of iterations to run with perf test */\n \t\t{ \"nb_iter\", 1, 0, ARG_NUM_OF_ITERATIONS},\n+\t\t/* Number of QPs. */\n+\t\t{ \"nb_qps\", 1, 0, ARG_NUM_OF_QPS},\n \t\t/* End of options */\n \t\t{ 0, 0, 0, 0 }\n \t};\n@@ -104,6 +118,9 @@ args_parse(int argc, char **argv, char *rules_file, char *data_file,\n \t\tcase ARG_NUM_OF_ITERATIONS:\n \t\t\t*nb_iterations = atoi(optarg);\n \t\t\tbreak;\n+\t\tcase ARG_NUM_OF_QPS:\n+\t\t\t*nb_qps = atoi(optarg);\n+\t\t\tbreak;\n \t\tcase ARG_HELP:\n \t\t\tusage(\"RegEx test app\");\n \t\t\tbreak;\n@@ -163,15 +180,17 @@ read_file(char *file, char **buf)\n }\n \n static int\n-init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches)\n+init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches,\n+\t  uint32_t nb_qps)\n {\n \tuint16_t id;\n+\tuint16_t qp_id;\n \tuint16_t num_devs;\n \tchar *rules = NULL;\n \tlong rules_len;\n \tstruct rte_regexdev_info info;\n \tstruct rte_regexdev_config dev_conf = {\n-\t\t.nb_queue_pairs = 1,\n+\t\t.nb_queue_pairs = nb_qps,\n \t\t.nb_groups = 1,\n \t};\n \tstruct rte_regexdev_qp_conf qp_conf = {\n@@ -203,7 +222,8 @@ init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches)\n \t\t*nb_max_matches = info.max_matches;\n \t\t*nb_max_payload = info.max_payload_size;\n \t\tif (info.regexdev_capa & RTE_REGEXDEV_SUPP_MATCH_AS_END_F)\n-\t\t\tdev_conf.dev_cfg_flags |= RTE_REGEXDEV_CFG_MATCH_AS_END_F;\n+\t\t\tdev_conf.dev_cfg_flags |=\n+\t\t\tRTE_REGEXDEV_CFG_MATCH_AS_END_F;\n \t\tdev_conf.nb_max_matches = info.max_matches;\n \t\tdev_conf.nb_rules_per_group = info.max_rules_per_group;\n \t\tdev_conf.rule_db_len = rules_len;\n@@ -214,12 +234,16 @@ init_port(uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches)\n \t\t\tgoto error;\n \t\t}\n \t\tif (info.regexdev_capa & RTE_REGEXDEV_CAPA_QUEUE_PAIR_OOS_F)\n-\t\t\tqp_conf.qp_conf_flags |= RTE_REGEX_QUEUE_PAIR_CFG_OOS_F;\n-\t\tres = rte_regexdev_queue_pair_setup(id, 0, &qp_conf);\n-\t\tif (res < 0) {\n-\t\t\tprintf(\"Error, can't setup queue pair for device %d.\\n\",\n-\t\t\t       id);\n-\t\t\tgoto error;\n+\t\t\tqp_conf.qp_conf_flags |=\n+\t\t\tRTE_REGEX_QUEUE_PAIR_CFG_OOS_F;\n+\t\tfor (qp_id = 0; qp_id < nb_qps; qp_id++) {\n+\t\t\tres = rte_regexdev_queue_pair_setup(id, qp_id,\n+\t\t\t\t\t\t\t    &qp_conf);\n+\t\t\tif (res < 0) {\n+\t\t\t\tprintf(\"Error, can't setup queue pair %u for \"\n+\t\t\t\t       \"device %d.\\n\", qp_id, id);\n+\t\t\t\tgoto error;\n+\t\t\t}\n \t\t}\n \t\tprintf(\":: initializing device: %d done\\n\", id);\n \t}\n@@ -239,122 +263,171 @@ extbuf_free_cb(void *addr __rte_unused, void *fcb_opaque __rte_unused)\n static int\n run_regex(uint32_t nb_jobs,\n \t  uint16_t nb_max_payload, bool perf_mode, uint32_t nb_iterations,\n-\t  char *data_file, uint8_t nb_max_matches)\n+\t  char *data_file, uint8_t nb_max_matches, uint32_t nb_qps)\n {\n \tchar *buf = NULL;\n-\tlong buf_len;\n-\tlong job_len;\n+\tlong buf_len = 0;\n+\tlong job_len = 0;\n \tuint32_t actual_jobs = 0;\n \tuint32_t i;\n-\tstruct rte_regex_ops **ops;\n+\tuint16_t qp_id;\n \tuint16_t dev_id = 0;\n-\tuint16_t qp_id = 0;\n \tuint8_t nb_matches;\n \tstruct rte_regexdev_match *match;\n-\tlong pos = 0;\n+\tlong pos;\n \tunsigned long d_ind = 0;\n \tstruct rte_mbuf_ext_shared_info shinfo;\n-\tuint32_t total_enqueue = 0;\n-\tuint32_t total_dequeue = 0;\n-\tuint32_t total_matches = 0;\n \tint res = 0;\n \ttime_t start;\n \ttime_t end;\n \tdouble time;\n-\tstruct job_ctx *jobs_ctx;\n \tstruct rte_mempool *mbuf_mp;\n+\tstruct qp_params *qp;\n+\tstruct qp_params *qps = NULL;\n+\tbool update;\n+\tuint16_t qps_used = 0;\n \n \tshinfo.free_cb = extbuf_free_cb;\n-\n-\tmbuf_mp = rte_pktmbuf_pool_create(\"mbuf_pool\", nb_jobs, 0,\n+\tmbuf_mp = rte_pktmbuf_pool_create(\"mbuf_pool\", nb_jobs * nb_qps, 0,\n \t\t\t0, MBUF_SIZE, rte_socket_id());\n \tif (mbuf_mp == NULL) {\n \t\tprintf(\"Error, can't create memory pool\\n\");\n \t\treturn -ENOMEM;\n \t}\n \n-\tops = rte_malloc(NULL, sizeof(*ops) * nb_jobs, 0);\n-\tif (!ops) {\n-\t\tprintf(\"Error, can't allocate memory for ops.\\n\");\n-\t\treturn -ENOMEM;\n-\t}\n-\n-\tjobs_ctx = rte_malloc(NULL, sizeof(struct job_ctx)*nb_jobs, 0);\n-\tif (!jobs_ctx) {\n-\t\tprintf(\"Error, can't allocate memory for jobs_ctx.\\n\");\n-\t\treturn -ENOMEM;\n+\tqps = rte_malloc(NULL, sizeof(*qps) * nb_qps, 0);\n+\tif (!qps) {\n+\t\tprintf(\"Error, can't allocate memory for QPs\\n\");\n+\t\tres = -ENOMEM;\n+\t\tgoto end;\n \t}\n \n-\t/* Allocate the jobs and assign each job with an mbuf. */\n-\tfor (i = 0; i < nb_jobs; i++) {\n-\t\tops[i] = rte_malloc(NULL, sizeof(*ops[0]) + nb_max_matches *\n-\t\t\t\t    sizeof(struct rte_regexdev_match), 0);\n-\t\tif (!ops[i]) {\n-\t\t\tprintf(\"Error, can't allocate memory for op.\\n\");\n+\tfor (qp_id = 0; qp_id < nb_qps; qp_id++) {\n+\t\tstruct rte_regex_ops **ops;\n+\t\tstruct job_ctx *jobs_ctx;\n+\n+\t\tqps_used++;\n+\t\tqp = &qps[qp_id];\n+\t\tqp->jobs_ctx = NULL;\n+\t\tqp->buf = NULL;\n+\t\tqp->ops = ops = rte_malloc(NULL, sizeof(*ops) * nb_jobs, 0);\n+\t\tif (!ops) {\n+\t\t\tprintf(\"Error, can't allocate memory for ops.\\n\");\n \t\t\tres = -ENOMEM;\n \t\t\tgoto end;\n \t\t}\n-\t\tops[i]->mbuf = rte_pktmbuf_alloc(mbuf_mp);\n-\t\tif (!ops[i]->mbuf) {\n-\t\t\tprintf(\"Error, can't attach mbuf.\\n\");\n+\n+\t\tqp->jobs_ctx = jobs_ctx =\n+\t\t\trte_malloc(NULL, sizeof(*jobs_ctx) * nb_jobs, 0);\n+\t\tif (!jobs_ctx) {\n+\t\t\tprintf(\"Error, can't allocate memory for jobs_ctx.\\n\");\n \t\t\tres = -ENOMEM;\n \t\t\tgoto end;\n \t\t}\n-\t}\n \n-\tbuf_len = read_file(data_file, &buf);\n-\tif (buf_len <= 0) {\n-\t\tprintf(\"Error, can't read file, or file is empty.\\n\");\n-\t\tres = -EXIT_FAILURE;\n-\t\tgoto end;\n-\t}\n+\t\t/* Allocate the jobs and assign each job with an mbuf. */\n+\t\tfor (i = 0; i < nb_jobs; i++) {\n+\t\t\tops[i] = rte_malloc(NULL, sizeof(*ops[0]) +\n+\t\t\t\t\tnb_max_matches *\n+\t\t\t\t\tsizeof(struct rte_regexdev_match), 0);\n+\t\t\tif (!ops[i]) {\n+\t\t\t\tprintf(\"Error, can't allocate \"\n+\t\t\t\t       \"memory for op.\\n\");\n+\t\t\t\tres = -ENOMEM;\n+\t\t\t\tgoto end;\n+\t\t\t}\n+\t\t\tops[i]->mbuf = rte_pktmbuf_alloc(mbuf_mp);\n+\t\t\tif (!ops[i]->mbuf) {\n+\t\t\t\tprintf(\"Error, can't attach mbuf.\\n\");\n+\t\t\t\tres = -ENOMEM;\n+\t\t\t\tgoto end;\n+\t\t\t}\n+\t\t}\n \n-\tjob_len = buf_len / nb_jobs;\n-\tif (job_len == 0) {\n-\t\tprintf(\"Error, To many jobs, for the given input.\\n\");\n-\t\tres = -EXIT_FAILURE;\n-\t\tgoto end;\n-\t}\n+\t\tbuf_len = read_file(data_file, &buf);\n+\t\tif (buf_len <= 0) {\n+\t\t\tprintf(\"Error, can't read file, or file is empty.\\n\");\n+\t\t\tres = -EXIT_FAILURE;\n+\t\t\tgoto end;\n+\t\t}\n \n-\tif (job_len > nb_max_payload) {\n-\t\tprintf(\"Error, not enough jobs to cover input.\\n\");\n-\t\tres = -EXIT_FAILURE;\n-\t\tgoto end;\n-\t}\n+\t\tjob_len = buf_len / nb_jobs;\n+\t\tif (job_len == 0) {\n+\t\t\tprintf(\"Error, To many jobs, for the given input.\\n\");\n+\t\t\tres = -EXIT_FAILURE;\n+\t\t\tgoto end;\n+\t\t}\n+\n+\t\tif (job_len > nb_max_payload) {\n+\t\t\tprintf(\"Error, not enough jobs to cover input.\\n\");\n+\t\t\tres = -EXIT_FAILURE;\n+\t\t\tgoto end;\n+\t\t}\n \n-\t/* Assign each mbuf with the data to handle. */\n-\tfor (i = 0; (pos < buf_len) && (i < nb_jobs) ; i++) {\n-\t\tlong act_job_len = RTE_MIN(job_len, buf_len - pos);\n-\t\trte_pktmbuf_attach_extbuf(ops[i]->mbuf, &buf[pos], 0,\n-\t\t\t\t\t  act_job_len, &shinfo);\n-\t\tjobs_ctx[i].mbuf = ops[i]->mbuf;\n-\t\tops[i]->mbuf->data_len = job_len;\n-\t\tops[i]->mbuf->pkt_len = act_job_len;\n-\t\tops[i]->user_id = i;\n-\t\tops[i]->group_id0 = 1;\n-\t\tpos += act_job_len;\n-\t\tactual_jobs++;\n+\t\t/* Assign each mbuf with the data to handle. */\n+\t\tactual_jobs = 0;\n+\t\tpos = 0;\n+\t\tfor (i = 0; (pos < buf_len) && (i < nb_jobs) ; i++) {\n+\t\t\tlong act_job_len = RTE_MIN(job_len, buf_len - pos);\n+\t\t\trte_pktmbuf_attach_extbuf(ops[i]->mbuf, &buf[pos], 0,\n+\t\t\t\t\tact_job_len, &shinfo);\n+\t\t\tjobs_ctx[i].mbuf = ops[i]->mbuf;\n+\t\t\tops[i]->mbuf->data_len = job_len;\n+\t\t\tops[i]->mbuf->pkt_len = act_job_len;\n+\t\t\tops[i]->user_id = i;\n+\t\t\tops[i]->group_id0 = 1;\n+\t\t\tpos += act_job_len;\n+\t\t\tactual_jobs++;\n+\t\t}\n+\n+\t\tqp->buf = buf;\n+\t\tqp->total_matches = 0;\n \t}\n \n \tstart = clock();\n \tfor (i = 0; i < nb_iterations; i++) {\n-\t\ttotal_enqueue = 0;\n-\t\ttotal_dequeue = 0;\n-\t\twhile (total_dequeue < actual_jobs) {\n-\t\t\tstruct rte_regex_ops **cur_ops_to_enqueue = ops +\n-\t\t\t\ttotal_enqueue;\n-\t\t\tstruct rte_regex_ops **cur_ops_to_dequeue = ops +\n-\t\t\t\ttotal_dequeue;\n-\n-\t\t\tif (actual_jobs - total_enqueue)\n-\t\t\t\ttotal_enqueue += rte_regexdev_enqueue_burst\n-\t\t\t\t\t(dev_id, qp_id, cur_ops_to_enqueue,\n-\t\t\t\t\t actual_jobs - total_enqueue);\n-\n-\t\t\ttotal_dequeue += rte_regexdev_dequeue_burst\n-\t\t\t\t(dev_id, qp_id, cur_ops_to_dequeue,\n-\t\t\t\t total_enqueue - total_dequeue);\n+\t\tfor (qp_id = 0; qp_id < nb_qps; qp_id++) {\n+\t\t\tqp = &qps[qp_id];\n+\t\t\tqp->total_enqueue = 0;\n+\t\t\tqp->total_dequeue = 0;\n \t\t}\n+\t\tdo {\n+\t\t\tupdate = false;\n+\t\t\tfor (qp_id = 0; qp_id < nb_qps; qp_id++) {\n+\t\t\t\tqp = &qps[qp_id];\n+\t\t\t\tif (qp->total_dequeue < actual_jobs) {\n+\t\t\t\t\tstruct rte_regex_ops **\n+\t\t\t\t\t\tcur_ops_to_enqueue = qp->ops +\n+\t\t\t\t\t\tqp->total_enqueue;\n+\n+\t\t\t\t\tif (actual_jobs - qp->total_enqueue)\n+\t\t\t\t\t\tqp->total_enqueue +=\n+\t\t\t\t\t\trte_regexdev_enqueue_burst\n+\t\t\t\t\t\t\t(dev_id,\n+\t\t\t\t\t\t\tqp_id,\n+\t\t\t\t\t\t\tcur_ops_to_enqueue,\n+\t\t\t\t\t\t\tactual_jobs -\n+\t\t\t\t\t\t\tqp->total_enqueue);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tfor (qp_id = 0; qp_id < nb_qps; qp_id++) {\n+\t\t\t\tqp = &qps[qp_id];\n+\t\t\t\tif (qp->total_dequeue < actual_jobs) {\n+\t\t\t\t\tstruct rte_regex_ops **\n+\t\t\t\t\t\tcur_ops_to_dequeue = qp->ops +\n+\t\t\t\t\t\tqp->total_dequeue;\n+\n+\t\t\t\t\tqp->total_dequeue +=\n+\t\t\t\t\t\trte_regexdev_dequeue_burst\n+\t\t\t\t\t\t\t(dev_id,\n+\t\t\t\t\t\t\tqp_id,\n+\t\t\t\t\t\t\tcur_ops_to_dequeue,\n+\t\t\t\t\t\t\tqp->total_enqueue -\n+\t\t\t\t\t\t\tqp->total_dequeue);\n+\t\t\t\t\tupdate = true;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} while (update);\n \t}\n \tend = clock();\n \ttime = ((double)end - start) / CLOCKS_PER_SEC;\n@@ -364,51 +437,59 @@ run_regex(uint32_t nb_jobs,\n \t       (((double)actual_jobs * job_len * nb_iterations * 8) / time) /\n \t\t1000000000.0);\n \n-\tif (!perf_mode) {\n+\tif (perf_mode)\n+\t\tgoto end;\n+\tfor (qp_id = 0; qp_id < nb_qps; qp_id++) {\n+\t\tprintf(\"\\n############ QP id=%u ############\\n\", qp_id);\n+\t\tqp = &qps[qp_id];\n \t\t/* Log results per job. */\n-\t\tfor (d_ind = 0; d_ind < total_dequeue; d_ind++) {\n-\t\t\tnb_matches = ops[d_ind % actual_jobs]->nb_matches;\n+\t\tfor (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {\n+\t\t\tnb_matches = qp->ops[d_ind % actual_jobs]->nb_matches;\n \t\t\tprintf(\"Job id %\"PRIu64\" number of matches = %d\\n\",\n-\t\t\t       ops[d_ind]->user_id, nb_matches);\n-\t\t\ttotal_matches += nb_matches;\n-\t\t\tmatch = ops[d_ind % actual_jobs]->matches;\n+\t\t\t\t\tqp->ops[d_ind]->user_id, nb_matches);\n+\t\t\tqp->total_matches += nb_matches;\n+\t\t\tmatch = qp->ops[d_ind % actual_jobs]->matches;\n \t\t\tfor (i = 0; i < nb_matches; i++) {\n-\t\t\t\tprintf(\"match %d, rule = %d, start = %d,len = %d\\n\",\n+\t\t\t\tprintf(\"match %d, rule = %d, \"\n+\t\t\t\t       \"start = %d,len = %d\\n\",\n \t\t\t\t       i, match->rule_id, match->start_offset,\n \t\t\t\t       match->len);\n \t\t\t\tmatch++;\n \t\t\t}\n \t\t}\n-\t\tprintf(\"Total matches = %d\\n\", total_matches);\n+\t\tprintf(\"Total matches = %d\\n\", qp->total_matches);\n \t\tprintf(\"All Matches:\\n\");\n-\n \t\t/* Log absolute results. */\n-\t\tfor (d_ind = 0; d_ind < total_dequeue; d_ind++) {\n-\t\t\tnb_matches = ops[d_ind % actual_jobs]->nb_matches;\n-\t\t\ttotal_matches += nb_matches;\n-\t\t\tmatch = ops[d_ind % actual_jobs]->matches;\n+\t\tfor (d_ind = 0; d_ind < qp->total_dequeue; d_ind++) {\n+\t\t\tnb_matches = qp->ops[d_ind % actual_jobs]->nb_matches;\n+\t\t\tqp->total_matches += nb_matches;\n+\t\t\tmatch = qp->ops[d_ind % actual_jobs]->matches;\n \t\t\tfor (i = 0; i < nb_matches; i++) {\n \t\t\t\tprintf(\"start = %ld, len = %d, rule = %d\\n\",\n-\t\t\t\t       match->start_offset + d_ind * job_len,\n-\t\t\t\t       match->len, match->rule_id);\n+\t\t\t\t\t\tmatch->start_offset +\n+\t\t\t\t\t\td_ind * job_len,\n+\t\t\t\t\t\tmatch->len, match->rule_id);\n \t\t\t\tmatch++;\n \t\t\t}\n \t\t}\n \t}\n end:\n-\tfor (i = 0; i < actual_jobs; i++) {\n-\t\tif (ops[i])\n-\t\t\trte_free(ops[i]);\n-\t\tif (jobs_ctx[i].mbuf)\n-\t\t\trte_pktmbuf_free(jobs_ctx[i].mbuf);\n+\tfor (qp_id = 0; qp_id < qps_used; qp_id++) {\n+\t\tqp = &qps[qp_id];\n+\t\tfor (i = 0; i < actual_jobs && qp->ops; i++)\n+\t\t\trte_free(qp->ops[i]);\n+\t\trte_free(qp->ops);\n+\t\tqp->ops = NULL;\n+\t\tfor (i = 0; i < actual_jobs && qp->jobs_ctx; i++)\n+\t\t\trte_pktmbuf_free(qp->jobs_ctx[i].mbuf);\n+\t\trte_free(qp->jobs_ctx);\n+\t\tqp->jobs_ctx = NULL;\n+\t\trte_free(qp->buf);\n+\t\tqp->buf = NULL;\n \t}\n-\trte_free(ops);\n-\trte_free(jobs_ctx);\n-\tif (buf)\n-\t\trte_free(buf);\n \tif (mbuf_mp)\n \t\trte_mempool_free(mbuf_mp);\n-\n+\trte_free(qps);\n \treturn res;\n }\n \n@@ -418,12 +499,14 @@ main(int argc, char **argv)\n \tchar rules_file[MAX_FILE_NAME];\n \tchar data_file[MAX_FILE_NAME];\n \tuint32_t nb_jobs = 0;\n-\tuint16_t nb_max_payload = 0;\n \tbool perf_mode = 0;\n \tuint32_t nb_iterations = 0;\n-\tuint8_t nb_max_matches = 0;\n \tint ret;\n+\tuint16_t nb_max_payload = 0;\n+\tuint8_t nb_max_matches = 0;\n+\tuint32_t nb_qps = 1;\n \n+\t/* Init EAL. */\n \tret = rte_eal_init(argc, argv);\n \tif (ret < 0)\n \t\trte_exit(EXIT_FAILURE, \"EAL init failed\\n\");\n@@ -431,13 +514,16 @@ main(int argc, char **argv)\n \targv += ret;\n \tif (argc > 1)\n \t\targs_parse(argc, argv, rules_file, data_file, &nb_jobs,\n-\t\t\t   &perf_mode, &nb_iterations);\n+\t\t\t\t&perf_mode, &nb_iterations, &nb_qps);\n \n-\tret = init_port(&nb_max_payload, rules_file, &nb_max_matches);\n+\tif (nb_qps == 0)\n+\t\trte_exit(EXIT_FAILURE, \"Number of QPs must be greater than 0\\n\");\n+\tret = init_port(&nb_max_payload, rules_file,\n+\t\t\t&nb_max_matches, nb_qps);\n \tif (ret < 0)\n \t\trte_exit(EXIT_FAILURE, \"init port failed\\n\");\n \tret = run_regex(nb_jobs, nb_max_payload, perf_mode,\n-\t\t\tnb_iterations, data_file, nb_max_matches);\n+\t\t\tnb_iterations, data_file, nb_max_matches, nb_qps);\n \tif (ret < 0) {\n \t\trte_exit(EXIT_FAILURE, \"RegEx function failed\\n\");\n \t}\n",
    "prefixes": [
        "v1",
        "2/6"
    ]
}