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