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