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