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