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