eal_common_options.c revision 8be94df6
1/*-
2 *   BSD LICENSE
3 *
4 *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 *   Copyright(c) 2014 6WIND S.A.
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 <stdlib.h>
35#include <unistd.h>
36#include <string.h>
37#include <syslog.h>
38#include <ctype.h>
39#include <limits.h>
40#include <errno.h>
41#include <getopt.h>
42#include <dlfcn.h>
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <dirent.h>
46
47#include <rte_eal.h>
48#include <rte_log.h>
49#include <rte_lcore.h>
50#include <rte_version.h>
51#include <rte_devargs.h>
52#include <rte_memcpy.h>
53
54#include "eal_internal_cfg.h"
55#include "eal_options.h"
56#include "eal_filesystem.h"
57
58#define BITS_PER_HEX 4
59
60const char
61eal_short_options[] =
62	"b:" /* pci-blacklist */
63	"c:" /* coremask */
64	"d:" /* driver */
65	"h"  /* help */
66	"l:" /* corelist */
67	"m:" /* memory size */
68	"n:" /* memory channels */
69	"r:" /* memory ranks */
70	"v"  /* version */
71	"w:" /* pci-whitelist */
72	;
73
74const struct option
75eal_long_options[] = {
76	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
77	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
78	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
79	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
80	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
81	{OPT_HUGE_UNLINK,       0, NULL, OPT_HUGE_UNLINK_NUM      },
82	{OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
83	{OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
84	{OPT_MASTER_LCORE,      1, NULL, OPT_MASTER_LCORE_NUM     },
85	{OPT_NO_HPET,           0, NULL, OPT_NO_HPET_NUM          },
86	{OPT_NO_HUGE,           0, NULL, OPT_NO_HUGE_NUM          },
87	{OPT_NO_PCI,            0, NULL, OPT_NO_PCI_NUM           },
88	{OPT_NO_SHCONF,         0, NULL, OPT_NO_SHCONF_NUM        },
89	{OPT_PCI_BLACKLIST,     1, NULL, OPT_PCI_BLACKLIST_NUM    },
90	{OPT_PCI_WHITELIST,     1, NULL, OPT_PCI_WHITELIST_NUM    },
91	{OPT_PROC_TYPE,         1, NULL, OPT_PROC_TYPE_NUM        },
92	{OPT_SOCKET_MEM,        1, NULL, OPT_SOCKET_MEM_NUM       },
93	{OPT_SYSLOG,            1, NULL, OPT_SYSLOG_NUM           },
94	{OPT_VDEV,              1, NULL, OPT_VDEV_NUM             },
95	{OPT_VFIO_INTR,         1, NULL, OPT_VFIO_INTR_NUM        },
96	{OPT_VMWARE_TSC_MAP,    0, NULL, OPT_VMWARE_TSC_MAP_NUM   },
97	{OPT_XEN_DOM0,          0, NULL, OPT_XEN_DOM0_NUM         },
98	{0,                     0, NULL, 0                        }
99};
100
101TAILQ_HEAD(shared_driver_list, shared_driver);
102
103/* Definition for shared object drivers. */
104struct shared_driver {
105	TAILQ_ENTRY(shared_driver) next;
106
107	char    name[PATH_MAX];
108	void*   lib_handle;
109};
110
111/* List of external loadable drivers */
112static struct shared_driver_list solib_list =
113TAILQ_HEAD_INITIALIZER(solib_list);
114
115/* Default path of external loadable drivers */
116static const char *default_solib_dir = RTE_EAL_PMD_PATH;
117
118/*
119 * Stringified version of solib path used by pmdinfo.py
120 * Note: PLEASE DO NOT ALTER THIS without making a corresponding
121 * change to tools/pmdinfo.py
122 */
123static const char dpdk_solib_path[] __attribute__((used)) =
124"DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
125
126
127static int master_lcore_parsed;
128static int mem_parsed;
129
130void
131eal_reset_internal_config(struct internal_config *internal_cfg)
132{
133	int i;
134
135	internal_cfg->memory = 0;
136	internal_cfg->force_nrank = 0;
137	internal_cfg->force_nchannel = 0;
138	internal_cfg->hugefile_prefix = HUGEFILE_PREFIX_DEFAULT;
139	internal_cfg->hugepage_dir = NULL;
140	internal_cfg->force_sockets = 0;
141	/* zero out the NUMA config */
142	for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
143		internal_cfg->socket_mem[i] = 0;
144	/* zero out hugedir descriptors */
145	for (i = 0; i < MAX_HUGEPAGE_SIZES; i++)
146		internal_cfg->hugepage_info[i].lock_descriptor = -1;
147	internal_cfg->base_virtaddr = 0;
148
149	internal_cfg->syslog_facility = LOG_DAEMON;
150	/* default value from build option */
151#if RTE_LOG_LEVEL >= RTE_LOG_DEBUG
152	internal_cfg->log_level = RTE_LOG_INFO;
153#else
154	internal_cfg->log_level = RTE_LOG_LEVEL;
155#endif
156
157	internal_cfg->xen_dom0_support = 0;
158
159	/* if set to NONE, interrupt mode is determined automatically */
160	internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
161
162#ifdef RTE_LIBEAL_USE_HPET
163	internal_cfg->no_hpet = 0;
164#else
165	internal_cfg->no_hpet = 1;
166#endif
167	internal_cfg->vmware_tsc_map = 0;
168	internal_cfg->create_uio_dev = 0;
169}
170
171static int
172eal_plugin_add(const char *path)
173{
174	struct shared_driver *solib;
175
176	solib = malloc(sizeof(*solib));
177	if (solib == NULL) {
178		RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
179		return -1;
180	}
181	memset(solib, 0, sizeof(*solib));
182	strncpy(solib->name, path, PATH_MAX-1);
183	solib->name[PATH_MAX-1] = 0;
184	TAILQ_INSERT_TAIL(&solib_list, solib, next);
185
186	return 0;
187}
188
189static int
190eal_plugindir_init(const char *path)
191{
192	DIR *d = NULL;
193	struct dirent *dent = NULL;
194	char sopath[PATH_MAX];
195
196	if (path == NULL || *path == '\0')
197		return 0;
198
199	d = opendir(path);
200	if (d == NULL) {
201		RTE_LOG(ERR, EAL, "failed to open directory %s: %s\n",
202			path, strerror(errno));
203		return -1;
204	}
205
206	while ((dent = readdir(d)) != NULL) {
207		struct stat sb;
208
209		snprintf(sopath, PATH_MAX-1, "%s/%s", path, dent->d_name);
210		sopath[PATH_MAX-1] = 0;
211
212		if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
213			continue;
214
215		if (eal_plugin_add(sopath) == -1)
216			break;
217	}
218
219	closedir(d);
220	/* XXX this ignores failures from readdir() itself */
221	return (dent == NULL) ? 0 : -1;
222}
223
224int
225eal_plugins_init(void)
226{
227	struct shared_driver *solib = NULL;
228
229	if (*default_solib_dir != '\0')
230		eal_plugin_add(default_solib_dir);
231
232	TAILQ_FOREACH(solib, &solib_list, next) {
233		struct stat sb;
234
235		if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
236			if (eal_plugindir_init(solib->name) == -1) {
237				RTE_LOG(ERR, EAL,
238					"Cannot init plugin directory %s\n",
239					solib->name);
240				return -1;
241			}
242		} else {
243			RTE_LOG(DEBUG, EAL, "open shared lib %s\n",
244				solib->name);
245			solib->lib_handle = dlopen(solib->name, RTLD_NOW);
246			if (solib->lib_handle == NULL) {
247				RTE_LOG(ERR, EAL, "%s\n", dlerror());
248				return -1;
249			}
250		}
251
252	}
253	return 0;
254}
255
256/*
257 * Parse the coremask given as argument (hexadecimal string) and fill
258 * the global configuration (core role and core count) with the parsed
259 * value.
260 */
261static int xdigit2val(unsigned char c)
262{
263	int val;
264
265	if (isdigit(c))
266		val = c - '0';
267	else if (isupper(c))
268		val = c - 'A' + 10;
269	else
270		val = c - 'a' + 10;
271	return val;
272}
273
274static int
275eal_parse_coremask(const char *coremask)
276{
277	struct rte_config *cfg = rte_eal_get_configuration();
278	int i, j, idx = 0;
279	unsigned count = 0;
280	char c;
281	int val;
282
283	if (coremask == NULL)
284		return -1;
285	/* Remove all blank characters ahead and after .
286	 * Remove 0x/0X if exists.
287	 */
288	while (isblank(*coremask))
289		coremask++;
290	if (coremask[0] == '0' && ((coremask[1] == 'x')
291		|| (coremask[1] == 'X')))
292		coremask += 2;
293	i = strlen(coremask);
294	while ((i > 0) && isblank(coremask[i - 1]))
295		i--;
296	if (i == 0)
297		return -1;
298
299	for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
300		c = coremask[i];
301		if (isxdigit(c) == 0) {
302			/* invalid characters */
303			return -1;
304		}
305		val = xdigit2val(c);
306		for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++)
307		{
308			if ((1 << j) & val) {
309				if (!lcore_config[idx].detected) {
310					RTE_LOG(ERR, EAL, "lcore %u "
311					        "unavailable\n", idx);
312					return -1;
313				}
314				cfg->lcore_role[idx] = ROLE_RTE;
315				lcore_config[idx].core_index = count;
316				count++;
317			} else {
318				cfg->lcore_role[idx] = ROLE_OFF;
319				lcore_config[idx].core_index = -1;
320			}
321		}
322	}
323	for (; i >= 0; i--)
324		if (coremask[i] != '0')
325			return -1;
326	for (; idx < RTE_MAX_LCORE; idx++) {
327		cfg->lcore_role[idx] = ROLE_OFF;
328		lcore_config[idx].core_index = -1;
329	}
330	if (count == 0)
331		return -1;
332	/* Update the count of enabled logical cores of the EAL configuration */
333	cfg->lcore_count = count;
334	return 0;
335}
336
337static int
338eal_parse_corelist(const char *corelist)
339{
340	struct rte_config *cfg = rte_eal_get_configuration();
341	int i, idx = 0;
342	unsigned count = 0;
343	char *end = NULL;
344	int min, max;
345
346	if (corelist == NULL)
347		return -1;
348
349	/* Remove all blank characters ahead and after */
350	while (isblank(*corelist))
351		corelist++;
352	i = strlen(corelist);
353	while ((i > 0) && isblank(corelist[i - 1]))
354		i--;
355
356	/* Reset config */
357	for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
358		cfg->lcore_role[idx] = ROLE_OFF;
359		lcore_config[idx].core_index = -1;
360	}
361
362	/* Get list of cores */
363	min = RTE_MAX_LCORE;
364	do {
365		while (isblank(*corelist))
366			corelist++;
367		if (*corelist == '\0')
368			return -1;
369		errno = 0;
370		idx = strtoul(corelist, &end, 10);
371		if (errno || end == NULL)
372			return -1;
373		while (isblank(*end))
374			end++;
375		if (*end == '-') {
376			min = idx;
377		} else if ((*end == ',') || (*end == '\0')) {
378			max = idx;
379			if (min == RTE_MAX_LCORE)
380				min = idx;
381			for (idx = min; idx <= max; idx++) {
382				if (cfg->lcore_role[idx] != ROLE_RTE) {
383					cfg->lcore_role[idx] = ROLE_RTE;
384					lcore_config[idx].core_index = count;
385					count++;
386				}
387			}
388			min = RTE_MAX_LCORE;
389		} else
390			return -1;
391		corelist = end + 1;
392	} while (*end != '\0');
393
394	if (count == 0)
395		return -1;
396
397	/* Update the count of enabled logical cores of the EAL configuration */
398	cfg->lcore_count = count;
399
400	return 0;
401}
402
403/* Changes the lcore id of the master thread */
404static int
405eal_parse_master_lcore(const char *arg)
406{
407	char *parsing_end;
408	struct rte_config *cfg = rte_eal_get_configuration();
409
410	errno = 0;
411	cfg->master_lcore = (uint32_t) strtol(arg, &parsing_end, 0);
412	if (errno || parsing_end[0] != 0)
413		return -1;
414	if (cfg->master_lcore >= RTE_MAX_LCORE)
415		return -1;
416	master_lcore_parsed = 1;
417	return 0;
418}
419
420/*
421 * Parse elem, the elem could be single number/range or '(' ')' group
422 * 1) A single number elem, it's just a simple digit. e.g. 9
423 * 2) A single range elem, two digits with a '-' between. e.g. 2-6
424 * 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
425 *    Within group elem, '-' used for a range separator;
426 *                       ',' used for a single number.
427 */
428static int
429eal_parse_set(const char *input, uint16_t set[], unsigned num)
430{
431	unsigned idx;
432	const char *str = input;
433	char *end = NULL;
434	unsigned min, max;
435
436	memset(set, 0, num * sizeof(uint16_t));
437
438	while (isblank(*str))
439		str++;
440
441	/* only digit or left bracket is qualify for start point */
442	if ((!isdigit(*str) && *str != '(') || *str == '\0')
443		return -1;
444
445	/* process single number or single range of number */
446	if (*str != '(') {
447		errno = 0;
448		idx = strtoul(str, &end, 10);
449		if (errno || end == NULL || idx >= num)
450			return -1;
451		else {
452			while (isblank(*end))
453				end++;
454
455			min = idx;
456			max = idx;
457			if (*end == '-') {
458				/* process single <number>-<number> */
459				end++;
460				while (isblank(*end))
461					end++;
462				if (!isdigit(*end))
463					return -1;
464
465				errno = 0;
466				idx = strtoul(end, &end, 10);
467				if (errno || end == NULL || idx >= num)
468					return -1;
469				max = idx;
470				while (isblank(*end))
471					end++;
472				if (*end != ',' && *end != '\0')
473					return -1;
474			}
475
476			if (*end != ',' && *end != '\0' &&
477			    *end != '@')
478				return -1;
479
480			for (idx = RTE_MIN(min, max);
481			     idx <= RTE_MAX(min, max); idx++)
482				set[idx] = 1;
483
484			return end - input;
485		}
486	}
487
488	/* process set within bracket */
489	str++;
490	while (isblank(*str))
491		str++;
492	if (*str == '\0')
493		return -1;
494
495	min = RTE_MAX_LCORE;
496	do {
497
498		/* go ahead to the first digit */
499		while (isblank(*str))
500			str++;
501		if (!isdigit(*str))
502			return -1;
503
504		/* get the digit value */
505		errno = 0;
506		idx = strtoul(str, &end, 10);
507		if (errno || end == NULL || idx >= num)
508			return -1;
509
510		/* go ahead to separator '-',',' and ')' */
511		while (isblank(*end))
512			end++;
513		if (*end == '-') {
514			if (min == RTE_MAX_LCORE)
515				min = idx;
516			else /* avoid continuous '-' */
517				return -1;
518		} else if ((*end == ',') || (*end == ')')) {
519			max = idx;
520			if (min == RTE_MAX_LCORE)
521				min = idx;
522			for (idx = RTE_MIN(min, max);
523			     idx <= RTE_MAX(min, max); idx++)
524				set[idx] = 1;
525
526			min = RTE_MAX_LCORE;
527		} else
528			return -1;
529
530		str = end + 1;
531	} while (*end != '\0' && *end != ')');
532
533	return str - input;
534}
535
536/* convert from set array to cpuset bitmap */
537static int
538convert_to_cpuset(rte_cpuset_t *cpusetp,
539	      uint16_t *set, unsigned num)
540{
541	unsigned idx;
542
543	CPU_ZERO(cpusetp);
544
545	for (idx = 0; idx < num; idx++) {
546		if (!set[idx])
547			continue;
548
549		if (!lcore_config[idx].detected) {
550			RTE_LOG(ERR, EAL, "core %u "
551				"unavailable\n", idx);
552			return -1;
553		}
554
555		CPU_SET(idx, cpusetp);
556	}
557
558	return 0;
559}
560
561/*
562 * The format pattern: --lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
563 * lcores, cpus could be a single digit/range or a group.
564 * '(' and ')' are necessary if it's a group.
565 * If not supply '@cpus', the value of cpus uses the same as lcores.
566 * e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below
567 *   lcore 0 runs on cpuset 0x41 (cpu 0,6)
568 *   lcore 1 runs on cpuset 0x2 (cpu 1)
569 *   lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
570 *   lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
571 *   lcore 6 runs on cpuset 0x41 (cpu 0,6)
572 *   lcore 7 runs on cpuset 0x80 (cpu 7)
573 *   lcore 8 runs on cpuset 0x100 (cpu 8)
574 */
575static int
576eal_parse_lcores(const char *lcores)
577{
578	struct rte_config *cfg = rte_eal_get_configuration();
579	static uint16_t set[RTE_MAX_LCORE];
580	unsigned idx = 0;
581	int i;
582	unsigned count = 0;
583	const char *lcore_start = NULL;
584	const char *end = NULL;
585	int offset;
586	rte_cpuset_t cpuset;
587	int lflags = 0;
588	int ret = -1;
589
590	if (lcores == NULL)
591		return -1;
592
593	/* Remove all blank characters ahead and after */
594	while (isblank(*lcores))
595		lcores++;
596	i = strlen(lcores);
597	while ((i > 0) && isblank(lcores[i - 1]))
598		i--;
599
600	CPU_ZERO(&cpuset);
601
602	/* Reset lcore config */
603	for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
604		cfg->lcore_role[idx] = ROLE_OFF;
605		lcore_config[idx].core_index = -1;
606		CPU_ZERO(&lcore_config[idx].cpuset);
607	}
608
609	/* Get list of cores */
610	do {
611		while (isblank(*lcores))
612			lcores++;
613		if (*lcores == '\0')
614			goto err;
615
616		/* record lcore_set start point */
617		lcore_start = lcores;
618
619		/* go across a complete bracket */
620		if (*lcore_start == '(') {
621			lcores += strcspn(lcores, ")");
622			if (*lcores++ == '\0')
623				goto err;
624		}
625
626		/* scan the separator '@', ','(next) or '\0'(finish) */
627		lcores += strcspn(lcores, "@,");
628
629		if (*lcores == '@') {
630			/* explicit assign cpu_set */
631			offset = eal_parse_set(lcores + 1, set, RTE_DIM(set));
632			if (offset < 0)
633				goto err;
634
635			/* prepare cpu_set and update the end cursor */
636			if (0 > convert_to_cpuset(&cpuset,
637						  set, RTE_DIM(set)))
638				goto err;
639			end = lcores + 1 + offset;
640		} else { /* ',' or '\0' */
641			/* haven't given cpu_set, current loop done */
642			end = lcores;
643
644			/* go back to check <number>-<number> */
645			offset = strcspn(lcore_start, "(-");
646			if (offset < (end - lcore_start) &&
647			    *(lcore_start + offset) != '(')
648				lflags = 1;
649		}
650
651		if (*end != ',' && *end != '\0')
652			goto err;
653
654		/* parse lcore_set from start point */
655		if (0 > eal_parse_set(lcore_start, set, RTE_DIM(set)))
656			goto err;
657
658		/* without '@', by default using lcore_set as cpu_set */
659		if (*lcores != '@' &&
660		    0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set)))
661			goto err;
662
663		/* start to update lcore_set */
664		for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
665			if (!set[idx])
666				continue;
667
668			if (cfg->lcore_role[idx] != ROLE_RTE) {
669				lcore_config[idx].core_index = count;
670				cfg->lcore_role[idx] = ROLE_RTE;
671				count++;
672			}
673
674			if (lflags) {
675				CPU_ZERO(&cpuset);
676				CPU_SET(idx, &cpuset);
677			}
678			rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
679				   sizeof(rte_cpuset_t));
680		}
681
682		lcores = end + 1;
683	} while (*end != '\0');
684
685	if (count == 0)
686		goto err;
687
688	cfg->lcore_count = count;
689	ret = 0;
690
691err:
692
693	return ret;
694}
695
696static int
697eal_parse_syslog(const char *facility, struct internal_config *conf)
698{
699	int i;
700	static struct {
701		const char *name;
702		int value;
703	} map[] = {
704		{ "auth", LOG_AUTH },
705		{ "cron", LOG_CRON },
706		{ "daemon", LOG_DAEMON },
707		{ "ftp", LOG_FTP },
708		{ "kern", LOG_KERN },
709		{ "lpr", LOG_LPR },
710		{ "mail", LOG_MAIL },
711		{ "news", LOG_NEWS },
712		{ "syslog", LOG_SYSLOG },
713		{ "user", LOG_USER },
714		{ "uucp", LOG_UUCP },
715		{ "local0", LOG_LOCAL0 },
716		{ "local1", LOG_LOCAL1 },
717		{ "local2", LOG_LOCAL2 },
718		{ "local3", LOG_LOCAL3 },
719		{ "local4", LOG_LOCAL4 },
720		{ "local5", LOG_LOCAL5 },
721		{ "local6", LOG_LOCAL6 },
722		{ "local7", LOG_LOCAL7 },
723		{ NULL, 0 }
724	};
725
726	for (i = 0; map[i].name; i++) {
727		if (!strcmp(facility, map[i].name)) {
728			conf->syslog_facility = map[i].value;
729			return 0;
730		}
731	}
732	return -1;
733}
734
735static int
736eal_parse_log_level(const char *level, uint32_t *log_level)
737{
738	char *end;
739	unsigned long tmp;
740
741	errno = 0;
742	tmp = strtoul(level, &end, 0);
743
744	/* check for errors */
745	if ((errno != 0) || (level[0] == '\0') ||
746	    end == NULL || (*end != '\0'))
747		return -1;
748
749	/* log_level is a uint32_t */
750	if (tmp >= UINT32_MAX)
751		return -1;
752
753	*log_level = tmp;
754	return 0;
755}
756
757static enum rte_proc_type_t
758eal_parse_proc_type(const char *arg)
759{
760	if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
761		return RTE_PROC_PRIMARY;
762	if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
763		return RTE_PROC_SECONDARY;
764	if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
765		return RTE_PROC_AUTO;
766
767	return RTE_PROC_INVALID;
768}
769
770int
771eal_parse_common_option(int opt, const char *optarg,
772			struct internal_config *conf)
773{
774	switch (opt) {
775	/* blacklist */
776	case 'b':
777		if (rte_eal_devargs_add(RTE_DEVTYPE_BLACKLISTED_PCI,
778				optarg) < 0) {
779			return -1;
780		}
781		break;
782	/* whitelist */
783	case 'w':
784		if (rte_eal_devargs_add(RTE_DEVTYPE_WHITELISTED_PCI,
785				optarg) < 0) {
786			return -1;
787		}
788		break;
789	/* coremask */
790	case 'c':
791		if (eal_parse_coremask(optarg) < 0) {
792			RTE_LOG(ERR, EAL, "invalid coremask\n");
793			return -1;
794		}
795		break;
796	/* corelist */
797	case 'l':
798		if (eal_parse_corelist(optarg) < 0) {
799			RTE_LOG(ERR, EAL, "invalid core list\n");
800			return -1;
801		}
802		break;
803	/* size of memory */
804	case 'm':
805		conf->memory = atoi(optarg);
806		conf->memory *= 1024ULL;
807		conf->memory *= 1024ULL;
808		mem_parsed = 1;
809		break;
810	/* force number of channels */
811	case 'n':
812		conf->force_nchannel = atoi(optarg);
813		if (conf->force_nchannel == 0) {
814			RTE_LOG(ERR, EAL, "invalid channel number\n");
815			return -1;
816		}
817		break;
818	/* force number of ranks */
819	case 'r':
820		conf->force_nrank = atoi(optarg);
821		if (conf->force_nrank == 0 ||
822		    conf->force_nrank > 16) {
823			RTE_LOG(ERR, EAL, "invalid rank number\n");
824			return -1;
825		}
826		break;
827	/* force loading of external driver */
828	case 'd':
829		if (eal_plugin_add(optarg) == -1)
830			return -1;
831		break;
832	case 'v':
833		/* since message is explicitly requested by user, we
834		 * write message at highest log level so it can always
835		 * be seen
836		 * even if info or warning messages are disabled */
837		RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
838		break;
839
840	/* long options */
841	case OPT_HUGE_UNLINK_NUM:
842		conf->hugepage_unlink = 1;
843		break;
844
845	case OPT_NO_HUGE_NUM:
846		conf->no_hugetlbfs = 1;
847		break;
848
849	case OPT_NO_PCI_NUM:
850		conf->no_pci = 1;
851		break;
852
853	case OPT_NO_HPET_NUM:
854		conf->no_hpet = 1;
855		break;
856
857	case OPT_VMWARE_TSC_MAP_NUM:
858		conf->vmware_tsc_map = 1;
859		break;
860
861	case OPT_NO_SHCONF_NUM:
862		conf->no_shconf = 1;
863		break;
864
865	case OPT_PROC_TYPE_NUM:
866		conf->process_type = eal_parse_proc_type(optarg);
867		break;
868
869	case OPT_MASTER_LCORE_NUM:
870		if (eal_parse_master_lcore(optarg) < 0) {
871			RTE_LOG(ERR, EAL, "invalid parameter for --"
872					OPT_MASTER_LCORE "\n");
873			return -1;
874		}
875		break;
876
877	case OPT_VDEV_NUM:
878		if (rte_eal_devargs_add(RTE_DEVTYPE_VIRTUAL,
879				optarg) < 0) {
880			return -1;
881		}
882		break;
883
884	case OPT_SYSLOG_NUM:
885		if (eal_parse_syslog(optarg, conf) < 0) {
886			RTE_LOG(ERR, EAL, "invalid parameters for --"
887					OPT_SYSLOG "\n");
888			return -1;
889		}
890		break;
891
892	case OPT_LOG_LEVEL_NUM: {
893		uint32_t log;
894
895		if (eal_parse_log_level(optarg, &log) < 0) {
896			RTE_LOG(ERR, EAL,
897				"invalid parameters for --"
898				OPT_LOG_LEVEL "\n");
899			return -1;
900		}
901		conf->log_level = log;
902		break;
903	}
904	case OPT_LCORES_NUM:
905		if (eal_parse_lcores(optarg) < 0) {
906			RTE_LOG(ERR, EAL, "invalid parameter for --"
907				OPT_LCORES "\n");
908			return -1;
909		}
910		break;
911
912	/* don't know what to do, leave this to caller */
913	default:
914		return 1;
915
916	}
917
918	return 0;
919}
920
921int
922eal_adjust_config(struct internal_config *internal_cfg)
923{
924	int i;
925	struct rte_config *cfg = rte_eal_get_configuration();
926
927	if (internal_config.process_type == RTE_PROC_AUTO)
928		internal_config.process_type = eal_proc_type_detect();
929
930	/* default master lcore is the first one */
931	if (!master_lcore_parsed)
932		cfg->master_lcore = rte_get_next_lcore(-1, 0, 0);
933
934	/* if no memory amounts were requested, this will result in 0 and
935	 * will be overridden later, right after eal_hugepage_info_init() */
936	for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
937		internal_cfg->memory += internal_cfg->socket_mem[i];
938
939	return 0;
940}
941
942int
943eal_check_common_options(struct internal_config *internal_cfg)
944{
945	struct rte_config *cfg = rte_eal_get_configuration();
946
947	if (cfg->lcore_role[cfg->master_lcore] != ROLE_RTE) {
948		RTE_LOG(ERR, EAL, "Master lcore is not enabled for DPDK\n");
949		return -1;
950	}
951
952	if (internal_cfg->process_type == RTE_PROC_INVALID) {
953		RTE_LOG(ERR, EAL, "Invalid process type specified\n");
954		return -1;
955	}
956	if (index(internal_cfg->hugefile_prefix, '%') != NULL) {
957		RTE_LOG(ERR, EAL, "Invalid char, '%%', in --"OPT_FILE_PREFIX" "
958			"option\n");
959		return -1;
960	}
961	if (mem_parsed && internal_cfg->force_sockets == 1) {
962		RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot "
963			"be specified at the same time\n");
964		return -1;
965	}
966	if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) {
967		RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot "
968			"be specified together with --"OPT_NO_HUGE"\n");
969		return -1;
970	}
971
972	if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink) {
973		RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot "
974			"be specified together with --"OPT_NO_HUGE"\n");
975		return -1;
976	}
977
978	if (rte_eal_devargs_type_count(RTE_DEVTYPE_WHITELISTED_PCI) != 0 &&
979		rte_eal_devargs_type_count(RTE_DEVTYPE_BLACKLISTED_PCI) != 0) {
980		RTE_LOG(ERR, EAL, "Options blacklist (-b) and whitelist (-w) "
981			"cannot be used at the same time\n");
982		return -1;
983	}
984
985	return 0;
986}
987
988void
989eal_common_usage(void)
990{
991	printf("[options]\n\n"
992	       "EAL common options:\n"
993	       "  -c COREMASK         Hexadecimal bitmask of cores to run on\n"
994	       "  -l CORELIST         List of cores to run on\n"
995	       "                      The argument format is <c1>[-c2][,c3[-c4],...]\n"
996	       "                      where c1, c2, etc are core indexes between 0 and %d\n"
997	       "  --"OPT_LCORES" COREMAP    Map lcore set to physical cpu set\n"
998	       "                      The argument format is\n"
999	       "                            '<lcores[@cpus]>[<,lcores[@cpus]>...]'\n"
1000	       "                      lcores and cpus list are grouped by '(' and ')'\n"
1001	       "                      Within the group, '-' is used for range separator,\n"
1002	       "                      ',' is used for single number separator.\n"
1003	       "                      '( )' can be omitted for single element group,\n"
1004	       "                      '@' can be omitted if cpus and lcores have the same value\n"
1005	       "  --"OPT_MASTER_LCORE" ID   Core ID that is used as master\n"
1006	       "  -n CHANNELS         Number of memory channels\n"
1007	       "  -m MB               Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
1008	       "  -r RANKS            Force number of memory ranks (don't detect)\n"
1009	       "  -b, --"OPT_PCI_BLACKLIST" Add a PCI device in black list.\n"
1010	       "                      Prevent EAL from using this PCI device. The argument\n"
1011	       "                      format is <domain:bus:devid.func>.\n"
1012	       "  -w, --"OPT_PCI_WHITELIST" Add a PCI device in white list.\n"
1013	       "                      Only use the specified PCI devices. The argument format\n"
1014	       "                      is <[domain:]bus:devid.func>. This option can be present\n"
1015	       "                      several times (once per device).\n"
1016	       "                      [NOTE: PCI whitelist cannot be used with -b option]\n"
1017	       "  --"OPT_VDEV"              Add a virtual device.\n"
1018	       "                      The argument format is <driver><id>[,key=val,...]\n"
1019	       "                      (ex: --vdev=eth_pcap0,iface=eth2).\n"
1020	       "  -d LIB.so|DIR       Add a driver or driver directory\n"
1021	       "                      (can be used multiple times)\n"
1022	       "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
1023	       "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
1024	       "  --"OPT_SYSLOG"            Set syslog facility\n"
1025	       "  --"OPT_LOG_LEVEL"         Set default log level\n"
1026	       "  -v                  Display version information on startup\n"
1027	       "  -h, --help          This help\n"
1028	       "\nEAL options for DEBUG use only:\n"
1029	       "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
1030	       "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"
1031	       "  --"OPT_NO_PCI"            Disable PCI\n"
1032	       "  --"OPT_NO_HPET"           Disable HPET\n"
1033	       "  --"OPT_NO_SHCONF"         No shared config (mmap'd files)\n"
1034	       "\n", RTE_MAX_LCORE);
1035}
1036