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