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