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