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