LCOV - code coverage report
Current view: top level - app/test-dma-perf - main.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 305 0.0 %
Date: 2025-12-01 19:08:10 Functions: 0 15 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdio.h>
       6                 :            : #include <stdlib.h>
       7                 :            : #include <getopt.h>
       8                 :            : #include <signal.h>
       9                 :            : #include <stdbool.h>
      10                 :            : #include <unistd.h>
      11                 :            : #include <sys/wait.h>
      12                 :            : #include <inttypes.h>
      13                 :            : #include <libgen.h>
      14                 :            : 
      15                 :            : #include <rte_argparse.h>
      16                 :            : #include <rte_eal.h>
      17                 :            : #include <rte_cfgfile.h>
      18                 :            : #include <rte_string_fns.h>
      19                 :            : #include <rte_lcore.h>
      20                 :            : #include <rte_dmadev.h>
      21                 :            : #include <rte_kvargs.h>
      22                 :            : 
      23                 :            : #include "main.h"
      24                 :            : 
      25                 :            : #define CSV_HDR_FMT "Case %u : %s,lcore,DMA,DMA ring size,kick batch size,buffer size(B),number of buffers,memory(MB),average cycle,bandwidth(Gbps),MOps\n"
      26                 :            : 
      27                 :            : #define DMA_MEM_COPY "DMA_MEM_COPY"
      28                 :            : #define CPU_MEM_COPY "CPU_MEM_COPY"
      29                 :            : 
      30                 :            : #define MAX_PARAMS_PER_ENTRY 4
      31                 :            : 
      32                 :            : #define MAX_TEST_CASES 16
      33                 :            : static struct test_configure test_cases[MAX_TEST_CASES];
      34                 :            : 
      35                 :            : #define GLOBAL_SECTION_NAME     "GLOBAL"
      36                 :            : struct global_configure global_cfg;
      37                 :            : 
      38                 :            : static char *config_path;
      39                 :            : static char *result_path;
      40                 :            : static bool  list_dma;
      41                 :            : 
      42                 :            : __rte_format_printf(1, 2)
      43                 :            : void
      44                 :          0 : output_csv(const char *fmt, ...)
      45                 :            : {
      46                 :            : #define MAX_OUTPUT_STR_LEN 512
      47                 :          0 :         char str[MAX_OUTPUT_STR_LEN] = {0};
      48                 :            :         va_list ap;
      49                 :            :         FILE *fd;
      50                 :            : 
      51                 :          0 :         fd = fopen(result_path, "a");
      52                 :          0 :         if (fd == NULL) {
      53                 :            :                 printf("Open output CSV file error.\n");
      54                 :          0 :                 return;
      55                 :            :         }
      56                 :            : 
      57                 :          0 :         va_start(ap, fmt);
      58                 :            :         vsnprintf(str, MAX_OUTPUT_STR_LEN, fmt, ap);
      59                 :          0 :         va_end(ap);
      60                 :            : 
      61                 :            :         fprintf(fd, "%s", str);
      62                 :            : 
      63                 :          0 :         fflush(fd);
      64                 :          0 :         fclose(fd);
      65                 :            : }
      66                 :            : 
      67                 :            : static void
      68                 :            : output_blanklines(int lines)
      69                 :            : {
      70                 :            :         int i;
      71                 :          0 :         for (i = 0; i < lines; i++)
      72                 :          0 :                 output_csv("%s\n", ",,,,,,,,");
      73                 :            : }
      74                 :            : 
      75                 :            : static void
      76                 :          0 : output_env_info(void)
      77                 :            : {
      78                 :            :         output_blanklines(2);
      79                 :          0 :         output_csv("Test Environment:\n"
      80                 :            :                    "CPU frequency,%.3lf Ghz\n", rte_get_timer_hz() / 1000000000.0);
      81                 :            :         output_blanklines(1);
      82                 :          0 : }
      83                 :            : 
      84                 :            : static void
      85                 :            : output_header(uint32_t case_id, struct test_configure *case_cfg)
      86                 :            : {
      87                 :            :         static const char * const type_str[] = { "NONE", DMA_MEM_COPY, CPU_MEM_COPY };
      88                 :          0 :         output_csv(CSV_HDR_FMT, case_id, type_str[case_cfg->test_type]);
      89                 :            : }
      90                 :            : 
      91                 :            : static int
      92                 :          0 : run_test_case(struct test_configure *case_cfg)
      93                 :            : {
      94                 :            :         int ret = 0;
      95                 :            : 
      96                 :          0 :         switch (case_cfg->test_type) {
      97                 :          0 :         case TEST_TYPE_DMA_MEM_COPY:
      98                 :            :         case TEST_TYPE_CPU_MEM_COPY:
      99                 :          0 :                 ret = mem_copy_benchmark(case_cfg);
     100                 :          0 :                 break;
     101                 :            :         default:
     102                 :            :                 printf("Unknown test type\n");
     103                 :            :                 break;
     104                 :            :         }
     105                 :            : 
     106                 :          0 :         return ret;
     107                 :            : }
     108                 :            : 
     109                 :            : static void
     110                 :          0 : run_test(uint32_t case_id, struct test_configure *case_cfg)
     111                 :            : {
     112                 :          0 :         uint32_t nb_lcores = rte_lcore_count();
     113                 :          0 :         struct test_configure_entry *mem_size = &case_cfg->mem_size;
     114                 :          0 :         struct test_configure_entry *buf_size = &case_cfg->buf_size;
     115                 :          0 :         struct test_configure_entry *ring_size = &case_cfg->ring_size;
     116                 :          0 :         struct test_configure_entry *kick_batch = &case_cfg->kick_batch;
     117                 :          0 :         struct test_configure_entry dummy = { 0 };
     118                 :            :         struct test_configure_entry *var_entry = &dummy;
     119                 :            : 
     120                 :          0 :         if (nb_lcores <= case_cfg->num_worker) {
     121                 :            :                 printf("Case %u: Not enough lcores.\n", case_id);
     122                 :          0 :                 return;
     123                 :            :         }
     124                 :            : 
     125                 :            :         printf("Number of used lcores: %u.\n", nb_lcores);
     126                 :            : 
     127                 :          0 :         if (mem_size->incr != 0)
     128                 :            :                 var_entry = mem_size;
     129                 :            : 
     130                 :          0 :         if (buf_size->incr != 0)
     131                 :            :                 var_entry = buf_size;
     132                 :            : 
     133                 :          0 :         if (ring_size->incr != 0)
     134                 :            :                 var_entry = ring_size;
     135                 :            : 
     136                 :          0 :         if (kick_batch->incr != 0)
     137                 :            :                 var_entry = kick_batch;
     138                 :            : 
     139                 :          0 :         case_cfg->scenario_id = 0;
     140                 :            : 
     141                 :            :         output_header(case_id, case_cfg);
     142                 :            : 
     143                 :          0 :         for (var_entry->cur = var_entry->first; var_entry->cur <= var_entry->last;) {
     144                 :          0 :                 case_cfg->scenario_id++;
     145                 :          0 :                 printf("\nRunning scenario %d\n", case_cfg->scenario_id);
     146                 :            : 
     147                 :          0 :                 if (run_test_case(case_cfg) < 0)
     148                 :            :                         printf("\nTest fails! skipping this scenario.\n");
     149                 :            : 
     150                 :          0 :                 if (var_entry->op == OP_ADD)
     151                 :          0 :                         var_entry->cur += var_entry->incr;
     152                 :          0 :                 else if (var_entry->op == OP_MUL)
     153                 :          0 :                         var_entry->cur *= var_entry->incr;
     154                 :            :                 else {
     155                 :            :                         printf("No proper operation for variable entry.\n");
     156                 :            :                         break;
     157                 :            :                 }
     158                 :            :         }
     159                 :            : }
     160                 :            : 
     161                 :            : /* Exit process if the entry couldn't find in the section. */
     162                 :            : static const char *
     163                 :          0 : get_cfgfile_entry(struct rte_cfgfile *cfgfile, const char *section_name, const char *entry_name)
     164                 :            : {
     165                 :          0 :         const char *entry = rte_cfgfile_get_entry(cfgfile, section_name, entry_name);
     166                 :          0 :         if (entry == NULL) {
     167                 :            :                 printf("Error: can't get entry '%s' in section '%s'\n", entry_name, section_name);
     168                 :          0 :                 exit(1);
     169                 :            :         }
     170                 :          0 :         return entry;
     171                 :            : }
     172                 :            : 
     173                 :            : static int
     174                 :          0 : parse_lcore(struct test_configure *test_case, const char *value)
     175                 :            : {
     176                 :            :         uint16_t len;
     177                 :            :         char *input;
     178                 :            :         struct lcore_dma_map_t *lcore_dma_map;
     179                 :            : 
     180                 :          0 :         len = strlen(value);
     181                 :          0 :         input = (char *)malloc((len + 1) * sizeof(char));
     182                 :            :         strlcpy(input, value, len + 1);
     183                 :            : 
     184                 :          0 :         char *token = strtok(input, ", ");
     185                 :          0 :         while (token != NULL) {
     186                 :          0 :                 lcore_dma_map = &(test_case->dma_config[test_case->num_worker++].lcore_dma_map);
     187                 :            :                 memset(lcore_dma_map, 0, sizeof(struct lcore_dma_map_t));
     188                 :          0 :                 if (test_case->num_worker >= MAX_WORKER_NB) {
     189                 :          0 :                         free(input);
     190                 :          0 :                         return -1;
     191                 :            :                 }
     192                 :            : 
     193                 :          0 :                 uint16_t lcore_id = atoi(token);
     194                 :          0 :                 lcore_dma_map->lcore = lcore_id;
     195                 :            : 
     196                 :          0 :                 token = strtok(NULL, ", ");
     197                 :            :         }
     198                 :            : 
     199                 :          0 :         free(input);
     200                 :          0 :         return 0;
     201                 :            : }
     202                 :            : 
     203                 :            : static void
     204                 :          0 : parse_cpu_config(struct test_configure *test_case, int case_id,
     205                 :            :                      struct rte_cfgfile *cfgfile, char *section_name)
     206                 :            : {
     207                 :          0 :         const char *lcore = get_cfgfile_entry(cfgfile, section_name, "lcore");
     208                 :          0 :         int lcore_ret = parse_lcore(test_case, lcore);
     209                 :          0 :         if (lcore_ret < 0) {
     210                 :            :                 printf("parse lcore error in case %d.\n", case_id);
     211                 :          0 :                 test_case->is_valid = false;
     212                 :            :         }
     213                 :          0 : }
     214                 :            : 
     215                 :            : static int
     216                 :          0 : parse_entry(const char *value, struct test_configure_entry *entry)
     217                 :            : {
     218                 :          0 :         char input[255] = {0};
     219                 :            :         char *args[MAX_PARAMS_PER_ENTRY];
     220                 :            :         int args_nr = -1;
     221                 :            :         int ret;
     222                 :            : 
     223                 :            :         strncpy(input, value, 254);
     224                 :          0 :         if (*input == '\0')
     225                 :          0 :                 goto out;
     226                 :            : 
     227                 :          0 :         ret = rte_strsplit(input, strlen(input), args, MAX_PARAMS_PER_ENTRY, ',');
     228                 :          0 :         if (ret != 1 && ret != 4)
     229                 :          0 :                 goto out;
     230                 :            : 
     231                 :          0 :         entry->cur = entry->first = (uint32_t)atoi(args[0]);
     232                 :            : 
     233                 :          0 :         if (ret == 4) {
     234                 :            :                 args_nr = 4;
     235                 :          0 :                 entry->last = (uint32_t)atoi(args[1]);
     236                 :          0 :                 entry->incr = (uint32_t)atoi(args[2]);
     237                 :          0 :                 if (!strcmp(args[3], "MUL"))
     238                 :          0 :                         entry->op = OP_MUL;
     239                 :          0 :                 else if (!strcmp(args[3], "ADD"))
     240                 :          0 :                         entry->op = OP_ADD;
     241                 :            :                 else {
     242                 :            :                         args_nr = -1;
     243                 :            :                         printf("Invalid op %s.\n", args[3]);
     244                 :            :                 }
     245                 :            : 
     246                 :            :         } else {
     247                 :            :                 args_nr = 1;
     248                 :          0 :                 entry->op = OP_NONE;
     249                 :          0 :                 entry->last = 0;
     250                 :          0 :                 entry->incr = 0;
     251                 :            :         }
     252                 :          0 : out:
     253                 :          0 :         return args_nr;
     254                 :            : }
     255                 :            : 
     256                 :          0 : static int populate_dma_dev_config(const char *key, const char *value, void *test)
     257                 :            : {
     258                 :            :         struct lcore_dma_config *dma_config = (struct lcore_dma_config *)test;
     259                 :            :         struct vchan_dev_config *vchan_config = &dma_config->vchan_dev;
     260                 :            :         struct lcore_dma_map_t *lcore_map = &dma_config->lcore_dma_map;
     261                 :            :         char *endptr;
     262                 :            :         int ret = 0;
     263                 :            : 
     264                 :          0 :         if (strcmp(key, "lcore") == 0)
     265                 :          0 :                 lcore_map->lcore = (uint16_t)atoi(value);
     266                 :          0 :         else if (strcmp(key, "dev") == 0)
     267                 :          0 :                 strlcpy(lcore_map->dma_names, value, RTE_DEV_NAME_MAX_LEN);
     268                 :          0 :         else if (strcmp(key, "dir") == 0 && strcmp(value, "mem2mem") == 0)
     269                 :          0 :                 vchan_config->tdir = RTE_DMA_DIR_MEM_TO_MEM;
     270                 :          0 :         else if (strcmp(key, "dir") == 0 && strcmp(value, "mem2dev") == 0)
     271                 :          0 :                 vchan_config->tdir = RTE_DMA_DIR_MEM_TO_DEV;
     272                 :          0 :         else if (strcmp(key, "dir") == 0 && strcmp(value, "dev2mem") == 0)
     273                 :          0 :                 vchan_config->tdir = RTE_DMA_DIR_DEV_TO_MEM;
     274                 :          0 :         else if (strcmp(key, "raddr") == 0)
     275                 :          0 :                 vchan_config->raddr = strtoull(value, &endptr, 16);
     276                 :          0 :         else if (strcmp(key, "coreid") == 0)
     277                 :          0 :                 vchan_config->port.pcie.coreid = (uint8_t)atoi(value);
     278                 :          0 :         else if (strcmp(key, "vfid") == 0)
     279                 :          0 :                 vchan_config->port.pcie.vfid = (uint16_t)atoi(value);
     280                 :          0 :         else if (strcmp(key, "pfid") == 0)
     281                 :          0 :                 vchan_config->port.pcie.pfid = (uint16_t)atoi(value);
     282                 :            :         else {
     283                 :            :                 printf("Invalid config param: %s\n", key);
     284                 :            :                 ret = -1;
     285                 :            :         }
     286                 :            : 
     287                 :          0 :         return ret;
     288                 :            : }
     289                 :            : 
     290                 :            : static void
     291                 :          0 : parse_dma_config(struct test_configure *test_case, int case_id,
     292                 :            :                      struct rte_cfgfile *cfgfile, char *section_name, int *nb_vp)
     293                 :            : {
     294                 :            :         const char *ring_size_str, *kick_batch_str, *src_sges_str, *dst_sges_str, *use_dma_ops;
     295                 :            :         char lc_dma[RTE_DEV_NAME_MAX_LEN];
     296                 :            :         struct rte_kvargs *kvlist;
     297                 :            :         const char *lcore_dma;
     298                 :            :         int args_nr;
     299                 :            :         int i;
     300                 :            : 
     301                 :          0 :         use_dma_ops = rte_cfgfile_get_entry(cfgfile, section_name, "use_enq_deq_ops");
     302                 :          0 :         test_case->use_ops = (use_dma_ops != NULL && (atoi(use_dma_ops) == 1));
     303                 :            : 
     304                 :          0 :         ring_size_str = get_cfgfile_entry(cfgfile, section_name, "dma_ring_size");
     305                 :          0 :         args_nr = parse_entry(ring_size_str, &test_case->ring_size);
     306                 :          0 :         if (args_nr < 0) {
     307                 :            :                 printf("parse error in case %d.\n", case_id);
     308                 :          0 :                 test_case->is_valid = false;
     309                 :          0 :                 return;
     310                 :          0 :         } else if (args_nr == 4)
     311                 :          0 :                 *nb_vp += 1;
     312                 :            : 
     313                 :          0 :         src_sges_str = rte_cfgfile_get_entry(cfgfile, section_name, "dma_src_sge");
     314                 :          0 :         if (src_sges_str != NULL)
     315                 :          0 :                 test_case->nb_src_sges = (int)atoi(src_sges_str);
     316                 :            : 
     317                 :          0 :         dst_sges_str = rte_cfgfile_get_entry(cfgfile, section_name, "dma_dst_sge");
     318                 :          0 :         if (dst_sges_str != NULL)
     319                 :          0 :                 test_case->nb_dst_sges = (int)atoi(dst_sges_str);
     320                 :            : 
     321                 :          0 :         if ((src_sges_str != NULL && dst_sges_str == NULL) ||
     322                 :            :             (src_sges_str == NULL && dst_sges_str != NULL)) {
     323                 :            :                 printf("parse dma_src_sge, dma_dst_sge error in case %d.\n", case_id);
     324                 :          0 :                 test_case->is_valid = false;
     325                 :          0 :                 return;
     326                 :          0 :         } else if (src_sges_str != NULL && dst_sges_str != NULL) {
     327                 :          0 :                 if (test_case->nb_src_sges == 0 || test_case->nb_dst_sges == 0) {
     328                 :            :                         printf("dma_src_sge and dma_dst_sge can not be 0 in case %d.\n", case_id);
     329                 :          0 :                         test_case->is_valid = false;
     330                 :          0 :                         return;
     331                 :            :                 }
     332                 :          0 :                 test_case->is_sg = true;
     333                 :            :         }
     334                 :            : 
     335                 :          0 :         kick_batch_str = get_cfgfile_entry(cfgfile, section_name, "kick_batch");
     336                 :          0 :         args_nr = parse_entry(kick_batch_str, &test_case->kick_batch);
     337                 :          0 :         if (args_nr < 0) {
     338                 :            :                 printf("parse error in case %d.\n", case_id);
     339                 :          0 :                 test_case->is_valid = false;
     340                 :          0 :                 return;
     341                 :          0 :         } else if (args_nr == 4)
     342                 :          0 :                 *nb_vp += 1;
     343                 :            : 
     344                 :            :         i = 0;
     345                 :            :         while (1) {
     346                 :          0 :                 snprintf(lc_dma, RTE_DEV_NAME_MAX_LEN, "lcore_dma%d", i);
     347                 :          0 :                 lcore_dma = rte_cfgfile_get_entry(cfgfile, section_name, lc_dma);
     348                 :          0 :                 if (lcore_dma == NULL)
     349                 :            :                         break;
     350                 :            : 
     351                 :          0 :                 kvlist = rte_kvargs_parse(lcore_dma, NULL);
     352                 :          0 :                 if (kvlist == NULL) {
     353                 :            :                         printf("rte_kvargs_parse() error");
     354                 :          0 :                         test_case->is_valid = false;
     355                 :          0 :                         break;
     356                 :            :                 }
     357                 :            : 
     358                 :          0 :                 if (rte_kvargs_process(kvlist, NULL, populate_dma_dev_config,
     359                 :          0 :                                        (void *)&test_case->dma_config[i]) < 0) {
     360                 :            :                         printf("rte_kvargs_process() error\n");
     361                 :          0 :                         rte_kvargs_free(kvlist);
     362                 :          0 :                         test_case->is_valid = false;
     363                 :          0 :                         break;
     364                 :            :                 }
     365                 :          0 :                 i++;
     366                 :          0 :                 test_case->num_worker++;
     367                 :          0 :                 rte_kvargs_free(kvlist);
     368                 :            :         }
     369                 :            : 
     370                 :          0 :         if (test_case->num_worker == 0) {
     371                 :            :                 printf("Error: Parsing %s Failed\n", lc_dma);
     372                 :          0 :                 test_case->is_valid = false;
     373                 :            :         }
     374                 :            : }
     375                 :            : 
     376                 :            : static int
     377                 :          0 : parse_global_config(struct rte_cfgfile *cfgfile)
     378                 :            : {
     379                 :            :         static char prog_name[] = "test-dma-perf";
     380                 :            :         char *tokens[MAX_EAL_ARGV_NB];
     381                 :            :         const char *entry;
     382                 :            :         int token_nb;
     383                 :            :         char *args;
     384                 :            :         int ret;
     385                 :            :         int i;
     386                 :            : 
     387                 :          0 :         ret = rte_cfgfile_num_sections(cfgfile, GLOBAL_SECTION_NAME, strlen(GLOBAL_SECTION_NAME));
     388                 :          0 :         if (ret != 1) {
     389                 :            :                 printf("Error: GLOBAL section not exist or has multiple!\n");
     390                 :          0 :                 return -1;
     391                 :            :         }
     392                 :            : 
     393                 :          0 :         entry = get_cfgfile_entry(cfgfile, GLOBAL_SECTION_NAME, "eal_args");
     394                 :          0 :         args = strdup(entry);
     395                 :          0 :         if (args == NULL) {
     396                 :            :                 printf("Error: dup GLOBAL 'eal_args' failed!\n");
     397                 :          0 :                 return -1;
     398                 :            :         }
     399                 :          0 :         token_nb = rte_strsplit(args, strlen(args), tokens, MAX_EAL_ARGV_NB, ' ');
     400                 :          0 :         global_cfg.eal_argv[0] = prog_name;
     401                 :          0 :         for (i = 0; i < token_nb; i++)
     402                 :          0 :                 global_cfg.eal_argv[i + 1] = tokens[i];
     403                 :          0 :         global_cfg.eal_argc = i + 1;
     404                 :            : 
     405                 :          0 :         entry = get_cfgfile_entry(cfgfile, GLOBAL_SECTION_NAME, "cache_flush");
     406                 :          0 :         global_cfg.cache_flush = (uint8_t)atoi(entry);
     407                 :            : 
     408                 :          0 :         entry = get_cfgfile_entry(cfgfile, GLOBAL_SECTION_NAME, "test_seconds");
     409                 :          0 :         global_cfg.test_secs = (uint16_t)atoi(entry);
     410                 :            : 
     411                 :          0 :         return 0;
     412                 :            : }
     413                 :            : 
     414                 :            : static uint16_t
     415                 :          0 : load_configs(const char *path)
     416                 :            : {
     417                 :            :         const char *mem_size_str, *buf_size_str;
     418                 :            :         struct test_configure *test_case;
     419                 :            :         char section_name[CFG_NAME_LEN];
     420                 :            :         struct rte_cfgfile *cfgfile;
     421                 :            :         const char *case_type;
     422                 :            :         int nb_sections, i;
     423                 :            :         int args_nr, nb_vp;
     424                 :            :         const char *skip;
     425                 :            : 
     426                 :            :         printf("config file parsing...\n");
     427                 :          0 :         cfgfile = rte_cfgfile_load(path, 0);
     428                 :          0 :         if (!cfgfile) {
     429                 :            :                 printf("Open configure file error.\n");
     430                 :          0 :                 exit(1);
     431                 :            :         }
     432                 :            : 
     433                 :          0 :         if (parse_global_config(cfgfile) != 0)
     434                 :          0 :                 exit(1);
     435                 :            : 
     436                 :          0 :         nb_sections = rte_cfgfile_num_sections(cfgfile, NULL, 0) - 1;
     437                 :          0 :         if (nb_sections > MAX_TEST_CASES) {
     438                 :            :                 printf("Error: The maximum number of cases is %d.\n", MAX_TEST_CASES);
     439                 :          0 :                 exit(1);
     440                 :            :         }
     441                 :            : 
     442                 :          0 :         for (i = 0; i < nb_sections; i++) {
     443                 :          0 :                 snprintf(section_name, CFG_NAME_LEN, "case%d", i + 1);
     444                 :          0 :                 test_case = &test_cases[i];
     445                 :            : 
     446                 :          0 :                 skip = rte_cfgfile_get_entry(cfgfile, section_name, "skip");
     447                 :          0 :                 if (skip && (atoi(skip) == 1)) {
     448                 :          0 :                         test_case->is_skip = true;
     449                 :          0 :                         continue;
     450                 :            :                 }
     451                 :            : 
     452                 :          0 :                 test_case->is_valid = true;
     453                 :          0 :                 case_type = get_cfgfile_entry(cfgfile, section_name, "type");
     454                 :          0 :                 if (strcmp(case_type, DMA_MEM_COPY) == 0) {
     455                 :          0 :                         test_case->test_type = TEST_TYPE_DMA_MEM_COPY;
     456                 :          0 :                 } else if (strcmp(case_type, CPU_MEM_COPY) == 0) {
     457                 :          0 :                         test_case->test_type = TEST_TYPE_CPU_MEM_COPY;
     458                 :            :                 } else {
     459                 :            :                         printf("Error: Wrong test case type %s in case%d.\n", case_type, i + 1);
     460                 :          0 :                         test_case->is_valid = false;
     461                 :          0 :                         continue;
     462                 :            :                 }
     463                 :            : 
     464                 :          0 :                 test_case->src_numa_node = (int)atoi(get_cfgfile_entry(cfgfile,
     465                 :            :                                                                 section_name, "src_numa_node"));
     466                 :          0 :                 test_case->dst_numa_node = (int)atoi(get_cfgfile_entry(cfgfile,
     467                 :            :                                                                 section_name, "dst_numa_node"));
     468                 :          0 :                 nb_vp = 0;
     469                 :          0 :                 mem_size_str = get_cfgfile_entry(cfgfile, section_name, "mem_size");
     470                 :          0 :                 args_nr = parse_entry(mem_size_str, &test_case->mem_size);
     471                 :          0 :                 if (args_nr < 0) {
     472                 :            :                         printf("parse error in case %d.\n", i + 1);
     473                 :          0 :                         test_case->is_valid = false;
     474                 :          0 :                         continue;
     475                 :          0 :                 } else if (args_nr == 4)
     476                 :          0 :                         nb_vp++;
     477                 :            : 
     478                 :          0 :                 buf_size_str = get_cfgfile_entry(cfgfile, section_name, "buf_size");
     479                 :          0 :                 args_nr = parse_entry(buf_size_str, &test_case->buf_size);
     480                 :          0 :                 if (args_nr < 0) {
     481                 :            :                         printf("parse error in case %d.\n", i + 1);
     482                 :          0 :                         test_case->is_valid = false;
     483                 :          0 :                         continue;
     484                 :          0 :                 } else if (args_nr == 4)
     485                 :          0 :                         nb_vp++;
     486                 :            : 
     487                 :          0 :                 if (test_case->test_type == TEST_TYPE_DMA_MEM_COPY)
     488                 :          0 :                         parse_dma_config(test_case, i + 1, cfgfile, section_name, &nb_vp);
     489                 :            :                 else
     490                 :          0 :                         parse_cpu_config(test_case, i + 1, cfgfile, section_name);
     491                 :            : 
     492                 :          0 :                 if (test_case->is_valid && nb_vp > 1) {
     493                 :            :                         printf("Case %d error, each section can only have a single variable parameter.\n",
     494                 :            :                                         i + 1);
     495                 :          0 :                         test_case->is_valid = false;
     496                 :          0 :                         continue;
     497                 :            :                 }
     498                 :            :         }
     499                 :            : 
     500                 :          0 :         rte_cfgfile_close(cfgfile);
     501                 :            :         printf("config file parsing complete.\n\n");
     502                 :          0 :         return i;
     503                 :            : }
     504                 :            : 
     505                 :            : static int
     506                 :          0 : parse_args(int argc, char **argv)
     507                 :            : {
     508                 :            :         static struct rte_argparse obj = {
     509                 :            :                 .prog_name = "test-dma-perf",
     510                 :            :                 .usage = "[optional parameters]",
     511                 :            :                 .descriptor = NULL,
     512                 :            :                 .epilog = NULL,
     513                 :            :                 .exit_on_error = true,
     514                 :            :                 .args = {
     515                 :            :                         { "--config", NULL, "Specify a configuration file",
     516                 :            :                           (void *)&config_path, NULL,
     517                 :            :                           RTE_ARGPARSE_VALUE_REQUIRED, RTE_ARGPARSE_VALUE_TYPE_STR,
     518                 :            :                         },
     519                 :            :                         { "--result", NULL, "Optional, specify a result file name",
     520                 :            :                           (void *)&result_path, NULL,
     521                 :            :                           RTE_ARGPARSE_VALUE_REQUIRED, RTE_ARGPARSE_VALUE_TYPE_STR,
     522                 :            :                         },
     523                 :            :                         { "--list-dma", NULL, "Optional, list dma devices and exit",
     524                 :            :                           (void *)&list_dma, (void *)true,
     525                 :            :                           RTE_ARGPARSE_VALUE_NONE, RTE_ARGPARSE_VALUE_TYPE_BOOL,
     526                 :            :                         },
     527                 :            :                         ARGPARSE_ARG_END(),
     528                 :            :                 },
     529                 :            :         };
     530                 :          0 :         char rst_path[PATH_MAX + 16] = {0};
     531                 :            :         FILE *fd;
     532                 :            :         int ret;
     533                 :            : 
     534                 :          0 :         ret = rte_argparse_parse(&obj, argc, argv);
     535                 :          0 :         if (ret < 0)
     536                 :          0 :                 exit(1);
     537                 :            : 
     538                 :          0 :         if (config_path == NULL) {
     539                 :            :                 printf("Config file not assigned.\n");
     540                 :          0 :                 exit(1);
     541                 :            :         }
     542                 :            : 
     543                 :          0 :         if (result_path == NULL) {
     544                 :          0 :                 rte_basename(config_path, rst_path, sizeof(rst_path));
     545                 :          0 :                 char *token = strtok(rst_path, ".");
     546                 :          0 :                 if (token == NULL) {
     547                 :            :                         printf("Config file error.\n");
     548                 :          0 :                         return -1;
     549                 :            :                 }
     550                 :          0 :                 strlcat(token, "_result.csv", sizeof(rst_path));
     551                 :          0 :                 result_path = strdup(rst_path);
     552                 :          0 :                 if (result_path == NULL) {
     553                 :            :                         printf("Generate result file path error.\n");
     554                 :          0 :                         exit(1);
     555                 :            :                 }
     556                 :            :         }
     557                 :          0 :         fd = fopen(result_path, "w");
     558                 :          0 :         if (fd == NULL) {
     559                 :            :                 printf("Open output CSV file error.\n");
     560                 :          0 :                 exit(1);
     561                 :            :         }
     562                 :          0 :         fclose(fd);
     563                 :            : 
     564                 :          0 :         return 0;
     565                 :            : }
     566                 :            : 
     567                 :            : static void
     568                 :          0 : list_dma_dev(void)
     569                 :            : {
     570                 :            :         static const struct {
     571                 :            :                 uint64_t capability;
     572                 :            :                 const char *name;
     573                 :            :         } capa_names[] = {
     574                 :            :                 { RTE_DMA_CAPA_MEM_TO_MEM,  "mem2mem" },
     575                 :            :                 { RTE_DMA_CAPA_MEM_TO_DEV,  "mem2dev" },
     576                 :            :                 { RTE_DMA_CAPA_DEV_TO_MEM,  "dev2mem" },
     577                 :            :                 { RTE_DMA_CAPA_DEV_TO_DEV,  "dev2dev" },
     578                 :            :         };
     579                 :            :         struct rte_dma_info info;
     580                 :            :         uint32_t count = 0;
     581                 :            :         int idx = 0;
     582                 :            :         uint32_t i;
     583                 :            :         int ret;
     584                 :            : 
     585                 :          0 :         ret = rte_eal_init(global_cfg.eal_argc, global_cfg.eal_argv);
     586                 :          0 :         if (ret < 0)
     587                 :          0 :                 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
     588                 :            : 
     589                 :          0 :         RTE_DMA_FOREACH_DEV(idx) {
     590                 :          0 :                 ret = rte_dma_info_get(idx, &info);
     591                 :          0 :                 if (ret != 0)
     592                 :          0 :                         continue;
     593                 :            : 
     594                 :          0 :                 printf("\nDMA device name: %s\n", info.dev_name);
     595                 :            :                 printf("    transfer-capa:");
     596                 :          0 :                 for (i = 0; i < RTE_DIM(capa_names); i++) {
     597                 :          0 :                         if (capa_names[i].capability & info.dev_capa)
     598                 :          0 :                                 printf(" %s", capa_names[i].name);
     599                 :            :                 }
     600                 :            :                 printf("\n");
     601                 :          0 :                 printf("    max-segs: %u numa-node: %d min-desc: %u max-desc: %u\n",
     602                 :          0 :                         info.max_sges, info.numa_node, info.min_desc, info.max_desc);
     603                 :          0 :                 count++;
     604                 :            :         }
     605                 :            : 
     606                 :            :         printf("\n");
     607                 :          0 :         if (count == 0)
     608                 :            :                 printf("There are no dmadev devices!\n\n");
     609                 :            : 
     610                 :          0 :         rte_eal_cleanup();
     611                 :          0 : }
     612                 :            : 
     613                 :            : int
     614                 :          0 : main(int argc, char *argv[])
     615                 :            : {
     616                 :            :         uint32_t i, nb_lcores;
     617                 :            :         pid_t cpid, wpid;
     618                 :            :         uint16_t case_nb;
     619                 :            :         int wstatus;
     620                 :            :         int ret;
     621                 :            : 
     622                 :          0 :         parse_args(argc, argv);
     623                 :            : 
     624                 :          0 :         case_nb = load_configs(config_path);
     625                 :            : 
     626                 :          0 :         if (list_dma) {
     627                 :          0 :                 list_dma_dev();
     628                 :          0 :                 return 0;
     629                 :            :         }
     630                 :            : 
     631                 :            :         printf("Running cases...\n");
     632                 :          0 :         for (i = 0; i < case_nb; i++) {
     633                 :          0 :                 if (test_cases[i].is_skip) {
     634                 :          0 :                         printf("Test case %d configured to be skipped.\n\n", i + 1);
     635                 :            :                         output_blanklines(2);
     636                 :          0 :                         output_csv("Skip the test-case %d\n", i + 1);
     637                 :          0 :                         continue;
     638                 :            :                 }
     639                 :            : 
     640                 :          0 :                 if (!test_cases[i].is_valid) {
     641                 :          0 :                         printf("Invalid test case %d.\n\n", i + 1);
     642                 :            :                         output_blanklines(2);
     643                 :          0 :                         output_csv("Invalid case %d\n", i + 1);
     644                 :          0 :                         continue;
     645                 :            :                 }
     646                 :            : 
     647                 :          0 :                 cpid = fork();
     648                 :          0 :                 if (cpid < 0) {
     649                 :          0 :                         printf("Fork case %d failed.\n", i + 1);
     650                 :          0 :                         exit(EXIT_FAILURE);
     651                 :          0 :                 } else if (cpid == 0) {
     652                 :          0 :                         printf("\nRunning case %u\n\n", i + 1);
     653                 :            : 
     654                 :          0 :                         ret = rte_eal_init(global_cfg.eal_argc, global_cfg.eal_argv);
     655                 :          0 :                         if (ret < 0)
     656                 :          0 :                                 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
     657                 :            : 
     658                 :            :                         /* Check lcores. */
     659                 :          0 :                         nb_lcores = rte_lcore_count();
     660                 :          0 :                         if (nb_lcores < 2)
     661                 :          0 :                                 rte_exit(EXIT_FAILURE,
     662                 :            :                                         "There should be at least 2 worker lcores.\n");
     663                 :            : 
     664                 :          0 :                         output_env_info();
     665                 :            : 
     666                 :          0 :                         run_test(i + 1, &test_cases[i]);
     667                 :            : 
     668                 :            :                         /* clean up the EAL */
     669                 :          0 :                         rte_eal_cleanup();
     670                 :            : 
     671                 :            :                         printf("\nCase %u completed.\n\n", i + 1);
     672                 :            : 
     673                 :          0 :                         exit(EXIT_SUCCESS);
     674                 :            :                 } else {
     675                 :          0 :                         wpid = waitpid(cpid, &wstatus, 0);
     676                 :          0 :                         if (wpid == -1) {
     677                 :            :                                 printf("waitpid error.\n");
     678                 :          0 :                                 exit(EXIT_FAILURE);
     679                 :            :                         }
     680                 :            : 
     681                 :          0 :                         if (WIFEXITED(wstatus))
     682                 :          0 :                                 printf("Case process exited. status %d\n\n",
     683                 :          0 :                                         WEXITSTATUS(wstatus));
     684                 :          0 :                         else if (WIFSIGNALED(wstatus))
     685                 :            :                                 printf("Case process killed by signal %d\n\n",
     686                 :            :                                         WTERMSIG(wstatus));
     687                 :          0 :                         else if (WIFSTOPPED(wstatus))
     688                 :          0 :                                 printf("Case process stopped by signal %d\n\n",
     689                 :          0 :                                         WSTOPSIG(wstatus));
     690                 :          0 :                         else if (WIFCONTINUED(wstatus))
     691                 :            :                                 printf("Case process continued.\n\n");
     692                 :            :                         else
     693                 :            :                                 printf("Case process unknown terminated.\n\n");
     694                 :            :                 }
     695                 :            :         }
     696                 :            : 
     697                 :            :         printf("Bye...\n");
     698                 :          0 :         return 0;
     699                 :            : }

Generated by: LCOV version 1.14