Imported Upstream version 16.07-rc1
[deb_dpdk.git] / examples / ip_pipeline / config_parse.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <getopt.h>
39 #include <errno.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <libgen.h>
43 #include <unistd.h>
44 #include <sys/wait.h>
45
46 #include <rte_errno.h>
47 #include <rte_cfgfile.h>
48 #include <rte_string_fns.h>
49
50 #include "app.h"
51 #include "parser.h"
52
53 /**
54  * Default config values
55  **/
56
57 static struct app_params app_params_default = {
58         .config_file = "./config/ip_pipeline.cfg",
59         .log_level = APP_LOG_LEVEL_HIGH,
60         .port_mask = 0,
61
62         .eal_params = {
63                 .channels = 4,
64         },
65 };
66
67 static const struct app_mempool_params mempool_params_default = {
68         .parsed = 0,
69         .buffer_size = 2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM,
70         .pool_size = 32 * 1024,
71         .cache_size = 256,
72         .cpu_socket_id = 0,
73 };
74
75 static const struct app_link_params link_params_default = {
76         .parsed = 0,
77         .pmd_id = 0,
78         .arp_q = 0,
79         .tcp_syn_q = 0,
80         .ip_local_q = 0,
81         .tcp_local_q = 0,
82         .udp_local_q = 0,
83         .sctp_local_q = 0,
84         .rss_qs = {0},
85         .n_rss_qs = 0,
86         .rss_proto_ipv4 = ETH_RSS_IPV4,
87         .rss_proto_ipv6 = ETH_RSS_IPV6,
88         .rss_proto_l2 = 0,
89         .state = 0,
90         .ip = 0,
91         .depth = 0,
92         .mac_addr = 0,
93         .pci_bdf = {0},
94
95         .conf = {
96                 .link_speeds = 0,
97                 .rxmode = {
98                         .mq_mode = ETH_MQ_RX_NONE,
99
100                         .header_split   = 0, /* Header split */
101                         .hw_ip_checksum = 0, /* IP checksum offload */
102                         .hw_vlan_filter = 0, /* VLAN filtering */
103                         .hw_vlan_strip  = 0, /* VLAN strip */
104                         .hw_vlan_extend = 0, /* Extended VLAN */
105                         .jumbo_frame    = 0, /* Jumbo frame support */
106                         .hw_strip_crc   = 0, /* CRC strip by HW */
107                         .enable_scatter = 0, /* Scattered packets RX handler */
108
109                         .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */
110                         .split_hdr_size = 0, /* Header split buffer size */
111                 },
112                 .rx_adv_conf = {
113                         .rss_conf = {
114                                 .rss_key = NULL,
115                                 .rss_key_len = 40,
116                                 .rss_hf = 0,
117                         },
118                 },
119                 .txmode = {
120                         .mq_mode = ETH_MQ_TX_NONE,
121                 },
122                 .lpbk_mode = 0,
123         },
124
125         .promisc = 1,
126 };
127
128 static const struct app_pktq_hwq_in_params default_hwq_in_params = {
129         .parsed = 0,
130         .mempool_id = 0,
131         .size = 128,
132         .burst = 32,
133
134         .conf = {
135                 .rx_thresh = {
136                                 .pthresh = 8,
137                                 .hthresh = 8,
138                                 .wthresh = 4,
139                 },
140                 .rx_free_thresh = 64,
141                 .rx_drop_en = 0,
142                 .rx_deferred_start = 0,
143         }
144 };
145
146 static const struct app_pktq_hwq_out_params default_hwq_out_params = {
147         .parsed = 0,
148         .size = 512,
149         .burst = 32,
150         .dropless = 0,
151         .n_retries = 0,
152
153         .conf = {
154                 .tx_thresh = {
155                         .pthresh = 36,
156                         .hthresh = 0,
157                         .wthresh = 0,
158                 },
159                 .tx_rs_thresh = 0,
160                 .tx_free_thresh = 0,
161                 .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
162                         ETH_TXQ_FLAGS_NOOFFLOADS,
163                 .tx_deferred_start = 0,
164         }
165 };
166
167 static const struct app_pktq_swq_params default_swq_params = {
168         .parsed = 0,
169         .size = 256,
170         .burst_read = 32,
171         .burst_write = 32,
172         .dropless = 0,
173         .n_retries = 0,
174         .cpu_socket_id = 0,
175         .ipv4_frag = 0,
176         .ipv6_frag = 0,
177         .ipv4_ras = 0,
178         .ipv6_ras = 0,
179         .mtu = 0,
180         .metadata_size = 0,
181         .mempool_direct_id = 0,
182         .mempool_indirect_id = 0,
183 };
184
185 struct app_pktq_tm_params default_tm_params = {
186         .parsed = 0,
187         .file_name = "./config/tm_profile.cfg",
188         .burst_read = 64,
189         .burst_write = 32,
190 };
191
192 struct app_pktq_kni_params default_kni_params = {
193         .parsed = 0,
194         .socket_id = 0,
195         .core_id = 0,
196         .hyper_th_id = 0,
197         .force_bind = 0,
198
199         .mempool_id = 0,
200         .burst_read = 32,
201         .burst_write = 32,
202         .dropless = 0,
203         .n_retries = 0,
204 };
205
206 struct app_pktq_source_params default_source_params = {
207         .parsed = 0,
208         .mempool_id = 0,
209         .burst = 32,
210         .file_name = NULL,
211         .n_bytes_per_pkt = 0,
212 };
213
214 struct app_pktq_sink_params default_sink_params = {
215         .parsed = 0,
216         .file_name = NULL,
217         .n_pkts_to_dump = 0,
218 };
219
220 struct app_msgq_params default_msgq_params = {
221         .parsed = 0,
222         .size = 64,
223         .cpu_socket_id = 0,
224 };
225
226 struct app_pipeline_params default_pipeline_params = {
227         .parsed = 0,
228         .socket_id = 0,
229         .core_id = 0,
230         .hyper_th_id = 0,
231         .n_pktq_in = 0,
232         .n_pktq_out = 0,
233         .n_msgq_in = 0,
234         .n_msgq_out = 0,
235         .timer_period = 1,
236         .n_args = 0,
237 };
238
239 static const char app_usage[] =
240         "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] [-p PORT_MASK] "
241         "[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n"
242         "\n"
243         "Arguments:\n"
244         "\t-f CONFIG_FILE: Default config file is %s\n"
245         "\t-p PORT_MASK: Mask of NIC port IDs in hex format (generated from "
246                 "config file when not provided)\n"
247         "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n"
248         "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n"
249         "\t--preproc PREPROCESSOR: Configuration file pre-processor\n"
250         "\t--preproc-args ARGS: Arguments to be passed to pre-processor\n"
251         "\n";
252
253 static void
254 app_print_usage(char *prgname)
255 {
256         rte_exit(0, app_usage, prgname, app_params_default.config_file);
257 }
258
259 #define APP_PARAM_ADD(set, key)                                         \
260 ({                                                                      \
261         ssize_t pos = APP_PARAM_FIND(set, key);                         \
262         ssize_t size = RTE_DIM(set);                                    \
263                                                                         \
264         if (pos < 0) {                                                  \
265                 for (pos = 0; pos < size; pos++) {                      \
266                         if (!APP_PARAM_VALID(&((set)[pos])))            \
267                                 break;                                  \
268                 }                                                       \
269                                                                         \
270                 APP_CHECK((pos < size),                                 \
271                         "Parse error: size of %s is limited to %u elements",\
272                         #set, (uint32_t) size);                         \
273                                                                         \
274                 (set)[pos].name = strdup(key);                          \
275                 APP_CHECK(((set)[pos].name),                            \
276                         "Parse error: no free memory");                 \
277         }                                                               \
278         pos;                                                            \
279 })
280
281 #define APP_PARAM_ADD_LINK_FOR_RXQ(app, rxq_name)                       \
282 ({                                                                      \
283         char link_name[APP_PARAM_NAME_SIZE];                            \
284         ssize_t link_param_pos;                                         \
285         uint32_t link_id, queue_id;                             \
286                                                                         \
287         sscanf((rxq_name), "RXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\
288         sprintf(link_name, "LINK%" PRIu32, link_id);                    \
289         link_param_pos = APP_PARAM_ADD((app)->link_params, link_name);  \
290         link_param_pos;                                                 \
291 })
292
293 #define APP_PARAM_ADD_LINK_FOR_TXQ(app, txq_name)                       \
294 ({                                                                      \
295         char link_name[APP_PARAM_NAME_SIZE];                            \
296         ssize_t link_param_pos;                                         \
297         uint32_t link_id, queue_id;                                     \
298                                                                         \
299         sscanf((txq_name), "TXQ%" SCNu32 ".%" SCNu32, &link_id, &queue_id);\
300         sprintf(link_name, "LINK%" PRIu32, link_id);                    \
301         link_param_pos = APP_PARAM_ADD((app)->link_params, link_name);  \
302         link_param_pos;                                                 \
303 })
304
305 #define APP_PARAM_ADD_LINK_FOR_TM(app, tm_name)                         \
306 ({                                                                      \
307         char link_name[APP_PARAM_NAME_SIZE];                            \
308         ssize_t link_param_pos;                                         \
309         uint32_t link_id;                                               \
310                                                                         \
311         sscanf((tm_name), "TM%" SCNu32, &link_id);                      \
312         sprintf(link_name, "LINK%" PRIu32, link_id);                    \
313         link_param_pos = APP_PARAM_ADD((app)->link_params, link_name);  \
314         link_param_pos;                                                 \
315 })
316
317 #define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name)                       \
318 ({                                                                      \
319         char link_name[APP_PARAM_NAME_SIZE];                            \
320         ssize_t link_param_pos;                                         \
321         uint32_t link_id;                                               \
322                                                                         \
323         sscanf((kni_name), "KNI%" SCNu32, &link_id);            \
324         sprintf(link_name, "LINK%" PRIu32, link_id);                    \
325         link_param_pos = APP_PARAM_ADD((app)->link_params, link_name);  \
326         link_param_pos;                                                 \
327 })
328
329 #define PARSE_CHECK_DUPLICATE_SECTION(obj)                              \
330 do {                                                                    \
331         APP_CHECK(((obj)->parsed == 0),                                 \
332                 "Parse error: duplicate \"%s\" section", (obj)->name);  \
333         (obj)->parsed++;                                        \
334 } while (0)
335
336 #define PARSE_CHECK_DUPLICATE_SECTION_EAL(obj)                          \
337 do {                                                                    \
338         APP_CHECK(((obj)->parsed == 0),                                 \
339                 "Parse error: duplicate \"%s\" section", "EAL");        \
340         (obj)->parsed++;                                        \
341 } while (0)
342
343 #define PARSE_ERROR(exp, section, entry)                                \
344 APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"", section, entry)
345
346 #define PARSE_ERROR_MESSAGE(exp, section, entry, message)               \
347 APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": %s",       \
348         section, entry, message)
349
350 #define PARSE_ERROR_NO_ELEMENTS(exp, section, entry)                    \
351 APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": "          \
352         "no elements detected",                                         \
353         section, entry)
354
355 #define PARSE_ERROR_TOO_MANY_ELEMENTS(exp, section, entry, max)         \
356 APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": "          \
357         "maximum number of elements allowed is %u",                     \
358         section, entry, max)
359
360 #define PARSE_ERROR_INVALID_ELEMENT(exp, section, entry, value)         \
361 APP_CHECK(exp, "Parse error in section \"%s\", entry \"%s\": "          \
362         "Invalid element value \"%s\"",                                 \
363         section, entry, value)
364
365 #define PARSE_ERROR_MALLOC(exp)                                         \
366 APP_CHECK(exp, "Parse error: no free memory")
367
368 #define PARSE_ERROR_SECTION(exp, section)                               \
369 APP_CHECK(exp, "Parse error in section \"%s\"", section)
370
371 #define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section)                    \
372 APP_CHECK(exp, "Parse error in section \"%s\": no entries", section)
373
374 #define PARSE_WARNING_IGNORED(exp, section, entry)                      \
375 do                                                                      \
376 if (!(exp))                                                             \
377         fprintf(stderr, "Parse warning in section \"%s\": "             \
378                 "entry \"%s\" is ignored", section, entry);             \
379 while (0)
380
381 #define PARSE_ERROR_INVALID(exp, section, entry)                        \
382 APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"",\
383         section, entry)
384
385 #define PARSE_ERROR_DUPLICATE(exp, section, entry)                      \
386 APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"", \
387         section, entry)
388
389 static int
390 validate_name(const char *name, const char *prefix, int num)
391 {
392         size_t i, j;
393
394         for (i = 0; (name[i] != '\0') && (prefix[i] != '\0'); i++) {
395                 if (name[i] != prefix[i])
396                         return -1;
397         }
398
399         if (prefix[i] != '\0')
400                 return -1;
401
402         if (!num) {
403                 if (name[i] != '\0')
404                         return -1;
405                 else
406                         return 0;
407         }
408
409         if (num == 2) {
410                 j = skip_digits(&name[i]);
411                 i += j;
412                 if ((j == 0) || (name[i] != '.'))
413                         return -1;
414                 i++;
415         }
416
417         if (num == 1) {
418                 j = skip_digits(&name[i]);
419                 i += j;
420                 if ((j == 0) || (name[i] != '\0'))
421                         return -1;
422         }
423
424         return 0;
425 }
426
427 static void
428 parse_eal(struct app_params *app,
429         const char *section_name,
430         struct rte_cfgfile *cfg)
431 {
432         struct app_eal_params *p = &app->eal_params;
433         struct rte_cfgfile_entry *entries;
434         int n_entries, i;
435
436         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
437         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
438
439         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
440         PARSE_ERROR_MALLOC(entries != NULL);
441
442         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
443
444         PARSE_CHECK_DUPLICATE_SECTION_EAL(p);
445
446         for (i = 0; i < n_entries; i++) {
447                 struct rte_cfgfile_entry *entry = &entries[i];
448
449                 /* coremask */
450                 if (strcmp(entry->name, "c") == 0) {
451                         PARSE_WARNING_IGNORED(0, section_name, entry->name);
452                         continue;
453                 }
454
455                 /* corelist */
456                 if (strcmp(entry->name, "l") == 0) {
457                         PARSE_WARNING_IGNORED(0, section_name, entry->name);
458                         continue;
459                 }
460
461                 /* coremap */
462                 if (strcmp(entry->name, "lcores") == 0) {
463                         PARSE_ERROR_DUPLICATE((p->coremap == NULL),
464                                 section_name,
465                                 entry->name);
466                         p->coremap = strdup(entry->value);
467                         continue;
468                 }
469
470                 /* master_lcore */
471                 if (strcmp(entry->name, "master_lcore") == 0) {
472                         int status;
473
474                         PARSE_ERROR_DUPLICATE((p->master_lcore_present == 0),
475                                 section_name,
476                                 entry->name);
477                         p->master_lcore_present = 1;
478
479                         status = parser_read_uint32(&p->master_lcore,
480                                 entry->value);
481                         PARSE_ERROR((status == 0), section_name, entry->name);
482                         continue;
483                 }
484
485                 /* channels */
486                 if (strcmp(entry->name, "n") == 0) {
487                         int status;
488
489                         PARSE_ERROR_DUPLICATE((p->channels_present == 0),
490                                 section_name,
491                                 entry->name);
492                         p->channels_present = 1;
493
494                         status = parser_read_uint32(&p->channels, entry->value);
495                         PARSE_ERROR((status == 0), section_name, entry->name);
496                         continue;
497                 }
498
499                 /* memory */
500                 if (strcmp(entry->name, "m") == 0) {
501                         int status;
502
503                         PARSE_ERROR_DUPLICATE((p->memory_present == 0),
504                                 section_name,
505                                 entry->name);
506                         p->memory_present = 1;
507
508                         status = parser_read_uint32(&p->memory, entry->value);
509                         PARSE_ERROR((status == 0), section_name, entry->name);
510                         continue;
511                 }
512
513                 /* ranks */
514                 if (strcmp(entry->name, "r") == 0) {
515                         int status;
516
517                         PARSE_ERROR_DUPLICATE((p->ranks_present == 0),
518                                 section_name,
519                                 entry->name);
520                         p->ranks_present = 1;
521
522                         status = parser_read_uint32(&p->ranks, entry->value);
523                         PARSE_ERROR((status == 0), section_name, entry->name);
524                         continue;
525                 }
526
527                 /* pci_blacklist */
528                 if ((strcmp(entry->name, "pci_blacklist") == 0) ||
529                         (strcmp(entry->name, "b") == 0)) {
530                         uint32_t i;
531
532                         for (i = 0; i < APP_MAX_LINKS; i++) {
533                                 if (p->pci_blacklist[i])
534                                         continue;
535
536                                 p->pci_blacklist[i] =
537                                         strdup(entry->value);
538                                 PARSE_ERROR_MALLOC(p->pci_blacklist[i]);
539
540                                 break;
541                         }
542
543                         PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS),
544                                 section_name, entry->name,
545                                 "too many elements");
546                         continue;
547                 }
548
549                 /* pci_whitelist */
550                 if ((strcmp(entry->name, "pci_whitelist") == 0) ||
551                         (strcmp(entry->name, "w") == 0)) {
552                         uint32_t i;
553
554                         PARSE_ERROR_MESSAGE((app->port_mask != 0),
555                                 section_name, entry->name, "entry to be "
556                                 "generated by the application (port_mask "
557                                 "not provided)");
558
559                         for (i = 0; i < APP_MAX_LINKS; i++) {
560                                 if (p->pci_whitelist[i])
561                                         continue;
562
563                                 p->pci_whitelist[i] = strdup(entry->value);
564                                 PARSE_ERROR_MALLOC(p->pci_whitelist[i]);
565
566                                 break;
567                         }
568
569                         PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS),
570                                 section_name, entry->name,
571                                 "too many elements");
572                         continue;
573                 }
574
575                 /* vdev */
576                 if (strcmp(entry->name, "vdev") == 0) {
577                         uint32_t i;
578
579                         for (i = 0; i < APP_MAX_LINKS; i++) {
580                                 if (p->vdev[i])
581                                         continue;
582
583                                 p->vdev[i] = strdup(entry->value);
584                                 PARSE_ERROR_MALLOC(p->vdev[i]);
585
586                                 break;
587                         }
588
589                         PARSE_ERROR_MESSAGE((i < APP_MAX_LINKS),
590                                 section_name, entry->name,
591                                 "too many elements");
592                         continue;
593                 }
594
595                 /* vmware_tsc_map */
596                 if (strcmp(entry->name, "vmware_tsc_map") == 0) {
597                         int val;
598
599                         PARSE_ERROR_DUPLICATE((p->vmware_tsc_map_present == 0),
600                                 section_name,
601                                 entry->name);
602                         p->vmware_tsc_map_present = 1;
603
604                         val = parser_read_arg_bool(entry->value);
605                         PARSE_ERROR((val >= 0), section_name, entry->name);
606                         p->vmware_tsc_map = val;
607                         continue;
608                 }
609
610                 /* proc_type */
611                 if (strcmp(entry->name, "proc_type") == 0) {
612                         PARSE_ERROR_DUPLICATE((p->proc_type == NULL),
613                                 section_name,
614                                 entry->name);
615                         p->proc_type = strdup(entry->value);
616                         continue;
617                 }
618
619                 /* syslog */
620                 if (strcmp(entry->name, "syslog") == 0) {
621                         PARSE_ERROR_DUPLICATE((p->syslog == NULL),
622                                 section_name,
623                                 entry->name);
624                         p->syslog = strdup(entry->value);
625                         continue;
626                 }
627
628                 /* log_level */
629                 if (strcmp(entry->name, "log_level") == 0) {
630                         int status;
631
632                         PARSE_ERROR_DUPLICATE((p->log_level_present == 0),
633                                 section_name,
634                                 entry->name);
635                         p->log_level_present = 1;
636
637                         status = parser_read_uint32(&p->log_level,
638                                 entry->value);
639                         PARSE_ERROR((status == 0), section_name, entry->name);
640                         continue;
641                 }
642
643                 /* version */
644                 if (strcmp(entry->name, "v") == 0) {
645                         int val;
646
647                         PARSE_ERROR_DUPLICATE((p->version_present == 0),
648                                 section_name,
649                                 entry->name);
650                         p->version_present = 1;
651
652                         val = parser_read_arg_bool(entry->value);
653                         PARSE_ERROR((val >= 0), section_name, entry->name);
654                         p->version = val;
655                         continue;
656                 }
657
658                 /* help */
659                 if ((strcmp(entry->name, "help") == 0) ||
660                         (strcmp(entry->name, "h") == 0)) {
661                         int val;
662
663                         PARSE_ERROR_DUPLICATE((p->help_present == 0),
664                                 section_name,
665                                 entry->name);
666                         p->help_present = 1;
667
668                         val = parser_read_arg_bool(entry->value);
669                         PARSE_ERROR((val >= 0), section_name, entry->name);
670                         p->help = val;
671                         continue;
672                 }
673
674                 /* no_huge */
675                 if (strcmp(entry->name, "no_huge") == 0) {
676                         int val;
677
678                         PARSE_ERROR_DUPLICATE((p->no_huge_present == 0),
679                                 section_name,
680                                 entry->name);
681                         p->no_huge_present = 1;
682
683                         val = parser_read_arg_bool(entry->value);
684                         PARSE_ERROR((val >= 0), section_name, entry->name);
685                         p->no_huge = val;
686                         continue;
687                 }
688
689                 /* no_pci */
690                 if (strcmp(entry->name, "no_pci") == 0) {
691                         int val;
692
693                         PARSE_ERROR_DUPLICATE((p->no_pci_present == 0),
694                                 section_name,
695                                 entry->name);
696                         p->no_pci_present = 1;
697
698                         val = parser_read_arg_bool(entry->value);
699                         PARSE_ERROR((val >= 0), section_name, entry->name);
700                         p->no_pci = val;
701                         continue;
702                 }
703
704                 /* no_hpet */
705                 if (strcmp(entry->name, "no_hpet") == 0) {
706                         int val;
707
708                         PARSE_ERROR_DUPLICATE((p->no_hpet_present == 0),
709                                 section_name,
710                                 entry->name);
711                         p->no_hpet_present = 1;
712
713                         val = parser_read_arg_bool(entry->value);
714                         PARSE_ERROR((val >= 0), section_name, entry->name);
715                         p->no_hpet = val;
716                         continue;
717                 }
718
719                 /* no_shconf */
720                 if (strcmp(entry->name, "no_shconf") == 0) {
721                         int val;
722
723                         PARSE_ERROR_DUPLICATE((p->no_shconf_present == 0),
724                                 section_name,
725                                 entry->name);
726                         p->no_shconf_present = 1;
727
728                         val = parser_read_arg_bool(entry->value);
729                         PARSE_ERROR((val >= 0), section_name, entry->name);
730                         p->no_shconf = val;
731                         continue;
732                 }
733
734                 /* add_driver */
735                 if (strcmp(entry->name, "d") == 0) {
736                         PARSE_ERROR_DUPLICATE((p->add_driver == NULL),
737                                 section_name,
738                                 entry->name);
739                         p->add_driver = strdup(entry->value);
740                         continue;
741                 }
742
743                 /* socket_mem */
744                 if (strcmp(entry->name, "socket_mem") == 0) {
745                         PARSE_ERROR_DUPLICATE((p->socket_mem == NULL),
746                                 section_name,
747                                 entry->name);
748                         p->socket_mem = strdup(entry->value);
749                         continue;
750                 }
751
752                 /* huge_dir */
753                 if (strcmp(entry->name, "huge_dir") == 0) {
754                         PARSE_ERROR_DUPLICATE((p->huge_dir == NULL),
755                                 section_name,
756                                 entry->name);
757                         p->huge_dir = strdup(entry->value);
758                         continue;
759                 }
760
761                 /* file_prefix */
762                 if (strcmp(entry->name, "file_prefix") == 0) {
763                         PARSE_ERROR_DUPLICATE((p->file_prefix == NULL),
764                                 section_name,
765                                 entry->name);
766                         p->file_prefix = strdup(entry->value);
767                         continue;
768                 }
769
770                 /* base_virtaddr */
771                 if (strcmp(entry->name, "base_virtaddr") == 0) {
772                         PARSE_ERROR_DUPLICATE((p->base_virtaddr == NULL),
773                                 section_name,
774                                 entry->name);
775                         p->base_virtaddr = strdup(entry->value);
776                         continue;
777                 }
778
779                 /* create_uio_dev */
780                 if (strcmp(entry->name, "create_uio_dev") == 0) {
781                         int val;
782
783                         PARSE_ERROR_DUPLICATE((p->create_uio_dev_present == 0),
784                                 section_name,
785                                 entry->name);
786                         p->create_uio_dev_present = 1;
787
788                         val = parser_read_arg_bool(entry->value);
789                         PARSE_ERROR((val >= 0), section_name, entry->name);
790                         p->create_uio_dev = val;
791                         continue;
792                 }
793
794                 /* vfio_intr */
795                 if (strcmp(entry->name, "vfio_intr") == 0) {
796                         PARSE_ERROR_DUPLICATE((p->vfio_intr == NULL),
797                                 section_name,
798                                 entry->name);
799                         p->vfio_intr = strdup(entry->value);
800                         continue;
801                 }
802
803                 /* xen_dom0 */
804                 if (strcmp(entry->name, "xen_dom0") == 0) {
805                         int val;
806
807                         PARSE_ERROR_DUPLICATE((p->xen_dom0_present == 0),
808                                 section_name,
809                                 entry->name);
810                         p->xen_dom0_present = 1;
811
812                         val = parser_read_arg_bool(entry->value);
813                         PARSE_ERROR((val >= 0), section_name, entry->name);
814                         p->xen_dom0 = val;
815                         continue;
816                 }
817
818                 /* unrecognized */
819                 PARSE_ERROR_INVALID(0, section_name, entry->name);
820         }
821
822         free(entries);
823 }
824
825 static void
826 parse_pipeline_pktq_in(struct app_params *app,
827         struct app_pipeline_params *p,
828         char *value)
829 {
830         p->n_pktq_in = 0;
831
832         while (1) {
833                 enum app_pktq_in_type type;
834                 int id;
835                 char *name = strtok_r(value, PARSE_DELIMITER, &value);
836
837                 if (name == NULL)
838                         break;
839
840                 PARSE_ERROR_TOO_MANY_ELEMENTS(
841                         (p->n_pktq_in < RTE_DIM(p->pktq_in)),
842                         p->name, "pktq_in", (uint32_t)RTE_DIM(p->pktq_in));
843
844                 if (validate_name(name, "RXQ", 2) == 0) {
845                         type = APP_PKTQ_IN_HWQ;
846                         id = APP_PARAM_ADD(app->hwq_in_params, name);
847                         APP_PARAM_ADD_LINK_FOR_RXQ(app, name);
848                 } else if (validate_name(name, "SWQ", 1) == 0) {
849                         type = APP_PKTQ_IN_SWQ;
850                         id = APP_PARAM_ADD(app->swq_params, name);
851                 } else if (validate_name(name, "TM", 1) == 0) {
852                         type = APP_PKTQ_IN_TM;
853                         id = APP_PARAM_ADD(app->tm_params, name);
854                         APP_PARAM_ADD_LINK_FOR_TM(app, name);
855                 } else if (validate_name(name, "KNI", 1) == 0) {
856                         type = APP_PKTQ_IN_KNI;
857                         id = APP_PARAM_ADD(app->kni_params, name);
858                         APP_PARAM_ADD_LINK_FOR_KNI(app, name);
859                 } else if (validate_name(name, "SOURCE", 1) == 0) {
860                         type = APP_PKTQ_IN_SOURCE;
861                         id = APP_PARAM_ADD(app->source_params, name);
862                 } else
863                         PARSE_ERROR_INVALID_ELEMENT(0,
864                                 p->name, "pktq_in", name);
865
866                 p->pktq_in[p->n_pktq_in].type = type;
867                 p->pktq_in[p->n_pktq_in].id = (uint32_t) id;
868                 p->n_pktq_in++;
869         }
870
871         PARSE_ERROR_NO_ELEMENTS((p->n_pktq_in > 0), p->name, "pktq_in");
872 }
873
874 static void
875 parse_pipeline_pktq_out(struct app_params *app,
876         struct app_pipeline_params *p,
877         char *value)
878 {
879         p->n_pktq_out = 0;
880
881         while (1) {
882                 enum app_pktq_out_type type;
883                 int id;
884                 char *name = strtok_r(value, PARSE_DELIMITER, &value);
885
886                 if (name == NULL)
887                         break;
888
889                 PARSE_ERROR_TOO_MANY_ELEMENTS(
890                         (p->n_pktq_out < RTE_DIM(p->pktq_out)),
891                         p->name, "pktq_out", (uint32_t)RTE_DIM(p->pktq_out));
892
893                 if (validate_name(name, "TXQ", 2) == 0) {
894                         type = APP_PKTQ_OUT_HWQ;
895                         id = APP_PARAM_ADD(app->hwq_out_params, name);
896                         APP_PARAM_ADD_LINK_FOR_TXQ(app, name);
897                 } else if (validate_name(name, "SWQ", 1) == 0) {
898                         type = APP_PKTQ_OUT_SWQ;
899                         id = APP_PARAM_ADD(app->swq_params, name);
900                 } else if (validate_name(name, "TM", 1) == 0) {
901                         type = APP_PKTQ_OUT_TM;
902                         id = APP_PARAM_ADD(app->tm_params, name);
903                         APP_PARAM_ADD_LINK_FOR_TM(app, name);
904                 } else if (validate_name(name, "KNI", 1) == 0) {
905                         type = APP_PKTQ_OUT_KNI;
906                         id = APP_PARAM_ADD(app->kni_params, name);
907                         APP_PARAM_ADD_LINK_FOR_KNI(app, name);
908                 } else if (validate_name(name, "SINK", 1) == 0) {
909                         type = APP_PKTQ_OUT_SINK;
910                         id = APP_PARAM_ADD(app->sink_params, name);
911                 } else
912                         PARSE_ERROR_INVALID_ELEMENT(0,
913                                 p->name, "pktq_out", name);
914
915                 p->pktq_out[p->n_pktq_out].type = type;
916                 p->pktq_out[p->n_pktq_out].id = id;
917                 p->n_pktq_out++;
918         }
919
920         PARSE_ERROR_NO_ELEMENTS((p->n_pktq_out > 0), p->name, "pktq_out");
921 }
922
923 static void
924 parse_pipeline_msgq_in(struct app_params *app,
925         struct app_pipeline_params *p,
926         char *value)
927 {
928         p->n_msgq_in = 0;
929
930         while (1) {
931                 int idx;
932                 char *name = strtok_r(value, PARSE_DELIMITER, &value);
933
934                 if (name == NULL)
935                         break;
936
937                 PARSE_ERROR_TOO_MANY_ELEMENTS(
938                         (p->n_msgq_in < RTE_DIM(p->msgq_in)),
939                         p->name, "msgq_in", (uint32_t)(RTE_DIM(p->msgq_in)));
940
941                 PARSE_ERROR_INVALID_ELEMENT(
942                         (validate_name(name, "MSGQ", 1) == 0),
943                         p->name, "msgq_in", name);
944
945                 idx = APP_PARAM_ADD(app->msgq_params, name);
946                 p->msgq_in[p->n_msgq_in] = idx;
947                 p->n_msgq_in++;
948         }
949
950         PARSE_ERROR_NO_ELEMENTS((p->n_msgq_in > 0), p->name, "msgq_in");
951 }
952
953 static void
954 parse_pipeline_msgq_out(struct app_params *app,
955         struct app_pipeline_params *p,
956         char *value)
957 {
958         p->n_msgq_out = 0;
959
960         while (1) {
961                 int idx;
962                 char *name = strtok_r(value, PARSE_DELIMITER, &value);
963
964                 if (name == NULL)
965                         break;
966
967                 PARSE_ERROR_TOO_MANY_ELEMENTS(
968                         (p->n_msgq_out < RTE_DIM(p->msgq_out)),
969                         p->name, "msgq_out", (uint32_t)RTE_DIM(p->msgq_out));
970
971                 PARSE_ERROR_INVALID_ELEMENT(
972                         (validate_name(name, "MSGQ", 1) == 0),
973                         p->name, "msgq_out", name);
974
975                 idx = APP_PARAM_ADD(app->msgq_params, name);
976                 p->msgq_out[p->n_msgq_out] = idx;
977                 p->n_msgq_out++;
978         }
979
980         PARSE_ERROR_NO_ELEMENTS((p->n_msgq_out > 0), p->name, "msgq_out");
981 }
982
983 static void
984 parse_pipeline(struct app_params *app,
985         const char *section_name,
986         struct rte_cfgfile *cfg)
987 {
988         char name[CFG_NAME_LEN];
989         struct app_pipeline_params *param;
990         struct rte_cfgfile_entry *entries;
991         ssize_t param_idx;
992         int n_entries, i;
993
994         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
995         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
996
997         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
998         PARSE_ERROR_MALLOC(entries != NULL);
999
1000         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1001
1002         param_idx = APP_PARAM_ADD(app->pipeline_params, section_name);
1003         param = &app->pipeline_params[param_idx];
1004         PARSE_CHECK_DUPLICATE_SECTION(param);
1005
1006         for (i = 0; i < n_entries; i++) {
1007                 struct rte_cfgfile_entry *ent = &entries[i];
1008
1009                 if (strcmp(ent->name, "type") == 0) {
1010                         int w_size = snprintf(param->type, RTE_DIM(param->type),
1011                                         "%s", ent->value);
1012
1013                         PARSE_ERROR(((w_size > 0) &&
1014                                 (w_size < (int)RTE_DIM(param->type))),
1015                                 section_name,
1016                                 ent->name);
1017                         continue;
1018                 }
1019
1020                 if (strcmp(ent->name, "core") == 0) {
1021                         int status = parse_pipeline_core(
1022                                 &param->socket_id, &param->core_id,
1023                                 &param->hyper_th_id, ent->value);
1024
1025                         PARSE_ERROR((status == 0), section_name,
1026                                 ent->name);
1027                         continue;
1028                 }
1029
1030                 if (strcmp(ent->name, "pktq_in") == 0) {
1031                         parse_pipeline_pktq_in(app, param, ent->value);
1032
1033                         continue;
1034                 }
1035
1036                 if (strcmp(ent->name, "pktq_out") == 0) {
1037                         parse_pipeline_pktq_out(app, param, ent->value);
1038
1039                         continue;
1040                 }
1041
1042                 if (strcmp(ent->name, "msgq_in") == 0) {
1043                         parse_pipeline_msgq_in(app, param, ent->value);
1044
1045                         continue;
1046                 }
1047
1048                 if (strcmp(ent->name, "msgq_out") == 0) {
1049                         parse_pipeline_msgq_out(app, param, ent->value);
1050
1051                         continue;
1052                 }
1053
1054                 if (strcmp(ent->name, "timer_period") == 0) {
1055                         int status = parser_read_uint32(
1056                                 &param->timer_period,
1057                                 ent->value);
1058
1059                         PARSE_ERROR((status == 0), section_name,
1060                                 ent->name);
1061                         continue;
1062                 }
1063
1064                 /* pipeline type specific items */
1065                 APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),
1066                         "Parse error in section \"%s\": too many "
1067                         "pipeline specified parameters", section_name);
1068
1069                 param->args_name[param->n_args] = strdup(ent->name);
1070                 param->args_value[param->n_args] = strdup(ent->value);
1071
1072                 APP_CHECK((param->args_name[param->n_args] != NULL) &&
1073                         (param->args_value[param->n_args] != NULL),
1074                         "Parse error: no free memory");
1075
1076                 param->n_args++;
1077         }
1078
1079         snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name);
1080         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1081         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1082         param->msgq_in[param->n_msgq_in++] = param_idx;
1083
1084         snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name);
1085         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1086         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1087         param->msgq_out[param->n_msgq_out++] = param_idx;
1088
1089         snprintf(name, sizeof(name), "MSGQ-REQ-CORE-s%" PRIu32 "c%" PRIu32 "%s",
1090                 param->socket_id,
1091                 param->core_id,
1092                 (param->hyper_th_id) ? "h" : "");
1093         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1094         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1095
1096         snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s",
1097                 param->socket_id,
1098                 param->core_id,
1099                 (param->hyper_th_id) ? "h" : "");
1100         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1101         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1102
1103         free(entries);
1104 }
1105
1106 static void
1107 parse_mempool(struct app_params *app,
1108         const char *section_name,
1109         struct rte_cfgfile *cfg)
1110 {
1111         struct app_mempool_params *param;
1112         struct rte_cfgfile_entry *entries;
1113         ssize_t param_idx;
1114         int n_entries, i;
1115
1116         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1117         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1118
1119         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1120         PARSE_ERROR_MALLOC(entries != NULL);
1121
1122         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1123
1124         param_idx = APP_PARAM_ADD(app->mempool_params, section_name);
1125         param = &app->mempool_params[param_idx];
1126         PARSE_CHECK_DUPLICATE_SECTION(param);
1127
1128         for (i = 0; i < n_entries; i++) {
1129                 struct rte_cfgfile_entry *ent = &entries[i];
1130
1131                 if (strcmp(ent->name, "buffer_size") == 0) {
1132                         int status = parser_read_uint32(
1133                                 &param->buffer_size, ent->value);
1134
1135                         PARSE_ERROR((status == 0), section_name,
1136                                 ent->name);
1137                         continue;
1138                 }
1139
1140                 if (strcmp(ent->name, "pool_size") == 0) {
1141                         int status = parser_read_uint32(
1142                                 &param->pool_size, ent->value);
1143
1144                         PARSE_ERROR((status == 0), section_name,
1145                                 ent->name);
1146                         continue;
1147                 }
1148
1149                 if (strcmp(ent->name, "cache_size") == 0) {
1150                         int status = parser_read_uint32(
1151                                 &param->cache_size, ent->value);
1152
1153                         PARSE_ERROR((status == 0), section_name,
1154                                 ent->name);
1155                         continue;
1156                 }
1157
1158                 if (strcmp(ent->name, "cpu") == 0) {
1159                         int status = parser_read_uint32(
1160                                 &param->cpu_socket_id, ent->value);
1161
1162                         PARSE_ERROR((status == 0), section_name,
1163                                 ent->name);
1164                         continue;
1165                 }
1166
1167                 /* unrecognized */
1168                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1169         }
1170
1171         free(entries);
1172 }
1173
1174 static int
1175 parse_link_rss_qs(struct app_link_params *p,
1176         char *value)
1177 {
1178         p->n_rss_qs = 0;
1179
1180         while (1) {
1181                 char *token = strtok_r(value, PARSE_DELIMITER, &value);
1182
1183                 if (token == NULL)
1184                         break;
1185
1186                 if (p->n_rss_qs == RTE_DIM(p->rss_qs))
1187                         return -ENOMEM;
1188
1189                 if (parser_read_uint32(&p->rss_qs[p->n_rss_qs++], token))
1190                         return -EINVAL;
1191         }
1192
1193         return 0;
1194 }
1195
1196 static int
1197 parse_link_rss_proto_ipv4(struct app_link_params *p,
1198         char *value)
1199 {
1200         uint64_t mask = 0;
1201
1202         while (1) {
1203                 char *token = strtok_r(value, PARSE_DELIMITER, &value);
1204
1205                 if (token == NULL)
1206                         break;
1207
1208                 if (strcmp(token, "IP") == 0) {
1209                         mask |= ETH_RSS_IPV4;
1210                         continue;
1211                 }
1212                 if (strcmp(token, "FRAG") == 0) {
1213                         mask |= ETH_RSS_FRAG_IPV4;
1214                         continue;
1215                 }
1216                 if (strcmp(token, "TCP") == 0) {
1217                         mask |= ETH_RSS_NONFRAG_IPV4_TCP;
1218                         continue;
1219                 }
1220                 if (strcmp(token, "UDP") == 0) {
1221                         mask |= ETH_RSS_NONFRAG_IPV4_UDP;
1222                         continue;
1223                 }
1224                 if (strcmp(token, "SCTP") == 0) {
1225                         mask |= ETH_RSS_NONFRAG_IPV4_SCTP;
1226                         continue;
1227                 }
1228                 if (strcmp(token, "OTHER") == 0) {
1229                         mask |= ETH_RSS_NONFRAG_IPV4_OTHER;
1230                         continue;
1231                 }
1232                 return -EINVAL;
1233         }
1234
1235         p->rss_proto_ipv4 = mask;
1236         return 0;
1237 }
1238
1239 static int
1240 parse_link_rss_proto_ipv6(struct app_link_params *p,
1241         char *value)
1242 {
1243         uint64_t mask = 0;
1244
1245         while (1) {
1246                 char *token = strtok_r(value, PARSE_DELIMITER, &value);
1247
1248                 if (token == NULL)
1249                         break;
1250
1251                 if (strcmp(token, "IP") == 0) {
1252                         mask |= ETH_RSS_IPV6;
1253                         continue;
1254                 }
1255                 if (strcmp(token, "FRAG") == 0) {
1256                         mask |= ETH_RSS_FRAG_IPV6;
1257                         continue;
1258                 }
1259                 if (strcmp(token, "TCP") == 0) {
1260                         mask |= ETH_RSS_NONFRAG_IPV6_TCP;
1261                         continue;
1262                 }
1263                 if (strcmp(token, "UDP") == 0) {
1264                         mask |= ETH_RSS_NONFRAG_IPV6_UDP;
1265                         continue;
1266                 }
1267                 if (strcmp(token, "SCTP") == 0) {
1268                         mask |= ETH_RSS_NONFRAG_IPV6_SCTP;
1269                         continue;
1270                 }
1271                 if (strcmp(token, "OTHER") == 0) {
1272                         mask |= ETH_RSS_NONFRAG_IPV6_OTHER;
1273                         continue;
1274                 }
1275                 if (strcmp(token, "IP_EX") == 0) {
1276                         mask |= ETH_RSS_IPV6_EX;
1277                         continue;
1278                 }
1279                 if (strcmp(token, "TCP_EX") == 0) {
1280                         mask |= ETH_RSS_IPV6_TCP_EX;
1281                         continue;
1282                 }
1283                 if (strcmp(token, "UDP_EX") == 0) {
1284                         mask |= ETH_RSS_IPV6_UDP_EX;
1285                         continue;
1286                 }
1287                 return -EINVAL;
1288         }
1289
1290         p->rss_proto_ipv6 = mask;
1291         return 0;
1292 }
1293
1294 static int
1295 parse_link_rss_proto_l2(struct app_link_params *p,
1296         char *value)
1297 {
1298         uint64_t mask = 0;
1299
1300         while (1) {
1301                 char *token = strtok_r(value, PARSE_DELIMITER, &value);
1302
1303                 if (token == NULL)
1304                         break;
1305
1306                 if (strcmp(token, "L2") == 0) {
1307                         mask |= ETH_RSS_L2_PAYLOAD;
1308                         continue;
1309                 }
1310                 return -EINVAL;
1311         }
1312
1313         p->rss_proto_l2 = mask;
1314         return 0;
1315 }
1316
1317 static void
1318 parse_link(struct app_params *app,
1319         const char *section_name,
1320         struct rte_cfgfile *cfg)
1321 {
1322         struct app_link_params *param;
1323         struct rte_cfgfile_entry *entries;
1324         int n_entries, i;
1325         int rss_qs_present = 0;
1326         int rss_proto_ipv4_present = 0;
1327         int rss_proto_ipv6_present = 0;
1328         int rss_proto_l2_present = 0;
1329         int pci_bdf_present = 0;
1330         ssize_t param_idx;
1331
1332         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1333         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1334
1335         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1336         PARSE_ERROR_MALLOC(entries != NULL);
1337
1338         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1339
1340         param_idx = APP_PARAM_ADD(app->link_params, section_name);
1341         param = &app->link_params[param_idx];
1342         PARSE_CHECK_DUPLICATE_SECTION(param);
1343
1344         for (i = 0; i < n_entries; i++) {
1345                 struct rte_cfgfile_entry *ent = &entries[i];
1346
1347                 if (strcmp(ent->name, "promisc") == 0) {
1348                         int status = parser_read_arg_bool(ent->value);
1349
1350                         PARSE_ERROR((status != -EINVAL), section_name,
1351                                 ent->name);
1352                         param->promisc = status;
1353                         continue;
1354                 }
1355
1356                 if (strcmp(ent->name, "arp_q") == 0) {
1357                         int status = parser_read_uint32(&param->arp_q,
1358                                 ent->value);
1359
1360                         PARSE_ERROR((status == 0), section_name,
1361                                 ent->name);
1362                         continue;
1363                 }
1364
1365                 if (strcmp(ent->name, "tcp_syn_q") == 0) {
1366                         int status = parser_read_uint32(
1367                                 &param->tcp_syn_q, ent->value);
1368
1369                         PARSE_ERROR((status == 0), section_name, ent->name);
1370                         continue;
1371                 }
1372
1373                 if (strcmp(ent->name, "ip_local_q") == 0) {
1374                         int status = parser_read_uint32(
1375                                 &param->ip_local_q, ent->value);
1376
1377                         PARSE_ERROR((status == 0), section_name,
1378                                 ent->name);
1379                         continue;
1380                 }
1381
1382                 if (strcmp(ent->name, "tcp_local_q") == 0) {
1383                         int status = parser_read_uint32(
1384                                 &param->tcp_local_q, ent->value);
1385
1386                         PARSE_ERROR((status == 0), section_name,
1387                                 ent->name);
1388                         continue;
1389                 }
1390
1391                 if (strcmp(ent->name, "udp_local_q") == 0) {
1392                         int status = parser_read_uint32(
1393                                 &param->udp_local_q, ent->value);
1394
1395                         PARSE_ERROR((status == 0), section_name,
1396                                 ent->name);
1397                         continue;
1398                 }
1399
1400                 if (strcmp(ent->name, "sctp_local_q") == 0) {
1401                         int status = parser_read_uint32(
1402                                 &param->sctp_local_q, ent->value);
1403
1404                         PARSE_ERROR((status == 0), section_name,
1405                                 ent->name);
1406                         continue;
1407                 }
1408
1409                 if (strcmp(ent->name, "rss_qs") == 0) {
1410                         int status = parse_link_rss_qs(param, ent->value);
1411
1412                         PARSE_ERROR((status == 0), section_name,
1413                                 ent->name);
1414                         rss_qs_present = 1;
1415                         continue;
1416                 }
1417
1418                 if (strcmp(ent->name, "rss_proto_ipv4") == 0) {
1419                         int status =
1420                                 parse_link_rss_proto_ipv4(param, ent->value);
1421
1422                         PARSE_ERROR((status != -EINVAL), section_name,
1423                                 ent->name);
1424                         rss_proto_ipv4_present = 1;
1425                         continue;
1426                 }
1427
1428                 if (strcmp(ent->name, "rss_proto_ipv6") == 0) {
1429                         int status =
1430                                 parse_link_rss_proto_ipv6(param, ent->value);
1431
1432                         PARSE_ERROR((status != -EINVAL), section_name,
1433                                 ent->name);
1434                         rss_proto_ipv6_present = 1;
1435                         continue;
1436                 }
1437
1438                 if (strcmp(ent->name, "rss_proto_l2") == 0) {
1439                         int status = parse_link_rss_proto_l2(param, ent->value);
1440
1441                         PARSE_ERROR((status != -EINVAL), section_name,
1442                                 ent->name);
1443                         rss_proto_l2_present = 1;
1444                         continue;
1445                 }
1446
1447                 if (strcmp(ent->name, "pci_bdf") == 0) {
1448                         PARSE_ERROR_DUPLICATE((pci_bdf_present == 0),
1449                                 section_name, ent->name);
1450
1451                         snprintf(param->pci_bdf, APP_LINK_PCI_BDF_SIZE,
1452                                 "%s", ent->value);
1453                         pci_bdf_present = 1;
1454                         continue;
1455                 }
1456
1457                 /* unrecognized */
1458                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1459         }
1460
1461         /* Check for mandatory fields */
1462         if (app->port_mask)
1463                 PARSE_ERROR_MESSAGE((pci_bdf_present == 0),
1464                         section_name, "pci_bdf",
1465                         "entry not allowed (port_mask is provided)");
1466         else
1467                 PARSE_ERROR_MESSAGE((pci_bdf_present),
1468                         section_name, "pci_bdf",
1469                         "this entry is mandatory (port_mask is not "
1470                         "provided)");
1471
1472         if (rss_proto_ipv4_present)
1473                 PARSE_ERROR_MESSAGE((rss_qs_present),
1474                         section_name, "rss_proto_ipv4",
1475                         "entry not allowed (rss_qs entry is not provided)");
1476         if (rss_proto_ipv6_present)
1477                 PARSE_ERROR_MESSAGE((rss_qs_present),
1478                         section_name, "rss_proto_ipv6",
1479                         "entry not allowed (rss_qs entry is not provided)");
1480         if (rss_proto_l2_present)
1481                 PARSE_ERROR_MESSAGE((rss_qs_present),
1482                         section_name, "rss_proto_l2",
1483                         "entry not allowed (rss_qs entry is not provided)");
1484         if (rss_proto_ipv4_present |
1485                 rss_proto_ipv6_present |
1486                 rss_proto_l2_present){
1487                 if (rss_proto_ipv4_present == 0)
1488                         param->rss_proto_ipv4 = 0;
1489                 if (rss_proto_ipv6_present == 0)
1490                         param->rss_proto_ipv6 = 0;
1491                 if (rss_proto_l2_present == 0)
1492                         param->rss_proto_l2 = 0;
1493         }
1494
1495         free(entries);
1496 }
1497
1498 static void
1499 parse_rxq(struct app_params *app,
1500         const char *section_name,
1501         struct rte_cfgfile *cfg)
1502 {
1503         struct app_pktq_hwq_in_params *param;
1504         struct rte_cfgfile_entry *entries;
1505         int n_entries, i;
1506         ssize_t param_idx;
1507
1508         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1509         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1510
1511         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1512         PARSE_ERROR_MALLOC(entries != NULL);
1513
1514         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1515
1516         param_idx = APP_PARAM_ADD(app->hwq_in_params, section_name);
1517         param = &app->hwq_in_params[param_idx];
1518         PARSE_CHECK_DUPLICATE_SECTION(param);
1519
1520         APP_PARAM_ADD_LINK_FOR_RXQ(app, section_name);
1521
1522         for (i = 0; i < n_entries; i++) {
1523                 struct rte_cfgfile_entry *ent = &entries[i];
1524
1525                 if (strcmp(ent->name, "mempool") == 0) {
1526                         int status = validate_name(ent->value,
1527                                 "MEMPOOL", 1);
1528                         ssize_t idx;
1529
1530                         PARSE_ERROR((status == 0), section_name,
1531                                 ent->name);
1532
1533                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1534                         param->mempool_id = idx;
1535                         continue;
1536                 }
1537
1538                 if (strcmp(ent->name, "size") == 0) {
1539                         int status = parser_read_uint32(&param->size,
1540                                 ent->value);
1541
1542                         PARSE_ERROR((status == 0), section_name,
1543                                 ent->name);
1544                         continue;
1545                 }
1546
1547                 if (strcmp(ent->name, "burst") == 0) {
1548                         int status = parser_read_uint32(&param->burst,
1549                                 ent->value);
1550
1551                         PARSE_ERROR((status == 0), section_name,
1552                                 ent->name);
1553                         continue;
1554                 }
1555
1556                 /* unrecognized */
1557                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1558         }
1559
1560         free(entries);
1561 }
1562
1563 static void
1564 parse_txq(struct app_params *app,
1565         const char *section_name,
1566         struct rte_cfgfile *cfg)
1567 {
1568         struct app_pktq_hwq_out_params *param;
1569         struct rte_cfgfile_entry *entries;
1570         int n_entries, i;
1571         ssize_t param_idx;
1572
1573         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1574         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1575
1576         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1577         PARSE_ERROR_MALLOC(entries != NULL);
1578
1579         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1580
1581         param_idx = APP_PARAM_ADD(app->hwq_out_params, section_name);
1582         param = &app->hwq_out_params[param_idx];
1583         PARSE_CHECK_DUPLICATE_SECTION(param);
1584
1585         APP_PARAM_ADD_LINK_FOR_TXQ(app, section_name);
1586
1587         for (i = 0; i < n_entries; i++) {
1588                 struct rte_cfgfile_entry *ent = &entries[i];
1589
1590                 if (strcmp(ent->name, "size") == 0) {
1591                         int status = parser_read_uint32(&param->size,
1592                                 ent->value);
1593
1594                         PARSE_ERROR((status == 0), section_name,
1595                                 ent->name);
1596                         continue;
1597                 }
1598
1599                 if (strcmp(ent->name, "burst") == 0) {
1600                         int status = parser_read_uint32(&param->burst,
1601                                 ent->value);
1602
1603                         PARSE_ERROR((status == 0), section_name,
1604                                 ent->name);
1605                         continue;
1606                 }
1607
1608                 if (strcmp(ent->name, "dropless") == 0) {
1609                         int status = parser_read_arg_bool(ent->value);
1610
1611
1612                         PARSE_ERROR((status != -EINVAL), section_name,
1613                                 ent->name);
1614                         param->dropless = status;
1615                         continue;
1616                 }
1617
1618                 if (strcmp(ent->name, "n_retries") == 0) {
1619                         int status = parser_read_uint64(&param->n_retries,
1620                                 ent->value);
1621
1622                         PARSE_ERROR((status == 0), section_name,
1623                                 ent->name);
1624                         continue;
1625                 }
1626
1627                 /* unrecognized */
1628                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1629         }
1630
1631         free(entries);
1632 }
1633
1634 static void
1635 parse_swq(struct app_params *app,
1636         const char *section_name,
1637         struct rte_cfgfile *cfg)
1638 {
1639         struct app_pktq_swq_params *param;
1640         struct rte_cfgfile_entry *entries;
1641         int n_entries, i;
1642         uint32_t mtu_present = 0;
1643         uint32_t metadata_size_present = 0;
1644         uint32_t mempool_direct_present = 0;
1645         uint32_t mempool_indirect_present = 0;
1646
1647         ssize_t param_idx;
1648
1649         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1650         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1651
1652         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1653         PARSE_ERROR_MALLOC(entries != NULL);
1654
1655         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1656
1657         param_idx = APP_PARAM_ADD(app->swq_params, section_name);
1658         param = &app->swq_params[param_idx];
1659         PARSE_CHECK_DUPLICATE_SECTION(param);
1660
1661         for (i = 0; i < n_entries; i++) {
1662                 struct rte_cfgfile_entry *ent = &entries[i];
1663
1664                 if (strcmp(ent->name, "size") == 0) {
1665                         int status = parser_read_uint32(&param->size,
1666                                 ent->value);
1667
1668                         PARSE_ERROR((status == 0), section_name,
1669                                 ent->name);
1670                         continue;
1671                 }
1672
1673                 if (strcmp(ent->name, "burst_read") == 0) {
1674                         int status = parser_read_uint32(&
1675                                 param->burst_read, ent->value);
1676
1677                         PARSE_ERROR((status == 0), section_name,
1678                                 ent->name);
1679                         continue;
1680                 }
1681
1682                 if (strcmp(ent->name, "burst_write") == 0) {
1683                         int status = parser_read_uint32(
1684                                 &param->burst_write, ent->value);
1685
1686                         PARSE_ERROR((status == 0), section_name,
1687                                 ent->name);
1688                         continue;
1689                 }
1690
1691                 if (strcmp(ent->name, "dropless") == 0) {
1692                         int status = parser_read_arg_bool(ent->value);
1693
1694                         PARSE_ERROR((status != -EINVAL), section_name,
1695                                 ent->name);
1696                         param->dropless = status;
1697                         continue;
1698                 }
1699
1700                 if (strcmp(ent->name, "n_retries") == 0) {
1701                         int status = parser_read_uint64(&param->n_retries,
1702                                 ent->value);
1703
1704                         PARSE_ERROR((status == 0), section_name,
1705                                 ent->name);
1706                         continue;
1707                 }
1708
1709                 if (strcmp(ent->name, "cpu") == 0) {
1710                         int status = parser_read_uint32(
1711                                 &param->cpu_socket_id, ent->value);
1712
1713                         PARSE_ERROR((status == 0), section_name, ent->name);
1714                         continue;
1715                 }
1716
1717                 if (strcmp(ent->name, "ipv4_frag") == 0) {
1718                         int status = parser_read_arg_bool(ent->value);
1719
1720                         PARSE_ERROR((status != -EINVAL), section_name,
1721                                 ent->name);
1722
1723                         param->ipv4_frag = status;
1724                         if (param->mtu == 0)
1725                                 param->mtu = 1500;
1726
1727                         continue;
1728                 }
1729
1730                 if (strcmp(ent->name, "ipv6_frag") == 0) {
1731                         int status = parser_read_arg_bool(ent->value);
1732
1733                         PARSE_ERROR((status != -EINVAL), section_name,
1734                                 ent->name);
1735                         param->ipv6_frag = status;
1736                         if (param->mtu == 0)
1737                                 param->mtu = 1320;
1738                         continue;
1739                 }
1740
1741                 if (strcmp(ent->name, "ipv4_ras") == 0) {
1742                         int status = parser_read_arg_bool(ent->value);
1743
1744                         PARSE_ERROR((status != -EINVAL), section_name,
1745                                 ent->name);
1746                         param->ipv4_ras = status;
1747                         continue;
1748                 }
1749
1750                 if (strcmp(ent->name, "ipv6_ras") == 0) {
1751                         int status = parser_read_arg_bool(ent->value);
1752
1753                         PARSE_ERROR((status != -EINVAL), section_name,
1754                                 ent->name);
1755                         param->ipv6_ras = status;
1756                         continue;
1757                 }
1758
1759                 if (strcmp(ent->name, "mtu") == 0) {
1760                         int status = parser_read_uint32(&param->mtu,
1761                                         ent->value);
1762
1763                         PARSE_ERROR((status == 0), section_name,
1764                                 ent->name);
1765                         mtu_present = 1;
1766                         continue;
1767                 }
1768
1769                 if (strcmp(ent->name, "metadata_size") == 0) {
1770                         int status = parser_read_uint32(
1771                                 &param->metadata_size, ent->value);
1772
1773                         PARSE_ERROR((status == 0), section_name,
1774                                 ent->name);
1775                         metadata_size_present = 1;
1776                         continue;
1777                 }
1778
1779                 if (strcmp(ent->name, "mempool_direct") == 0) {
1780                         int status = validate_name(ent->value,
1781                                 "MEMPOOL", 1);
1782                         ssize_t idx;
1783
1784                         PARSE_ERROR((status == 0), section_name,
1785                                 ent->name);
1786
1787                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1788                         param->mempool_direct_id = idx;
1789
1790                         mempool_direct_present = 1;
1791                         continue;
1792                 }
1793
1794                 if (strcmp(ent->name, "mempool_indirect") == 0) {
1795                         int status = validate_name(ent->value,
1796                                 "MEMPOOL", 1);
1797                         ssize_t idx;
1798
1799                         PARSE_ERROR((status == 0), section_name,
1800                                 ent->name);
1801
1802                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1803                         param->mempool_indirect_id = idx;
1804
1805                         mempool_indirect_present = 1;
1806                         continue;
1807                 }
1808
1809                 /* unrecognized */
1810                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1811         }
1812
1813         APP_CHECK(((mtu_present == 0) ||
1814                 ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
1815                 "Parse error in section \"%s\": IPv4/IPv6 fragmentation "
1816                 "is off, therefore entry \"mtu\" is not allowed",
1817                 section_name);
1818
1819         APP_CHECK(((metadata_size_present == 0) ||
1820                 ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
1821                 "Parse error in section \"%s\": IPv4/IPv6 fragmentation "
1822                 "is off, therefore entry \"metadata_size\" is "
1823                 "not allowed", section_name);
1824
1825         APP_CHECK(((mempool_direct_present == 0) ||
1826                 ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
1827                 "Parse error in section \"%s\": IPv4/IPv6 fragmentation "
1828                 "is off, therefore entry \"mempool_direct\" is "
1829                 "not allowed", section_name);
1830
1831         APP_CHECK(((mempool_indirect_present == 0) ||
1832                 ((param->ipv4_frag == 1) || (param->ipv6_frag == 1))),
1833                 "Parse error in section \"%s\": IPv4/IPv6 fragmentation "
1834                 "is off, therefore entry \"mempool_indirect\" is "
1835                 "not allowed", section_name);
1836
1837         free(entries);
1838 }
1839
1840 static void
1841 parse_tm(struct app_params *app,
1842         const char *section_name,
1843         struct rte_cfgfile *cfg)
1844 {
1845         struct app_pktq_tm_params *param;
1846         struct rte_cfgfile_entry *entries;
1847         int n_entries, i;
1848         ssize_t param_idx;
1849
1850         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1851         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1852
1853         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1854         PARSE_ERROR_MALLOC(entries != NULL);
1855
1856         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1857
1858         param_idx = APP_PARAM_ADD(app->tm_params, section_name);
1859         param = &app->tm_params[param_idx];
1860         PARSE_CHECK_DUPLICATE_SECTION(param);
1861
1862         APP_PARAM_ADD_LINK_FOR_TM(app, section_name);
1863
1864         for (i = 0; i < n_entries; i++) {
1865                 struct rte_cfgfile_entry *ent = &entries[i];
1866
1867                 if (strcmp(ent->name, "cfg") == 0) {
1868                         param->file_name = strdup(ent->value);
1869                         PARSE_ERROR_MALLOC(param->file_name != NULL);
1870                         continue;
1871                 }
1872
1873                 if (strcmp(ent->name, "burst_read") == 0) {
1874                         int status = parser_read_uint32(
1875                                 &param->burst_read, ent->value);
1876
1877                         PARSE_ERROR((status == 0), section_name,
1878                                 ent->name);
1879                         continue;
1880                 }
1881
1882                 if (strcmp(ent->name, "burst_write") == 0) {
1883                         int status = parser_read_uint32(
1884                                 &param->burst_write, ent->value);
1885
1886                         PARSE_ERROR((status == 0), section_name,
1887                                 ent->name);
1888                         continue;
1889                 }
1890
1891                 /* unrecognized */
1892                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1893         }
1894
1895         free(entries);
1896 }
1897
1898 static void
1899 parse_kni(struct app_params *app,
1900                   const char *section_name,
1901                   struct rte_cfgfile *cfg)
1902 {
1903         struct app_pktq_kni_params *param;
1904         struct rte_cfgfile_entry *entries;
1905         int n_entries, i;
1906         ssize_t param_idx;
1907
1908         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1909         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1910
1911         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1912         PARSE_ERROR_MALLOC(entries != NULL);
1913
1914         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1915
1916         param_idx = APP_PARAM_ADD(app->kni_params, section_name);
1917         param = &app->kni_params[param_idx];
1918         PARSE_CHECK_DUPLICATE_SECTION(param);
1919
1920         APP_PARAM_ADD_LINK_FOR_KNI(app, section_name);
1921
1922         for (i = 0; i < n_entries; i++) {
1923                 struct rte_cfgfile_entry *ent = &entries[i];
1924
1925                 if (strcmp(ent->name, "core") == 0) {
1926                         int status = parse_pipeline_core(
1927                                         &param->socket_id,
1928                                         &param->core_id,
1929                                         &param->hyper_th_id,
1930                                         ent->value);
1931
1932                         PARSE_ERROR((status == 0), section_name,
1933                                                 ent->name);
1934                         param->force_bind = 1;
1935                         continue;
1936                 }
1937
1938                 if (strcmp(ent->name, "mempool") == 0) {
1939                         int status = validate_name(ent->value,
1940                                 "MEMPOOL", 1);
1941                         ssize_t idx;
1942
1943                         PARSE_ERROR((status == 0), section_name,
1944                                                 ent->name);
1945
1946                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1947                         param->mempool_id = idx;
1948                         continue;
1949                 }
1950
1951                 if (strcmp(ent->name, "burst_read") == 0) {
1952                         int status = parser_read_uint32(&param->burst_read,
1953                                                 ent->value);
1954
1955                         PARSE_ERROR((status == 0), section_name,
1956                                                 ent->name);
1957                         continue;
1958                 }
1959
1960                 if (strcmp(ent->name, "burst_write") == 0) {
1961                         int status = parser_read_uint32(&param->burst_write,
1962                                                 ent->value);
1963
1964                         PARSE_ERROR((status == 0), section_name,
1965                                                 ent->name);
1966                         continue;
1967                 }
1968
1969                 if (strcmp(ent->name, "dropless") == 0) {
1970                         int status = parser_read_arg_bool(ent->value);
1971
1972                         PARSE_ERROR((status != -EINVAL), section_name,
1973                                                 ent->name);
1974                         param->dropless = status;
1975                         continue;
1976                 }
1977
1978                 if (strcmp(ent->name, "n_retries") == 0) {
1979                         int status = parser_read_uint64(&param->n_retries,
1980                                                 ent->value);
1981
1982                         PARSE_ERROR((status == 0), section_name,
1983                                                 ent->name);
1984                         continue;
1985                 }
1986
1987                 /* unrecognized */
1988                 PARSE_ERROR_INVALID(0, section_name, ent->name);
1989         }
1990
1991         free(entries);
1992 }
1993
1994 static void
1995 parse_source(struct app_params *app,
1996         const char *section_name,
1997         struct rte_cfgfile *cfg)
1998 {
1999         struct app_pktq_source_params *param;
2000         struct rte_cfgfile_entry *entries;
2001         int n_entries, i;
2002         ssize_t param_idx;
2003         uint32_t pcap_file_present = 0;
2004         uint32_t pcap_size_present = 0;
2005
2006         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
2007         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
2008
2009         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
2010         PARSE_ERROR_MALLOC(entries != NULL);
2011
2012         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
2013
2014         param_idx = APP_PARAM_ADD(app->source_params, section_name);
2015         param = &app->source_params[param_idx];
2016         PARSE_CHECK_DUPLICATE_SECTION(param);
2017
2018         for (i = 0; i < n_entries; i++) {
2019                 struct rte_cfgfile_entry *ent = &entries[i];
2020
2021                 if (strcmp(ent->name, "mempool") == 0) {
2022                         int status = validate_name(ent->value,
2023                                 "MEMPOOL", 1);
2024                         ssize_t idx;
2025
2026                         PARSE_ERROR((status == 0), section_name,
2027                                 ent->name);
2028
2029                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
2030                         param->mempool_id = idx;
2031                         continue;
2032                 }
2033
2034                 if (strcmp(ent->name, "burst") == 0) {
2035                         int status = parser_read_uint32(&param->burst,
2036                                 ent->value);
2037
2038                         PARSE_ERROR((status == 0), section_name,
2039                                 ent->name);
2040                         continue;
2041                 }
2042
2043                 if (strcmp(ent->name, "pcap_file_rd") == 0) {
2044                         PARSE_ERROR_DUPLICATE((pcap_file_present == 0),
2045                                 section_name, ent->name);
2046
2047                         param->file_name = strdup(ent->value);
2048
2049                         PARSE_ERROR_MALLOC(param->file_name != NULL);
2050                         pcap_file_present = 1;
2051
2052                         continue;
2053                 }
2054
2055                 if (strcmp(ent->name, "pcap_bytes_rd_per_pkt") == 0) {
2056                         int status;
2057
2058                         PARSE_ERROR_DUPLICATE((pcap_size_present == 0),
2059                                 section_name, ent->name);
2060
2061                         status = parser_read_uint32(
2062                                 &param->n_bytes_per_pkt, ent->value);
2063
2064                         PARSE_ERROR((status == 0), section_name,
2065                                 ent->name);
2066                         pcap_size_present = 1;
2067
2068                         continue;
2069                 }
2070
2071                 /* unrecognized */
2072                 PARSE_ERROR_INVALID(0, section_name, ent->name);
2073         }
2074
2075         free(entries);
2076 }
2077
2078 static void
2079 parse_sink(struct app_params *app,
2080         const char *section_name,
2081         struct rte_cfgfile *cfg)
2082 {
2083         struct app_pktq_sink_params *param;
2084         struct rte_cfgfile_entry *entries;
2085         int n_entries, i;
2086         ssize_t param_idx;
2087         uint32_t pcap_file_present = 0;
2088         uint32_t pcap_n_pkt_present = 0;
2089
2090         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
2091         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
2092
2093         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
2094         PARSE_ERROR_MALLOC(entries != NULL);
2095
2096         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
2097
2098         param_idx = APP_PARAM_ADD(app->sink_params, section_name);
2099         param = &app->sink_params[param_idx];
2100         PARSE_CHECK_DUPLICATE_SECTION(param);
2101
2102         for (i = 0; i < n_entries; i++) {
2103                 struct rte_cfgfile_entry *ent = &entries[i];
2104
2105                 if (strcmp(ent->name, "pcap_file_wr") == 0) {
2106                         PARSE_ERROR_DUPLICATE((pcap_file_present == 0),
2107                                 section_name, ent->name);
2108
2109                         param->file_name = strdup(ent->value);
2110
2111                         PARSE_ERROR_MALLOC((param->file_name != NULL));
2112
2113                         continue;
2114                 }
2115
2116                 if (strcmp(ent->name, "pcap_n_pkt_wr") == 0) {
2117                         int status;
2118
2119                         PARSE_ERROR_DUPLICATE((pcap_n_pkt_present == 0),
2120                                 section_name, ent->name);
2121
2122                         status = parser_read_uint32(
2123                                 &param->n_pkts_to_dump, ent->value);
2124
2125                         PARSE_ERROR((status == 0), section_name,
2126                                 ent->name);
2127
2128                         continue;
2129                 }
2130
2131                 /* unrecognized */
2132                 PARSE_ERROR_INVALID(0, section_name, ent->name);
2133         }
2134
2135         free(entries);
2136 }
2137
2138 static void
2139 parse_msgq_req_pipeline(struct app_params *app,
2140         const char *section_name,
2141         struct rte_cfgfile *cfg)
2142 {
2143         struct app_msgq_params *param;
2144         struct rte_cfgfile_entry *entries;
2145         int n_entries, i;
2146         ssize_t param_idx;
2147
2148         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
2149         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
2150
2151         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
2152         PARSE_ERROR_MALLOC(entries != NULL);
2153
2154         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
2155
2156         param_idx = APP_PARAM_ADD(app->msgq_params, section_name);
2157         param = &app->msgq_params[param_idx];
2158         PARSE_CHECK_DUPLICATE_SECTION(param);
2159
2160         for (i = 0; i < n_entries; i++) {
2161                 struct rte_cfgfile_entry *ent = &entries[i];
2162
2163                 if (strcmp(ent->name, "size") == 0) {
2164                         int status = parser_read_uint32(&param->size,
2165                                 ent->value);
2166
2167                         PARSE_ERROR((status == 0), section_name,
2168                                 ent->name);
2169                         continue;
2170                 }
2171
2172                 /* unrecognized */
2173                 PARSE_ERROR_INVALID(0, section_name, ent->name);
2174         }
2175
2176         free(entries);
2177 }
2178
2179 static void
2180 parse_msgq_rsp_pipeline(struct app_params *app,
2181         const char *section_name,
2182         struct rte_cfgfile *cfg)
2183 {
2184         struct app_msgq_params *param;
2185         struct rte_cfgfile_entry *entries;
2186         int n_entries, i;
2187         ssize_t param_idx;
2188
2189         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
2190         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
2191
2192         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
2193         PARSE_ERROR_MALLOC(entries != NULL);
2194
2195         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
2196
2197         param_idx = APP_PARAM_ADD(app->msgq_params, section_name);
2198         param = &app->msgq_params[param_idx];
2199         PARSE_CHECK_DUPLICATE_SECTION(param);
2200
2201         for (i = 0; i < n_entries; i++) {
2202                 struct rte_cfgfile_entry *ent = &entries[i];
2203
2204                 if (strcmp(ent->name, "size") == 0) {
2205                         int status = parser_read_uint32(&param->size,
2206                                 ent->value);
2207
2208                         PARSE_ERROR((status == 0), section_name,
2209                                 ent->name);
2210                         continue;
2211                 }
2212
2213                 /* unrecognized */
2214                 PARSE_ERROR_INVALID(0, section_name, ent->name);
2215         }
2216
2217         free(entries);
2218 }
2219
2220 static void
2221 parse_msgq(struct app_params *app,
2222         const char *section_name,
2223         struct rte_cfgfile *cfg)
2224 {
2225         struct app_msgq_params *param;
2226         struct rte_cfgfile_entry *entries;
2227         int n_entries, i;
2228         ssize_t param_idx;
2229
2230         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
2231         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
2232
2233         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
2234         PARSE_ERROR_MALLOC(entries != NULL);
2235
2236         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
2237
2238         param_idx = APP_PARAM_ADD(app->msgq_params, section_name);
2239         param = &app->msgq_params[param_idx];
2240         PARSE_CHECK_DUPLICATE_SECTION(param);
2241
2242         for (i = 0; i < n_entries; i++) {
2243                 struct rte_cfgfile_entry *ent = &entries[i];
2244
2245                 if (strcmp(ent->name, "size") == 0) {
2246                         int status = parser_read_uint32(&param->size,
2247                                 ent->value);
2248
2249                         PARSE_ERROR((status == 0), section_name,
2250                                 ent->name);
2251                         continue;
2252                 }
2253
2254                 if (strcmp(ent->name, "cpu") == 0) {
2255                         int status = parser_read_uint32(
2256                                 &param->cpu_socket_id, ent->value);
2257
2258                         PARSE_ERROR((status == 0), section_name,
2259                                 ent->name);
2260                         continue;
2261                 }
2262
2263                 /* unrecognized */
2264                 PARSE_ERROR_INVALID(0, section_name, ent->name);
2265         }
2266
2267         free(entries);
2268 }
2269
2270 typedef void (*config_section_load)(struct app_params *p,
2271         const char *section_name,
2272         struct rte_cfgfile *cfg);
2273
2274 struct config_section {
2275         const char prefix[CFG_NAME_LEN];
2276         int numbers;
2277         config_section_load load;
2278 };
2279
2280 static const struct config_section cfg_file_scheme[] = {
2281         {"EAL", 0, parse_eal},
2282         {"PIPELINE", 1, parse_pipeline},
2283         {"MEMPOOL", 1, parse_mempool},
2284         {"LINK", 1, parse_link},
2285         {"RXQ", 2, parse_rxq},
2286         {"TXQ", 2, parse_txq},
2287         {"SWQ", 1, parse_swq},
2288         {"TM", 1, parse_tm},
2289         {"KNI", 1, parse_kni},
2290         {"SOURCE", 1, parse_source},
2291         {"SINK", 1, parse_sink},
2292         {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline},
2293         {"MSGQ-RSP-PIPELINE", 1, parse_msgq_rsp_pipeline},
2294         {"MSGQ", 1, parse_msgq},
2295 };
2296
2297 static void
2298 create_implicit_mempools(struct app_params *app)
2299 {
2300         APP_PARAM_ADD(app->mempool_params, "MEMPOOL0");
2301 }
2302
2303 static void
2304 create_implicit_links_from_port_mask(struct app_params *app,
2305         uint64_t port_mask)
2306 {
2307         uint32_t pmd_id, link_id;
2308
2309         link_id = 0;
2310         for (pmd_id = 0; pmd_id < RTE_MAX_ETHPORTS; pmd_id++) {
2311                 char name[APP_PARAM_NAME_SIZE];
2312                 ssize_t idx;
2313
2314                 if ((port_mask & (1LLU << pmd_id)) == 0)
2315                         continue;
2316
2317                 snprintf(name, sizeof(name), "LINK%" PRIu32, link_id);
2318                 idx = APP_PARAM_ADD(app->link_params, name);
2319
2320                 app->link_params[idx].pmd_id = pmd_id;
2321                 link_id++;
2322         }
2323 }
2324
2325 static void
2326 assign_link_pmd_id_from_pci_bdf(struct app_params *app)
2327 {
2328         uint32_t i;
2329
2330         for (i = 0; i < app->n_links; i++) {
2331                 struct app_link_params *link = &app->link_params[i];
2332
2333                 APP_CHECK((strlen(link->pci_bdf)),
2334                         "Parse error: %s pci_bdf is not configured "
2335                         "(port_mask is not provided)",
2336                         link->name);
2337
2338                 link->pmd_id = i;
2339         }
2340 }
2341
2342 int
2343 app_config_parse(struct app_params *app, const char *file_name)
2344 {
2345         struct rte_cfgfile *cfg;
2346         char **section_names;
2347         int i, j, sect_count;
2348
2349         /* Implicit mempools */
2350         create_implicit_mempools(app);
2351
2352         /* Port mask */
2353         if (app->port_mask)
2354                 create_implicit_links_from_port_mask(app, app->port_mask);
2355
2356         /* Load application configuration file */
2357         cfg = rte_cfgfile_load(file_name, 0);
2358         APP_CHECK((cfg != NULL), "Parse error: Unable to load config "
2359                 "file %s", file_name);
2360
2361         sect_count = rte_cfgfile_num_sections(cfg, NULL, 0);
2362         APP_CHECK((sect_count > 0), "Parse error: number of sections "
2363                 "in file \"%s\" return %d", file_name,
2364                 sect_count);
2365
2366         section_names = malloc(sect_count * sizeof(char *));
2367         PARSE_ERROR_MALLOC(section_names != NULL);
2368
2369         for (i = 0; i < sect_count; i++)
2370                 section_names[i] = malloc(CFG_NAME_LEN);
2371
2372         rte_cfgfile_sections(cfg, section_names, sect_count);
2373
2374         for (i = 0; i < sect_count; i++) {
2375                 const struct config_section *sch_s;
2376                 int len, cfg_name_len;
2377
2378                 cfg_name_len = strlen(section_names[i]);
2379
2380                 /* Find section type */
2381                 for (j = 0; j < (int)RTE_DIM(cfg_file_scheme); j++) {
2382                         sch_s = &cfg_file_scheme[j];
2383                         len = strlen(sch_s->prefix);
2384
2385                         if (cfg_name_len < len)
2386                                 continue;
2387
2388                         /* After section name we expect only '\0' or digit or
2389                          * digit dot digit, so protect against false matching,
2390                          * for example: "ABC" should match section name
2391                          * "ABC0.0", but it should not match section_name
2392                          * "ABCDEF".
2393                          */
2394                         if ((section_names[i][len] != '\0') &&
2395                                 !isdigit(section_names[i][len]))
2396                                 continue;
2397
2398                         if (strncmp(sch_s->prefix, section_names[i], len) == 0)
2399                                 break;
2400                 }
2401
2402                 APP_CHECK(j < (int)RTE_DIM(cfg_file_scheme),
2403                         "Parse error: unknown section %s",
2404                         section_names[i]);
2405
2406                 APP_CHECK(validate_name(section_names[i],
2407                         sch_s->prefix,
2408                         sch_s->numbers) == 0,
2409                         "Parse error: invalid section name \"%s\"",
2410                         section_names[i]);
2411
2412                 sch_s->load(app, section_names[i], cfg);
2413         }
2414
2415         for (i = 0; i < sect_count; i++)
2416                 free(section_names[i]);
2417
2418         free(section_names);
2419
2420         rte_cfgfile_close(cfg);
2421
2422         APP_PARAM_COUNT(app->mempool_params, app->n_mempools);
2423         APP_PARAM_COUNT(app->link_params, app->n_links);
2424         APP_PARAM_COUNT(app->hwq_in_params, app->n_pktq_hwq_in);
2425         APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out);
2426         APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq);
2427         APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm);
2428         APP_PARAM_COUNT(app->kni_params, app->n_pktq_kni);
2429         APP_PARAM_COUNT(app->source_params, app->n_pktq_source);
2430         APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink);
2431         APP_PARAM_COUNT(app->msgq_params, app->n_msgq);
2432         APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines);
2433
2434         if (app->port_mask == 0)
2435                 assign_link_pmd_id_from_pci_bdf(app);
2436
2437         /* Save configuration to output file */
2438         app_config_save(app, app->output_file);
2439
2440         /* Load TM configuration files */
2441         app_config_parse_tm(app);
2442
2443         return 0;
2444 }
2445
2446 static void
2447 save_eal_params(struct app_params *app, FILE *f)
2448 {
2449         struct app_eal_params *p = &app->eal_params;
2450         uint32_t i;
2451
2452         fprintf(f, "[EAL]\n");
2453
2454         if (p->coremap)
2455                 fprintf(f, "%s = %s\n", "lcores", p->coremap);
2456
2457         if (p->master_lcore_present)
2458                 fprintf(f, "%s = %" PRIu32 "\n",
2459                         "master_lcore", p->master_lcore);
2460
2461         fprintf(f, "%s = %" PRIu32 "\n", "n", p->channels);
2462
2463         if (p->memory_present)
2464                 fprintf(f, "%s = %" PRIu32 "\n", "m", p->memory);
2465
2466         if (p->ranks_present)
2467                 fprintf(f, "%s = %" PRIu32 "\n", "r", p->ranks);
2468
2469         for (i = 0; i < APP_MAX_LINKS; i++) {
2470                 if (p->pci_blacklist[i] == NULL)
2471                         break;
2472
2473                 fprintf(f, "%s = %s\n", "pci_blacklist",
2474                         p->pci_blacklist[i]);
2475         }
2476
2477         for (i = 0; i < APP_MAX_LINKS; i++) {
2478                 if (p->pci_whitelist[i] == NULL)
2479                         break;
2480
2481                 fprintf(f, "%s = %s\n", "pci_whitelist",
2482                         p->pci_whitelist[i]);
2483         }
2484
2485         for (i = 0; i < APP_MAX_LINKS; i++) {
2486                 if (p->vdev[i] == NULL)
2487                         break;
2488
2489                 fprintf(f, "%s = %s\n", "vdev",
2490                         p->vdev[i]);
2491         }
2492
2493         if (p->vmware_tsc_map_present)
2494                 fprintf(f, "%s = %s\n", "vmware_tsc_map",
2495                         (p->vmware_tsc_map) ? "yes" : "no");
2496
2497         if (p->proc_type)
2498                 fprintf(f, "%s = %s\n", "proc_type", p->proc_type);
2499
2500         if (p->syslog)
2501                 fprintf(f, "%s = %s\n", "syslog", p->syslog);
2502
2503         if (p->log_level_present)
2504                 fprintf(f, "%s = %" PRIu32 "\n", "log_level", p->log_level);
2505
2506         if (p->version_present)
2507                 fprintf(f, "%s = %s\n", "v", (p->version) ? "yes" : "no");
2508
2509         if (p->help_present)
2510                 fprintf(f, "%s = %s\n", "help", (p->help) ? "yes" : "no");
2511
2512         if (p->no_huge_present)
2513                 fprintf(f, "%s = %s\n", "no_huge", (p->no_huge) ? "yes" : "no");
2514
2515         if (p->no_pci_present)
2516                 fprintf(f, "%s = %s\n", "no_pci", (p->no_pci) ? "yes" : "no");
2517
2518         if (p->no_hpet_present)
2519                 fprintf(f, "%s = %s\n", "no_hpet", (p->no_hpet) ? "yes" : "no");
2520
2521         if (p->no_shconf_present)
2522                 fprintf(f, "%s = %s\n", "no_shconf",
2523                         (p->no_shconf) ? "yes" : "no");
2524
2525         if (p->add_driver)
2526                 fprintf(f, "%s = %s\n", "d", p->add_driver);
2527
2528         if (p->socket_mem)
2529                 fprintf(f, "%s = %s\n", "socket_mem", p->socket_mem);
2530
2531         if (p->huge_dir)
2532                 fprintf(f, "%s = %s\n", "huge_dir", p->huge_dir);
2533
2534         if (p->file_prefix)
2535                 fprintf(f, "%s = %s\n", "file_prefix", p->file_prefix);
2536
2537         if (p->base_virtaddr)
2538                 fprintf(f, "%s = %s\n", "base_virtaddr", p->base_virtaddr);
2539
2540         if (p->create_uio_dev_present)
2541                 fprintf(f, "%s = %s\n", "create_uio_dev",
2542                         (p->create_uio_dev) ? "yes" : "no");
2543
2544         if (p->vfio_intr)
2545                 fprintf(f, "%s = %s\n", "vfio_intr", p->vfio_intr);
2546
2547         if (p->xen_dom0_present)
2548                 fprintf(f, "%s = %s\n", "xen_dom0",
2549                         (p->xen_dom0) ? "yes" : "no");
2550
2551         fputc('\n', f);
2552 }
2553
2554 static void
2555 save_mempool_params(struct app_params *app, FILE *f)
2556 {
2557         struct app_mempool_params *p;
2558         size_t i, count;
2559
2560         count = RTE_DIM(app->mempool_params);
2561         for (i = 0; i < count; i++) {
2562                 p = &app->mempool_params[i];
2563                 if (!APP_PARAM_VALID(p))
2564                         continue;
2565
2566                 fprintf(f, "[%s]\n", p->name);
2567                 fprintf(f, "%s = %" PRIu32 "\n", "buffer_size", p->buffer_size);
2568                 fprintf(f, "%s = %" PRIu32 "\n", "pool_size", p->pool_size);
2569                 fprintf(f, "%s = %" PRIu32 "\n", "cache_size", p->cache_size);
2570                 fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
2571
2572                 fputc('\n', f);
2573         }
2574 }
2575
2576 static void
2577 save_links_params(struct app_params *app, FILE *f)
2578 {
2579         struct app_link_params *p;
2580         size_t i, count;
2581
2582         count = RTE_DIM(app->link_params);
2583         for (i = 0; i < count; i++) {
2584                 p = &app->link_params[i];
2585                 if (!APP_PARAM_VALID(p))
2586                         continue;
2587
2588                 fprintf(f, "[%s]\n", p->name);
2589                 fprintf(f, "; %s = %" PRIu32 "\n", "pmd_id", p->pmd_id);
2590                 fprintf(f, "%s = %s\n", "promisc", p->promisc ? "yes" : "no");
2591                 fprintf(f, "%s = %" PRIu32 "\n", "arp_q", p->arp_q);
2592                 fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_q",
2593                         p->tcp_syn_q);
2594                 fprintf(f, "%s = %" PRIu32 "\n", "ip_local_q", p->ip_local_q);
2595                 fprintf(f, "%s = %" PRIu32 "\n", "tcp_local_q", p->tcp_local_q);
2596                 fprintf(f, "%s = %" PRIu32 "\n", "udp_local_q", p->udp_local_q);
2597                 fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q",
2598                         p->sctp_local_q);
2599
2600                 if (p->n_rss_qs) {
2601                         uint32_t j;
2602
2603                         /* rss_qs */
2604                         fprintf(f, "rss_qs = ");
2605                         for (j = 0; j < p->n_rss_qs; j++)
2606                                 fprintf(f, "%" PRIu32 " ",      p->rss_qs[j]);
2607                         fputc('\n', f);
2608
2609                         /* rss_proto_ipv4 */
2610                         if (p->rss_proto_ipv4) {
2611                                 fprintf(f, "rss_proto_ipv4 = ");
2612                                 if (p->rss_proto_ipv4 & ETH_RSS_IPV4)
2613                                         fprintf(f, "IP ");
2614                                 if (p->rss_proto_ipv4 & ETH_RSS_FRAG_IPV4)
2615                                         fprintf(f, "FRAG ");
2616                                 if (p->rss_proto_ipv4 &
2617                                         ETH_RSS_NONFRAG_IPV4_TCP)
2618                                         fprintf(f, "TCP ");
2619                                 if (p->rss_proto_ipv4 &
2620                                         ETH_RSS_NONFRAG_IPV4_UDP)
2621                                         fprintf(f, "UDP ");
2622                                 if (p->rss_proto_ipv4 &
2623                                         ETH_RSS_NONFRAG_IPV4_SCTP)
2624                                         fprintf(f, "SCTP ");
2625                                 if (p->rss_proto_ipv4 &
2626                                         ETH_RSS_NONFRAG_IPV4_OTHER)
2627                                         fprintf(f, "OTHER ");
2628                                 fprintf(f, "\n");
2629                         } else
2630                                 fprintf(f, "; rss_proto_ipv4 = <NONE>\n");
2631
2632                         /* rss_proto_ipv6 */
2633                         if (p->rss_proto_ipv6) {
2634                                 fprintf(f, "rss_proto_ipv6 = ");
2635                                 if (p->rss_proto_ipv6 & ETH_RSS_IPV6)
2636                                         fprintf(f, "IP ");
2637                                 if (p->rss_proto_ipv6 & ETH_RSS_FRAG_IPV6)
2638                                         fprintf(f, "FRAG ");
2639                                 if (p->rss_proto_ipv6 &
2640                                         ETH_RSS_NONFRAG_IPV6_TCP)
2641                                         fprintf(f, "TCP ");
2642                                 if (p->rss_proto_ipv6 &
2643                                         ETH_RSS_NONFRAG_IPV6_UDP)
2644                                         fprintf(f, "UDP ");
2645                                 if (p->rss_proto_ipv6 &
2646                                         ETH_RSS_NONFRAG_IPV6_SCTP)
2647                                         fprintf(f, "SCTP ");
2648                                 if (p->rss_proto_ipv6 &
2649                                         ETH_RSS_NONFRAG_IPV6_OTHER)
2650                                         fprintf(f, "OTHER ");
2651                                 if (p->rss_proto_ipv6 & ETH_RSS_IPV6_EX)
2652                                         fprintf(f, "IP_EX ");
2653                                 if (p->rss_proto_ipv6 &
2654                                         ETH_RSS_IPV6_TCP_EX)
2655                                         fprintf(f, "TCP_EX ");
2656                                 if (p->rss_proto_ipv6 &
2657                                         ETH_RSS_IPV6_UDP_EX)
2658                                         fprintf(f, "UDP_EX ");
2659                                 fprintf(f, "\n");
2660                         } else
2661                                 fprintf(f, "; rss_proto_ipv6 = <NONE>\n");
2662
2663                         /* rss_proto_l2 */
2664                         if (p->rss_proto_l2) {
2665                                 fprintf(f, "rss_proto_l2 = ");
2666                                 if (p->rss_proto_l2 & ETH_RSS_L2_PAYLOAD)
2667                                         fprintf(f, "L2 ");
2668                                 fprintf(f, "\n");
2669                         } else
2670                                 fprintf(f, "; rss_proto_l2 = <NONE>\n");
2671                 } else {
2672                         fprintf(f, "; rss_qs = <NONE>\n");
2673                         fprintf(f, "; rss_proto_ipv4 = <NONE>\n");
2674                         fprintf(f, "; rss_proto_ipv6 = <NONE>\n");
2675                         fprintf(f, "; rss_proto_l2 = <NONE>\n");
2676                 }
2677
2678                 if (strlen(p->pci_bdf))
2679                         fprintf(f, "%s = %s\n", "pci_bdf", p->pci_bdf);
2680
2681                 fputc('\n', f);
2682         }
2683 }
2684
2685 static void
2686 save_rxq_params(struct app_params *app, FILE *f)
2687 {
2688         struct app_pktq_hwq_in_params *p;
2689         size_t i, count;
2690
2691         count = RTE_DIM(app->hwq_in_params);
2692         for (i = 0; i < count; i++) {
2693                 p = &app->hwq_in_params[i];
2694                 if (!APP_PARAM_VALID(p))
2695                         continue;
2696
2697                 fprintf(f, "[%s]\n", p->name);
2698                 fprintf(f, "%s = %s\n",
2699                         "mempool",
2700                         app->mempool_params[p->mempool_id].name);
2701                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2702                 fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst);
2703
2704                 fputc('\n', f);
2705         }
2706 }
2707
2708 static void
2709 save_txq_params(struct app_params *app, FILE *f)
2710 {
2711         struct app_pktq_hwq_out_params *p;
2712         size_t i, count;
2713
2714         count = RTE_DIM(app->hwq_out_params);
2715         for (i = 0; i < count; i++) {
2716                 p = &app->hwq_out_params[i];
2717                 if (!APP_PARAM_VALID(p))
2718                         continue;
2719
2720                 fprintf(f, "[%s]\n", p->name);
2721                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2722                 fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst);
2723                 fprintf(f, "%s = %s\n",
2724                         "dropless",
2725                         p->dropless ? "yes" : "no");
2726                 fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
2727
2728                 fputc('\n', f);
2729         }
2730 }
2731
2732 static void
2733 save_swq_params(struct app_params *app, FILE *f)
2734 {
2735         struct app_pktq_swq_params *p;
2736         size_t i, count;
2737
2738         count = RTE_DIM(app->swq_params);
2739         for (i = 0; i < count; i++) {
2740                 p = &app->swq_params[i];
2741                 if (!APP_PARAM_VALID(p))
2742                         continue;
2743
2744                 fprintf(f, "[%s]\n", p->name);
2745                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2746                 fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
2747                 fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
2748                 fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no");
2749                 fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
2750                 fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
2751                 fprintf(f, "%s = %s\n", "ipv4_frag", p->ipv4_frag ? "yes" : "no");
2752                 fprintf(f, "%s = %s\n", "ipv6_frag", p->ipv6_frag ? "yes" : "no");
2753                 fprintf(f, "%s = %s\n", "ipv4_ras", p->ipv4_ras ? "yes" : "no");
2754                 fprintf(f, "%s = %s\n", "ipv6_ras", p->ipv6_ras ? "yes" : "no");
2755                 if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) {
2756                         fprintf(f, "%s = %" PRIu32 "\n", "mtu", p->mtu);
2757                         fprintf(f, "%s = %" PRIu32 "\n", "metadata_size", p->metadata_size);
2758                         fprintf(f, "%s = %s\n",
2759                                 "mempool_direct",
2760                                 app->mempool_params[p->mempool_direct_id].name);
2761                         fprintf(f, "%s = %s\n",
2762                                 "mempool_indirect",
2763                                 app->mempool_params[p->mempool_indirect_id].name);
2764                 }
2765
2766                 fputc('\n', f);
2767         }
2768 }
2769
2770 static void
2771 save_tm_params(struct app_params *app, FILE *f)
2772 {
2773         struct app_pktq_tm_params *p;
2774         size_t i, count;
2775
2776         count = RTE_DIM(app->tm_params);
2777         for (i = 0; i < count; i++) {
2778                 p = &app->tm_params[i];
2779                 if (!APP_PARAM_VALID(p))
2780                         continue;
2781
2782                 fprintf(f, "[%s]\n", p->name);
2783                 fprintf(f, "%s = %s\n", "cfg", p->file_name);
2784                 fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
2785                 fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
2786
2787                 fputc('\n', f);
2788         }
2789 }
2790
2791 static void
2792 save_kni_params(struct app_params *app, FILE *f)
2793 {
2794         struct app_pktq_kni_params *p;
2795         size_t i, count;
2796
2797         count = RTE_DIM(app->kni_params);
2798         for (i = 0; i < count; i++) {
2799                 p = &app->kni_params[i];
2800                 if (!APP_PARAM_VALID(p))
2801                         continue;
2802
2803                 /* section name */
2804                 fprintf(f, "[%s]\n", p->name);
2805
2806                 /* core */
2807                 if (p->force_bind) {
2808                         fprintf(f, "; force_bind = 1\n");
2809                         fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n",
2810                                         p->socket_id,
2811                                         p->core_id,
2812                                         (p->hyper_th_id) ? "h" : "");
2813                 } else
2814                         fprintf(f, "; force_bind = 0\n");
2815
2816                 /* mempool */
2817                 fprintf(f, "%s = %s\n", "mempool",
2818                                 app->mempool_params[p->mempool_id].name);
2819
2820                 /* burst_read */
2821                 fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
2822
2823                 /* burst_write */
2824                 fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
2825
2826                 /* dropless */
2827                 fprintf(f, "%s = %s\n",
2828                                 "dropless",
2829                                 p->dropless ? "yes" : "no");
2830
2831                 /* n_retries */
2832                 fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
2833
2834                 fputc('\n', f);
2835         }
2836 }
2837
2838 static void
2839 save_source_params(struct app_params *app, FILE *f)
2840 {
2841         struct app_pktq_source_params *p;
2842         size_t i, count;
2843
2844         count = RTE_DIM(app->source_params);
2845         for (i = 0; i < count; i++) {
2846                 p = &app->source_params[i];
2847                 if (!APP_PARAM_VALID(p))
2848                         continue;
2849
2850                 fprintf(f, "[%s]\n", p->name);
2851                 fprintf(f, "%s = %s\n",
2852                         "mempool",
2853                         app->mempool_params[p->mempool_id].name);
2854                 fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst);
2855                 fprintf(f, "%s = %s\n", "pcap_file_rd", p->file_name);
2856                 fprintf(f, "%s = %" PRIu32 "\n", "pcap_bytes_rd_per_pkt",
2857                         p->n_bytes_per_pkt);
2858                 fputc('\n', f);
2859         }
2860 }
2861
2862 static void
2863 save_sink_params(struct app_params *app, FILE *f)
2864 {
2865         struct app_pktq_sink_params *p;
2866         size_t i, count;
2867
2868         count = RTE_DIM(app->sink_params);
2869         for (i = 0; i < count; i++) {
2870                 p = &app->sink_params[i];
2871                 if (!APP_PARAM_VALID(p))
2872                         continue;
2873
2874                 fprintf(f, "[%s]\n", p->name);
2875                 fprintf(f, "%s = %s\n", "pcap_file_wr", p->file_name);
2876                 fprintf(f, "%s = %" PRIu32 "\n",
2877                                 "pcap_n_pkt_wr", p->n_pkts_to_dump);
2878                 fputc('\n', f);
2879         }
2880 }
2881
2882 static void
2883 save_msgq_params(struct app_params *app, FILE *f)
2884 {
2885         struct app_msgq_params *p;
2886         size_t i, count;
2887
2888         count = RTE_DIM(app->msgq_params);
2889         for (i = 0; i < count; i++) {
2890                 p = &app->msgq_params[i];
2891                 if (!APP_PARAM_VALID(p))
2892                         continue;
2893
2894                 fprintf(f, "[%s]\n", p->name);
2895                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2896                 fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
2897
2898                 fputc('\n', f);
2899         }
2900 }
2901
2902 static void
2903 save_pipeline_params(struct app_params *app, FILE *f)
2904 {
2905         size_t i, count;
2906
2907         count = RTE_DIM(app->pipeline_params);
2908         for (i = 0; i < count; i++) {
2909                 struct app_pipeline_params *p = &app->pipeline_params[i];
2910
2911                 if (!APP_PARAM_VALID(p))
2912                         continue;
2913
2914                 /* section name */
2915                 fprintf(f, "[%s]\n", p->name);
2916
2917                 /* type */
2918                 fprintf(f, "type = %s\n", p->type);
2919
2920                 /* core */
2921                 fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n",
2922                         p->socket_id,
2923                         p->core_id,
2924                         (p->hyper_th_id) ? "h" : "");
2925
2926                 /* pktq_in */
2927                 if (p->n_pktq_in) {
2928                         uint32_t j;
2929
2930                         fprintf(f, "pktq_in =");
2931                         for (j = 0; j < p->n_pktq_in; j++) {
2932                                 struct app_pktq_in_params *pp = &p->pktq_in[j];
2933                                 char *name;
2934
2935                                 switch (pp->type) {
2936                                 case APP_PKTQ_IN_HWQ:
2937                                         name = app->hwq_in_params[pp->id].name;
2938                                         break;
2939                                 case APP_PKTQ_IN_SWQ:
2940                                         name = app->swq_params[pp->id].name;
2941                                         break;
2942                                 case APP_PKTQ_IN_TM:
2943                                         name = app->tm_params[pp->id].name;
2944                                         break;
2945                                 case APP_PKTQ_IN_KNI:
2946                                         name = app->kni_params[pp->id].name;
2947                                         break;
2948                                 case APP_PKTQ_IN_SOURCE:
2949                                         name = app->source_params[pp->id].name;
2950                                         break;
2951                                 default:
2952                                         APP_CHECK(0, "System error "
2953                                                 "occurred while saving "
2954                                                 "parameter to file");
2955                                 }
2956
2957                                 fprintf(f, " %s", name);
2958                         }
2959                         fprintf(f, "\n");
2960                 }
2961
2962                 /* pktq_in */
2963                 if (p->n_pktq_out) {
2964                         uint32_t j;
2965
2966                         fprintf(f, "pktq_out =");
2967                         for (j = 0; j < p->n_pktq_out; j++) {
2968                                 struct app_pktq_out_params *pp =
2969                                         &p->pktq_out[j];
2970                                 char *name;
2971
2972                                 switch (pp->type) {
2973                                 case APP_PKTQ_OUT_HWQ:
2974                                         name = app->hwq_out_params[pp->id].name;
2975                                         break;
2976                                 case APP_PKTQ_OUT_SWQ:
2977                                         name = app->swq_params[pp->id].name;
2978                                         break;
2979                                 case APP_PKTQ_OUT_TM:
2980                                         name = app->tm_params[pp->id].name;
2981                                         break;
2982                                 case APP_PKTQ_OUT_KNI:
2983                                         name = app->kni_params[pp->id].name;
2984                                         break;
2985                                 case APP_PKTQ_OUT_SINK:
2986                                         name = app->sink_params[pp->id].name;
2987                                         break;
2988                                 default:
2989                                         APP_CHECK(0, "System error "
2990                                                 "occurred while saving "
2991                                                 "parameter to file");
2992                                 }
2993
2994                                 fprintf(f, " %s", name);
2995                         }
2996                         fprintf(f, "\n");
2997                 }
2998
2999                 /* msgq_in */
3000                 if (p->n_msgq_in) {
3001                         uint32_t j;
3002
3003                         fprintf(f, "msgq_in =");
3004                         for (j = 0; j < p->n_msgq_in; j++) {
3005                                 uint32_t id = p->msgq_in[j];
3006                                 char *name = app->msgq_params[id].name;
3007
3008                                 fprintf(f, " %s", name);
3009                         }
3010                         fprintf(f, "\n");
3011                 }
3012
3013                 /* msgq_out */
3014                 if (p->n_msgq_out) {
3015                         uint32_t j;
3016
3017                         fprintf(f, "msgq_out =");
3018                         for (j = 0; j < p->n_msgq_out; j++) {
3019                                 uint32_t id = p->msgq_out[j];
3020                                 char *name = app->msgq_params[id].name;
3021
3022                                 fprintf(f, " %s", name);
3023                         }
3024                         fprintf(f, "\n");
3025                 }
3026
3027                 /* timer_period */
3028                 fprintf(f, "timer_period = %" PRIu32 "\n", p->timer_period);
3029
3030                 /* args */
3031                 if (p->n_args) {
3032                         uint32_t j;
3033
3034                         for (j = 0; j < p->n_args; j++)
3035                                 fprintf(f, "%s = %s\n", p->args_name[j],
3036                                         p->args_value[j]);
3037                 }
3038
3039                 fprintf(f, "\n");
3040         }
3041 }
3042
3043 void
3044 app_config_save(struct app_params *app, const char *file_name)
3045 {
3046         FILE *file;
3047         char *name, *dir_name;
3048         int status;
3049
3050         name = strdup(file_name);
3051         dir_name = dirname(name);
3052         status = access(dir_name, W_OK);
3053         APP_CHECK((status == 0),
3054                 "Error: need write access privilege to directory "
3055                 "\"%s\" to save configuration\n", dir_name);
3056
3057         file = fopen(file_name, "w");
3058         APP_CHECK((file != NULL),
3059                 "Error: failed to save configuration to file \"%s\"",
3060                 file_name);
3061
3062         save_eal_params(app, file);
3063         save_pipeline_params(app, file);
3064         save_mempool_params(app, file);
3065         save_links_params(app, file);
3066         save_rxq_params(app, file);
3067         save_txq_params(app, file);
3068         save_swq_params(app, file);
3069         save_tm_params(app, file);
3070         save_kni_params(app, file);
3071         save_source_params(app, file);
3072         save_sink_params(app, file);
3073         save_msgq_params(app, file);
3074
3075         fclose(file);
3076         free(name);
3077 }
3078
3079 int
3080 app_config_init(struct app_params *app)
3081 {
3082         size_t i;
3083
3084         memcpy(app, &app_params_default, sizeof(struct app_params));
3085
3086         /* configure default_source_params */
3087         default_source_params.file_name = strdup("./config/packets.pcap");
3088         PARSE_ERROR_MALLOC(default_source_params.file_name != NULL);
3089
3090         for (i = 0; i < RTE_DIM(app->mempool_params); i++)
3091                 memcpy(&app->mempool_params[i],
3092                         &mempool_params_default,
3093                         sizeof(struct app_mempool_params));
3094
3095         for (i = 0; i < RTE_DIM(app->link_params); i++)
3096                 memcpy(&app->link_params[i],
3097                         &link_params_default,
3098                         sizeof(struct app_link_params));
3099
3100         for (i = 0; i < RTE_DIM(app->hwq_in_params); i++)
3101                 memcpy(&app->hwq_in_params[i],
3102                         &default_hwq_in_params,
3103                         sizeof(default_hwq_in_params));
3104
3105         for (i = 0; i < RTE_DIM(app->hwq_out_params); i++)
3106                 memcpy(&app->hwq_out_params[i],
3107                         &default_hwq_out_params,
3108                         sizeof(default_hwq_out_params));
3109
3110         for (i = 0; i < RTE_DIM(app->swq_params); i++)
3111                 memcpy(&app->swq_params[i],
3112                         &default_swq_params,
3113                         sizeof(default_swq_params));
3114
3115         for (i = 0; i < RTE_DIM(app->tm_params); i++)
3116                 memcpy(&app->tm_params[i],
3117                         &default_tm_params,
3118                         sizeof(default_tm_params));
3119
3120         for (i = 0; i < RTE_DIM(app->kni_params); i++)
3121                 memcpy(&app->kni_params[i],
3122                            &default_kni_params,
3123                            sizeof(default_kni_params));
3124
3125         for (i = 0; i < RTE_DIM(app->source_params); i++)
3126                 memcpy(&app->source_params[i],
3127                         &default_source_params,
3128                         sizeof(default_source_params));
3129
3130         for (i = 0; i < RTE_DIM(app->sink_params); i++)
3131                 memcpy(&app->sink_params[i],
3132                         &default_sink_params,
3133                         sizeof(default_sink_params));
3134
3135         for (i = 0; i < RTE_DIM(app->msgq_params); i++)
3136                 memcpy(&app->msgq_params[i],
3137                         &default_msgq_params,
3138                         sizeof(default_msgq_params));
3139
3140         for (i = 0; i < RTE_DIM(app->pipeline_params); i++)
3141                 memcpy(&app->pipeline_params[i],
3142                         &default_pipeline_params,
3143                         sizeof(default_pipeline_params));
3144
3145         return 0;
3146 }
3147
3148 static char *
3149 filenamedup(const char *filename, const char *suffix)
3150 {
3151         char *s = malloc(strlen(filename) + strlen(suffix) + 1);
3152
3153         if (!s)
3154                 return NULL;
3155
3156         sprintf(s, "%s%s", filename, suffix);
3157         return s;
3158 }
3159
3160 int
3161 app_config_args(struct app_params *app, int argc, char **argv)
3162 {
3163         const char *optname;
3164         int opt, option_index;
3165         int f_present, s_present, p_present, l_present;
3166         int preproc_present, preproc_params_present;
3167         int scaned = 0;
3168
3169         static struct option lgopts[] = {
3170                 { "preproc", 1, 0, 0 },
3171                 { "preproc-args", 1, 0, 0 },
3172                 { NULL,  0, 0, 0 }
3173         };
3174
3175         /* Copy application name */
3176         strncpy(app->app_name, argv[0], APP_APPNAME_SIZE - 1);
3177
3178         f_present = 0;
3179         s_present = 0;
3180         p_present = 0;
3181         l_present = 0;
3182         preproc_present = 0;
3183         preproc_params_present = 0;
3184
3185         while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts,
3186                         &option_index)) != EOF)
3187                 switch (opt) {
3188                 case 'f':
3189                         if (f_present)
3190                                 rte_panic("Error: Config file is provided "
3191                                         "more than once\n");
3192                         f_present = 1;
3193
3194                         if (!strlen(optarg))
3195                                 rte_panic("Error: Config file name is null\n");
3196
3197                         app->config_file = strdup(optarg);
3198                         if (app->config_file == NULL)
3199                                 rte_panic("Error: Memory allocation failure\n");
3200
3201                         break;
3202
3203                 case 's':
3204                         if (s_present)
3205                                 rte_panic("Error: Script file is provided "
3206                                         "more than once\n");
3207                         s_present = 1;
3208
3209                         if (!strlen(optarg))
3210                                 rte_panic("Error: Script file name is null\n");
3211
3212                         app->script_file = strdup(optarg);
3213                         if (app->script_file == NULL)
3214                                 rte_panic("Error: Memory allocation failure\n");
3215
3216                         break;
3217
3218                 case 'p':
3219                         if (p_present)
3220                                 rte_panic("Error: PORT_MASK is provided "
3221                                         "more than once\n");
3222                         p_present = 1;
3223
3224                         if ((sscanf(optarg, "%" SCNx64 "%n", &app->port_mask,
3225                                 &scaned) != 1) ||
3226                                 ((size_t) scaned != strlen(optarg)))
3227                                 rte_panic("Error: PORT_MASK is not "
3228                                         "a hexadecimal integer\n");
3229
3230                         if (app->port_mask == 0)
3231                                 rte_panic("Error: PORT_MASK is null\n");
3232
3233                         break;
3234
3235                 case 'l':
3236                         if (l_present)
3237                                 rte_panic("Error: LOG_LEVEL is provided "
3238                                         "more than once\n");
3239                         l_present = 1;
3240
3241                         if ((sscanf(optarg, "%" SCNu32 "%n", &app->log_level,
3242                                 &scaned) != 1) ||
3243                                 ((size_t) scaned != strlen(optarg)) ||
3244                                 (app->log_level >= APP_LOG_LEVELS))
3245                                 rte_panic("Error: LOG_LEVEL invalid value\n");
3246
3247                         break;
3248
3249                 case 0:
3250                         optname = lgopts[option_index].name;
3251
3252                         if (strcmp(optname, "preproc") == 0) {
3253                                 if (preproc_present)
3254                                         rte_panic("Error: Preprocessor argument "
3255                                                 "is provided more than once\n");
3256                                 preproc_present = 1;
3257
3258                                 app->preproc = strdup(optarg);
3259                                 break;
3260                         }
3261
3262                         if (strcmp(optname, "preproc-args") == 0) {
3263                                 if (preproc_params_present)
3264                                         rte_panic("Error: Preprocessor args "
3265                                                 "are provided more than once\n");
3266                                 preproc_params_present = 1;
3267
3268                                 app->preproc_args = strdup(optarg);
3269                                 break;
3270                         }
3271
3272                         app_print_usage(argv[0]);
3273                         break;
3274
3275                 default:
3276                         app_print_usage(argv[0]);
3277                 }
3278
3279         optind = 0; /* reset getopt lib */
3280
3281         /* Check dependencies between args */
3282         if (preproc_params_present && (preproc_present == 0))
3283                 rte_panic("Error: Preprocessor args specified while "
3284                         "preprocessor is not defined\n");
3285
3286         app->parser_file = preproc_present ?
3287                 filenamedup(app->config_file, ".preproc") :
3288                 strdup(app->config_file);
3289         app->output_file = filenamedup(app->config_file, ".out");
3290
3291         return 0;
3292 }
3293
3294 int
3295 app_config_preproc(struct app_params *app)
3296 {
3297         char buffer[256];
3298         int status;
3299
3300         if (app->preproc == NULL)
3301                 return 0;
3302
3303         status = access(app->config_file, F_OK | R_OK);
3304         APP_CHECK((status == 0), "Error: Unable to open file %s",
3305                 app->config_file);
3306
3307         snprintf(buffer, sizeof(buffer), "%s %s %s > %s",
3308                 app->preproc,
3309                 app->preproc_args ? app->preproc_args : "",
3310                 app->config_file,
3311                 app->parser_file);
3312
3313         status = system(buffer);
3314         APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)),
3315                 "Error occurred while pre-processing file \"%s\"\n",
3316                 app->config_file);
3317
3318         return status;
3319 }