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