1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Intel Corporation
13 #include <rte_string_fns.h>
16 #include "comp_perf_options.h"
18 #define CPERF_PTEST_TYPE ("ptest")
19 #define CPERF_DRIVER_NAME ("driver-name")
20 #define CPERF_TEST_FILE ("input-file")
21 #define CPERF_SEG_SIZE ("seg-sz")
22 #define CPERF_BURST_SIZE ("burst-sz")
23 #define CPERF_EXTENDED_SIZE ("extended-input-sz")
24 #define CPERF_POOL_SIZE ("pool-sz")
25 #define CPERF_MAX_SGL_SEGS ("max-num-sgl-segs")
26 #define CPERF_NUM_ITER ("num-iter")
27 #define CPERF_OPTYPE ("operation")
28 #define CPERF_HUFFMAN_ENC ("huffman-enc")
29 #define CPERF_LEVEL ("compress-level")
30 #define CPERF_WINDOW_SIZE ("window-sz")
31 #define CPERF_EXTERNAL_MBUFS ("external-mbufs")
33 /* cyclecount-specific options */
34 #define CPERF_CYCLECOUNT_DELAY_US ("cc-delay-us")
44 printf("%s [EAL options] --\n"
45 " --ptest throughput / verify / pmd-cyclecount\n"
46 " --driver-name NAME: compress driver to use\n"
47 " --input-file NAME: file to compress and decompress\n"
48 " --extended-input-sz N: extend file data up to this size (default: no extension)\n"
49 " --seg-sz N: size of segment to store the data (default: 2048)\n"
50 " --burst-sz N: compress operation burst size\n"
51 " --pool-sz N: mempool size for compress operations/mbufs\n"
53 " --max-num-sgl-segs N: maximum number of segments for each mbuf\n"
55 " --num-iter N: number of times the file will be\n"
56 " compressed/decompressed (default: 10000)\n"
57 " --operation [comp/decomp/comp_and_decomp]: perform test on\n"
58 " compression, decompression or both operations\n"
59 " --huffman-enc [fixed/dynamic/default]: Huffman encoding\n"
60 " (default: dynamic)\n"
61 " --compress-level N: compression level, which could be a single value, list or range\n"
62 " (default: range between 1 and 9)\n"
63 " --window-sz N: base two log value of compression window size\n"
64 " (e.g.: 15 => 32k, default: max supported by PMD)\n"
65 " --external-mbufs: use memzones as external buffers instead of\n"
66 " keeping the data directly in mbuf area\n"
67 " --cc-delay-us N: delay between enqueue and dequeue operations in microseconds\n"
68 " valid only for cyclecount perf test (default: 500 us)\n"
69 " -h: prints this help\n",
74 get_str_key_id_mapping(struct name_id_map *map, unsigned int map_len,
79 for (i = 0; i < map_len; i++) {
81 if (strcmp(str_key, map[i].name) == 0)
89 parse_cperf_test_type(struct comp_test_data *test_data, const char *arg)
91 struct name_id_map cperftest_namemap[] = {
93 comp_perf_test_type_strs[CPERF_TEST_TYPE_THROUGHPUT],
94 CPERF_TEST_TYPE_THROUGHPUT
97 comp_perf_test_type_strs[CPERF_TEST_TYPE_VERIFY],
98 CPERF_TEST_TYPE_VERIFY
101 comp_perf_test_type_strs[CPERF_TEST_TYPE_PMDCC],
102 CPERF_TEST_TYPE_PMDCC
106 int id = get_str_key_id_mapping(
107 (struct name_id_map *)cperftest_namemap,
108 RTE_DIM(cperftest_namemap), arg);
110 RTE_LOG(ERR, USER1, "failed to parse test type");
114 test_data->test = (enum cperf_test_type)id;
120 parse_uint32_t(uint32_t *value, const char *arg)
123 unsigned long n = strtoul(arg, &end, 10);
125 if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
131 *value = (uint32_t) n;
137 parse_uint16_t(uint16_t *value, const char *arg)
140 int ret = parse_uint32_t(&val, arg);
145 if (val > UINT16_MAX)
148 *value = (uint16_t) val;
154 parse_range(const char *arg, uint8_t *min, uint8_t *max, uint8_t *inc)
159 char *copy_arg = strdup(arg);
161 if (copy_arg == NULL)
165 token = strtok(copy_arg, ":");
167 /* Parse minimum value */
169 number = strtoul(token, NULL, 10);
171 if (errno == EINVAL || errno == ERANGE)
178 token = strtok(NULL, ":");
180 /* Parse increment value */
182 number = strtoul(token, NULL, 10);
184 if (errno == EINVAL || errno == ERANGE ||
192 token = strtok(NULL, ":");
194 /* Parse maximum value */
196 number = strtoul(token, NULL, 10);
198 if (errno == EINVAL || errno == ERANGE ||
206 if (strtok(NULL, ":") != NULL)
218 parse_list(const char *arg, uint8_t *list, uint8_t *min, uint8_t *max)
226 char *copy_arg = strdup(arg);
228 if (copy_arg == NULL)
232 token = strtok(copy_arg, ",");
234 /* Parse first value */
236 number = strtoul(token, NULL, 10);
238 if (errno == EINVAL || errno == ERANGE)
241 list[count++] = number;
247 token = strtok(NULL, ",");
249 while (token != NULL) {
250 if (count == MAX_LIST) {
251 RTE_LOG(WARNING, USER1,
252 "Using only the first %u sizes\n",
257 number = strtoul(token, NULL, 10);
259 if (errno == EINVAL || errno == ERANGE)
262 list[count++] = number;
264 if (number < temp_min)
266 if (number > temp_max)
269 token = strtok(NULL, ",");
286 parse_num_iter(struct comp_test_data *test_data, const char *arg)
288 int ret = parse_uint32_t(&test_data->num_iter, arg);
291 RTE_LOG(ERR, USER1, "Failed to parse total iteration count\n");
295 if (test_data->num_iter == 0) {
297 "Total number of iterations must be higher than 0\n");
305 parse_pool_sz(struct comp_test_data *test_data, const char *arg)
307 int ret = parse_uint32_t(&test_data->pool_sz, arg);
310 RTE_LOG(ERR, USER1, "Failed to parse pool size");
314 if (test_data->pool_sz == 0) {
315 RTE_LOG(ERR, USER1, "Pool size must be higher than 0\n");
323 parse_burst_sz(struct comp_test_data *test_data, const char *arg)
325 int ret = parse_uint16_t(&test_data->burst_sz, arg);
328 RTE_LOG(ERR, USER1, "Failed to parse burst size/s\n");
332 if (test_data->burst_sz == 0) {
333 RTE_LOG(ERR, USER1, "Burst size must be higher than 0\n");
341 parse_extended_input_sz(struct comp_test_data *test_data, const char *arg)
344 int ret = parse_uint32_t(&tmp, arg);
347 RTE_LOG(ERR, USER1, "Failed to parse extended input size\n");
350 test_data->input_data_sz = tmp;
354 "Extended file size must be higher than 0\n");
361 parse_seg_sz(struct comp_test_data *test_data, const char *arg)
363 int ret = parse_uint16_t(&test_data->seg_sz, arg);
366 RTE_LOG(ERR, USER1, "Failed to parse segment size\n");
370 if (test_data->seg_sz < MIN_COMPRESSED_BUF_SIZE) {
371 RTE_LOG(ERR, USER1, "Segment size must be higher than %d\n",
372 MIN_COMPRESSED_BUF_SIZE - 1);
376 if (test_data->seg_sz > MAX_SEG_SIZE) {
377 RTE_LOG(ERR, USER1, "Segment size must be lower than %d\n",
386 parse_max_num_sgl_segs(struct comp_test_data *test_data, const char *arg)
388 int ret = parse_uint16_t(&test_data->max_sgl_segs, arg);
392 "Failed to parse max number of segments per mbuf chain\n");
396 if (test_data->max_sgl_segs == 0) {
397 RTE_LOG(ERR, USER1, "Max number of segments per mbuf chain "
398 "must be higher than 0\n");
406 parse_window_sz(struct comp_test_data *test_data, const char *arg)
409 int ret = parse_uint16_t(&tmp, arg);
412 RTE_LOG(ERR, USER1, "Failed to parse window size\n");
415 test_data->window_sz = (int)tmp;
421 parse_driver_name(struct comp_test_data *test_data, const char *arg)
423 if (strlen(arg) > (sizeof(test_data->driver_name) - 1))
426 strlcpy(test_data->driver_name, arg,
427 sizeof(test_data->driver_name));
433 parse_test_file(struct comp_test_data *test_data, const char *arg)
435 if (strlen(arg) > (sizeof(test_data->input_file) - 1))
438 strlcpy(test_data->input_file, arg, sizeof(test_data->input_file));
444 parse_op_type(struct comp_test_data *test_data, const char *arg)
446 struct name_id_map optype_namemap[] = {
461 int id = get_str_key_id_mapping(optype_namemap,
462 RTE_DIM(optype_namemap), arg);
464 RTE_LOG(ERR, USER1, "Invalid operation type specified\n");
468 test_data->test_op = (enum comp_operation)id;
474 parse_huffman_enc(struct comp_test_data *test_data, const char *arg)
476 struct name_id_map huffman_namemap[] = {
479 RTE_COMP_HUFFMAN_DEFAULT
483 RTE_COMP_HUFFMAN_FIXED
487 RTE_COMP_HUFFMAN_DYNAMIC
491 int id = get_str_key_id_mapping(huffman_namemap,
492 RTE_DIM(huffman_namemap), arg);
494 RTE_LOG(ERR, USER1, "Invalid Huffmane encoding specified\n");
498 test_data->huffman_enc = (enum rte_comp_huffman)id;
504 parse_level(struct comp_test_data *test_data, const char *arg)
509 * Try parsing the argument as a range, if it fails,
512 if (parse_range(arg, &test_data->level_lst.min,
513 &test_data->level_lst.max,
514 &test_data->level_lst.inc) < 0) {
515 ret = parse_list(arg, test_data->level_lst.list,
516 &test_data->level_lst.min,
517 &test_data->level_lst.max);
520 "Failed to parse compression level/s\n");
523 test_data->level_lst.count = ret;
525 if (test_data->level_lst.max > RTE_COMP_LEVEL_MAX) {
526 RTE_LOG(ERR, USER1, "Level cannot be higher than %u\n",
536 parse_external_mbufs(struct comp_test_data *test_data,
537 const char *arg __rte_unused)
539 test_data->use_external_mbufs = 1;
544 parse_cyclecount_delay_us(struct comp_test_data *test_data,
547 int ret = parse_uint32_t(&(test_data->cyclecount_delay), arg);
550 RTE_LOG(ERR, USER1, "Failed to parse cyclecount delay\n");
556 typedef int (*option_parser_t)(struct comp_test_data *test_data,
559 struct long_opt_parser {
560 const char *lgopt_name;
561 option_parser_t parser_fn;
564 static struct option lgopts[] = {
565 { CPERF_PTEST_TYPE, required_argument, 0, 0 },
566 { CPERF_DRIVER_NAME, required_argument, 0, 0 },
567 { CPERF_TEST_FILE, required_argument, 0, 0 },
568 { CPERF_SEG_SIZE, required_argument, 0, 0 },
569 { CPERF_BURST_SIZE, required_argument, 0, 0 },
570 { CPERF_EXTENDED_SIZE, required_argument, 0, 0 },
571 { CPERF_POOL_SIZE, required_argument, 0, 0 },
572 { CPERF_MAX_SGL_SEGS, required_argument, 0, 0},
573 { CPERF_NUM_ITER, required_argument, 0, 0 },
574 { CPERF_OPTYPE, required_argument, 0, 0 },
575 { CPERF_HUFFMAN_ENC, required_argument, 0, 0 },
576 { CPERF_LEVEL, required_argument, 0, 0 },
577 { CPERF_WINDOW_SIZE, required_argument, 0, 0 },
578 { CPERF_EXTERNAL_MBUFS, 0, 0, 0 },
579 { CPERF_CYCLECOUNT_DELAY_US, required_argument, 0, 0 },
584 comp_perf_opts_parse_long(int opt_idx, struct comp_test_data *test_data)
586 struct long_opt_parser parsermap[] = {
587 { CPERF_PTEST_TYPE, parse_cperf_test_type },
588 { CPERF_DRIVER_NAME, parse_driver_name },
589 { CPERF_TEST_FILE, parse_test_file },
590 { CPERF_SEG_SIZE, parse_seg_sz },
591 { CPERF_BURST_SIZE, parse_burst_sz },
592 { CPERF_EXTENDED_SIZE, parse_extended_input_sz },
593 { CPERF_POOL_SIZE, parse_pool_sz },
594 { CPERF_MAX_SGL_SEGS, parse_max_num_sgl_segs },
595 { CPERF_NUM_ITER, parse_num_iter },
596 { CPERF_OPTYPE, parse_op_type },
597 { CPERF_HUFFMAN_ENC, parse_huffman_enc },
598 { CPERF_LEVEL, parse_level },
599 { CPERF_WINDOW_SIZE, parse_window_sz },
600 { CPERF_EXTERNAL_MBUFS, parse_external_mbufs },
601 { CPERF_CYCLECOUNT_DELAY_US, parse_cyclecount_delay_us },
605 for (i = 0; i < RTE_DIM(parsermap); i++) {
606 if (strncmp(lgopts[opt_idx].name, parsermap[i].lgopt_name,
607 strlen(lgopts[opt_idx].name)) == 0)
608 return parsermap[i].parser_fn(test_data, optarg);
615 comp_perf_options_parse(struct comp_test_data *test_data, int argc, char **argv)
617 int opt, retval, opt_idx;
619 while ((opt = getopt_long(argc, argv, "h", lgopts, &opt_idx)) != EOF) {
623 rte_exit(EXIT_SUCCESS, "Displayed help\n");
627 retval = comp_perf_opts_parse_long(opt_idx, test_data);
643 comp_perf_options_default(struct comp_test_data *test_data)
645 test_data->seg_sz = 2048;
646 test_data->burst_sz = 32;
647 test_data->pool_sz = 8192;
648 test_data->max_sgl_segs = 16;
649 test_data->num_iter = 10000;
650 test_data->huffman_enc = RTE_COMP_HUFFMAN_DYNAMIC;
651 test_data->test_op = COMPRESS_DECOMPRESS;
652 test_data->window_sz = -1;
653 test_data->level_lst.min = RTE_COMP_LEVEL_MIN;
654 test_data->level_lst.max = RTE_COMP_LEVEL_MAX;
655 test_data->level_lst.inc = 1;
656 test_data->test = CPERF_TEST_TYPE_THROUGHPUT;
657 test_data->use_external_mbufs = 0;
658 test_data->cyclecount_delay = 500;
662 comp_perf_options_check(struct comp_test_data *test_data)
664 if (test_data->driver_name[0] == '\0') {
665 RTE_LOG(ERR, USER1, "Driver name has to be set\n");
669 if (test_data->input_file[0] == '\0') {
670 RTE_LOG(ERR, USER1, "Input file name has to be set\n");