From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 732B6A04A2; Wed, 3 Jun 2020 23:29:31 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1CA6E1D58A; Wed, 3 Jun 2020 23:29:31 +0200 (CEST) Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by dpdk.org (Postfix) with ESMTP id 3D9D71D585 for ; Wed, 3 Jun 2020 23:29:30 +0200 (CEST) Received: from Internal Mail-Server by MTLPINE1 (envelope-from orika@mellanox.com) with ESMTPS (AES256-SHA encrypted); 4 Jun 2020 00:29:28 +0300 Received: from pegasus03.mtr.labs.mlnx. (pegasus03.mtr.labs.mlnx [10.210.16.124]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 053LTSVD029877; Thu, 4 Jun 2020 00:29:28 +0300 From: Ori Kam To: jerinj@marvell.com, xiang.w.wang@intel.com Cc: guyk@marvell.com, dev@dpdk.org, pbhagavatula@marvell.com, shahafs@mellanox.com, hemant.agrawal@nxp.com, opher@mellanox.com, alexr@mellanox.com, dovrat@marvell.com, pkapoor@marvell.com, nipun.gupta@nxp.com, bruce.richardson@intel.com, yang.a.hong@intel.com, harry.chang@intel.com, gu.jian1@zte.com.cn, shanjiangh@chinatelecom.cn, zhangy.yun@chinatelecom.cn, lixingfu@huachentel.com, wushuai@inspur.com, yuyingxia@yxlink.com, fanchenggang@sunyainfo.com, davidfgao@tencent.com, liuzhong1@chinaunicom.cn, zhaoyong11@huawei.com, oc@yunify.com, jim@netgate.com, hongjun.ni@intel.com, j.bromhead@titan-ic.com, deri@ntop.org, fc@napatech.com, arthur.su@lionic.com, thomas@monjalon.net, orika@mellanox.com Date: Wed, 3 Jun 2020 21:29:12 +0000 Message-Id: <1591219752-46544-1-git-send-email-orika@mellanox.com> X-Mailer: git-send-email 1.8.3.1 Subject: [dpdk-dev] [RFC] 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Following the new RegEx class [1]. There is a need to create a dedecated test application in order to validate this class and PMD. Unlike net device this application loads data from a file. This commit introduce the new RegEx test app. The basic app flow: 1. query probed RegEx device. 2. configure the probed device accoding to the device caps. 3. read a rule database file. 4. read a data file to be searched. 5. allocate one mbuf. 6. select the request job len, based on the number of jobs requsted. 7. create one RegEx op which uses the mbuf defined in step 5. 8. attach the data buffer at offset 0 with len accoding to request len to the mbuf as external buffer. 9. enqueue one job. 10. wait for completion of the job. 11. check job results and print them. 12. move the mbuf to point to the next part of the buffer. 13. while there are more parts jump to 9. Future improvments to this application may include: 1. submiting more then one job at a time. 2. working with more then one queue. 3. support out of order. 4. allow runtime rule updating. This commit is only at RFC level, which means that the code is only basic reference and can't be compiled and doesn't include error or edge case handling. [1]https://patches.dpdk.org/cover/69919/ Signed-off-by: Ori Kam --- app/test-regex/main.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 app/test-regex/main.c diff --git a/app/test-regex/main.c b/app/test-regex/main.c new file mode 100644 index 0000000..ca90855 --- /dev/null +++ b/app/test-regex/main.c @@ -0,0 +1,217 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2020 Mellanox Technologies, Ltd + * + * This file contain the application main file + * This application provides a way to test the RegEx class. + */ + +#define HELP_VAL 0 +#define RULES_VAL 1 +#define DATA_VAL 2 +#define JOB_VAL 3 +#define MAX_FILE_NAME 255 +static char rules_file[MAX_FILE_NAME]; +static char data_file[MAX_FILE_NAME]; +static int jobs; +static struct rte_mempool *mbuf_mp; +static uint16_t nb_max_matches; +static uint8_t nb_max_matches; + +static void +args_parse(int argc, char **argv) +{ + char **argvopt; + int opt; + int opt_idx; + static struct option lgopts[] = { + { "help", 0, 0, HELP_VAL }, + { "rules", 1, 0, RULES_VAL }, + /* Rules database file to load. */ + { "data", 1, 0, DATA_VAL }, + /* Data file to load. */ + { "job", 1, 0, JOB_VAL }, + /* Number of jobs to create. */ + }; + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "", + lgopts, &opt_idx)) != EOF) { + switch (opt) { + case RULES_VAL: + strncpy(rules_file, optarg, MAX_FILE_NAME); + break; + case DATA_VAL: + strncpy(data_file, optarg, MAX_FILE_NAME); + break; + case JOB_VAL: + jobs = atoi(optarg); + break; + default: + fprintf(stderr, "Invalid option: %s\n", argv[optind]); + usage(argv[0]); + rte_exit(EXIT_SUCCESS, "Invalid option\n"); + break; + } + } +} + +static long +read_file(char *file, char **buf) +{ + FILE *fp; + long buf_len; + size_t read_len; + + fp = fopen(file, "r"); + if (fp != NULL) + return -EIO; + if (fseek(fp, 0L, SEEK_END) == 0) { + buf_len = ftell(fp); + if (buf_len == -1) + goto error; + *buf = rte_malloc(sizeof(char) * (buf_len + 1)); + if (fseek(fp, 0L, SEEK_SET) != 0) + goto error; + newLen = fread(source, sizeof(char), buf_len, fp); + if (new_len != buf_len) + goto error; + } + fclose(fp); + return buf_size; +error: + if (fp) + fclose(fp); + if (*buf) + rte_free(*buf); + return -EIO; +} + +static void +init_port(void) +{ + int ret; + uint16_t id; + uint16_t num_devs; + char *rules; + long rules_len; + char *data = NULL; + long data_size; + struct rte_regexdev_info info; + struct rte_regexdev_config dev_conf = { + .nb_queue_pairs = 1, + .nb_groups = 1, + }; + struct rte_regexdev_qp_conf qp_conf = { + .nb_desc = 1024, + }; + + num_devs = rte_regexdev_count(); + if (nr_ports == 0) + rte_exit(EXIT_FAILURE, "Error: no devices detected\n"); + + mbuf_mp = rte_pktmbuf_pool_create("mbuf_pool", + TOTAL_MBUF_NUM, MBUF_CACHE_SIZE, + 0, MBUF_SIZE, + rte_socket_id()); + if (mbuf_mp == NULL) + rte_exit(EXIT_FAILURE, "Error: can't init mbuf pool\n"); + rules_len = read_file(rule_file, &rules); + if (rule_size < 0) + rte_exit(EXIT_FAILURE, "Error: can't read rule file\n"); + for (id = 0; id < num_devs; id++) { + ret = rte_regexdev_info_get(id, &info); + if (ret != 0) + rte_exit(EXIT_FAILURE, + "Error during getting device" + " (port %u) info: %s\n", id, strerror(-ret)); + printf(":: initializing dev: %d\n", id); + nb_max_matches = info.max_matches; + if (info.regexdev_capa & RTE_REGEXDEV_SUPP_MATCH_AS_END_F) + conf->dev_cfg_flags |= RTE_REGEXDEV_CFG_MATCH_AS_END_F; + dev_conf->nb_max_matches = info.max_matches; + dev_conf->nb_rules_per_group = info.max_rules_per_group; + dev_conf->db_len = rules_len; + dev_conf->rule_db = rules; + ret = rte_regexdev_configure(id, &dev_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, + ":: cannot configure device: err=%d, dev=%u\n", + ret, port_id); + ret = rte_regexdev_queue_pair_setup(id, 0, qp_conf); + if (ret < 0) + rte_exit(EXIT_FAILURE, + ":: cannot configure qp %d: err=%d, dev=%u\n", + 0, ret, port_id); + ret = rte_regexdev_start(id); + if (ret < 0) + rte_exit(EXIT_FAILURE, "can't start dev %d\n", id); + printf(":: initializing device: %d done\n", id); + } +} + +void +main_loop(void) +{ + char *buf; + long buf_len; + long job_len; + int i; + struct rte_regex_ops *ops[1]; + uint16_t dev_id = 0; + uint16_t qp_id = 0; + uint32_t job_ind = 0; + uint8_t nb_matches; + struct rte_regexdev_match *match; + struct rte_mbuf *mbuf_job[1]; + long pos; + + ops[0] = rte_malloc(NULL, sizeof(*ops[0]) + nb_max_matches * + sizeof(struct rte_regexdev_match), 0); + if (!ops[0]) + goto main_loop_err; + ops[0]->group_id0 = 0; + buf_len = read_file(data_file, &buf); + if (buf_len <= 0) + return; + job_len = buf_len / jobs; + mbuf_job = rte_pktmbuf_allocate(mbuf_mp); + ops[0]->mbuf = mbuf_job; + pos = 0; + while (pos < buf_len) { + rte_pktmbuf_attach_extbuf(mbuf_job, pos, 0, job_len, NULL); + rte_regexdev_enqueue_burst(dev_id, qp_id, ops, 1); + while(rte_regexdev_dequeue_burst(dev_id, qp_id, ops, 1)); + nb_matches = ops[0]->nb_matches; + printf("Job id %d number of matches = %d\n", job_ind, + nb_matches); + match = ops[0]->matches; + for (i = 0; i < nb_maches; i++) { + printf("match %d, rule = %d, start = %d, len = %d\n", + i, match->rule_id, match->start_offet, + match->len); + match++; + } + pos += job_len; + } +main_loop_err: + if (ops[0]) + rte_free(ops[0]); +} + +int +main(int argc, char **argv) +{ + int ret; + + ret = rte_eal_init(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "EAL init failed\n"); + argc -= ret; + argv += ret; + if (argc > 1) + args_parse(argc, argv); + init_port(); + main_loop(); + return 0; +} -- 1.8.3.1