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_eal.h>
16 : : #include <rte_cfgfile.h>
17 : : #include <rte_string_fns.h>
18 : : #include <rte_lcore.h>
19 : :
20 : : #include "main.h"
21 : :
22 : : #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"
23 : :
24 : : #define MAX_EAL_PARAM_NB 100
25 : : #define MAX_EAL_PARAM_LEN 1024
26 : :
27 : : #define DMA_MEM_COPY "DMA_MEM_COPY"
28 : : #define CPU_MEM_COPY "CPU_MEM_COPY"
29 : :
30 : : #define CMDLINE_CONFIG_ARG "--config"
31 : : #define CMDLINE_RESULT_ARG "--result"
32 : :
33 : : #define MAX_PARAMS_PER_ENTRY 4
34 : :
35 : : #define MAX_LONG_OPT_SZ 64
36 : :
37 : : enum {
38 : : TEST_TYPE_NONE = 0,
39 : : TEST_TYPE_DMA_MEM_COPY,
40 : : TEST_TYPE_CPU_MEM_COPY
41 : : };
42 : :
43 : : #define MAX_TEST_CASES 16
44 : : static struct test_configure test_cases[MAX_TEST_CASES];
45 : :
46 : : char output_str[MAX_WORKER_NB + 1][MAX_OUTPUT_STR_LEN];
47 : :
48 : : static FILE *fd;
49 : :
50 : : static void
51 : 0 : output_csv(bool need_blankline)
52 : : {
53 : : uint32_t i;
54 : :
55 : 0 : if (need_blankline) {
56 : 0 : fprintf(fd, ",,,,,,,,\n");
57 : 0 : fprintf(fd, ",,,,,,,,\n");
58 : : }
59 : :
60 : 0 : for (i = 0; i < RTE_DIM(output_str); i++) {
61 : 0 : if (output_str[i][0]) {
62 : 0 : fprintf(fd, "%s", output_str[i]);
63 : 0 : output_str[i][0] = '\0';
64 : : }
65 : : }
66 : :
67 : 0 : fflush(fd);
68 : 0 : }
69 : :
70 : : static void
71 : 0 : output_env_info(void)
72 : : {
73 : : snprintf(output_str[0], MAX_OUTPUT_STR_LEN, "Test Environment:\n");
74 : 0 : snprintf(output_str[1], MAX_OUTPUT_STR_LEN, "CPU frequency,%.3lf Ghz",
75 : : rte_get_timer_hz() / 1000000000.0);
76 : :
77 : 0 : output_csv(true);
78 : 0 : }
79 : :
80 : : static void
81 : 0 : output_header(uint32_t case_id, struct test_configure *case_cfg)
82 : : {
83 : 0 : snprintf(output_str[0], MAX_OUTPUT_STR_LEN,
84 : : CSV_HDR_FMT, case_id, case_cfg->test_type_str);
85 : :
86 : 0 : output_csv(true);
87 : 0 : }
88 : :
89 : : static void
90 : 0 : run_test_case(struct test_configure *case_cfg)
91 : : {
92 : 0 : switch (case_cfg->test_type) {
93 : 0 : case TEST_TYPE_DMA_MEM_COPY:
94 : 0 : mem_copy_benchmark(case_cfg, true);
95 : 0 : break;
96 : 0 : case TEST_TYPE_CPU_MEM_COPY:
97 : 0 : mem_copy_benchmark(case_cfg, false);
98 : 0 : break;
99 : 0 : default:
100 : 0 : printf("Unknown test type. %s\n", case_cfg->test_type_str);
101 : : break;
102 : : }
103 : 0 : }
104 : :
105 : : static void
106 : 0 : run_test(uint32_t case_id, struct test_configure *case_cfg)
107 : : {
108 : : uint32_t i;
109 : 0 : uint32_t nb_lcores = rte_lcore_count();
110 : 0 : struct test_configure_entry *mem_size = &case_cfg->mem_size;
111 : 0 : struct test_configure_entry *buf_size = &case_cfg->buf_size;
112 : 0 : struct test_configure_entry *ring_size = &case_cfg->ring_size;
113 : 0 : struct test_configure_entry *kick_batch = &case_cfg->kick_batch;
114 : 0 : struct test_configure_entry dummy = { 0 };
115 : : struct test_configure_entry *var_entry = &dummy;
116 : :
117 : 0 : for (i = 0; i < RTE_DIM(output_str); i++)
118 : 0 : memset(output_str[i], 0, MAX_OUTPUT_STR_LEN);
119 : :
120 : 0 : if (nb_lcores <= case_cfg->lcore_dma_map.cnt) {
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 : 0 : 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 : run_test_case(case_cfg);
148 : 0 : output_csv(false);
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 : : static int
162 : 0 : parse_lcore(struct test_configure *test_case, const char *value)
163 : : {
164 : : uint16_t len;
165 : : char *input;
166 : : struct lcore_dma_map_t *lcore_dma_map;
167 : :
168 : 0 : if (test_case == NULL || value == NULL)
169 : : return -1;
170 : :
171 : 0 : len = strlen(value);
172 : 0 : input = (char *)malloc((len + 1) * sizeof(char));
173 : : strlcpy(input, value, len + 1);
174 : 0 : lcore_dma_map = &(test_case->lcore_dma_map);
175 : :
176 : : memset(lcore_dma_map, 0, sizeof(struct lcore_dma_map_t));
177 : :
178 : 0 : char *token = strtok(input, ", ");
179 : 0 : while (token != NULL) {
180 : 0 : if (lcore_dma_map->cnt >= MAX_WORKER_NB) {
181 : 0 : free(input);
182 : 0 : return -1;
183 : : }
184 : :
185 : 0 : uint16_t lcore_id = atoi(token);
186 : 0 : lcore_dma_map->lcores[lcore_dma_map->cnt++] = lcore_id;
187 : :
188 : 0 : token = strtok(NULL, ", ");
189 : : }
190 : :
191 : 0 : free(input);
192 : 0 : return 0;
193 : : }
194 : :
195 : : static int
196 : 0 : parse_lcore_dma(struct test_configure *test_case, const char *value)
197 : : {
198 : : struct lcore_dma_map_t *lcore_dma_map;
199 : : char *input, *addrs;
200 : : char *ptrs[2];
201 : : char *start, *end, *substr;
202 : : uint16_t lcore_id;
203 : : int ret = 0;
204 : :
205 : 0 : if (test_case == NULL || value == NULL)
206 : : return -1;
207 : :
208 : 0 : input = strndup(value, strlen(value) + 1);
209 : 0 : if (input == NULL)
210 : : return -1;
211 : : addrs = input;
212 : :
213 : 0 : while (*addrs == '\0')
214 : 0 : addrs++;
215 : : if (*addrs == '\0') {
216 : : fprintf(stderr, "No input DMA addresses\n");
217 : : ret = -1;
218 : : goto out;
219 : : }
220 : :
221 : 0 : substr = strtok(addrs, ",");
222 : 0 : if (substr == NULL) {
223 : 0 : fprintf(stderr, "No input DMA address\n");
224 : : ret = -1;
225 : 0 : goto out;
226 : : }
227 : :
228 : 0 : memset(&test_case->lcore_dma_map, 0, sizeof(struct lcore_dma_map_t));
229 : :
230 : : do {
231 : 0 : if (rte_strsplit(substr, strlen(substr), ptrs, 2, '@') < 0) {
232 : 0 : fprintf(stderr, "Illegal DMA address\n");
233 : : ret = -1;
234 : 0 : break;
235 : : }
236 : :
237 : 0 : start = strstr(ptrs[0], "lcore");
238 : 0 : if (start == NULL) {
239 : 0 : fprintf(stderr, "Illegal lcore\n");
240 : : ret = -1;
241 : 0 : break;
242 : : }
243 : :
244 : 0 : start += 5;
245 : 0 : lcore_id = strtol(start, &end, 0);
246 : 0 : if (end == start) {
247 : 0 : fprintf(stderr, "No input lcore ID or ID %d is wrong\n", lcore_id);
248 : : ret = -1;
249 : 0 : break;
250 : : }
251 : :
252 : : lcore_dma_map = &test_case->lcore_dma_map;
253 : 0 : if (lcore_dma_map->cnt >= MAX_WORKER_NB) {
254 : 0 : fprintf(stderr, "lcores count error\n");
255 : : ret = -1;
256 : 0 : break;
257 : : }
258 : :
259 : 0 : lcore_dma_map->lcores[lcore_dma_map->cnt] = lcore_id;
260 : 0 : strlcpy(lcore_dma_map->dma_names[lcore_dma_map->cnt], ptrs[1],
261 : : RTE_DEV_NAME_MAX_LEN);
262 : 0 : lcore_dma_map->cnt++;
263 : 0 : substr = strtok(NULL, ",");
264 : 0 : } while (substr != NULL);
265 : :
266 : 0 : out:
267 : 0 : free(input);
268 : 0 : return ret;
269 : : }
270 : :
271 : : static int
272 : 0 : parse_entry(const char *value, struct test_configure_entry *entry)
273 : : {
274 : 0 : char input[255] = {0};
275 : : char *args[MAX_PARAMS_PER_ENTRY];
276 : : int args_nr = -1;
277 : : int ret;
278 : :
279 : 0 : if (value == NULL || entry == NULL)
280 : 0 : goto out;
281 : :
282 : : strncpy(input, value, 254);
283 : 0 : if (*input == '\0')
284 : 0 : goto out;
285 : :
286 : 0 : ret = rte_strsplit(input, strlen(input), args, MAX_PARAMS_PER_ENTRY, ',');
287 : 0 : if (ret != 1 && ret != 4)
288 : 0 : goto out;
289 : :
290 : 0 : entry->cur = entry->first = (uint32_t)atoi(args[0]);
291 : :
292 : 0 : if (ret == 4) {
293 : : args_nr = 4;
294 : 0 : entry->last = (uint32_t)atoi(args[1]);
295 : 0 : entry->incr = (uint32_t)atoi(args[2]);
296 : 0 : if (!strcmp(args[3], "MUL"))
297 : 0 : entry->op = OP_MUL;
298 : 0 : else if (!strcmp(args[3], "ADD"))
299 : 0 : entry->op = OP_ADD;
300 : : else {
301 : : args_nr = -1;
302 : : printf("Invalid op %s.\n", args[3]);
303 : : }
304 : :
305 : : } else {
306 : : args_nr = 1;
307 : 0 : entry->op = OP_NONE;
308 : 0 : entry->last = 0;
309 : 0 : entry->incr = 0;
310 : : }
311 : 0 : out:
312 : 0 : return args_nr;
313 : : }
314 : :
315 : : static uint16_t
316 : 0 : load_configs(const char *path)
317 : : {
318 : : struct rte_cfgfile *cfgfile;
319 : : int nb_sections, i;
320 : : struct test_configure *test_case;
321 : : char section_name[CFG_NAME_LEN];
322 : : const char *case_type;
323 : : const char *lcore_dma;
324 : : const char *mem_size_str, *buf_size_str, *ring_size_str, *kick_batch_str;
325 : : int args_nr, nb_vp;
326 : : bool is_dma;
327 : :
328 : : printf("config file parsing...\n");
329 : 0 : cfgfile = rte_cfgfile_load(path, 0);
330 : 0 : if (!cfgfile) {
331 : : printf("Open configure file error.\n");
332 : 0 : exit(1);
333 : : }
334 : :
335 : 0 : nb_sections = rte_cfgfile_num_sections(cfgfile, NULL, 0);
336 : 0 : if (nb_sections > MAX_TEST_CASES) {
337 : : printf("Error: The maximum number of cases is %d.\n", MAX_TEST_CASES);
338 : 0 : exit(1);
339 : : }
340 : :
341 : 0 : for (i = 0; i < nb_sections; i++) {
342 : 0 : snprintf(section_name, CFG_NAME_LEN, "case%d", i + 1);
343 : 0 : test_case = &test_cases[i];
344 : 0 : case_type = rte_cfgfile_get_entry(cfgfile, section_name, "type");
345 : 0 : if (case_type == NULL) {
346 : : printf("Error: No case type in case %d, the test will be finished here.\n",
347 : : i + 1);
348 : 0 : test_case->is_valid = false;
349 : 0 : continue;
350 : : }
351 : :
352 : 0 : if (strcmp(case_type, DMA_MEM_COPY) == 0) {
353 : 0 : test_case->test_type = TEST_TYPE_DMA_MEM_COPY;
354 : 0 : test_case->test_type_str = DMA_MEM_COPY;
355 : : is_dma = true;
356 : 0 : } else if (strcmp(case_type, CPU_MEM_COPY) == 0) {
357 : 0 : test_case->test_type = TEST_TYPE_CPU_MEM_COPY;
358 : 0 : test_case->test_type_str = CPU_MEM_COPY;
359 : : is_dma = false;
360 : : } else {
361 : : printf("Error: Wrong test case type %s in case%d.\n", case_type, i + 1);
362 : 0 : test_case->is_valid = false;
363 : 0 : continue;
364 : : }
365 : :
366 : 0 : test_case->src_numa_node = (int)atoi(rte_cfgfile_get_entry(cfgfile,
367 : : section_name, "src_numa_node"));
368 : 0 : test_case->dst_numa_node = (int)atoi(rte_cfgfile_get_entry(cfgfile,
369 : : section_name, "dst_numa_node"));
370 : : nb_vp = 0;
371 : 0 : mem_size_str = rte_cfgfile_get_entry(cfgfile, section_name, "mem_size");
372 : 0 : args_nr = parse_entry(mem_size_str, &test_case->mem_size);
373 : 0 : if (args_nr < 0) {
374 : : printf("parse error in case %d.\n", i + 1);
375 : 0 : test_case->is_valid = false;
376 : 0 : continue;
377 : 0 : } else if (args_nr == 4)
378 : : nb_vp++;
379 : :
380 : 0 : buf_size_str = rte_cfgfile_get_entry(cfgfile, section_name, "buf_size");
381 : 0 : args_nr = parse_entry(buf_size_str, &test_case->buf_size);
382 : 0 : if (args_nr < 0) {
383 : : printf("parse error in case %d.\n", i + 1);
384 : 0 : test_case->is_valid = false;
385 : 0 : continue;
386 : 0 : } else if (args_nr == 4)
387 : 0 : nb_vp++;
388 : :
389 : 0 : if (is_dma) {
390 : 0 : ring_size_str = rte_cfgfile_get_entry(cfgfile, section_name,
391 : : "dma_ring_size");
392 : 0 : args_nr = parse_entry(ring_size_str, &test_case->ring_size);
393 : 0 : if (args_nr < 0) {
394 : : printf("parse error in case %d.\n", i + 1);
395 : 0 : test_case->is_valid = false;
396 : 0 : continue;
397 : 0 : } else if (args_nr == 4)
398 : 0 : nb_vp++;
399 : :
400 : 0 : kick_batch_str = rte_cfgfile_get_entry(cfgfile, section_name, "kick_batch");
401 : 0 : args_nr = parse_entry(kick_batch_str, &test_case->kick_batch);
402 : 0 : if (args_nr < 0) {
403 : : printf("parse error in case %d.\n", i + 1);
404 : 0 : test_case->is_valid = false;
405 : 0 : continue;
406 : 0 : } else if (args_nr == 4)
407 : 0 : nb_vp++;
408 : :
409 : 0 : lcore_dma = rte_cfgfile_get_entry(cfgfile, section_name, "lcore_dma");
410 : 0 : int lcore_ret = parse_lcore_dma(test_case, lcore_dma);
411 : 0 : if (lcore_ret < 0) {
412 : : printf("parse lcore dma error in case %d.\n", i + 1);
413 : 0 : test_case->is_valid = false;
414 : 0 : continue;
415 : : }
416 : : } else {
417 : 0 : lcore_dma = rte_cfgfile_get_entry(cfgfile, section_name, "lcore");
418 : 0 : int lcore_ret = parse_lcore(test_case, lcore_dma);
419 : 0 : if (lcore_ret < 0) {
420 : : printf("parse lcore error in case %d.\n", i + 1);
421 : 0 : test_case->is_valid = false;
422 : 0 : continue;
423 : : }
424 : : }
425 : :
426 : 0 : if (nb_vp > 1) {
427 : : printf("Case %d error, each section can only have a single variable parameter.\n",
428 : : i + 1);
429 : 0 : test_case->is_valid = false;
430 : 0 : continue;
431 : : }
432 : :
433 : 0 : test_case->cache_flush =
434 : 0 : (uint8_t)atoi(rte_cfgfile_get_entry(cfgfile, section_name, "cache_flush"));
435 : 0 : test_case->test_secs = (uint16_t)atoi(rte_cfgfile_get_entry(cfgfile,
436 : : section_name, "test_seconds"));
437 : :
438 : 0 : test_case->eal_args = rte_cfgfile_get_entry(cfgfile, section_name, "eal_args");
439 : 0 : test_case->is_valid = true;
440 : : }
441 : :
442 : 0 : rte_cfgfile_close(cfgfile);
443 : : printf("config file parsing complete.\n\n");
444 : 0 : return i;
445 : : }
446 : :
447 : : /* Parse the argument given in the command line of the application */
448 : : static int
449 : 0 : append_eal_args(int argc, char **argv, const char *eal_args, char **new_argv)
450 : : {
451 : : int i;
452 : : char *tokens[MAX_EAL_PARAM_NB];
453 : 0 : char args[MAX_EAL_PARAM_LEN] = {0};
454 : : int token_nb, new_argc = 0;
455 : :
456 : 0 : for (i = 0; i < argc; i++) {
457 : 0 : if ((strcmp(argv[i], CMDLINE_CONFIG_ARG) == 0) ||
458 : 0 : (strcmp(argv[i], CMDLINE_RESULT_ARG) == 0)) {
459 : 0 : i++;
460 : 0 : continue;
461 : : }
462 : 0 : strlcpy(new_argv[new_argc], argv[i], MAX_EAL_PARAM_LEN);
463 : 0 : new_argc++;
464 : : }
465 : :
466 : 0 : if (eal_args) {
467 : : strlcpy(args, eal_args, MAX_EAL_PARAM_LEN);
468 : 0 : token_nb = rte_strsplit(args, strlen(args),
469 : : tokens, MAX_EAL_PARAM_NB, ' ');
470 : 0 : for (i = 0; i < token_nb; i++)
471 : 0 : strlcpy(new_argv[new_argc++], tokens[i], MAX_EAL_PARAM_LEN);
472 : : }
473 : :
474 : 0 : return new_argc;
475 : : }
476 : :
477 : : int
478 : 0 : main(int argc, char *argv[])
479 : : {
480 : : int ret;
481 : : uint16_t case_nb;
482 : : uint32_t i, nb_lcores;
483 : : pid_t cpid, wpid;
484 : : int wstatus;
485 : : char args[MAX_EAL_PARAM_NB][MAX_EAL_PARAM_LEN];
486 : : char *pargs[MAX_EAL_PARAM_NB];
487 : : char *cfg_path_ptr = NULL;
488 : : char *rst_path_ptr = NULL;
489 : : char rst_path[PATH_MAX];
490 : : int new_argc;
491 : :
492 : : memset(args, 0, sizeof(args));
493 : :
494 : 0 : for (i = 0; i < RTE_DIM(pargs); i++)
495 : 0 : pargs[i] = args[i];
496 : :
497 : 0 : for (i = 0; i < (uint32_t)argc; i++) {
498 : 0 : if (strncmp(argv[i], CMDLINE_CONFIG_ARG, MAX_LONG_OPT_SZ) == 0)
499 : 0 : cfg_path_ptr = argv[i + 1];
500 : 0 : if (strncmp(argv[i], CMDLINE_RESULT_ARG, MAX_LONG_OPT_SZ) == 0)
501 : 0 : rst_path_ptr = argv[i + 1];
502 : : }
503 : 0 : if (cfg_path_ptr == NULL) {
504 : : printf("Config file not assigned.\n");
505 : 0 : return -1;
506 : : }
507 : 0 : if (rst_path_ptr == NULL) {
508 : : strlcpy(rst_path, cfg_path_ptr, PATH_MAX);
509 : 0 : char *token = strtok(basename(rst_path), ".");
510 : 0 : if (token == NULL) {
511 : : printf("Config file error.\n");
512 : 0 : return -1;
513 : : }
514 : : strcat(token, "_result.csv");
515 : : rst_path_ptr = rst_path;
516 : : }
517 : :
518 : 0 : case_nb = load_configs(cfg_path_ptr);
519 : 0 : fd = fopen(rst_path_ptr, "w");
520 : 0 : if (fd == NULL) {
521 : : printf("Open output CSV file error.\n");
522 : 0 : return -1;
523 : : }
524 : 0 : fclose(fd);
525 : :
526 : : printf("Running cases...\n");
527 : 0 : for (i = 0; i < case_nb; i++) {
528 : 0 : if (!test_cases[i].is_valid) {
529 : 0 : printf("Invalid test case %d.\n\n", i + 1);
530 : : snprintf(output_str[0], MAX_OUTPUT_STR_LEN, "Invalid case %d\n", i + 1);
531 : :
532 : 0 : fd = fopen(rst_path_ptr, "a");
533 : 0 : if (!fd) {
534 : : printf("Open output CSV file error.\n");
535 : 0 : return 0;
536 : : }
537 : 0 : output_csv(true);
538 : 0 : fclose(fd);
539 : 0 : continue;
540 : : }
541 : :
542 : 0 : if (test_cases[i].test_type == TEST_TYPE_NONE) {
543 : 0 : printf("No valid test type in test case %d.\n\n", i + 1);
544 : : snprintf(output_str[0], MAX_OUTPUT_STR_LEN, "Invalid case %d\n", i + 1);
545 : :
546 : 0 : fd = fopen(rst_path_ptr, "a");
547 : 0 : if (!fd) {
548 : : printf("Open output CSV file error.\n");
549 : 0 : return 0;
550 : : }
551 : 0 : output_csv(true);
552 : 0 : fclose(fd);
553 : 0 : continue;
554 : : }
555 : :
556 : 0 : cpid = fork();
557 : 0 : if (cpid < 0) {
558 : 0 : printf("Fork case %d failed.\n", i + 1);
559 : 0 : exit(EXIT_FAILURE);
560 : 0 : } else if (cpid == 0) {
561 : 0 : printf("\nRunning case %u\n\n", i + 1);
562 : :
563 : 0 : new_argc = append_eal_args(argc, argv, test_cases[i].eal_args, pargs);
564 : 0 : ret = rte_eal_init(new_argc, pargs);
565 : 0 : if (ret < 0)
566 : 0 : rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
567 : :
568 : : /* Check lcores. */
569 : 0 : nb_lcores = rte_lcore_count();
570 : 0 : if (nb_lcores < 2)
571 : 0 : rte_exit(EXIT_FAILURE,
572 : : "There should be at least 2 worker lcores.\n");
573 : :
574 : 0 : fd = fopen(rst_path_ptr, "a");
575 : 0 : if (!fd) {
576 : : printf("Open output CSV file error.\n");
577 : 0 : return 0;
578 : : }
579 : :
580 : 0 : output_env_info();
581 : :
582 : 0 : run_test(i + 1, &test_cases[i]);
583 : :
584 : : /* clean up the EAL */
585 : 0 : rte_eal_cleanup();
586 : :
587 : 0 : fclose(fd);
588 : :
589 : : printf("\nCase %u completed.\n\n", i + 1);
590 : :
591 : 0 : exit(EXIT_SUCCESS);
592 : : } else {
593 : 0 : wpid = waitpid(cpid, &wstatus, 0);
594 : 0 : if (wpid == -1) {
595 : : printf("waitpid error.\n");
596 : 0 : exit(EXIT_FAILURE);
597 : : }
598 : :
599 : 0 : if (WIFEXITED(wstatus))
600 : 0 : printf("Case process exited. status %d\n\n",
601 : 0 : WEXITSTATUS(wstatus));
602 : 0 : else if (WIFSIGNALED(wstatus))
603 : : printf("Case process killed by signal %d\n\n",
604 : : WTERMSIG(wstatus));
605 : 0 : else if (WIFSTOPPED(wstatus))
606 : 0 : printf("Case process stopped by signal %d\n\n",
607 : 0 : WSTOPSIG(wstatus));
608 : 0 : else if (WIFCONTINUED(wstatus))
609 : : printf("Case process continued.\n\n");
610 : : else
611 : : printf("Case process unknown terminated.\n\n");
612 : : }
613 : : }
614 : :
615 : : printf("Bye...\n");
616 : 0 : return 0;
617 : : }
|