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