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