examples/ip_pipeline: enable promiscuous mode configuration
[dpdk.git] / examples / ip_pipeline / config_parse.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 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 #include <stdint.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <getopt.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <string.h>
41 #include <libgen.h>
42 #include <unistd.h>
43
44 #include <rte_errno.h>
45 #include <rte_cfgfile.h>
46 #include <rte_string_fns.h>
47
48 #include "app.h"
49
50 /**
51  * Default config values
52  **/
53
54 static struct app_params app_params_default = {
55         .config_file = "./config/ip_pipeline.cfg",
56         .log_level = APP_LOG_LEVEL_HIGH,
57
58         .eal_params = {
59                 .channels = 4,
60         },
61 };
62
63 static const struct app_mempool_params mempool_params_default = {
64         .parsed = 0,
65         .buffer_size = 2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM,
66         .pool_size = 32 * 1024,
67         .cache_size = 256,
68         .cpu_socket_id = 0,
69 };
70
71 static const struct app_link_params link_params_default = {
72         .parsed = 0,
73         .pmd_id = 0,
74         .arp_q = 0,
75         .tcp_syn_local_q = 0,
76         .ip_local_q = 0,
77         .tcp_local_q = 0,
78         .udp_local_q = 0,
79         .sctp_local_q = 0,
80         .state = 0,
81         .ip = 0,
82         .depth = 0,
83         .mac_addr = 0,
84
85         .conf = {
86                 .link_speed = 0,
87                 .link_duplex = 0,
88                 .rxmode = {
89                         .mq_mode = ETH_MQ_RX_NONE,
90
91                         .header_split   = 0, /* Header split */
92                         .hw_ip_checksum = 0, /* IP checksum offload */
93                         .hw_vlan_filter = 0, /* VLAN filtering */
94                         .hw_vlan_strip  = 0, /* VLAN strip */
95                         .hw_vlan_extend = 0, /* Extended VLAN */
96                         .jumbo_frame    = 0, /* Jumbo frame support */
97                         .hw_strip_crc   = 0, /* CRC strip by HW */
98                         .enable_scatter = 0, /* Scattered packets RX handler */
99
100                         .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */
101                         .split_hdr_size = 0, /* Header split buffer size */
102                 },
103                 .txmode = {
104                         .mq_mode = ETH_MQ_TX_NONE,
105                 },
106                 .lpbk_mode = 0,
107         },
108
109         .promisc = 1,
110 };
111
112 static const struct app_pktq_hwq_in_params default_hwq_in_params = {
113         .parsed = 0,
114         .mempool_id = 0,
115         .size = 128,
116         .burst = 32,
117
118         .conf = {
119                 .rx_thresh = {
120                                 .pthresh = 8,
121                                 .hthresh = 8,
122                                 .wthresh = 4,
123                 },
124                 .rx_free_thresh = 64,
125                 .rx_drop_en = 0,
126                 .rx_deferred_start = 0,
127         }
128 };
129
130 static const struct app_pktq_hwq_out_params default_hwq_out_params = {
131         .parsed = 0,
132         .size = 512,
133         .burst = 32,
134         .dropless = 0,
135         .n_retries = 0,
136
137         .conf = {
138                 .tx_thresh = {
139                         .pthresh = 36,
140                         .hthresh = 0,
141                         .wthresh = 0,
142                 },
143                 .tx_rs_thresh = 0,
144                 .tx_free_thresh = 0,
145                 .txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
146                         ETH_TXQ_FLAGS_NOOFFLOADS,
147                 .tx_deferred_start = 0,
148         }
149 };
150
151 static const struct app_pktq_swq_params default_swq_params = {
152         .parsed = 0,
153         .size = 256,
154         .burst_read = 32,
155         .burst_write = 32,
156         .dropless = 0,
157         .n_retries = 0,
158         .cpu_socket_id = 0,
159         .ipv4_frag = 0,
160         .ipv6_frag = 0,
161         .ipv4_ras = 0,
162         .ipv6_ras = 0,
163         .mtu = 0,
164         .metadata_size = 0,
165         .mempool_direct_id = 0,
166         .mempool_indirect_id = 0,
167 };
168
169 struct app_pktq_tm_params default_tm_params = {
170         .parsed = 0,
171         .file_name = "./config/tm_profile.cfg",
172         .burst_read = 64,
173         .burst_write = 32,
174 };
175
176 struct app_pktq_source_params default_source_params = {
177         .parsed = 0,
178         .mempool_id = 0,
179         .burst = 32,
180 };
181
182 struct app_pktq_sink_params default_sink_params = {
183         .parsed = 0,
184 };
185
186 struct app_msgq_params default_msgq_params = {
187         .parsed = 0,
188         .size = 64,
189         .cpu_socket_id = 0,
190 };
191
192 struct app_pipeline_params default_pipeline_params = {
193         .parsed = 0,
194         .socket_id = 0,
195         .core_id = 0,
196         .hyper_th_id = 0,
197         .n_pktq_in = 0,
198         .n_pktq_out = 0,
199         .n_msgq_in = 0,
200         .n_msgq_out = 0,
201         .timer_period = 1,
202         .n_args = 0,
203 };
204
205 static const char app_usage[] =
206         "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK "
207         "[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n"
208         "\n"
209         "Arguments:\n"
210         "\t-f CONFIG_FILE: Default config file is %s\n"
211         "\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\n"
212         "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n"
213         "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n"
214         "\t--preproc PREPROCESSOR: Configuration file pre-processor\n"
215         "\t--preproc-args ARGS: Arguments to be passed to pre-processor\n"
216         "\n";
217
218 static void
219 app_print_usage(char *prgname)
220 {
221         rte_exit(0, app_usage, prgname, app_params_default.config_file);
222 }
223
224 #define skip_white_spaces(pos)                  \
225 ({                                              \
226         __typeof__(pos) _p = (pos);             \
227         for ( ; isspace(*_p); _p++);            \
228         _p;                                     \
229 })
230
231 #define PARSER_IMPLICIT_PARAM_ADD_CHECK(result, section_name)           \
232 do {                                                                    \
233         APP_CHECK((result != -EINVAL),                                  \
234                 "CFG: [%s] name too long", section_name);               \
235         APP_CHECK(result != -ENOMEM,                                    \
236                 "CFG: [%s] too much sections", section_name);           \
237         APP_CHECK(result >= 0,                                          \
238                 "CFG: [%s] Unknown error while adding '%s'",            \
239                 section_name, section_name);                            \
240 } while (0)
241
242 #define PARSER_PARAM_ADD_CHECK(result, params_array, section_name)      \
243 do {                                                                    \
244         APP_CHECK((result != -EINVAL),                                  \
245                 "CFG: [%s] name too long", section_name);               \
246         APP_CHECK((result != -ENOMEM),                                  \
247                 "CFG: [%s] too much sections", section_name);           \
248         APP_CHECK(((result >= 0) && (params_array)[result].parsed == 0),\
249                 "CFG: [%s] duplicate section", section_name);           \
250         APP_CHECK((result >= 0),                                        \
251                 "CFG: [%s] Unknown error while adding '%s'",            \
252                 section_name, section_name);                            \
253 } while (0)
254
255 static int
256 parser_read_arg_bool(const char *p)
257 {
258         p = skip_white_spaces(p);
259         int result = -EINVAL;
260
261         if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
262                 ((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
263                 p += 3;
264                 result = 1;
265         }
266
267         if (((p[0] == 'o') && (p[1] == 'n')) ||
268                 ((p[0] == 'O') && (p[1] == 'N'))) {
269                 p += 2;
270                 result = 1;
271         }
272
273         if (((p[0] == 'n') && (p[1] == 'o')) ||
274                 ((p[0] == 'N') && (p[1] == 'O'))) {
275                 p += 2;
276                 result = 0;
277         }
278
279         if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
280                 ((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
281                 p += 3;
282                 result = 0;
283         }
284
285         p = skip_white_spaces(p);
286
287         if (p[0] != '\0')
288                 return -EINVAL;
289
290         return result;
291 }
292
293 #define PARSE_ERROR(exp, section, entry)                                \
294 APP_CHECK(exp, "Parse error in section \"%s\": entry \"%s\"\n", section, entry)
295
296 #define PARSE_ERROR_MALLOC(exp)                                         \
297 APP_CHECK(exp, "Parse error: no free memory\n")
298
299 #define PARSE_ERROR_SECTION(exp, section)                               \
300 APP_CHECK(exp, "Parse error in section \"%s\"", section)
301
302 #define PARSE_ERROR_SECTION_NO_ENTRIES(exp, section)                    \
303 APP_CHECK(exp, "Parse error in section \"%s\": no entries\n", section)
304
305 #define PARSE_WARNING_IGNORED(exp, section, entry)                      \
306 do                                                                      \
307 if (!(exp))                                                             \
308         fprintf(stderr, "Parse warning in section \"%s\": "             \
309                 "entry \"%s\" is ignored\n", section, entry);           \
310 while (0)
311
312 #define PARSE_ERROR_INVALID(exp, section, entry)                        \
313 APP_CHECK(exp, "Parse error in section \"%s\": unrecognized entry \"%s\"\n",\
314         section, entry)
315
316 #define PARSE_ERROR_DUPLICATE(exp, section, entry)                      \
317 APP_CHECK(exp, "Parse error in section \"%s\": duplicate entry \"%s\"\n",\
318         section, entry)
319
320 static int
321 parser_read_uint64(uint64_t *value, const char *p)
322 {
323         char *next;
324         uint64_t val;
325
326         p = skip_white_spaces(p);
327         if (!isdigit(*p))
328                 return -EINVAL;
329
330         val = strtoul(p, &next, 10);
331         if (p == next)
332                 return -EINVAL;
333
334         p = next;
335         switch (*p) {
336         case 'T':
337                 val *= 1024ULL;
338                 /* fall trought */
339         case 'G':
340                 val *= 1024ULL;
341                 /* fall trought */
342         case 'M':
343                 val *= 1024ULL;
344                 /* fall trought */
345         case 'k':
346         case 'K':
347                 val *= 1024ULL;
348                 p++;
349                 break;
350         }
351
352         p = skip_white_spaces(p);
353         if (*p != '\0')
354                 return -EINVAL;
355
356         *value = val;
357         return 0;
358 }
359
360 static int
361 parser_read_uint32(uint32_t *value, const char *p)
362 {
363         uint64_t val = 0;
364         int ret = parser_read_uint64(&val, p);
365
366         if (ret < 0)
367                 return ret;
368         else if (val > UINT32_MAX)
369                 return -ERANGE;
370
371         *value = val;
372         return 0;
373 }
374
375 static int
376 parse_pipeline_core(uint32_t *socket,
377         uint32_t *core,
378         uint32_t *ht,
379         const char *entry)
380 {
381         size_t num_len;
382         char num[8];
383
384         uint32_t s = 0, c = 0, h = 0, val;
385         uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
386         const char *next = skip_white_spaces(entry);
387         char type;
388
389         /* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
390         while (*next != '\0') {
391                 /* If everything parsed nothing should left */
392                 if (s_parsed && c_parsed && h_parsed)
393                         return -EINVAL;
394
395                 type = *next;
396                 switch (type) {
397                 case 's':
398                 case 'S':
399                         if (s_parsed || c_parsed || h_parsed)
400                                 return -EINVAL;
401                         s_parsed = 1;
402                         next++;
403                         break;
404                 case 'c':
405                 case 'C':
406                         if (c_parsed || h_parsed)
407                                 return -EINVAL;
408                         c_parsed = 1;
409                         next++;
410                         break;
411                 case 'h':
412                 case 'H':
413                         if (h_parsed)
414                                 return -EINVAL;
415                         h_parsed = 1;
416                         next++;
417                         break;
418                 default:
419                         /* If it start from digit it must be only core id. */
420                         if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
421                                 return -EINVAL;
422
423                         type = 'C';
424                 }
425
426                 for (num_len = 0; *next != '\0'; next++, num_len++) {
427                         if (num_len == RTE_DIM(num))
428                                 return -EINVAL;
429
430                         if (!isdigit(*next))
431                                 break;
432
433                         num[num_len] = *next;
434                 }
435
436                 if (num_len == 0 && type != 'h' && type != 'H')
437                         return -EINVAL;
438
439                 if (num_len != 0 && (type == 'h' || type == 'H'))
440                         return -EINVAL;
441
442                 num[num_len] = '\0';
443                 val = strtol(num, NULL, 10);
444
445                 h = 0;
446                 switch (type) {
447                 case 's':
448                 case 'S':
449                         s = val;
450                         break;
451                 case 'c':
452                 case 'C':
453                         c = val;
454                         break;
455                 case 'h':
456                 case 'H':
457                         h = 1;
458                         break;
459                 }
460         }
461
462         *socket = s;
463         *core = c;
464         *ht = h;
465         return 0;
466 }
467
468 static uint32_t
469 get_hex_val(char c)
470 {
471         switch (c) {
472         case '0': case '1': case '2': case '3': case '4': case '5':
473         case '6': case '7': case '8': case '9':
474                 return c - '0';
475         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
476                 return c - 'A' + 10;
477         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
478                 return c - 'a' + 10;
479         default:
480                 return 0;
481         }
482 }
483
484 int
485 parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
486 {
487         char *c;
488         uint32_t len, i;
489
490         /* Check input parameters */
491         if ((src == NULL) ||
492                 (dst == NULL) ||
493                 (size == NULL) ||
494                 (*size == 0))
495                 return -1;
496
497         len = strlen(src);
498         if (((len & 3) != 0) ||
499                 (len > (*size) * 2))
500                 return -1;
501         *size = len / 2;
502
503         for (c = src; *c != 0; c++) {
504                 if ((((*c) >= '0') && ((*c) <= '9')) ||
505                         (((*c) >= 'A') && ((*c) <= 'F')) ||
506                         (((*c) >= 'a') && ((*c) <= 'f')))
507                         continue;
508
509                 return -1;
510         }
511
512         /* Convert chars to bytes */
513         for (i = 0; i < *size; i++)
514                 dst[i] = get_hex_val(src[2 * i]) * 16 +
515                         get_hex_val(src[2 * i + 1]);
516
517         return 0;
518 }
519
520 static size_t
521 skip_digits(const char *src)
522 {
523         size_t i;
524
525         for (i = 0; isdigit(src[i]); i++);
526
527         return i;
528 }
529
530 static int
531 validate_name(const char *name, const char *prefix, int num)
532 {
533         size_t i, j;
534
535         for (i = 0; (name[i] != '\0') && (prefix[i] != '\0'); i++) {
536                 if (name[i] != prefix[i])
537                         return -1;
538         }
539
540         if (prefix[i] != '\0')
541                 return -1;
542
543         if (!num) {
544                 if (name[i] != '\0')
545                         return -1;
546                 else
547                         return 0;
548         }
549
550         if (num == 2) {
551                 j = skip_digits(&name[i]);
552                 i += j;
553                 if ((j == 0) || (name[i] != '.'))
554                         return -1;
555                 i++;
556         }
557
558         if (num == 1) {
559                 j = skip_digits(&name[i]);
560                 i += j;
561                 if ((j == 0) || (name[i] != '\0'))
562                         return -1;
563         }
564
565         return 0;
566 }
567
568 static void
569 parse_eal(struct app_params *app,
570         const char *section_name,
571         struct rte_cfgfile *cfg)
572 {
573         struct app_eal_params *p = &app->eal_params;
574         struct rte_cfgfile_entry *entries;
575         int n_entries, i;
576
577         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
578         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
579
580         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
581         PARSE_ERROR_MALLOC(entries != NULL);
582
583         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
584
585         for (i = 0; i < n_entries; i++) {
586                 struct rte_cfgfile_entry *entry = &entries[i];
587
588                 /* coremask */
589                 if (strcmp(entry->name, "c") == 0) {
590                         PARSE_WARNING_IGNORED(0, section_name, entry->name);
591                         continue;
592                 }
593
594                 /* corelist */
595                 if (strcmp(entry->name, "l") == 0) {
596                         PARSE_WARNING_IGNORED(0, section_name, entry->name);
597                         continue;
598                 }
599
600                 /* coremap */
601                 if (strcmp(entry->name, "lcores") == 0) {
602                         PARSE_ERROR_DUPLICATE((p->coremap == NULL),
603                                 section_name,
604                                 entry->name);
605                         p->coremap = strdup(entry->value);
606                         continue;
607                 }
608
609                 /* master_lcore */
610                 if (strcmp(entry->name, "master_lcore") == 0) {
611                         int status;
612
613                         PARSE_ERROR_DUPLICATE((p->master_lcore_present == 0),
614                                 section_name,
615                                 entry->name);
616                         p->master_lcore_present = 1;
617
618                         status = parser_read_uint32(&p->master_lcore,
619                                 entry->value);
620                         PARSE_ERROR((status == 0), section_name, entry->name);
621                         continue;
622                 }
623
624                 /* channels */
625                 if (strcmp(entry->name, "n") == 0) {
626                         int status;
627
628                         PARSE_ERROR_DUPLICATE((p->channels_present == 0),
629                                 section_name,
630                                 entry->name);
631                         p->channels_present = 1;
632
633                         status = parser_read_uint32(&p->channels, entry->value);
634                         PARSE_ERROR((status == 0), section_name, entry->name);
635                         continue;
636                 }
637
638                 /* memory */
639                 if (strcmp(entry->name, "m") == 0) {
640                         int status;
641
642                         PARSE_ERROR_DUPLICATE((p->memory_present == 0),
643                                 section_name,
644                                 entry->name);
645                         p->memory_present = 1;
646
647                         status = parser_read_uint32(&p->memory, entry->value);
648                         PARSE_ERROR((status == 0), section_name, entry->name);
649                         continue;
650                 }
651
652                 /* ranks */
653                 if (strcmp(entry->name, "r") == 0) {
654                         int status;
655
656                         PARSE_ERROR_DUPLICATE((p->ranks_present == 0),
657                                 section_name,
658                                 entry->name);
659                         p->ranks_present = 1;
660
661                         status = parser_read_uint32(&p->ranks, entry->value);
662                         PARSE_ERROR((status == 0), section_name, entry->name);
663                         continue;
664                 }
665
666                 /* pci_blacklist */
667                 if ((strcmp(entry->name, "pci_blacklist") == 0) ||
668                         (strcmp(entry->name, "b") == 0)) {
669                         PARSE_ERROR_DUPLICATE((p->pci_blacklist == NULL),
670                                 section_name,
671                                 entry->name);
672                         p->pci_blacklist = strdup(entry->value);
673                         continue;
674                 }
675
676                 /* pci_whitelist */
677                 if ((strcmp(entry->name, "pci_whitelist") == 0) ||
678                         (strcmp(entry->name, "w") == 0)) {
679                         PARSE_ERROR_DUPLICATE((p->pci_whitelist == NULL),
680                                 section_name,
681                                 entry->name);
682                         p->pci_whitelist = strdup(entry->value);
683                         continue;
684                 }
685
686                 /* vdev */
687                 if (strcmp(entry->name, "vdev") == 0) {
688                         PARSE_ERROR_DUPLICATE((p->vdev == NULL),
689                                 section_name,
690                                 entry->name);
691                         p->vdev = strdup(entry->value);
692                         continue;
693                 }
694
695                 /* vmware_tsc_map */
696                 if (strcmp(entry->name, "vmware_tsc_map") == 0) {
697                         int val;
698
699                         PARSE_ERROR_DUPLICATE((p->vmware_tsc_map_present == 0),
700                                 section_name,
701                                 entry->name);
702                         p->vmware_tsc_map_present = 1;
703
704                         val = parser_read_arg_bool(entry->value);
705                         PARSE_ERROR((val >= 0), section_name, entry->name);
706                         p->vmware_tsc_map = val;
707                         continue;
708                 }
709
710                 /* proc_type */
711                 if (strcmp(entry->name, "proc_type") == 0) {
712                         PARSE_ERROR_DUPLICATE((p->proc_type == NULL),
713                                 section_name,
714                                 entry->name);
715                         p->proc_type = strdup(entry->value);
716                         continue;
717                 }
718
719                 /* syslog */
720                 if (strcmp(entry->name, "syslog") == 0) {
721                         PARSE_ERROR_DUPLICATE((p->syslog == NULL),
722                                 section_name,
723                                 entry->name);
724                         p->syslog = strdup(entry->value);
725                         continue;
726                 }
727
728                 /* log_level */
729                 if (strcmp(entry->name, "log_level") == 0) {
730                         int status;
731
732                         PARSE_ERROR_DUPLICATE((p->log_level_present == 0),
733                                 section_name,
734                                 entry->name);
735                         p->log_level_present = 1;
736
737                         status = parser_read_uint32(&p->log_level,
738                                 entry->value);
739                         PARSE_ERROR((status == 0), section_name, entry->name);
740                         continue;
741                 }
742
743                 /* version */
744                 if (strcmp(entry->name, "v") == 0) {
745                         int val;
746
747                         PARSE_ERROR_DUPLICATE((p->version_present == 0),
748                                 section_name,
749                                 entry->name);
750                         p->version_present = 1;
751
752                         val = parser_read_arg_bool(entry->value);
753                         PARSE_ERROR((val >= 0), section_name, entry->name);
754                         p->version = val;
755                         continue;
756                 }
757
758                 /* help */
759                 if ((strcmp(entry->name, "help") == 0) ||
760                         (strcmp(entry->name, "h") == 0)) {
761                         int val;
762
763                         PARSE_ERROR_DUPLICATE((p->help_present == 0),
764                                 section_name,
765                                 entry->name);
766                         p->help_present = 1;
767
768                         val = parser_read_arg_bool(entry->value);
769                         PARSE_ERROR((val >= 0), section_name, entry->name);
770                         p->help = val;
771                         continue;
772                 }
773
774                 /* no_huge */
775                 if (strcmp(entry->name, "no_huge") == 0) {
776                         int val;
777
778                         PARSE_ERROR_DUPLICATE((p->no_huge_present == 0),
779                                 section_name,
780                                 entry->name);
781                         p->no_huge_present = 1;
782
783                         val = parser_read_arg_bool(entry->value);
784                         PARSE_ERROR((val >= 0), section_name, entry->name);
785                         p->no_huge = val;
786                         continue;
787                 }
788
789                 /* no_pci */
790                 if (strcmp(entry->name, "no_pci") == 0) {
791                         int val;
792
793                         PARSE_ERROR_DUPLICATE((p->no_pci_present == 0),
794                                 section_name,
795                                 entry->name);
796                         p->no_pci_present = 1;
797
798                         val = parser_read_arg_bool(entry->value);
799                         PARSE_ERROR((val >= 0), section_name, entry->name);
800                         p->no_pci = val;
801                         continue;
802                 }
803
804                 /* no_hpet */
805                 if (strcmp(entry->name, "no_hpet") == 0) {
806                         int val;
807
808                         PARSE_ERROR_DUPLICATE((p->no_hpet_present == 0),
809                                 section_name,
810                                 entry->name);
811                         p->no_hpet_present = 1;
812
813                         val = parser_read_arg_bool(entry->value);
814                         PARSE_ERROR((val >= 0), section_name, entry->name);
815                         p->no_hpet = val;
816                         continue;
817                 }
818
819                 /* no_shconf */
820                 if (strcmp(entry->name, "no_shconf") == 0) {
821                         int val;
822
823                         PARSE_ERROR_DUPLICATE((p->no_shconf_present == 0),
824                                 section_name,
825                                 entry->name);
826                         p->no_shconf_present = 1;
827
828                         val = parser_read_arg_bool(entry->value);
829                         PARSE_ERROR((val >= 0), section_name, entry->name);
830                         p->no_shconf = val;
831                         continue;
832                 }
833
834                 /* add_driver */
835                 if (strcmp(entry->name, "d") == 0) {
836                         PARSE_ERROR_DUPLICATE((p->add_driver == NULL),
837                                 section_name,
838                                 entry->name);
839                         p->add_driver = strdup(entry->value);
840                         continue;
841                 }
842
843                 /* socket_mem */
844                 if (strcmp(entry->name, "socket_mem") == 0) {
845                         PARSE_ERROR_DUPLICATE((p->socket_mem == NULL),
846                                 section_name,
847                                 entry->name);
848                         p->socket_mem = strdup(entry->value);
849                         continue;
850                 }
851
852                 /* huge_dir */
853                 if (strcmp(entry->name, "huge_dir") == 0) {
854                         PARSE_ERROR_DUPLICATE((p->huge_dir == NULL),
855                                 section_name,
856                                 entry->name);
857                         p->huge_dir = strdup(entry->value);
858                         continue;
859                 }
860
861                 /* file_prefix */
862                 if (strcmp(entry->name, "file_prefix") == 0) {
863                         PARSE_ERROR_DUPLICATE((p->file_prefix == NULL),
864                                 section_name,
865                                 entry->name);
866                         p->file_prefix = strdup(entry->value);
867                         continue;
868                 }
869
870                 /* base_virtaddr */
871                 if (strcmp(entry->name, "base_virtaddr") == 0) {
872                         PARSE_ERROR_DUPLICATE((p->base_virtaddr == NULL),
873                                 section_name,
874                                 entry->name);
875                         p->base_virtaddr = strdup(entry->value);
876                         continue;
877                 }
878
879                 /* create_uio_dev */
880                 if (strcmp(entry->name, "create_uio_dev") == 0) {
881                         int val;
882
883                         PARSE_ERROR_DUPLICATE((p->create_uio_dev_present == 0),
884                                 section_name,
885                                 entry->name);
886                         p->create_uio_dev_present = 1;
887
888                         val = parser_read_arg_bool(entry->value);
889                         PARSE_ERROR((val >= 0), section_name, entry->name);
890                         p->create_uio_dev = val;
891                         continue;
892                 }
893
894                 /* vfio_intr */
895                 if (strcmp(entry->name, "vfio_intr") == 0) {
896                         PARSE_ERROR_DUPLICATE((p->vfio_intr == NULL),
897                                 section_name,
898                                 entry->name);
899                         p->vfio_intr = strdup(entry->value);
900                         continue;
901                 }
902
903                 /* xen_dom0 */
904                 if (strcmp(entry->name, "xen_dom0") == 0) {
905                         int val;
906
907                         PARSE_ERROR_DUPLICATE((p->xen_dom0_present == 0),
908                                 section_name,
909                                 entry->name);
910                         p->xen_dom0_present = 1;
911
912                         val = parser_read_arg_bool(entry->value);
913                         PARSE_ERROR((val >= 0), section_name, entry->name);
914                         p->xen_dom0 = val;
915                         continue;
916                 }
917
918                 /* unrecognized */
919                 PARSE_ERROR_INVALID(0, section_name, entry->name);
920         }
921
922         free(entries);
923 }
924
925 static int
926 parse_pipeline_pktq_in(struct app_params *app,
927         struct app_pipeline_params *p,
928         const char *value)
929 {
930         const char *next = value;
931         char *end;
932         char name[APP_PARAM_NAME_SIZE];
933         size_t name_len;
934
935         while (*next != '\0') {
936                 enum app_pktq_in_type type;
937                 int id;
938
939                 end = strchr(next, ' ');
940                 if (!end)
941                         name_len = strlen(next);
942                 else
943                         name_len = end - next;
944
945                 if (name_len == 0 || name_len == sizeof(name))
946                         return -EINVAL;
947
948                 strncpy(name, next, name_len);
949                 name[name_len] = '\0';
950                 next += name_len;
951                 if (*next != '\0')
952                         next++;
953
954                 if (validate_name(name, "RXQ", 2) == 0) {
955                         type = APP_PKTQ_IN_HWQ;
956                         id = APP_PARAM_ADD(app->hwq_in_params, name);
957                 } else if (validate_name(name, "SWQ", 1) == 0) {
958                         type = APP_PKTQ_IN_SWQ;
959                         id = APP_PARAM_ADD(app->swq_params, name);
960                 } else if (validate_name(name, "TM", 1) == 0) {
961                         type = APP_PKTQ_IN_TM;
962                         id = APP_PARAM_ADD(app->tm_params, name);
963                 } else if (validate_name(name, "SOURCE", 1) == 0) {
964                         type = APP_PKTQ_IN_SOURCE;
965                         id = APP_PARAM_ADD(app->source_params, name);
966                 } else
967                         return -EINVAL;
968
969                 if (id < 0)
970                         return id;
971
972                 p->pktq_in[p->n_pktq_in].type = type;
973                 p->pktq_in[p->n_pktq_in].id = (uint32_t) id;
974                 p->n_pktq_in++;
975         }
976
977         return 0;
978 }
979
980 static int
981 parse_pipeline_pktq_out(struct app_params *app,
982         struct app_pipeline_params *p,
983         const char *value)
984 {
985         const char *next = value;
986         char *end;
987         char name[APP_PARAM_NAME_SIZE];
988         size_t name_len;
989
990         while (*next != '\0') {
991                 enum app_pktq_out_type type;
992                 int id;
993
994                 end = strchr(next, ' ');
995                 if (!end)
996                         name_len = strlen(next);
997                 else
998                         name_len = end - next;
999
1000                 if (name_len == 0 || name_len == sizeof(name))
1001                         return -EINVAL;
1002
1003                 strncpy(name, next, name_len);
1004                 name[name_len] = '\0';
1005                 next += name_len;
1006                 if (*next != '\0')
1007                         next++;
1008
1009                 if (validate_name(name, "TXQ", 2) == 0) {
1010                         type = APP_PKTQ_OUT_HWQ;
1011                         id = APP_PARAM_ADD(app->hwq_out_params, name);
1012                 } else if (validate_name(name, "SWQ", 1) == 0) {
1013                         type = APP_PKTQ_OUT_SWQ;
1014                         id = APP_PARAM_ADD(app->swq_params, name);
1015                 } else if (validate_name(name, "TM", 1) == 0) {
1016                         type = APP_PKTQ_OUT_TM;
1017                         id = APP_PARAM_ADD(app->tm_params, name);
1018                 } else if (validate_name(name, "SINK", 1) == 0) {
1019                         type = APP_PKTQ_OUT_SINK;
1020                         id = APP_PARAM_ADD(app->sink_params, name);
1021                 } else
1022                         return -EINVAL;
1023
1024                 if (id < 0)
1025                         return id;
1026
1027                 p->pktq_out[p->n_pktq_out].type = type;
1028                 p->pktq_out[p->n_pktq_out].id = id;
1029                 p->n_pktq_out++;
1030         }
1031
1032         return 0;
1033 }
1034
1035 static int
1036 parse_pipeline_msgq_in(struct app_params *app,
1037         struct app_pipeline_params *p,
1038         const char *value)
1039 {
1040         const char *next = value;
1041         char *end;
1042         char name[APP_PARAM_NAME_SIZE];
1043         size_t name_len;
1044         ssize_t idx;
1045
1046         while (*next != '\0') {
1047                 end = strchr(next, ' ');
1048                 if (!end)
1049                         name_len = strlen(next);
1050                 else
1051                         name_len = end - next;
1052
1053                 if (name_len == 0 || name_len == sizeof(name))
1054                         return -EINVAL;
1055
1056                 strncpy(name, next, name_len);
1057                 name[name_len] = '\0';
1058                 next += name_len;
1059                 if (*next != '\0')
1060                         next++;
1061
1062                 if (validate_name(name, "MSGQ", 1) != 0)
1063                         return -EINVAL;
1064
1065                 idx = APP_PARAM_ADD(app->msgq_params, name);
1066                 if (idx < 0)
1067                         return idx;
1068
1069                 p->msgq_in[p->n_msgq_in] = idx;
1070                 p->n_msgq_in++;
1071         }
1072
1073         return 0;
1074 }
1075
1076 static int
1077 parse_pipeline_msgq_out(struct app_params *app,
1078         struct app_pipeline_params *p,
1079         const char *value)
1080 {
1081         const char *next = value;
1082         char *end;
1083         char name[APP_PARAM_NAME_SIZE];
1084         size_t name_len;
1085         ssize_t idx;
1086
1087         while (*next != '\0') {
1088                 end = strchr(next, ' ');
1089                 if (!end)
1090                         name_len = strlen(next);
1091                 else
1092                         name_len = end - next;
1093
1094                 if (name_len == 0 || name_len == sizeof(name))
1095                         return -EINVAL;
1096
1097                 strncpy(name, next, name_len);
1098                 name[name_len] = '\0';
1099                 next += name_len;
1100                 if (*next != '\0')
1101                         next++;
1102
1103                 if (validate_name(name, "MSGQ", 1) != 0)
1104                         return -EINVAL;
1105
1106                 idx = APP_PARAM_ADD(app->msgq_params, name);
1107                 if (idx < 0)
1108                         return idx;
1109
1110                 p->msgq_out[p->n_msgq_out] = idx;
1111                 p->n_msgq_out++;
1112         }
1113
1114         return 0;
1115 }
1116
1117
1118 static void
1119 parse_pipeline(struct app_params *app,
1120         const char *section_name,
1121         struct rte_cfgfile *cfg)
1122 {
1123         char name[CFG_NAME_LEN];
1124         struct app_pipeline_params *param;
1125         struct rte_cfgfile_entry *entries;
1126         ssize_t param_idx;
1127         int n_entries, ret, i;
1128
1129         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1130         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1131
1132         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1133         PARSE_ERROR_MALLOC(entries != NULL);
1134
1135         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1136
1137         param_idx = APP_PARAM_ADD(app->pipeline_params, section_name);
1138         PARSER_PARAM_ADD_CHECK(param_idx, app->pipeline_params, section_name);
1139
1140         param = &app->pipeline_params[param_idx];
1141         param->parsed = 1;
1142
1143         for (i = 0; i < n_entries; i++) {
1144                 struct rte_cfgfile_entry *ent = &entries[i];
1145
1146                 if (strcmp(ent->name, "type") == 0) {
1147                         ret = snprintf(param->type,
1148                                 RTE_DIM(param->type),
1149                                 "%s",
1150                                 ent->value);
1151                         if ((ret > 0) && (ret < (int)RTE_DIM(param->type)))
1152                                 ret = 0;
1153                         else
1154                                 ret = -EINVAL;
1155                 } else if (strcmp(ent->name, "core") == 0)
1156                         ret = parse_pipeline_core(&param->socket_id,
1157                                 &param->core_id,
1158                                 &param->hyper_th_id,
1159                                 ent->value);
1160                 else if (strcmp(ent->name, "pktq_in") == 0)
1161                         ret = parse_pipeline_pktq_in(app, param, ent->value);
1162                 else if (strcmp(ent->name, "pktq_out") == 0)
1163                         ret = parse_pipeline_pktq_out(app, param, ent->value);
1164                 else if (strcmp(ent->name, "msgq_in") == 0)
1165                         ret = parse_pipeline_msgq_in(app, param, ent->value);
1166                 else if (strcmp(ent->name, "msgq_out") == 0)
1167                         ret = parse_pipeline_msgq_out(app, param, ent->value);
1168                 else if (strcmp(ent->name, "timer_period") == 0)
1169                         ret = parser_read_uint32(&param->timer_period,
1170                                 ent->value);
1171                 else {
1172                         APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS),
1173                                 "CFG: [%s] out of memory",
1174                                 section_name);
1175
1176                         param->args_name[param->n_args] = strdup(ent->name);
1177                         param->args_value[param->n_args] = strdup(ent->value);
1178
1179                         APP_CHECK((param->args_name[param->n_args] != NULL) &&
1180                                 (param->args_value[param->n_args] != NULL),
1181                                 "CFG: [%s] out of memory",
1182                                 section_name);
1183
1184                         param->n_args++;
1185                         ret = 0;
1186                 }
1187
1188                 APP_CHECK(ret == 0,
1189                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1190                         section_name,
1191                         ent->name,
1192                         ent->value);
1193         }
1194
1195         snprintf(name, sizeof(name), "MSGQ-REQ-%s", section_name);
1196         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1197         PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);
1198         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1199         param->msgq_in[param->n_msgq_in++] = param_idx;
1200
1201         snprintf(name, sizeof(name), "MSGQ-RSP-%s", section_name);
1202         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1203         PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);
1204         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1205         param->msgq_out[param->n_msgq_out++] = param_idx;
1206
1207         snprintf(name, sizeof(name), "MSGQ-REQ-CORE-s%" PRIu32 "c%" PRIu32 "%s",
1208                 param->socket_id,
1209                 param->core_id,
1210                 (param->hyper_th_id) ? "h" : "");
1211         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1212         PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);
1213         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1214
1215         snprintf(name, sizeof(name), "MSGQ-RSP-CORE-s%" PRIu32 "c%" PRIu32 "%s",
1216                 param->socket_id,
1217                 param->core_id,
1218                 (param->hyper_th_id) ? "h" : "");
1219         param_idx = APP_PARAM_ADD(app->msgq_params, name);
1220         PARSER_IMPLICIT_PARAM_ADD_CHECK(param_idx, name);
1221         app->msgq_params[param_idx].cpu_socket_id = param->socket_id;
1222
1223         free(entries);
1224 }
1225
1226 static void
1227 parse_mempool(struct app_params *app,
1228         const char *section_name,
1229         struct rte_cfgfile *cfg)
1230 {
1231         struct app_mempool_params *param;
1232         struct rte_cfgfile_entry *entries;
1233         ssize_t param_idx;
1234         int n_entries, ret, i;
1235
1236         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1237         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1238
1239         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1240         PARSE_ERROR_MALLOC(entries != NULL);
1241
1242         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1243
1244         param_idx = APP_PARAM_ADD(app->mempool_params, section_name);
1245         PARSER_PARAM_ADD_CHECK(param_idx, app->mempool_params, section_name);
1246
1247         param = &app->mempool_params[param_idx];
1248         param->parsed = 1;
1249
1250         for (i = 0; i < n_entries; i++) {
1251                 struct rte_cfgfile_entry *ent = &entries[i];
1252
1253                 ret = -ESRCH;
1254                 if (strcmp(ent->name, "buffer_size") == 0)
1255                         ret = parser_read_uint32(&param->buffer_size,
1256                                 ent->value);
1257                 else if (strcmp(ent->name, "pool_size") == 0)
1258                         ret = parser_read_uint32(&param->pool_size,
1259                                 ent->value);
1260                 else if (strcmp(ent->name, "cache_size") == 0)
1261                         ret = parser_read_uint32(&param->cache_size,
1262                                 ent->value);
1263                 else if (strcmp(ent->name, "cpu") == 0)
1264                         ret = parser_read_uint32(&param->cpu_socket_id,
1265                                 ent->value);
1266
1267                 APP_CHECK(ret != -ESRCH,
1268                         "CFG: [%s] entry '%s': unknown entry\n",
1269                         section_name,
1270                         ent->name);
1271                 APP_CHECK(ret == 0,
1272                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1273                         section_name,
1274                         ent->name,
1275                         ent->value);
1276         }
1277
1278         free(entries);
1279 }
1280
1281 static void
1282 parse_link(struct app_params *app,
1283         const char *section_name,
1284         struct rte_cfgfile *cfg)
1285 {
1286         struct app_link_params *param;
1287         struct rte_cfgfile_entry *entries;
1288         int n_entries, ret, i;
1289         ssize_t param_idx;
1290
1291         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1292         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1293
1294         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1295         PARSE_ERROR_MALLOC(entries != NULL);
1296
1297         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1298
1299         param_idx = APP_PARAM_ADD(app->link_params, section_name);
1300         PARSER_PARAM_ADD_CHECK(param_idx, app->link_params, section_name);
1301
1302         param = &app->link_params[param_idx];
1303         param->parsed = 1;
1304
1305         for (i = 0; i < n_entries; i++) {
1306                 struct rte_cfgfile_entry *ent = &entries[i];
1307
1308                 ret = -ESRCH;
1309                 if (strcmp(ent->name, "promisc") == 0) {
1310                         ret = parser_read_arg_bool(ent->value);
1311                         if (ret >= 0) {
1312                                 param->promisc = ret;
1313                                 ret = 0;
1314                         }
1315                 } else if (strcmp(ent->name, "arp_q") == 0)
1316                         ret = parser_read_uint32(&param->arp_q,
1317                                 ent->value);
1318                 else if (strcmp(ent->name, "tcp_syn_q") == 0)
1319                         ret = parser_read_uint32(&param->tcp_syn_local_q,
1320                                 ent->value);
1321                 else if (strcmp(ent->name, "ip_local_q") == 0)
1322                         ret = parser_read_uint32(&param->ip_local_q,
1323                                 ent->value);
1324                 else if (strcmp(ent->name, "tcp_local_q") == 0)
1325                         ret = parser_read_uint32(&param->tcp_local_q,
1326                                 ent->value);
1327                 else if (strcmp(ent->name, "udp_local_q") == 0)
1328                         ret = parser_read_uint32(&param->udp_local_q,
1329                                 ent->value);
1330                 else if (strcmp(ent->name, "sctp_local_q") == 0)
1331                         ret = parser_read_uint32(&param->sctp_local_q,
1332                                 ent->value);
1333
1334                 APP_CHECK(ret != -ESRCH,
1335                         "CFG: [%s] entry '%s': unknown entry\n",
1336                         section_name,
1337                         ent->name);
1338                 APP_CHECK(ret == 0,
1339                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1340                         section_name,
1341                         ent->name,
1342                         ent->value);
1343         }
1344
1345         free(entries);
1346 }
1347
1348 static void
1349 parse_rxq(struct app_params *app,
1350         const char *section_name,
1351         struct rte_cfgfile *cfg)
1352 {
1353         struct app_pktq_hwq_in_params *param;
1354         struct rte_cfgfile_entry *entries;
1355         int n_entries, ret, i;
1356         ssize_t param_idx;
1357
1358         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1359         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1360
1361         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1362         PARSE_ERROR_MALLOC(entries != NULL);
1363
1364         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1365
1366         param_idx = APP_PARAM_ADD(app->hwq_in_params, section_name);
1367         PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_in_params, section_name);
1368
1369         param = &app->hwq_in_params[param_idx];
1370         param->parsed = 1;
1371
1372         for (i = 0; i < n_entries; i++) {
1373                 struct rte_cfgfile_entry *ent = &entries[i];
1374
1375                 ret = -ESRCH;
1376                 if (strcmp(ent->name, "mempool") == 0) {
1377                         int status = validate_name(ent->value, "MEMPOOL", 1);
1378                         ssize_t idx;
1379
1380                         APP_CHECK((status == 0),
1381                                 "CFG: [%s] entry '%s': invalid mempool\n",
1382                                 section_name,
1383                                 ent->name);
1384
1385                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1386                         PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
1387                         param->mempool_id = idx;
1388                         ret = 0;
1389                 } else if (strcmp(ent->name, "size") == 0)
1390                         ret = parser_read_uint32(&param->size,
1391                                 ent->value);
1392                 else if (strcmp(ent->name, "burst") == 0)
1393                         ret = parser_read_uint32(&param->burst,
1394                                 ent->value);
1395
1396                 APP_CHECK(ret != -ESRCH,
1397                         "CFG: [%s] entry '%s': unknown entry\n",
1398                         section_name,
1399                         ent->name);
1400                 APP_CHECK(ret == 0,
1401                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1402                         section_name,
1403                         ent->name,
1404                         ent->value);
1405         }
1406
1407         free(entries);
1408 }
1409
1410 static void
1411 parse_txq(struct app_params *app,
1412         const char *section_name,
1413         struct rte_cfgfile *cfg)
1414 {
1415         struct app_pktq_hwq_out_params *param;
1416         struct rte_cfgfile_entry *entries;
1417         int n_entries, ret, i;
1418         ssize_t param_idx;
1419
1420         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1421         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1422
1423         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1424         PARSE_ERROR_MALLOC(entries != NULL);
1425
1426         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1427
1428         param_idx = APP_PARAM_ADD(app->hwq_out_params, section_name);
1429         PARSER_PARAM_ADD_CHECK(param_idx, app->hwq_out_params, section_name);
1430
1431         param = &app->hwq_out_params[param_idx];
1432         param->parsed = 1;
1433
1434         for (i = 0; i < n_entries; i++) {
1435                 struct rte_cfgfile_entry *ent = &entries[i];
1436
1437                 ret = -ESRCH;
1438                 if (strcmp(ent->name, "size") == 0)
1439                         ret = parser_read_uint32(&param->size, ent->value);
1440                 else if (strcmp(ent->name, "burst") == 0)
1441                         ret = parser_read_uint32(&param->burst, ent->value);
1442                 else if (strcmp(ent->name, "dropless") == 0) {
1443                         ret = parser_read_arg_bool(ent->value);
1444                         if (ret >= 0) {
1445                                 param->dropless = ret;
1446                                 ret = 0;
1447                         }
1448                 }
1449
1450                 APP_CHECK(ret != -ESRCH,
1451                         "CFG: [%s] entry '%s': unknown entry\n",
1452                         section_name,
1453                         ent->name);
1454                 APP_CHECK(ret == 0,
1455                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1456                         section_name,
1457                         ent->name,
1458                         ent->value);
1459         }
1460
1461         free(entries);
1462 }
1463
1464 static void
1465 parse_swq(struct app_params *app,
1466         const char *section_name,
1467         struct rte_cfgfile *cfg)
1468 {
1469         struct app_pktq_swq_params *param;
1470         struct rte_cfgfile_entry *entries;
1471         int n_entries, ret, i;
1472         unsigned frag_entries = 0;
1473         ssize_t param_idx;
1474
1475         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1476         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1477
1478         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1479         PARSE_ERROR_MALLOC(entries != NULL);
1480
1481         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1482
1483         param_idx = APP_PARAM_ADD(app->swq_params, section_name);
1484         PARSER_PARAM_ADD_CHECK(param_idx, app->swq_params, section_name);
1485
1486         param = &app->swq_params[param_idx];
1487         param->parsed = 1;
1488
1489         for (i = 0; i < n_entries; i++) {
1490                 struct rte_cfgfile_entry *ent = &entries[i];
1491
1492                 ret = -ESRCH;
1493                 if (strcmp(ent->name, "size") == 0)
1494                         ret = parser_read_uint32(&param->size,
1495                                 ent->value);
1496                 else if (strcmp(ent->name, "burst_read") == 0)
1497                         ret = parser_read_uint32(&param->burst_read,
1498                                 ent->value);
1499                 else if (strcmp(ent->name, "burst_write") == 0)
1500                         ret = parser_read_uint32(&param->burst_write,
1501                                 ent->value);
1502                 else if (strcmp(ent->name, "dropless") == 0) {
1503                         ret = parser_read_arg_bool(ent->value);
1504                         if (ret >= 0) {
1505                                 param->dropless = ret;
1506                                 ret = 0;
1507                         }
1508                 } else if (strcmp(ent->name, "n_retries") == 0)
1509                         ret = parser_read_uint64(&param->n_retries,
1510                                 ent->value);
1511                 else if (strcmp(ent->name, "cpu") == 0)
1512                         ret = parser_read_uint32(&param->cpu_socket_id,
1513                                 ent->value);
1514                 else if (strcmp(ent->name, "ipv4_frag") == 0) {
1515                         ret = parser_read_arg_bool(ent->value);
1516                         if (ret >= 0) {
1517                                 param->ipv4_frag = ret;
1518                                 if (param->mtu == 0)
1519                                         param->mtu = 1500;
1520                                 ret = 0;
1521                         }
1522                 } else if (strcmp(ent->name, "ipv6_frag") == 0) {
1523                         ret = parser_read_arg_bool(ent->value);
1524                         if (ret >= 0) {
1525                                 param->ipv6_frag = ret;
1526                                 if (param->mtu == 0)
1527                                         param->mtu = 1320;
1528                                 ret = 0;
1529                         }
1530                 } else if (strcmp(ent->name, "ipv4_ras") == 0) {
1531                         ret = parser_read_arg_bool(ent->value);
1532                         if (ret >= 0) {
1533                                 param->ipv4_ras = ret;
1534                                 ret = 0;
1535                         }
1536                 } else if (strcmp(ent->name, "ipv6_ras") == 0) {
1537                         ret = parser_read_arg_bool(ent->value);
1538                         if (ret >= 0) {
1539                                 param->ipv6_ras = ret;
1540                                 ret = 0;
1541                         }
1542                 } else if (strcmp(ent->name, "mtu") == 0) {
1543                         frag_entries = 1;
1544                         ret = parser_read_uint32(&param->mtu,
1545                                 ent->value);
1546                 } else if (strcmp(ent->name, "metadata_size") == 0) {
1547                         frag_entries = 1;
1548                         ret = parser_read_uint32(&param->metadata_size,
1549                                 ent->value);
1550                 } else if (strcmp(ent->name, "mempool_direct") == 0) {
1551                         int status = validate_name(ent->value, "MEMPOOL", 1);
1552                         ssize_t idx;
1553
1554                         APP_CHECK((status == 0),
1555                                 "CFG: [%s] entry '%s': invalid mempool\n",
1556                                 section_name,
1557                                 ent->name);
1558
1559                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1560                         PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
1561                         param->mempool_direct_id = idx;
1562                         frag_entries = 1;
1563                         ret = 0;
1564                 } else if (strcmp(ent->name, "mempool_indirect") == 0) {
1565                         int status = validate_name(ent->value, "MEMPOOL", 1);
1566                         ssize_t idx;
1567
1568                         APP_CHECK((status == 0),
1569                                 "CFG: [%s] entry '%s': invalid mempool\n",
1570                                 section_name,
1571                                 ent->name);
1572
1573                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1574                         PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
1575                         param->mempool_indirect_id = idx;
1576                         frag_entries = 1;
1577                         ret = 0;
1578                 }
1579
1580                 APP_CHECK(ret != -ESRCH,
1581                         "CFG: [%s] entry '%s': unknown entry\n",
1582                         section_name,
1583                         ent->name);
1584                 APP_CHECK(ret == 0,
1585                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1586                         section_name,
1587                         ent->name,
1588                         ent->value);
1589         }
1590
1591         if (frag_entries == 1) {
1592                 APP_CHECK(((param->ipv4_frag == 1) || (param->ipv6_frag == 1)),
1593                         "CFG: [%s] ipv4/ipv6 frag is off : unsupported entries on this"
1594                         " configuration\n",
1595                         section_name);
1596         }
1597
1598         free(entries);
1599 }
1600
1601 static void
1602 parse_tm(struct app_params *app,
1603         const char *section_name,
1604         struct rte_cfgfile *cfg)
1605 {
1606         struct app_pktq_tm_params *param;
1607         struct rte_cfgfile_entry *entries;
1608         int n_entries, ret, i;
1609         ssize_t param_idx;
1610
1611         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1612         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1613
1614         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1615         PARSE_ERROR_MALLOC(entries != NULL);
1616
1617         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1618
1619         param_idx = APP_PARAM_ADD(app->tm_params, section_name);
1620         PARSER_PARAM_ADD_CHECK(param_idx, app->tm_params, section_name);
1621
1622         param = &app->tm_params[param_idx];
1623         param->parsed = 1;
1624
1625         for (i = 0; i < n_entries; i++) {
1626                 struct rte_cfgfile_entry *ent = &entries[i];
1627
1628                 ret = -ESRCH;
1629                 if (strcmp(ent->name, "cfg") == 0) {
1630                         param->file_name = strdup(ent->value);
1631                         if (param->file_name == NULL)
1632                                 ret = -EINVAL;
1633
1634                         ret = 0;
1635                 } else if (strcmp(ent->name, "burst_read") == 0)
1636                         ret = parser_read_uint32(&param->burst_read,
1637                                 ent->value);
1638                 else if (strcmp(ent->name, "burst_write") == 0)
1639                         ret = parser_read_uint32(&param->burst_write,
1640                                 ent->value);
1641
1642                 APP_CHECK(ret != -ESRCH,
1643                         "CFG: [%s] entry '%s': unknown entry\n",
1644                         section_name,
1645                         ent->name);
1646                 APP_CHECK(ret != -EBADF,
1647                         "CFG: [%s] entry '%s': TM cfg parse error '%s'\n",
1648                         section_name,
1649                         ent->name,
1650                         ent->value);
1651                 APP_CHECK(ret == 0,
1652                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1653                         section_name,
1654                         ent->name,
1655                         ent->value);
1656         }
1657
1658         free(entries);
1659 }
1660
1661 static void
1662 parse_source(struct app_params *app,
1663         const char *section_name,
1664         struct rte_cfgfile *cfg)
1665 {
1666         struct app_pktq_source_params *param;
1667         struct rte_cfgfile_entry *entries;
1668         int n_entries, ret, i;
1669         ssize_t param_idx;
1670
1671         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1672         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1673
1674         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1675         PARSE_ERROR_MALLOC(entries != NULL);
1676
1677         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1678
1679         param_idx = APP_PARAM_ADD(app->source_params, section_name);
1680         PARSER_PARAM_ADD_CHECK(param_idx, app->source_params, section_name);
1681
1682         param = &app->source_params[param_idx];
1683         param->parsed = 1;
1684
1685         for (i = 0; i < n_entries; i++) {
1686                 struct rte_cfgfile_entry *ent = &entries[i];
1687
1688                 ret = -ESRCH;
1689                 if (strcmp(ent->name, "mempool") == 0) {
1690                         int status = validate_name(ent->value, "MEMPOOL", 1);
1691                         ssize_t idx;
1692
1693                         APP_CHECK((status == 0),
1694                                 "CFG: [%s] entry '%s': invalid mempool\n",
1695                                         section_name,
1696                                         ent->name);
1697
1698                         idx = APP_PARAM_ADD(app->mempool_params, ent->value);
1699                         PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name);
1700                         param->mempool_id = idx;
1701                         ret = 0;
1702                 } else if (strcmp(ent->name, "burst") == 0)
1703                         ret = parser_read_uint32(&param->burst, ent->value);
1704
1705                 APP_CHECK(ret != -ESRCH,
1706                         "CFG: [%s] entry '%s': unknown entry\n",
1707                         section_name,
1708                         ent->name);
1709                 APP_CHECK(ret == 0,
1710                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1711                         section_name,
1712                         ent->name,
1713                         ent->value);
1714         }
1715
1716         free(entries);
1717 }
1718
1719 static void
1720 parse_msgq_req_pipeline(struct app_params *app,
1721         const char *section_name,
1722         struct rte_cfgfile *cfg)
1723 {
1724         struct app_msgq_params *param;
1725         struct rte_cfgfile_entry *entries;
1726         int n_entries, ret, i;
1727         ssize_t param_idx;
1728
1729         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1730         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1731
1732         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1733         PARSE_ERROR_MALLOC(entries != NULL);
1734
1735         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1736
1737         param_idx = APP_PARAM_ADD(app->msgq_params, section_name);
1738         PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);
1739
1740         param = &app->msgq_params[param_idx];
1741         param->parsed = 1;
1742
1743         for (i = 0; i < n_entries; i++) {
1744                 struct rte_cfgfile_entry *ent = &entries[i];
1745
1746                 ret = -ESRCH;
1747                 if (strcmp(ent->name, "size") == 0)
1748                         ret = parser_read_uint32(&param->size, ent->value);
1749
1750                 APP_CHECK(ret != -ESRCH,
1751                         "CFG: [%s] entry '%s': unknown entry\n",
1752                         section_name,
1753                         ent->name);
1754                 APP_CHECK(ret == 0,
1755                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1756                         section_name,
1757                         ent->name,
1758                         ent->value);
1759         }
1760
1761         free(entries);
1762 }
1763
1764 static void
1765 parse_msgq_rsp_pipeline(struct app_params *app,
1766         const char *section_name,
1767         struct rte_cfgfile *cfg)
1768 {
1769         struct app_msgq_params *param;
1770         struct rte_cfgfile_entry *entries;
1771         int n_entries, ret, i;
1772         ssize_t param_idx;
1773
1774         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1775         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1776
1777         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1778         PARSE_ERROR_MALLOC(entries != NULL);
1779
1780         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1781
1782         param_idx = APP_PARAM_ADD(app->msgq_params, section_name);
1783         PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);
1784
1785         param = &app->msgq_params[param_idx];
1786         param->parsed = 1;
1787
1788         for (i = 0; i < n_entries; i++) {
1789                 struct rte_cfgfile_entry *ent = &entries[i];
1790
1791                 ret = -ESRCH;
1792                 if (strcmp(ent->name, "size") == 0)
1793                         ret = parser_read_uint32(&param->size, ent->value);
1794
1795                 APP_CHECK(ret != -ESRCH,
1796                         "CFG: [%s] entry '%s': unknown entry\n",
1797                         section_name,
1798                         ent->name);
1799                 APP_CHECK(ret == 0,
1800                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1801                         section_name,
1802                         ent->name,
1803                         ent->value);
1804         }
1805
1806         free(entries);
1807 }
1808
1809 static void
1810 parse_msgq(struct app_params *app,
1811         const char *section_name,
1812         struct rte_cfgfile *cfg)
1813 {
1814         struct app_msgq_params *param;
1815         struct rte_cfgfile_entry *entries;
1816         int n_entries, ret, i;
1817         ssize_t param_idx;
1818
1819         n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
1820         PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
1821
1822         entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
1823         PARSE_ERROR_MALLOC(entries != NULL);
1824
1825         rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
1826
1827         param_idx = APP_PARAM_ADD(app->msgq_params, section_name);
1828         PARSER_PARAM_ADD_CHECK(param_idx, app->msgq_params, section_name);
1829
1830         param = &app->msgq_params[param_idx];
1831         param->parsed = 1;
1832
1833         for (i = 0; i < n_entries; i++) {
1834                 struct rte_cfgfile_entry *ent = &entries[i];
1835
1836                 ret = -ESRCH;
1837                 if (strcmp(ent->name, "size") == 0)
1838                         ret = parser_read_uint32(&param->size,
1839                                 ent->value);
1840                 else if (strcmp(ent->name, "cpu") == 0)
1841                         ret = parser_read_uint32(&param->cpu_socket_id,
1842                                 ent->value);
1843
1844                 APP_CHECK(ret != -ESRCH,
1845                         "CFG: [%s] entry '%s': unknown entry\n",
1846                         section_name,
1847                         ent->name);
1848                 APP_CHECK(ret == 0,
1849                         "CFG: [%s] entry '%s': Invalid value '%s'\n",
1850                         section_name,
1851                         ent->name,
1852                         ent->value);
1853         }
1854
1855         free(entries);
1856 }
1857
1858 typedef void (*config_section_load)(struct app_params *p,
1859         const char *section_name,
1860         struct rte_cfgfile *cfg);
1861
1862 struct config_section {
1863         const char prefix[CFG_NAME_LEN];
1864         int numbers;
1865         config_section_load load;
1866 };
1867
1868 static const struct config_section cfg_file_scheme[] = {
1869         {"EAL", 0, parse_eal},
1870         {"PIPELINE", 1, parse_pipeline},
1871         {"MEMPOOL", 1, parse_mempool},
1872         {"LINK", 1, parse_link},
1873         {"RXQ", 2, parse_rxq},
1874         {"TXQ", 2, parse_txq},
1875         {"SWQ", 1, parse_swq},
1876         {"TM", 1, parse_tm},
1877         {"SOURCE", 1, parse_source},
1878         {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline},
1879         {"MSGQ-RSP-PIPELINE", 1, parse_msgq_rsp_pipeline},
1880         {"MSGQ", 1, parse_msgq},
1881 };
1882
1883 static void
1884 create_implicit_mempools(struct app_params *app)
1885 {
1886         ssize_t idx;
1887
1888         idx = APP_PARAM_ADD(app->mempool_params, "MEMPOOL0");
1889         PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, "start-up");
1890 }
1891
1892 static void
1893 parse_port_mask(struct app_params *app, uint64_t port_mask)
1894 {
1895         uint32_t pmd_id, link_id;
1896
1897         link_id = 0;
1898         for (pmd_id = 0; pmd_id < RTE_MAX_ETHPORTS; pmd_id++) {
1899                 char name[APP_PARAM_NAME_SIZE];
1900                 ssize_t idx;
1901
1902                 if ((port_mask & (1LLU << pmd_id)) == 0)
1903                         continue;
1904
1905                 snprintf(name, sizeof(name), "LINK%" PRIu32, link_id);
1906                 idx = APP_PARAM_ADD(app->link_params, name);
1907                 PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, name);
1908
1909                 app->link_params[idx].pmd_id = pmd_id;
1910                 link_id++;
1911         }
1912 }
1913
1914 int
1915 app_config_parse(struct app_params *app, const char *file_name)
1916 {
1917         struct rte_cfgfile *cfg;
1918         char **section_names;
1919         int i, j, sect_count;
1920
1921         /* Implicit mempools */
1922         create_implicit_mempools(app);
1923
1924         /* Port mask */
1925         parse_port_mask(app, app->port_mask);
1926
1927         /* Load application configuration file */
1928         cfg = rte_cfgfile_load(file_name, 0);
1929         APP_CHECK(cfg != NULL, "Unable to load config file %s", file_name);
1930
1931         sect_count = rte_cfgfile_num_sections(cfg, NULL, 0);
1932         section_names = malloc(sect_count * sizeof(char *));
1933         for (i = 0; i < sect_count; i++)
1934                 section_names[i] = malloc(CFG_NAME_LEN);
1935
1936         rte_cfgfile_sections(cfg, section_names, sect_count);
1937
1938         for (i = 0; i < sect_count; i++) {
1939                 const struct config_section *sch_s;
1940                 int len, cfg_name_len;
1941
1942                 cfg_name_len = strlen(section_names[i]);
1943
1944                 /* Find section type */
1945                 for (j = 0; j < (int)RTE_DIM(cfg_file_scheme); j++) {
1946                         sch_s = &cfg_file_scheme[j];
1947                         len = strlen(sch_s->prefix);
1948
1949                         if (cfg_name_len < len)
1950                                 continue;
1951
1952                         /* After section name we expect only '\0' or digit or
1953                          * digit dot digit, so protect against false matching,
1954                          * for example: "ABC" should match section name
1955                          * "ABC0.0", but it should not match section_name
1956                          * "ABCDEF".
1957                          */
1958                         if ((section_names[i][len] != '\0') &&
1959                                 !isdigit(section_names[i][len]))
1960                                 continue;
1961
1962                         if (strncmp(sch_s->prefix, section_names[i], len) == 0)
1963                                 break;
1964                 }
1965
1966                 APP_CHECK(j < (int)RTE_DIM(cfg_file_scheme),
1967                         "Unknown section %s",
1968                         section_names[i]);
1969
1970                 APP_CHECK(validate_name(section_names[i],
1971                         sch_s->prefix,
1972                         sch_s->numbers) == 0,
1973                         "Invalid section name '%s'",
1974                         section_names[i]);
1975
1976                 sch_s->load(app, section_names[i], cfg);
1977         }
1978
1979         for (i = 0; i < sect_count; i++)
1980                 free(section_names[i]);
1981
1982         free(section_names);
1983
1984         rte_cfgfile_close(cfg);
1985
1986         APP_PARAM_COUNT(app->mempool_params, app->n_mempools);
1987         APP_PARAM_COUNT(app->link_params, app->n_links);
1988         APP_PARAM_COUNT(app->hwq_in_params, app->n_pktq_hwq_in);
1989         APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out);
1990         APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq);
1991         APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm);
1992         APP_PARAM_COUNT(app->source_params, app->n_pktq_source);
1993         APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink);
1994         APP_PARAM_COUNT(app->msgq_params, app->n_msgq);
1995         APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines);
1996
1997         /* Save configuration to output file */
1998         app_config_save(app, app->output_file);
1999
2000         /* Load TM configuration files */
2001         app_config_parse_tm(app);
2002
2003         return 0;
2004 }
2005
2006 static void
2007 save_eal_params(struct app_params *app, FILE *f)
2008 {
2009         struct app_eal_params *p = &app->eal_params;
2010
2011         fprintf(f, "[EAL]\n");
2012
2013         if (p->coremap)
2014                 fprintf(f, "%s = %s\n", "lcores", p->coremap);
2015
2016         if (p->master_lcore_present)
2017                 fprintf(f, "%s = %" PRIu32 "\n",
2018                         "master_lcore", p->master_lcore);
2019
2020         fprintf(f, "%s = %" PRIu32 "\n", "n", p->channels);
2021
2022         if (p->memory_present)
2023                 fprintf(f, "%s = %" PRIu32 "\n", "m", p->memory);
2024
2025         if (p->ranks_present)
2026                 fprintf(f, "%s = %" PRIu32 "\n", "r", p->ranks);
2027
2028         if (p->pci_blacklist)
2029                 fprintf(f, "%s = %s\n", "pci_blacklist", p->pci_blacklist);
2030
2031         if (p->pci_whitelist)
2032                 fprintf(f, "%s = %s\n", "pci_whitelist", p->pci_whitelist);
2033
2034         if (p->vdev)
2035                 fprintf(f, "%s = %s\n", "vdev", p->vdev);
2036
2037         if (p->vmware_tsc_map_present)
2038                 fprintf(f, "%s = %s\n", "vmware_tsc_map",
2039                         (p->vmware_tsc_map) ? "yes" : "no");
2040
2041         if (p->proc_type)
2042                 fprintf(f, "%s = %s\n", "proc_type", p->proc_type);
2043
2044         if (p->syslog)
2045                 fprintf(f, "%s = %s\n", "syslog", p->syslog);
2046
2047         if (p->log_level_present)
2048                 fprintf(f, "%s = %" PRIu32 "\n", "log_level", p->log_level);
2049
2050         if (p->version_present)
2051                 fprintf(f, "%s = %s\n", "v", (p->version) ? "yes" : "no");
2052
2053         if (p->help_present)
2054                 fprintf(f, "%s = %s\n", "help", (p->help) ? "yes" : "no");
2055
2056         if (p->no_huge_present)
2057                 fprintf(f, "%s = %s\n", "no_huge", (p->no_huge) ? "yes" : "no");
2058
2059         if (p->no_pci_present)
2060                 fprintf(f, "%s = %s\n", "no_pci", (p->no_pci) ? "yes" : "no");
2061
2062         if (p->no_hpet_present)
2063                 fprintf(f, "%s = %s\n", "no_hpet", (p->no_hpet) ? "yes" : "no");
2064
2065         if (p->no_shconf_present)
2066                 fprintf(f, "%s = %s\n", "no_shconf",
2067                         (p->no_shconf) ? "yes" : "no");
2068
2069         if (p->add_driver)
2070                 fprintf(f, "%s = %s\n", "d", p->add_driver);
2071
2072         if (p->socket_mem)
2073                 fprintf(f, "%s = %s\n", "socket_mem", p->socket_mem);
2074
2075         if (p->huge_dir)
2076                 fprintf(f, "%s = %s\n", "huge_dir", p->huge_dir);
2077
2078         if (p->file_prefix)
2079                 fprintf(f, "%s = %s\n", "file_prefix", p->file_prefix);
2080
2081         if (p->base_virtaddr)
2082                 fprintf(f, "%s = %s\n", "base_virtaddr", p->base_virtaddr);
2083
2084         if (p->create_uio_dev_present)
2085                 fprintf(f, "%s = %s\n", "create_uio_dev",
2086                         (p->create_uio_dev) ? "yes" : "no");
2087
2088         if (p->vfio_intr)
2089                 fprintf(f, "%s = %s\n", "vfio_intr", p->vfio_intr);
2090
2091         if (p->xen_dom0_present)
2092                 fprintf(f, "%s = %s\n", "xen_dom0",
2093                         (p->xen_dom0) ? "yes" : "no");
2094
2095         fputc('\n', f);
2096 }
2097
2098 static void
2099 save_mempool_params(struct app_params *app, FILE *f)
2100 {
2101         struct app_mempool_params *p;
2102         size_t i, count;
2103
2104         count = RTE_DIM(app->mempool_params);
2105         for (i = 0; i < count; i++) {
2106                 p = &app->mempool_params[i];
2107                 if (!APP_PARAM_VALID(p))
2108                         continue;
2109
2110                 fprintf(f, "[%s]\n", p->name);
2111                 fprintf(f, "%s = %" PRIu32 "\n", "buffer_size", p->buffer_size);
2112                 fprintf(f, "%s = %" PRIu32 "\n", "pool_size", p->pool_size);
2113                 fprintf(f, "%s = %" PRIu32 "\n", "cache_size", p->cache_size);
2114                 fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
2115
2116                 fputc('\n', f);
2117         }
2118 }
2119
2120 static void
2121 save_links_params(struct app_params *app, FILE *f)
2122 {
2123         struct app_link_params *p;
2124         size_t i, count;
2125
2126         count = RTE_DIM(app->link_params);
2127         for (i = 0; i < count; i++) {
2128                 p = &app->link_params[i];
2129                 if (!APP_PARAM_VALID(p))
2130                         continue;
2131
2132                 fprintf(f, "[%s]\n", p->name);
2133                 fprintf(f, "; %s = %" PRIu32 "\n", "pmd_id", p->pmd_id);
2134                 fprintf(f, "%s = %s\n", "promisc", p->promisc ? "yes" : "no");
2135                 fprintf(f, "%s = %" PRIu32 "\n", "arp_q", p->arp_q);
2136                 fprintf(f, "%s = %" PRIu32 "\n", "tcp_syn_local_q",
2137                         p->tcp_syn_local_q);
2138                 fprintf(f, "%s = %" PRIu32 "\n", "ip_local_q", p->ip_local_q);
2139                 fprintf(f, "%s = %" PRIu32 "\n", "tcp_local_q", p->tcp_local_q);
2140                 fprintf(f, "%s = %" PRIu32 "\n", "udp_local_q", p->udp_local_q);
2141                 fprintf(f, "%s = %" PRIu32 "\n", "sctp_local_q",
2142                         p->sctp_local_q);
2143
2144                 fputc('\n', f);
2145         }
2146 }
2147
2148 static void
2149 save_rxq_params(struct app_params *app, FILE *f)
2150 {
2151         struct app_pktq_hwq_in_params *p;
2152         size_t i, count;
2153
2154         count = RTE_DIM(app->hwq_in_params);
2155         for (i = 0; i < count; i++) {
2156                 p = &app->hwq_in_params[i];
2157                 if (!APP_PARAM_VALID(p))
2158                         continue;
2159
2160                 fprintf(f, "[%s]\n", p->name);
2161                 fprintf(f, "%s = %s\n",
2162                         "mempool",
2163                         app->mempool_params[p->mempool_id].name);
2164                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2165                 fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst);
2166
2167                 fputc('\n', f);
2168         }
2169 }
2170
2171 static void
2172 save_txq_params(struct app_params *app, FILE *f)
2173 {
2174         struct app_pktq_hwq_out_params *p;
2175         size_t i, count;
2176
2177         count = RTE_DIM(app->hwq_out_params);
2178         for (i = 0; i < count; i++) {
2179                 p = &app->hwq_out_params[i];
2180                 if (!APP_PARAM_VALID(p))
2181                         continue;
2182
2183                 fprintf(f, "[%s]\n", p->name);
2184                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2185                 fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst);
2186                 fprintf(f, "%s = %s\n",
2187                         "dropless",
2188                         p->dropless ? "yes" : "no");
2189
2190                 fputc('\n', f);
2191         }
2192 }
2193
2194 static void
2195 save_swq_params(struct app_params *app, FILE *f)
2196 {
2197         struct app_pktq_swq_params *p;
2198         size_t i, count;
2199
2200         count = RTE_DIM(app->swq_params);
2201         for (i = 0; i < count; i++) {
2202                 p = &app->swq_params[i];
2203                 if (!APP_PARAM_VALID(p))
2204                         continue;
2205
2206                 fprintf(f, "[%s]\n", p->name);
2207                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2208                 fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
2209                 fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
2210                 fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no");
2211                 fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
2212                 fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
2213                 fprintf(f, "%s = %s\n", "ipv4_frag", p->ipv4_frag ? "yes" : "no");
2214                 fprintf(f, "%s = %s\n", "ipv6_frag", p->ipv6_frag ? "yes" : "no");
2215                 fprintf(f, "%s = %s\n", "ipv4_ras", p->ipv4_ras ? "yes" : "no");
2216                 fprintf(f, "%s = %s\n", "ipv6_ras", p->ipv6_ras ? "yes" : "no");
2217                 if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) {
2218                         fprintf(f, "%s = %" PRIu32 "\n", "mtu", p->mtu);
2219                         fprintf(f, "%s = %" PRIu32 "\n", "metadata_size", p->metadata_size);
2220                         fprintf(f, "%s = %s\n",
2221                                 "mempool_direct",
2222                                 app->mempool_params[p->mempool_direct_id].name);
2223                         fprintf(f, "%s = %s\n",
2224                                 "mempool_indirect",
2225                                 app->mempool_params[p->mempool_indirect_id].name);
2226                 }
2227
2228                 fputc('\n', f);
2229         }
2230 }
2231
2232 static void
2233 save_tm_params(struct app_params *app, FILE *f)
2234 {
2235         struct app_pktq_tm_params *p;
2236         size_t i, count;
2237
2238         count = RTE_DIM(app->tm_params);
2239         for (i = 0; i < count; i++) {
2240                 p = &app->tm_params[i];
2241                 if (!APP_PARAM_VALID(p))
2242                         continue;
2243
2244                 fprintf(f, "[%s]\n", p->name);
2245                 fprintf(f, "%s = %s\n", "cfg", p->file_name);
2246                 fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
2247                 fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
2248
2249                 fputc('\n', f);
2250         }
2251 }
2252
2253 static void
2254 save_source_params(struct app_params *app, FILE *f)
2255 {
2256         struct app_pktq_source_params *p;
2257         size_t i, count;
2258
2259         count = RTE_DIM(app->source_params);
2260         for (i = 0; i < count; i++) {
2261                 p = &app->source_params[i];
2262                 if (!APP_PARAM_VALID(p))
2263                         continue;
2264
2265                 fprintf(f, "[%s]\n", p->name);
2266                 fprintf(f, "%s = %s\n",
2267                         "mempool",
2268                         app->mempool_params[p->mempool_id].name);
2269                 fprintf(f, "%s = %" PRIu32 "\n", "burst", p->burst);
2270                 fputc('\n', f);
2271         }
2272 }
2273
2274 static void
2275 save_msgq_params(struct app_params *app, FILE *f)
2276 {
2277         struct app_msgq_params *p;
2278         size_t i, count;
2279
2280         count = RTE_DIM(app->msgq_params);
2281         for (i = 0; i < count; i++) {
2282                 p = &app->msgq_params[i];
2283                 if (!APP_PARAM_VALID(p))
2284                         continue;
2285
2286                 fprintf(f, "[%s]\n", p->name);
2287                 fprintf(f, "%s = %" PRIu32 "\n", "size", p->size);
2288                 fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id);
2289
2290                 fputc('\n', f);
2291         }
2292 }
2293
2294 static void
2295 save_pipeline_params(struct app_params *app, FILE *f)
2296 {
2297         size_t i, count;
2298
2299         count = RTE_DIM(app->pipeline_params);
2300         for (i = 0; i < count; i++) {
2301                 struct app_pipeline_params *p = &app->pipeline_params[i];
2302
2303                 if (!APP_PARAM_VALID(p))
2304                         continue;
2305
2306                 /* section name */
2307                 fprintf(f, "[%s]\n", p->name);
2308
2309                 /* type */
2310                 fprintf(f, "type = %s\n", p->type);
2311
2312                 /* core */
2313                 fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n",
2314                         p->socket_id,
2315                         p->core_id,
2316                         (p->hyper_th_id) ? "h" : "");
2317
2318                 /* pktq_in */
2319                 if (p->n_pktq_in) {
2320                         uint32_t j;
2321
2322                         fprintf(f, "pktq_in =");
2323                         for (j = 0; j < p->n_pktq_in; j++) {
2324                                 struct app_pktq_in_params *pp = &p->pktq_in[j];
2325                                 char *name;
2326
2327                                 switch (pp->type) {
2328                                 case APP_PKTQ_IN_HWQ:
2329                                         name = app->hwq_in_params[pp->id].name;
2330                                         break;
2331                                 case APP_PKTQ_IN_SWQ:
2332                                         name = app->swq_params[pp->id].name;
2333                                         break;
2334                                 case APP_PKTQ_IN_TM:
2335                                         name = app->tm_params[pp->id].name;
2336                                         break;
2337                                 case APP_PKTQ_IN_SOURCE:
2338                                         name = app->source_params[pp->id].name;
2339                                         break;
2340                                 default:
2341                                         APP_CHECK(0, "Error\n");
2342                                 }
2343
2344                                 fprintf(f, " %s", name);
2345                         }
2346                         fprintf(f, "\n");
2347                 }
2348
2349                 /* pktq_in */
2350                 if (p->n_pktq_out) {
2351                         uint32_t j;
2352
2353                         fprintf(f, "pktq_out =");
2354                         for (j = 0; j < p->n_pktq_out; j++) {
2355                                 struct app_pktq_out_params *pp =
2356                                         &p->pktq_out[j];
2357                                 char *name;
2358
2359                                 switch (pp->type) {
2360                                 case APP_PKTQ_OUT_HWQ:
2361                                         name = app->hwq_out_params[pp->id].name;
2362                                         break;
2363                                 case APP_PKTQ_OUT_SWQ:
2364                                         name = app->swq_params[pp->id].name;
2365                                         break;
2366                                 case APP_PKTQ_OUT_TM:
2367                                         name = app->tm_params[pp->id].name;
2368                                         break;
2369                                 case APP_PKTQ_OUT_SINK:
2370                                         name = app->sink_params[pp->id].name;
2371                                         break;
2372                                 default:
2373                                         APP_CHECK(0, "Error\n");
2374                                 }
2375
2376                                 fprintf(f, " %s", name);
2377                         }
2378                         fprintf(f, "\n");
2379                 }
2380
2381                 /* msgq_in */
2382                 if (p->n_msgq_in) {
2383                         uint32_t j;
2384
2385                         fprintf(f, "msgq_in =");
2386                         for (j = 0; j < p->n_msgq_in; j++) {
2387                                 uint32_t id = p->msgq_in[j];
2388                                 char *name = app->msgq_params[id].name;
2389
2390                                 fprintf(f, " %s", name);
2391                         }
2392                         fprintf(f, "\n");
2393                 }
2394
2395                 /* msgq_out */
2396                 if (p->n_msgq_in) {
2397                         uint32_t j;
2398
2399                         fprintf(f, "msgq_out =");
2400                         for (j = 0; j < p->n_msgq_out; j++) {
2401                                 uint32_t id = p->msgq_out[j];
2402                                 char *name = app->msgq_params[id].name;
2403
2404                                 fprintf(f, " %s", name);
2405                         }
2406                         fprintf(f, "\n");
2407                 }
2408
2409                 /* timer_period */
2410                 fprintf(f, "timer_period = %" PRIu32 "\n", p->timer_period);
2411
2412                 /* args */
2413                 if (p->n_args) {
2414                         uint32_t j;
2415
2416                         for (j = 0; j < p->n_args; j++)
2417                                 fprintf(f, "%s = %s\n", p->args_name[j],
2418                                         p->args_value[j]);
2419                 }
2420
2421                 fprintf(f, "\n");
2422         }
2423 }
2424
2425 void
2426 app_config_save(struct app_params *app, const char *file_name)
2427 {
2428         FILE *file;
2429         char *name, *dir_name;
2430         int status;
2431
2432         name = strdup(file_name);
2433         dir_name = dirname(name);
2434         status = access(dir_name, W_OK);
2435         APP_CHECK((status == 0),
2436                 "Need write access to directory \"%s\" to save configuration\n",
2437                 dir_name);
2438
2439         file = fopen(file_name, "w");
2440         APP_CHECK((file != NULL),
2441                 "Failed to save configuration to file \"%s\"", file_name);
2442
2443         save_eal_params(app, file);
2444         save_pipeline_params(app, file);
2445         save_mempool_params(app, file);
2446         save_links_params(app, file);
2447         save_rxq_params(app, file);
2448         save_txq_params(app, file);
2449         save_swq_params(app, file);
2450         save_tm_params(app, file);
2451         save_source_params(app, file);
2452         save_msgq_params(app, file);
2453
2454         fclose(file);
2455         free(name);
2456 }
2457
2458 int
2459 app_config_init(struct app_params *app)
2460 {
2461         size_t i;
2462
2463         memcpy(app, &app_params_default, sizeof(struct app_params));
2464
2465         for (i = 0; i < RTE_DIM(app->mempool_params); i++)
2466                 memcpy(&app->mempool_params[i],
2467                         &mempool_params_default,
2468                         sizeof(struct app_mempool_params));
2469
2470         for (i = 0; i < RTE_DIM(app->link_params); i++)
2471                 memcpy(&app->link_params[i],
2472                         &link_params_default,
2473                         sizeof(struct app_link_params));
2474
2475         for (i = 0; i < RTE_DIM(app->hwq_in_params); i++)
2476                 memcpy(&app->hwq_in_params[i],
2477                         &default_hwq_in_params,
2478                         sizeof(default_hwq_in_params));
2479
2480         for (i = 0; i < RTE_DIM(app->hwq_out_params); i++)
2481                 memcpy(&app->hwq_out_params[i],
2482                         &default_hwq_out_params,
2483                         sizeof(default_hwq_out_params));
2484
2485         for (i = 0; i < RTE_DIM(app->swq_params); i++)
2486                 memcpy(&app->swq_params[i],
2487                         &default_swq_params,
2488                         sizeof(default_swq_params));
2489
2490         for (i = 0; i < RTE_DIM(app->tm_params); i++)
2491                 memcpy(&app->tm_params[i],
2492                         &default_tm_params,
2493                         sizeof(default_tm_params));
2494
2495         for (i = 0; i < RTE_DIM(app->source_params); i++)
2496                 memcpy(&app->source_params[i],
2497                         &default_source_params,
2498                         sizeof(default_source_params));
2499
2500         for (i = 0; i < RTE_DIM(app->sink_params); i++)
2501                 memcpy(&app->sink_params[i],
2502                         &default_sink_params,
2503                         sizeof(default_sink_params));
2504
2505         for (i = 0; i < RTE_DIM(app->msgq_params); i++)
2506                 memcpy(&app->msgq_params[i],
2507                         &default_msgq_params,
2508                         sizeof(default_msgq_params));
2509
2510         for (i = 0; i < RTE_DIM(app->pipeline_params); i++)
2511                 memcpy(&app->pipeline_params[i],
2512                         &default_pipeline_params,
2513                         sizeof(default_pipeline_params));
2514
2515         return 0;
2516 }
2517
2518 static char *
2519 filenamedup(const char *filename, const char *suffix)
2520 {
2521         char *s = malloc(strlen(filename) + strlen(suffix) + 1);
2522
2523         if (!s)
2524                 return NULL;
2525
2526         sprintf(s, "%s%s", filename, suffix);
2527         return s;
2528 }
2529
2530 int
2531 app_config_args(struct app_params *app, int argc, char **argv)
2532 {
2533         const char *optname;
2534         int opt, option_index;
2535         int f_present, s_present, p_present, l_present;
2536         int preproc_present, preproc_params_present;
2537         int scaned = 0;
2538
2539         static struct option lgopts[] = {
2540                 { "preproc", 1, 0, 0 },
2541                 { "preproc-args", 1, 0, 0 },
2542                 { NULL,  0, 0, 0 }
2543         };
2544
2545         /* Copy application name */
2546         strncpy(app->app_name, argv[0], APP_APPNAME_SIZE - 1);
2547
2548         f_present = 0;
2549         s_present = 0;
2550         p_present = 0;
2551         l_present = 0;
2552         preproc_present = 0;
2553         preproc_params_present = 0;
2554
2555         while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts,
2556                         &option_index)) != EOF)
2557                 switch (opt) {
2558                 case 'f':
2559                         if (f_present)
2560                                 rte_panic("Error: Config file is provided "
2561                                         "more than once\n");
2562                         f_present = 1;
2563
2564                         if (!strlen(optarg))
2565                                 rte_panic("Error: Config file name is null\n");
2566
2567                         app->config_file = strdup(optarg);
2568                         if (app->config_file == NULL)
2569                                 rte_panic("Error: Memory allocation failure\n");
2570
2571                         break;
2572
2573                 case 's':
2574                         if (s_present)
2575                                 rte_panic("Error: Script file is provided "
2576                                         "more than once\n");
2577                         s_present = 1;
2578
2579                         if (!strlen(optarg))
2580                                 rte_panic("Error: Script file name is null\n");
2581
2582                         app->script_file = strdup(optarg);
2583                         if (app->script_file == NULL)
2584                                 rte_panic("Error: Memory allocation failure\n");
2585
2586                         break;
2587
2588                 case 'p':
2589                         if (p_present)
2590                                 rte_panic("Error: PORT_MASK is provided "
2591                                         "more than once\n");
2592                         p_present = 1;
2593
2594                         if ((sscanf(optarg, "%" SCNx64 "%n", &app->port_mask,
2595                                 &scaned) != 1) ||
2596                                 ((size_t) scaned != strlen(optarg)))
2597                                 rte_panic("Error: PORT_MASK is not "
2598                                         "a hexadecimal integer\n");
2599
2600                         if (app->port_mask == 0)
2601                                 rte_panic("Error: PORT_MASK is null\n");
2602
2603                         break;
2604
2605                 case 'l':
2606                         if (l_present)
2607                                 rte_panic("Error: LOG_LEVEL is provided "
2608                                         "more than once\n");
2609                         l_present = 1;
2610
2611                         if ((sscanf(optarg, "%" SCNu32 "%n", &app->log_level,
2612                                 &scaned) != 1) ||
2613                                 ((size_t) scaned != strlen(optarg)) ||
2614                                 (app->log_level >= APP_LOG_LEVELS))
2615                                 rte_panic("Error: LOG_LEVEL invalid value\n");
2616
2617                         break;
2618
2619                 case 0:
2620                         optname = lgopts[option_index].name;
2621
2622                         if (strcmp(optname, "preproc") == 0) {
2623                                 if (preproc_present)
2624                                         rte_panic("Error: Preprocessor argument "
2625                                                 "is provided more than once\n");
2626                                 preproc_present = 1;
2627
2628                                 app->preproc = strdup(optarg);
2629                                 break;
2630                         }
2631
2632                         if (strcmp(optname, "preproc-args") == 0) {
2633                                 if (preproc_params_present)
2634                                         rte_panic("Error: Preprocessor args "
2635                                                 "are provided more than once\n");
2636                                 preproc_params_present = 1;
2637
2638                                 app->preproc_args = strdup(optarg);
2639                                 break;
2640                         }
2641
2642                         app_print_usage(argv[0]);
2643                         break;
2644
2645                 default:
2646                         app_print_usage(argv[0]);
2647                 }
2648
2649         optind = 0; /* reset getopt lib */
2650
2651         /* Check that mandatory args have been provided */
2652         if (!p_present)
2653                 rte_panic("Error: PORT_MASK is not provided\n");
2654
2655         /* Check dependencies between args */
2656         if (preproc_params_present && (preproc_present == 0))
2657                 rte_panic("Error: Preprocessor args specified while "
2658                         "preprocessor is not defined\n");
2659
2660         app->parser_file = preproc_present ?
2661                 filenamedup(app->config_file, ".preproc") :
2662                 strdup(app->config_file);
2663         app->output_file = filenamedup(app->config_file, ".out");
2664
2665         return 0;
2666 }
2667
2668 int
2669 app_config_preproc(struct app_params *app)
2670 {
2671         char buffer[256];
2672         int status;
2673
2674         if (app->preproc == NULL)
2675                 return 0;
2676
2677         status = access(app->config_file, F_OK | R_OK);
2678         APP_CHECK((status == 0), "Unable to open file %s", app->config_file);
2679
2680         snprintf(buffer, sizeof(buffer), "%s %s %s > %s",
2681                 app->preproc,
2682                 app->preproc_args ? app->preproc_args : "",
2683                 app->config_file,
2684                 app->parser_file);
2685
2686         status = system(buffer);
2687         APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)),
2688                 "Error while preprocessing file \"%s\"\n", app->config_file);
2689
2690         return status;
2691 }