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