get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 75014,
    "url": "http://patches.dpdk.org/api/patches/75014/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1596046198-134903-1-git-send-email-orika@mellanox.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": "<1596046198-134903-1-git-send-email-orika@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1596046198-134903-1-git-send-email-orika@mellanox.com",
    "date": "2020-07-29T18:09:57",
    "name": "[v4] app/test-regex: add RegEx test application",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "a5afae297b9614218f40f79e0346af8830078a88",
    "submitter": {
        "id": 795,
        "url": "http://patches.dpdk.org/api/people/795/?format=api",
        "name": "Ori Kam",
        "email": "orika@mellanox.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/1596046198-134903-1-git-send-email-orika@mellanox.com/mbox/",
    "series": [
        {
            "id": 11407,
            "url": "http://patches.dpdk.org/api/series/11407/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=11407",
            "date": "2020-07-29T18:09:57",
            "name": "[v4] app/test-regex: add RegEx test application",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/11407/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/75014/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/75014/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 2D004A052B;\n\tWed, 29 Jul 2020 20:10:40 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id DCEA837B7;\n\tWed, 29 Jul 2020 20:10:38 +0200 (CEST)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id F135710A3\n for <dev@dpdk.org>; Wed, 29 Jul 2020 20:10:36 +0200 (CEST)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n orika@mellanox.com) with SMTP; 29 Jul 2020 21:10:34 +0300",
            "from pegasus04.mtr.labs.mlnx. (pegasus04.mtr.labs.mlnx\n [10.210.16.126])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 06TIAYEp031107;\n Wed, 29 Jul 2020 21:10:34 +0300"
        ],
        "From": "Ori Kam <orika@mellanox.com>",
        "To": "jerinj@marvell.com, xiang.w.wang@intel.com, matan@mellanox.com,\n viacheslavo@mellanox.com, John McNamara <john.mcnamara@intel.com>,\n Marko Kovacevic <marko.kovacevic@intel.com>",
        "Cc": "guyk@marvell.com, dev@dpdk.org, pbhagavatula@marvell.com,\n shahafs@mellanox.com, hemant.agrawal@nxp.com, opher@mellanox.com,\n alexr@mellanox.com, dovrat@marvell.com, pkapoor@marvell.com,\n nipun.gupta@nxp.com, bruce.richardson@intel.com, yang.a.hong@intel.com,\n harry.chang@intel.com, gu.jian1@zte.com.cn, shanjiangh@chinatelecom.cn,\n zhangy.yun@chinatelecom.cn, lixingfu@huachentel.com,\n wushuai@inspur.com, yuyingxia@yxlink.com, fanchenggang@sunyainfo.com,\n davidfgao@tencent.com, liuzhong1@chinaunicom.cn, zhaoyong11@huawei.com,\n oc@yunify.com, jim@netgate.com, hongjun.ni@intel.com, deri@ntop.org,\n fc@napatech.com, arthur.su@lionic.com, thomas@monjalon.net,\n orika@mellanox.com, rasland@mellanox.com,\n Yuval Avnery <yuvalav@mellanox.com>",
        "Date": "Wed, 29 Jul 2020 18:09:57 +0000",
        "Message-Id": "<1596046198-134903-1-git-send-email-orika@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1595793496-73205-1-git-send-email-orika@mellanox.com>",
        "References": "<1595793496-73205-1-git-send-email-orika@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v4] app/test-regex: add RegEx test application",
        "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": "From: Yuval Avnery <yuvalav@mellanox.com>\n\nFollowing the new RegEx class.\nThere is a need to create a dedicated test application in order to\nvalidate this class and PMD.\n\nUnlike net device this application loads data from a file.\n\nThis commit introduces the new RegEx test app.\n\nThe basic app flow:\n1. Configure the RegEx device to use one queue, and set the rule\n   database, using precompiled file.\n2. Allocate mbufs based on the requested number of jobs, each job will\ni  get one mbuf.\n3. Enqueue as much as possible jobs.\n4. Dequeue jobs.\n5. if the number of dequeue jobs < requested number of jobs job to step\n\nSigned-off-by: Ori Kam <orika@mellanox.com>\nSigned-off-by: Yuval Avnery <yuvalav@mellanox.com>\n---\nv4:\n * Address ML comments.\nv3:\n * Fix possible issue in case of error.\nv2:\n * Remove rule file and data generation data.\n * Address ML comments. \n---\n app/Makefile                   |   1 +\n app/meson.build                |   1 +\n app/test-regex/Makefile        |  17 ++\n app/test-regex/main.c          | 436 +++++++++++++++++++++++++++++++++++++++++\n app/test-regex/meson.build     |   5 +\n doc/guides/tools/index.rst     |   1 +\n doc/guides/tools/testregex.rst |  73 +++++++\n 7 files changed, 534 insertions(+)\n create mode 100644 app/test-regex/Makefile\n create mode 100644 app/test-regex/main.c\n create mode 100644 app/test-regex/meson.build\n create mode 100644 doc/guides/tools/testregex.rst",
    "diff": "diff --git a/app/Makefile b/app/Makefile\nindex 0392a7d..453c4fe 100644\n--- a/app/Makefile\n+++ b/app/Makefile\n@@ -13,6 +13,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_FIB) += test-fib\n DIRS-$(CONFIG_RTE_TEST_FLOW_PERF) += test-flow-perf\n DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += test-pipeline\n DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += test-sad\n+DIRS-$(CONFIG_RTE_LIBRTE_REGEXDEV) += test-regex\n \n ifeq ($(CONFIG_RTE_LIBRTE_BBDEV),y)\n DIRS-$(CONFIG_RTE_TEST_BBDEV) += test-bbdev\ndiff --git a/app/meson.build b/app/meson.build\nindex 585b908..eb74f21 100644\n--- a/app/meson.build\n+++ b/app/meson.build\n@@ -18,6 +18,7 @@ apps = [\n \t'test-flow-perf',\n \t'test-pipeline',\n \t'test-pmd',\n+\t'test-regex',\n \t'test-sad']\n \n # for BSD only\ndiff --git a/app/test-regex/Makefile b/app/test-regex/Makefile\nnew file mode 100644\nindex 0000000..a059a8c\n--- /dev/null\n+++ b/app/test-regex/Makefile\n@@ -0,0 +1,17 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright 2020 Mellanox Technologies, Ltd\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+APP = testregex\n+\n+CFLAGS += -O3\n+CFLAGS += $(WERROR_FLAGS)\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+\n+#\n+# all source are stored in SRCS-y\n+#\n+SRCS-y := main.c\n+\n+include $(RTE_SDK)/mk/rte.app.mk\ndiff --git a/app/test-regex/main.c b/app/test-regex/main.c\nnew file mode 100644\nindex 0000000..9cdf1da\n--- /dev/null\n+++ b/app/test-regex/main.c\n@@ -0,0 +1,436 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2020 Mellanox Technologies, Ltd\n+ */\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <stdint.h>\n+#include <stdbool.h>\n+#include <stdarg.h>\n+#include <ctype.h>\n+#include <errno.h>\n+#include <getopt.h>\n+#include <signal.h>\n+\n+#include <rte_eal.h>\n+#include <rte_common.h>\n+#include <rte_malloc.h>\n+#include <rte_mempool.h>\n+#include <rte_mbuf.h>\n+#include <rte_cycles.h>\n+#include <rte_regexdev.h>\n+\n+#define MAX_FILE_NAME 255\n+#define MBUF_CACHE_SIZE 256\n+#define MBUF_SIZE (1 << 8)\n+#define START_BURST_SIZE 32u\n+\n+enum app_args {\n+\tARG_HELP,\n+\tARG_RULES_FILE_NAME,\n+\tARG_DATA_FILE_NAME,\n+\tARG_NUM_OF_JOBS,\n+\tARG_PERF_MODE,\n+\tARG_NUM_OF_ITERATIONS,\n+\n+};\n+\n+static void\n+usage(const char *prog_name)\n+{\n+\tprintf(\"%s [EAL options] --\\n\"\n+\t\t\" --rules NAME: precompiled rules file\\n\"\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\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+{\n+\tchar **argvopt;\n+\tint opt;\n+\tint opt_idx;\n+\tsize_t len;\n+\tstatic struct option lgopts[] = {\n+\t\t{ \"help\",  0, 0, ARG_HELP},\n+\t\t{ \"rules\",  1, 0, ARG_RULES_FILE_NAME},\n+\t\t/* Rules database file to load. */\n+\t\t{ \"data\",  1, 0, ARG_DATA_FILE_NAME},\n+\t\t/* Data file to load. */\n+\t\t{ \"nb_jobs\",  1, 0, ARG_NUM_OF_JOBS},\n+\t\t/* Number of jobs to create. */\n+\t\t{ \"perf\", 0, 0, ARG_PERF_MODE},\n+\t\t/* Perf test only */\n+\t\t{ \"nb_iter\", 1, 0, ARG_NUM_OF_ITERATIONS}\n+\t\t/* Number of iterations to run with perf test */\n+\t};\n+\n+\targvopt = argv;\n+\twhile ((opt = getopt_long(argc, argvopt, \"\",\n+\t\t\t\tlgopts, &opt_idx)) != EOF) {\n+\t\tswitch (opt) {\n+\t\tcase ARG_RULES_FILE_NAME:\n+\t\t\tlen = strnlen(optarg, MAX_FILE_NAME - 1);\n+\t\t\tif (len == MAX_FILE_NAME)\n+\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t \"Rule file name to long max %d\\n\",\n+\t\t\t\t\t MAX_FILE_NAME - 1);\n+\t\t\tstrncpy(rules_file, optarg, MAX_FILE_NAME - 1);\n+\t\t\tbreak;\n+\t\tcase ARG_DATA_FILE_NAME:\n+\t\t\tlen = strnlen(optarg, MAX_FILE_NAME - 1);\n+\t\t\tif (len == MAX_FILE_NAME)\n+\t\t\t\trte_exit(EXIT_FAILURE,\n+\t\t\t\t\t \"Data file name to long max %d\\n\",\n+\t\t\t\t\t MAX_FILE_NAME - 1);\n+\t\t\tstrncpy(data_file, optarg, MAX_FILE_NAME - 1);\n+\t\t\tbreak;\n+\t\tcase ARG_NUM_OF_JOBS:\n+\t\t\t*nb_jobs = atoi(optarg);\n+\t\t\tbreak;\n+\t\tcase ARG_PERF_MODE:\n+\t\t\t*perf_mode = true;\n+\t\t\tbreak;\n+\t\tcase ARG_NUM_OF_ITERATIONS:\n+\t\t\t*nb_iterations = atoi(optarg);\n+\t\t\tbreak;\n+\t\tcase ARG_HELP:\n+\t\t\tusage(\"RegEx test app\");\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tfprintf(stderr, \"Invalid option: %s\\n\", argv[optind]);\n+\t\t\tusage(\"RegEx test app\");\n+\t\t\trte_exit(EXIT_FAILURE, \"Invalid option\\n\");\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (!perf_mode)\n+\t\t*nb_iterations = 1;\n+}\n+\n+static long\n+read_file(char *file, char **buf)\n+{\n+\tFILE *fp;\n+\tlong buf_len = 0;\n+\tsize_t read_len;\n+\tint res = 0;\n+\n+\tfp = fopen(file, \"r\");\n+\tif (!fp)\n+\t\treturn -EIO;\n+\tif (fseek(fp, 0L, SEEK_END) == 0) {\n+\t\tbuf_len = ftell(fp);\n+\t\tif (buf_len == -1) {\n+\t\t\tres = EIO;\n+\t\t\tgoto error;\n+\t\t}\n+\t\t*buf = rte_malloc(NULL, sizeof(char) * (buf_len + 1), 4096);\n+\t\tif (!*buf) {\n+\t\t\tres = ENOMEM;\n+\t\t\tgoto error;\n+\t\t}\n+\t\tif (fseek(fp, 0L, SEEK_SET) != 0) {\n+\t\t\tres = EIO;\n+\t\t\tgoto error;\n+\t\t}\n+\t\tread_len = fread(*buf, sizeof(char), buf_len, fp);\n+\t\tif (read_len != (unsigned long)buf_len) {\n+\t\t\tres = EIO;\n+\t\t\tgoto error;\n+\t\t}\n+\t}\n+\tfclose(fp);\n+\treturn buf_len;\n+error:\n+\tprintf(\"Error, can't open file %s\\n, err = %d\", file, res);\n+\tif (fp)\n+\t\tfclose(fp);\n+\tif (*buf)\n+\t\trte_free(*buf);\n+\treturn -res;\n+}\n+\n+static int\n+init_port(struct rte_mempool **mbuf_mp, uint32_t nb_jobs,\n+\t  uint16_t *nb_max_payload, char *rules_file, uint8_t *nb_max_matches)\n+{\n+\tuint16_t 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_groups = 1,\n+\t};\n+\tstruct rte_regexdev_qp_conf qp_conf = {\n+\t\t.nb_desc = 1024,\n+\t\t.qp_conf_flags = RTE_REGEX_QUEUE_PAIR_CFG_OOS_F,\n+\t};\n+\tint res = 0;\n+\n+\tnum_devs = rte_regexdev_count();\n+\tif (num_devs == 0) {\n+\t\tprintf(\"Error, no devices detected.\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t*mbuf_mp = rte_pktmbuf_pool_create(\"mbuf_pool\", nb_jobs, 0,\n+\t\t\t\t\t  0, MBUF_SIZE, rte_socket_id());\n+\tif (*mbuf_mp == NULL) {\n+\t\tprintf(\"Error, can't create memory pool\\n\");\n+\t\tres = -ENOMEM;\n+\t\tgoto error;\n+\t}\n+\n+\trules_len = read_file(rules_file, &rules);\n+\tif (rules_len < 0) {\n+\t\tprintf(\"Error, can't read rules files.\\n\");\n+\t\tres = -EIO;\n+\t\tgoto error;\n+\t}\n+\n+\tfor (id = 0; id < num_devs; id++) {\n+\t\tres = rte_regexdev_info_get(id, &info);\n+\t\tif (res != 0) {\n+\t\t\tprintf(\"Error, can't get device info.\\n\");\n+\t\t\tgoto error;\n+\t\t}\n+\t\tprintf(\":: initializing dev: %d\\n\", id);\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\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+\t\tdev_conf.rule_db = rules;\n+\t\tres = rte_regexdev_configure(id, &dev_conf);\n+\t\tif (res < 0) {\n+\t\t\tprintf(\"Error, can't configure device %d.\\n\", id);\n+\t\t\tgoto error;\n+\t\t}\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}\n+\t\tprintf(\":: initializing device: %d done\\n\", id);\n+\t}\n+\trte_free(rules);\n+\treturn 0;\n+error:\n+\tif (rules)\n+\t\trte_free(rules);\n+\tif (*mbuf_mp)\n+\t\trte_mempool_free(*mbuf_mp);\n+\treturn res;\n+\n+}\n+\n+static void\n+extbuf_free_cb(void *addr __rte_unused, void *fcb_opaque __rte_unused)\n+{\n+\n+}\n+\n+static int\n+run_regex(struct rte_mempool *mbuf_mp, 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+{\n+\tchar *buf = NULL;\n+\tlong buf_len;\n+\tlong job_len;\n+\tuint32_t actual_jobs = 0;\n+\tuint32_t i;\n+\tstruct rte_regex_ops **ops;\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+\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+\n+\tshinfo.free_cb = extbuf_free_cb;\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+\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+\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+\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+\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+\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+\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\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}\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\t}\n+\t}\n+\tend = clock();\n+\ttime = ((double)end - start) / CLOCKS_PER_SEC;\n+\tprintf(\"Job len = %ld Bytes\\n\",  job_len);\n+\tprintf(\"Time = %lf sec\\n\",  time);\n+\tprintf(\"Perf = %lf Gbps\\n\",\n+\t       (((double)actual_jobs * job_len * nb_iterations * 8) / time) /\n+\t\t1000000000.0);\n+\n+\tif (!perf_mode) {\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\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\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\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(\"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\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\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\tif (ops[i]->mbuf)\n+\t\t\t\trte_pktmbuf_free(ops[i]->mbuf);\n+\t\t\trte_free(ops[i]);\n+\t\t}\n+\t}\n+\trte_free(ops);\n+\tif (buf)\n+\t\trte_free(buf);\n+\treturn res;\n+}\n+\n+int\n+main(int argc, char **argv)\n+{\n+\tchar rules_file[MAX_FILE_NAME];\n+\tchar data_file[MAX_FILE_NAME];\n+\tstruct rte_mempool *mbuf_mp = NULL;\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+\n+\tret = rte_eal_init(argc, argv);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"EAL init failed\\n\");\n+\targc -= ret;\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+\n+\tret = init_port(&mbuf_mp, nb_jobs, &nb_max_payload, rules_file,\n+\t\t\t&nb_max_matches);\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"init port failed\\n\");\n+\tret = run_regex(mbuf_mp, nb_jobs, nb_max_payload, perf_mode,\n+\t\t\tnb_iterations, data_file, nb_max_matches);\n+\tif (ret < 0) {\n+\t\trte_mempool_free(mbuf_mp);\n+\t\trte_exit(EXIT_FAILURE, \"RegEx function failed\\n\");\n+\t}\n+\trte_mempool_free(mbuf_mp);\n+\treturn 0;\n+}\ndiff --git a/app/test-regex/meson.build b/app/test-regex/meson.build\nnew file mode 100644\nindex 0000000..472677f\n--- /dev/null\n+++ b/app/test-regex/meson.build\n@@ -0,0 +1,5 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright 2020 Mellanox Technologies, Ltd\n+\n+sources = files('main.c')\n+deps = ['regexdev']\ndiff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst\nindex 4840cf47..c721943 100644\n--- a/doc/guides/tools/index.rst\n+++ b/doc/guides/tools/index.rst\n@@ -17,3 +17,4 @@ DPDK Tools User Guides\n     cryptoperf\n     comp_perf\n     testeventdev\n+    testregex\ndiff --git a/doc/guides/tools/testregex.rst b/doc/guides/tools/testregex.rst\nnew file mode 100644\nindex 0000000..347d607\n--- /dev/null\n+++ b/doc/guides/tools/testregex.rst\n@@ -0,0 +1,73 @@\n+.. SPDX-License-Identifier: BSD-3-Clause\n+   Copyright 2020 Mellanox Technologies, Ltd\n+\n+dpdk-test-regex Tool\n+====================\n+\n+The ``dpdk-test-regex`` tool is a Data Plane Development Kit (DPDK)\n+application that allows functional testing and performance measurement for\n+the RegEx PMDs.\n+The test supports only one core and one PMD.\n+It is based on precompiled rule file, and an input file, both of them can\n+be selected using command-line options.\n+\n+In general case, each PMD has its own rule file.\n+\n+The test outputs the following data:\n+\n+* Performance, in gigabit per second.\n+\n+* Matching results (rule id, position, length), for each job.\n+\n+* Matching results in absolute location (rule id, position , length),\n+  relative to the start of the input data.\n+\n+\n+Limitations\n+~~~~~~~~~~~\n+\n+* Only one queue is supported.\n+\n+* Supports only precompiled rules.\n+\n+\n+Application Options\n+~~~~~~~~~~~~~~~~~~~\n+\n+``--rules NAME``\n+  precompiled rule file\n+\n+``--data NAME``\n+  data file to use\n+\n+``--nb_jobs N``\n+  number of jobs to use\n+\n+``--perf N``\n+  only outputs the performance data\n+\n+``--nb_iter N``\n+  number of iteration to run\n+\n+``--help``\n+  prints this help\n+\n+\n+Running the Tool\n+----------------\n+\n+**Step 1: Compile a rule file**\n+\n+In order for the RegEx to work it must have a precompiled rule file.\n+to generate this file there is a need to use a RegEx compiler that matches the\n+RegEx PMD.\n+\n+**Step 2: Generate a data file**\n+\n+The data file, will be used as a source data for the RegEx to work on.\n+\n+**Step 3: Run the tool**\n+\n+The tool has a number of command line options. Here is the sample command line::\n+\n+   ./dpdk-test-regex -w 83:00.0 -- --rules rule_file.rof2 --data data_file.txt --job 100\n",
    "prefixes": [
        "v4"
    ]
}