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