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