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