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