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