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