2018-01-29 13:11:25 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
* Copyright(c) 2010-2014 Intel Corporation.
|
|
|
|
* Copyright(c) 2014 6WIND S.A.
|
2014-09-22 08:37:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2014-06-27 14:09:32 +00:00
|
|
|
#include <unistd.h>
|
2014-09-22 08:37:59 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <getopt.h>
|
2015-11-10 14:28:14 +00:00
|
|
|
#include <dlfcn.h>
|
2015-11-10 14:28:15 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <dirent.h>
|
2014-09-22 08:37:59 +00:00
|
|
|
|
|
|
|
#include <rte_eal.h>
|
|
|
|
#include <rte_log.h>
|
|
|
|
#include <rte_lcore.h>
|
2017-08-02 17:10:22 +00:00
|
|
|
#include <rte_tailq.h>
|
2014-09-22 08:37:59 +00:00
|
|
|
#include <rte_version.h>
|
|
|
|
#include <rte_devargs.h>
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
#include <rte_memcpy.h>
|
2014-09-22 08:37:59 +00:00
|
|
|
|
|
|
|
#include "eal_internal_cfg.h"
|
|
|
|
#include "eal_options.h"
|
2014-11-17 09:08:39 +00:00
|
|
|
#include "eal_filesystem.h"
|
2018-04-25 03:17:48 +00:00
|
|
|
#include "eal_private.h"
|
2014-09-22 08:37:59 +00:00
|
|
|
|
|
|
|
#define BITS_PER_HEX 4
|
2018-02-02 14:51:28 +00:00
|
|
|
#define LCORE_OPT_LST 1
|
|
|
|
#define LCORE_OPT_MSK 2
|
|
|
|
#define LCORE_OPT_MAP 3
|
2014-09-22 08:37:59 +00:00
|
|
|
|
|
|
|
const char
|
|
|
|
eal_short_options[] =
|
|
|
|
"b:" /* pci-blacklist */
|
2014-06-27 14:09:32 +00:00
|
|
|
"c:" /* coremask */
|
2017-07-11 14:19:29 +00:00
|
|
|
"s:" /* service coremask */
|
2015-01-29 16:42:31 +00:00
|
|
|
"d:" /* driver */
|
2015-01-29 16:51:17 +00:00
|
|
|
"h" /* help */
|
2014-06-27 14:09:32 +00:00
|
|
|
"l:" /* corelist */
|
2017-07-17 15:21:54 +00:00
|
|
|
"S:" /* service corelist */
|
2015-01-29 16:42:31 +00:00
|
|
|
"m:" /* memory size */
|
|
|
|
"n:" /* memory channels */
|
|
|
|
"r:" /* memory ranks */
|
|
|
|
"v" /* version */
|
|
|
|
"w:" /* pci-whitelist */
|
|
|
|
;
|
2014-09-22 08:37:59 +00:00
|
|
|
|
|
|
|
const struct option
|
|
|
|
eal_long_options[] = {
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_BASE_VIRTADDR, 1, NULL, OPT_BASE_VIRTADDR_NUM },
|
2015-03-23 08:11:39 +00:00
|
|
|
{OPT_CREATE_UIO_DEV, 0, NULL, OPT_CREATE_UIO_DEV_NUM },
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_FILE_PREFIX, 1, NULL, OPT_FILE_PREFIX_NUM },
|
2015-01-29 16:51:17 +00:00
|
|
|
{OPT_HELP, 0, NULL, OPT_HELP_NUM },
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_HUGE_DIR, 1, NULL, OPT_HUGE_DIR_NUM },
|
2015-10-28 22:04:25 +00:00
|
|
|
{OPT_HUGE_UNLINK, 0, NULL, OPT_HUGE_UNLINK_NUM },
|
2018-10-03 20:53:12 +00:00
|
|
|
{OPT_IOVA_MODE, 1, NULL, OPT_IOVA_MODE_NUM },
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
{OPT_LCORES, 1, NULL, OPT_LCORES_NUM },
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_LOG_LEVEL, 1, NULL, OPT_LOG_LEVEL_NUM },
|
|
|
|
{OPT_MASTER_LCORE, 1, NULL, OPT_MASTER_LCORE_NUM },
|
2017-10-06 07:45:29 +00:00
|
|
|
{OPT_MBUF_POOL_OPS_NAME, 1, NULL, OPT_MBUF_POOL_OPS_NAME_NUM},
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_NO_HPET, 0, NULL, OPT_NO_HPET_NUM },
|
|
|
|
{OPT_NO_HUGE, 0, NULL, OPT_NO_HUGE_NUM },
|
|
|
|
{OPT_NO_PCI, 0, NULL, OPT_NO_PCI_NUM },
|
|
|
|
{OPT_NO_SHCONF, 0, NULL, OPT_NO_SHCONF_NUM },
|
2018-07-13 12:48:03 +00:00
|
|
|
{OPT_IN_MEMORY, 0, NULL, OPT_IN_MEMORY_NUM },
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_PCI_BLACKLIST, 1, NULL, OPT_PCI_BLACKLIST_NUM },
|
|
|
|
{OPT_PCI_WHITELIST, 1, NULL, OPT_PCI_WHITELIST_NUM },
|
|
|
|
{OPT_PROC_TYPE, 1, NULL, OPT_PROC_TYPE_NUM },
|
|
|
|
{OPT_SOCKET_MEM, 1, NULL, OPT_SOCKET_MEM_NUM },
|
2018-05-31 17:35:33 +00:00
|
|
|
{OPT_SOCKET_LIMIT, 1, NULL, OPT_SOCKET_LIMIT_NUM },
|
2015-01-29 16:42:31 +00:00
|
|
|
{OPT_SYSLOG, 1, NULL, OPT_SYSLOG_NUM },
|
|
|
|
{OPT_VDEV, 1, NULL, OPT_VDEV_NUM },
|
|
|
|
{OPT_VFIO_INTR, 1, NULL, OPT_VFIO_INTR_NUM },
|
|
|
|
{OPT_VMWARE_TSC_MAP, 0, NULL, OPT_VMWARE_TSC_MAP_NUM },
|
2018-04-11 12:30:22 +00:00
|
|
|
{OPT_LEGACY_MEM, 0, NULL, OPT_LEGACY_MEM_NUM },
|
2018-04-11 12:30:28 +00:00
|
|
|
{OPT_SINGLE_FILE_SEGMENTS, 0, NULL, OPT_SINGLE_FILE_SEGMENTS_NUM},
|
2018-12-14 17:13:03 +00:00
|
|
|
{OPT_MATCH_ALLOCATIONS, 0, NULL, OPT_MATCH_ALLOCATIONS_NUM},
|
2015-01-29 16:42:31 +00:00
|
|
|
{0, 0, NULL, 0 }
|
2014-09-22 08:37:59 +00:00
|
|
|
};
|
|
|
|
|
2015-11-10 14:28:14 +00:00
|
|
|
TAILQ_HEAD(shared_driver_list, shared_driver);
|
|
|
|
|
|
|
|
/* Definition for shared object drivers. */
|
|
|
|
struct shared_driver {
|
|
|
|
TAILQ_ENTRY(shared_driver) next;
|
|
|
|
|
|
|
|
char name[PATH_MAX];
|
|
|
|
void* lib_handle;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* List of external loadable drivers */
|
|
|
|
static struct shared_driver_list solib_list =
|
|
|
|
TAILQ_HEAD_INITIALIZER(solib_list);
|
|
|
|
|
2015-11-10 14:28:15 +00:00
|
|
|
/* Default path of external loadable drivers */
|
|
|
|
static const char *default_solib_dir = RTE_EAL_PMD_PATH;
|
|
|
|
|
2016-06-17 18:46:22 +00:00
|
|
|
/*
|
2016-07-20 13:38:54 +00:00
|
|
|
* Stringified version of solib path used by dpdk-pmdinfo.py
|
2016-06-17 18:46:22 +00:00
|
|
|
* Note: PLEASE DO NOT ALTER THIS without making a corresponding
|
2016-12-15 21:25:36 +00:00
|
|
|
* change to usertools/dpdk-pmdinfo.py
|
2016-06-17 18:46:22 +00:00
|
|
|
*/
|
|
|
|
static const char dpdk_solib_path[] __attribute__((used)) =
|
|
|
|
"DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
|
|
|
|
|
2017-08-02 17:10:22 +00:00
|
|
|
TAILQ_HEAD(device_option_list, device_option);
|
|
|
|
|
|
|
|
struct device_option {
|
|
|
|
TAILQ_ENTRY(device_option) next;
|
|
|
|
|
|
|
|
enum rte_devtype type;
|
|
|
|
char arg[];
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct device_option_list devopt_list =
|
|
|
|
TAILQ_HEAD_INITIALIZER(devopt_list);
|
2016-06-17 18:46:22 +00:00
|
|
|
|
2014-07-08 08:28:30 +00:00
|
|
|
static int master_lcore_parsed;
|
2014-11-17 09:14:10 +00:00
|
|
|
static int mem_parsed;
|
2016-12-02 17:48:56 +00:00
|
|
|
static int core_parsed;
|
2014-11-17 09:14:10 +00:00
|
|
|
|
2017-08-02 17:10:22 +00:00
|
|
|
static int
|
|
|
|
eal_option_device_add(enum rte_devtype type, const char *optarg)
|
|
|
|
{
|
|
|
|
struct device_option *devopt;
|
|
|
|
size_t optlen;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
optlen = strlen(optarg) + 1;
|
|
|
|
devopt = calloc(1, sizeof(*devopt) + optlen);
|
|
|
|
if (devopt == NULL) {
|
|
|
|
RTE_LOG(ERR, EAL, "Unable to allocate device option\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
devopt->type = type;
|
|
|
|
ret = snprintf(devopt->arg, optlen, "%s", optarg);
|
|
|
|
if (ret < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "Unable to copy device option\n");
|
|
|
|
free(devopt);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
TAILQ_INSERT_TAIL(&devopt_list, devopt, next);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
eal_option_device_parse(void)
|
|
|
|
{
|
|
|
|
struct device_option *devopt;
|
|
|
|
void *tmp;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) {
|
|
|
|
if (ret == 0) {
|
2018-04-23 23:54:52 +00:00
|
|
|
ret = rte_devargs_add(devopt->type, devopt->arg);
|
2017-08-02 17:10:22 +00:00
|
|
|
if (ret)
|
|
|
|
RTE_LOG(ERR, EAL, "Unable to parse device '%s'\n",
|
|
|
|
devopt->arg);
|
|
|
|
}
|
|
|
|
TAILQ_REMOVE(&devopt_list, devopt, next);
|
|
|
|
free(devopt);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
eal: fix strdup usages in internal config
Currently, we use strdup in a few places to store command-line
parameter values for certain internal config values. There are
several issues with that.
First of all, they're never freed, so memory ends up leaking
either after EAL exit, or when these command-line options are
supplied multiple times.
Second of all, they're defined as `const char *`, so they
*cannot* be freed even if we wanted to.
Finally, strdup may return NULL, which will be stored in the
config. For most fields, NULL is a valid value, but for the
default prefix, the value is always expected to be valid.
To fix all of this, three things are done. First, we change
the definitions of these values to `char *` as opposed to
`const char *`. This does not break the ABI, and previous
code assumes constness (which is more restrictive), so it's
safe to do so.
Then, fix all usages of strdup to check return value, and add
a cleanup function that will free the memory occupied by
these strings, as well as freeing them before assigning a new
value to prevent leaks when parameter is specified multiple
times.
And finally, add an internal API to query hugefile prefix, so
that, absent of a valid value, a default value will be
returned, and also fix up all usages of hugefile prefix to
use this API instead of accessing hugefile prefix directly.
Bugzilla ID: 108
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
2019-01-10 13:38:59 +00:00
|
|
|
const char *
|
|
|
|
eal_get_hugefile_prefix(void)
|
|
|
|
{
|
|
|
|
if (internal_config.hugefile_prefix != NULL)
|
|
|
|
return internal_config.hugefile_prefix;
|
|
|
|
return HUGEFILE_PREFIX_DEFAULT;
|
|
|
|
}
|
|
|
|
|
2014-11-17 09:08:39 +00:00
|
|
|
void
|
|
|
|
eal_reset_internal_config(struct internal_config *internal_cfg)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
internal_cfg->memory = 0;
|
|
|
|
internal_cfg->force_nrank = 0;
|
|
|
|
internal_cfg->force_nchannel = 0;
|
eal: fix strdup usages in internal config
Currently, we use strdup in a few places to store command-line
parameter values for certain internal config values. There are
several issues with that.
First of all, they're never freed, so memory ends up leaking
either after EAL exit, or when these command-line options are
supplied multiple times.
Second of all, they're defined as `const char *`, so they
*cannot* be freed even if we wanted to.
Finally, strdup may return NULL, which will be stored in the
config. For most fields, NULL is a valid value, but for the
default prefix, the value is always expected to be valid.
To fix all of this, three things are done. First, we change
the definitions of these values to `char *` as opposed to
`const char *`. This does not break the ABI, and previous
code assumes constness (which is more restrictive), so it's
safe to do so.
Then, fix all usages of strdup to check return value, and add
a cleanup function that will free the memory occupied by
these strings, as well as freeing them before assigning a new
value to prevent leaks when parameter is specified multiple
times.
And finally, add an internal API to query hugefile prefix, so
that, absent of a valid value, a default value will be
returned, and also fix up all usages of hugefile prefix to
use this API instead of accessing hugefile prefix directly.
Bugzilla ID: 108
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
2019-01-10 13:38:59 +00:00
|
|
|
internal_cfg->hugefile_prefix = NULL;
|
2014-11-17 09:08:39 +00:00
|
|
|
internal_cfg->hugepage_dir = NULL;
|
|
|
|
internal_cfg->force_sockets = 0;
|
|
|
|
/* zero out the NUMA config */
|
|
|
|
for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
|
|
|
|
internal_cfg->socket_mem[i] = 0;
|
2018-05-31 17:35:33 +00:00
|
|
|
internal_cfg->force_socket_limits = 0;
|
|
|
|
/* zero out the NUMA limits config */
|
|
|
|
for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
|
|
|
|
internal_cfg->socket_limit[i] = 0;
|
2014-11-17 09:08:39 +00:00
|
|
|
/* zero out hugedir descriptors */
|
2018-04-11 12:30:33 +00:00
|
|
|
for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) {
|
|
|
|
memset(&internal_cfg->hugepage_info[i], 0,
|
|
|
|
sizeof(internal_cfg->hugepage_info[0]));
|
2014-11-17 09:08:39 +00:00
|
|
|
internal_cfg->hugepage_info[i].lock_descriptor = -1;
|
2018-04-11 12:30:33 +00:00
|
|
|
}
|
2014-11-17 09:08:39 +00:00
|
|
|
internal_cfg->base_virtaddr = 0;
|
|
|
|
|
|
|
|
internal_cfg->syslog_facility = LOG_DAEMON;
|
|
|
|
|
|
|
|
/* if set to NONE, interrupt mode is determined automatically */
|
|
|
|
internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
|
|
|
|
|
|
|
|
#ifdef RTE_LIBEAL_USE_HPET
|
|
|
|
internal_cfg->no_hpet = 0;
|
|
|
|
#else
|
|
|
|
internal_cfg->no_hpet = 1;
|
|
|
|
#endif
|
|
|
|
internal_cfg->vmware_tsc_map = 0;
|
2015-03-23 08:11:39 +00:00
|
|
|
internal_cfg->create_uio_dev = 0;
|
2018-10-03 20:53:12 +00:00
|
|
|
internal_cfg->iova_mode = RTE_IOVA_DC;
|
2018-01-29 08:10:44 +00:00
|
|
|
internal_cfg->user_mbuf_pool_ops_name = NULL;
|
2018-03-13 17:42:35 +00:00
|
|
|
internal_cfg->init_complete = 0;
|
2014-11-17 09:08:39 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 14:28:14 +00:00
|
|
|
static int
|
|
|
|
eal_plugin_add(const char *path)
|
|
|
|
{
|
|
|
|
struct shared_driver *solib;
|
|
|
|
|
|
|
|
solib = malloc(sizeof(*solib));
|
|
|
|
if (solib == NULL) {
|
|
|
|
RTE_LOG(ERR, EAL, "malloc(solib) failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
memset(solib, 0, sizeof(*solib));
|
2018-11-02 19:06:06 +00:00
|
|
|
strlcpy(solib->name, path, PATH_MAX-1);
|
2015-11-10 14:28:14 +00:00
|
|
|
solib->name[PATH_MAX-1] = 0;
|
|
|
|
TAILQ_INSERT_TAIL(&solib_list, solib, next);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-11-10 14:28:15 +00:00
|
|
|
static int
|
|
|
|
eal_plugindir_init(const char *path)
|
|
|
|
{
|
|
|
|
DIR *d = NULL;
|
|
|
|
struct dirent *dent = NULL;
|
|
|
|
char sopath[PATH_MAX];
|
|
|
|
|
|
|
|
if (path == NULL || *path == '\0')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
d = opendir(path);
|
|
|
|
if (d == NULL) {
|
|
|
|
RTE_LOG(ERR, EAL, "failed to open directory %s: %s\n",
|
|
|
|
path, strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dent = readdir(d)) != NULL) {
|
2015-11-18 06:45:23 +00:00
|
|
|
struct stat sb;
|
2015-11-10 14:28:15 +00:00
|
|
|
|
|
|
|
snprintf(sopath, PATH_MAX-1, "%s/%s", path, dent->d_name);
|
|
|
|
sopath[PATH_MAX-1] = 0;
|
|
|
|
|
2015-11-18 06:45:23 +00:00
|
|
|
if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
|
|
|
|
continue;
|
|
|
|
|
2015-11-10 14:28:15 +00:00
|
|
|
if (eal_plugin_add(sopath) == -1)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(d);
|
|
|
|
/* XXX this ignores failures from readdir() itself */
|
|
|
|
return (dent == NULL) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
2015-11-10 14:28:14 +00:00
|
|
|
int
|
|
|
|
eal_plugins_init(void)
|
|
|
|
{
|
|
|
|
struct shared_driver *solib = NULL;
|
2017-10-19 08:49:12 +00:00
|
|
|
struct stat sb;
|
2015-11-10 14:28:14 +00:00
|
|
|
|
2017-11-06 13:58:00 +00:00
|
|
|
if (*default_solib_dir != '\0' && stat(default_solib_dir, &sb) == 0 &&
|
2017-10-19 08:49:12 +00:00
|
|
|
S_ISDIR(sb.st_mode))
|
2015-11-10 14:28:15 +00:00
|
|
|
eal_plugin_add(default_solib_dir);
|
|
|
|
|
2015-11-10 14:28:14 +00:00
|
|
|
TAILQ_FOREACH(solib, &solib_list, next) {
|
2015-11-10 14:28:15 +00:00
|
|
|
|
2015-11-23 12:05:55 +00:00
|
|
|
if (stat(solib->name, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
2015-11-10 14:28:15 +00:00
|
|
|
if (eal_plugindir_init(solib->name) == -1) {
|
|
|
|
RTE_LOG(ERR, EAL,
|
|
|
|
"Cannot init plugin directory %s\n",
|
|
|
|
solib->name);
|
|
|
|
return -1;
|
|
|
|
}
|
2015-11-23 12:05:55 +00:00
|
|
|
} else {
|
2015-11-10 14:28:15 +00:00
|
|
|
RTE_LOG(DEBUG, EAL, "open shared lib %s\n",
|
|
|
|
solib->name);
|
|
|
|
solib->lib_handle = dlopen(solib->name, RTLD_NOW);
|
|
|
|
if (solib->lib_handle == NULL) {
|
|
|
|
RTE_LOG(ERR, EAL, "%s\n", dlerror());
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-10 14:28:14 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
/*
|
|
|
|
* Parse the coremask given as argument (hexadecimal string) and fill
|
|
|
|
* the global configuration (core role and core count) with the parsed
|
|
|
|
* value.
|
|
|
|
*/
|
|
|
|
static int xdigit2val(unsigned char c)
|
|
|
|
{
|
|
|
|
int val;
|
|
|
|
|
|
|
|
if (isdigit(c))
|
|
|
|
val = c - '0';
|
|
|
|
else if (isupper(c))
|
|
|
|
val = c - 'A' + 10;
|
|
|
|
else
|
|
|
|
val = c - 'a' + 10;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2017-07-11 14:19:29 +00:00
|
|
|
static int
|
|
|
|
eal_parse_service_coremask(const char *coremask)
|
|
|
|
{
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
int i, j, idx = 0;
|
|
|
|
unsigned int count = 0;
|
|
|
|
char c;
|
|
|
|
int val;
|
2018-07-26 16:31:59 +00:00
|
|
|
uint32_t taken_lcore_count = 0;
|
2017-07-11 14:19:29 +00:00
|
|
|
|
|
|
|
if (coremask == NULL)
|
|
|
|
return -1;
|
|
|
|
/* Remove all blank characters ahead and after .
|
|
|
|
* Remove 0x/0X if exists.
|
|
|
|
*/
|
|
|
|
while (isblank(*coremask))
|
|
|
|
coremask++;
|
|
|
|
if (coremask[0] == '0' && ((coremask[1] == 'x')
|
|
|
|
|| (coremask[1] == 'X')))
|
|
|
|
coremask += 2;
|
|
|
|
i = strlen(coremask);
|
|
|
|
while ((i > 0) && isblank(coremask[i - 1]))
|
|
|
|
i--;
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
|
|
|
|
c = coremask[i];
|
|
|
|
if (isxdigit(c) == 0) {
|
|
|
|
/* invalid characters */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
val = xdigit2val(c);
|
|
|
|
for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE;
|
|
|
|
j++, idx++) {
|
|
|
|
if ((1 << j) & val) {
|
|
|
|
/* handle master lcore already parsed */
|
|
|
|
uint32_t lcore = idx;
|
|
|
|
if (master_lcore_parsed &&
|
|
|
|
cfg->master_lcore == lcore) {
|
|
|
|
RTE_LOG(ERR, EAL,
|
2018-07-26 16:31:59 +00:00
|
|
|
"lcore %u is master lcore, cannot use as service core\n",
|
2017-07-11 14:19:29 +00:00
|
|
|
idx);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!lcore_config[idx].detected) {
|
|
|
|
RTE_LOG(ERR, EAL,
|
|
|
|
"lcore %u unavailable\n", idx);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-07-26 16:31:59 +00:00
|
|
|
|
|
|
|
if (cfg->lcore_role[idx] == ROLE_RTE)
|
|
|
|
taken_lcore_count++;
|
|
|
|
|
2017-07-11 14:19:29 +00:00
|
|
|
lcore_config[idx].core_role = ROLE_SERVICE;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; i >= 0; i--)
|
|
|
|
if (coremask[i] != '0')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (; idx < RTE_MAX_LCORE; idx++)
|
|
|
|
lcore_config[idx].core_index = -1;
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-07-26 16:31:59 +00:00
|
|
|
if (core_parsed && taken_lcore_count != count) {
|
|
|
|
RTE_LOG(WARNING, EAL,
|
|
|
|
"Not all service cores are in the coremask. "
|
|
|
|
"Please ensure -c or -l includes service cores\n");
|
|
|
|
}
|
|
|
|
|
2017-07-11 14:19:29 +00:00
|
|
|
cfg->service_lcore_count = count;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-26 16:31:59 +00:00
|
|
|
static int
|
|
|
|
eal_service_cores_parsed(void)
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
|
|
|
|
if (lcore_config[idx].core_role == ROLE_SERVICE)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
static int
|
|
|
|
eal_parse_coremask(const char *coremask)
|
|
|
|
{
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
int i, j, idx = 0;
|
|
|
|
unsigned count = 0;
|
|
|
|
char c;
|
|
|
|
int val;
|
|
|
|
|
2018-07-26 16:31:59 +00:00
|
|
|
if (eal_service_cores_parsed())
|
|
|
|
RTE_LOG(WARNING, EAL,
|
|
|
|
"Service cores parsed before dataplane cores. "
|
|
|
|
"Please ensure -c is before -s or -S\n");
|
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
if (coremask == NULL)
|
|
|
|
return -1;
|
|
|
|
/* Remove all blank characters ahead and after .
|
|
|
|
* Remove 0x/0X if exists.
|
|
|
|
*/
|
|
|
|
while (isblank(*coremask))
|
|
|
|
coremask++;
|
|
|
|
if (coremask[0] == '0' && ((coremask[1] == 'x')
|
|
|
|
|| (coremask[1] == 'X')))
|
|
|
|
coremask += 2;
|
2015-02-17 02:08:01 +00:00
|
|
|
i = strlen(coremask);
|
2014-09-22 08:37:59 +00:00
|
|
|
while ((i > 0) && isblank(coremask[i - 1]))
|
|
|
|
i--;
|
|
|
|
if (i == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
|
|
|
|
c = coremask[i];
|
|
|
|
if (isxdigit(c) == 0) {
|
|
|
|
/* invalid characters */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
val = xdigit2val(c);
|
|
|
|
for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++)
|
|
|
|
{
|
|
|
|
if ((1 << j) & val) {
|
|
|
|
if (!lcore_config[idx].detected) {
|
|
|
|
RTE_LOG(ERR, EAL, "lcore %u "
|
|
|
|
"unavailable\n", idx);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-07-26 16:31:59 +00:00
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
cfg->lcore_role[idx] = ROLE_RTE;
|
2014-06-11 20:45:09 +00:00
|
|
|
lcore_config[idx].core_index = count;
|
2014-09-22 08:37:59 +00:00
|
|
|
count++;
|
|
|
|
} else {
|
|
|
|
cfg->lcore_role[idx] = ROLE_OFF;
|
2014-06-11 20:45:09 +00:00
|
|
|
lcore_config[idx].core_index = -1;
|
2014-09-22 08:37:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (; i >= 0; i--)
|
|
|
|
if (coremask[i] != '0')
|
|
|
|
return -1;
|
2014-06-11 20:45:09 +00:00
|
|
|
for (; idx < RTE_MAX_LCORE; idx++) {
|
2014-09-22 08:37:59 +00:00
|
|
|
cfg->lcore_role[idx] = ROLE_OFF;
|
2014-06-11 20:45:09 +00:00
|
|
|
lcore_config[idx].core_index = -1;
|
|
|
|
}
|
2014-09-22 08:37:59 +00:00
|
|
|
if (count == 0)
|
|
|
|
return -1;
|
|
|
|
/* Update the count of enabled logical cores of the EAL configuration */
|
|
|
|
cfg->lcore_count = count;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-17 15:21:54 +00:00
|
|
|
static int
|
|
|
|
eal_parse_service_corelist(const char *corelist)
|
|
|
|
{
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
int i, idx = 0;
|
|
|
|
unsigned count = 0;
|
|
|
|
char *end = NULL;
|
|
|
|
int min, max;
|
2018-07-26 16:31:59 +00:00
|
|
|
uint32_t taken_lcore_count = 0;
|
2017-07-17 15:21:54 +00:00
|
|
|
|
|
|
|
if (corelist == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Remove all blank characters ahead and after */
|
|
|
|
while (isblank(*corelist))
|
|
|
|
corelist++;
|
|
|
|
i = strlen(corelist);
|
|
|
|
while ((i > 0) && isblank(corelist[i - 1]))
|
|
|
|
i--;
|
|
|
|
|
|
|
|
/* Get list of cores */
|
|
|
|
min = RTE_MAX_LCORE;
|
|
|
|
do {
|
|
|
|
while (isblank(*corelist))
|
|
|
|
corelist++;
|
|
|
|
if (*corelist == '\0')
|
|
|
|
return -1;
|
|
|
|
errno = 0;
|
|
|
|
idx = strtoul(corelist, &end, 10);
|
|
|
|
if (errno || end == NULL)
|
|
|
|
return -1;
|
|
|
|
while (isblank(*end))
|
|
|
|
end++;
|
|
|
|
if (*end == '-') {
|
|
|
|
min = idx;
|
|
|
|
} else if ((*end == ',') || (*end == '\0')) {
|
|
|
|
max = idx;
|
|
|
|
if (min == RTE_MAX_LCORE)
|
|
|
|
min = idx;
|
|
|
|
for (idx = min; idx <= max; idx++) {
|
|
|
|
if (cfg->lcore_role[idx] != ROLE_SERVICE) {
|
|
|
|
/* handle master lcore already parsed */
|
|
|
|
uint32_t lcore = idx;
|
|
|
|
if (cfg->master_lcore == lcore &&
|
|
|
|
master_lcore_parsed) {
|
|
|
|
RTE_LOG(ERR, EAL,
|
|
|
|
"Error: lcore %u is master lcore, cannot use as service core\n",
|
|
|
|
idx);
|
|
|
|
return -1;
|
|
|
|
}
|
2018-07-26 16:31:59 +00:00
|
|
|
if (cfg->lcore_role[idx] == ROLE_RTE)
|
|
|
|
taken_lcore_count++;
|
|
|
|
|
2017-07-17 15:21:54 +00:00
|
|
|
lcore_config[idx].core_role =
|
|
|
|
ROLE_SERVICE;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
min = RTE_MAX_LCORE;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
corelist = end + 1;
|
|
|
|
} while (*end != '\0');
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
return -1;
|
|
|
|
|
2018-07-26 16:31:59 +00:00
|
|
|
if (core_parsed && taken_lcore_count != count) {
|
|
|
|
RTE_LOG(WARNING, EAL,
|
|
|
|
"Not all service cores were in the coremask. "
|
|
|
|
"Please ensure -c or -l includes service cores\n");
|
|
|
|
}
|
|
|
|
|
2017-07-17 15:21:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-27 14:09:32 +00:00
|
|
|
static int
|
|
|
|
eal_parse_corelist(const char *corelist)
|
|
|
|
{
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
int i, idx = 0;
|
|
|
|
unsigned count = 0;
|
|
|
|
char *end = NULL;
|
|
|
|
int min, max;
|
|
|
|
|
2018-07-26 16:31:59 +00:00
|
|
|
if (eal_service_cores_parsed())
|
|
|
|
RTE_LOG(WARNING, EAL,
|
|
|
|
"Service cores parsed before dataplane cores. "
|
|
|
|
"Please ensure -l is before -s or -S\n");
|
|
|
|
|
2014-06-27 14:09:32 +00:00
|
|
|
if (corelist == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Remove all blank characters ahead and after */
|
|
|
|
while (isblank(*corelist))
|
|
|
|
corelist++;
|
2015-02-17 02:08:01 +00:00
|
|
|
i = strlen(corelist);
|
2014-06-27 14:09:32 +00:00
|
|
|
while ((i > 0) && isblank(corelist[i - 1]))
|
|
|
|
i--;
|
|
|
|
|
2014-06-11 20:45:09 +00:00
|
|
|
/* Reset config */
|
|
|
|
for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
|
2014-06-27 14:09:32 +00:00
|
|
|
cfg->lcore_role[idx] = ROLE_OFF;
|
2014-06-11 20:45:09 +00:00
|
|
|
lcore_config[idx].core_index = -1;
|
|
|
|
}
|
2014-06-27 14:09:32 +00:00
|
|
|
|
|
|
|
/* Get list of cores */
|
|
|
|
min = RTE_MAX_LCORE;
|
|
|
|
do {
|
|
|
|
while (isblank(*corelist))
|
|
|
|
corelist++;
|
|
|
|
if (*corelist == '\0')
|
|
|
|
return -1;
|
|
|
|
errno = 0;
|
2019-01-17 12:13:12 +00:00
|
|
|
idx = strtol(corelist, &end, 10);
|
|
|
|
if (idx < 0 || idx >= (int)cfg->lcore_count)
|
|
|
|
return -1;
|
2014-06-27 14:09:32 +00:00
|
|
|
if (errno || end == NULL)
|
|
|
|
return -1;
|
|
|
|
while (isblank(*end))
|
|
|
|
end++;
|
|
|
|
if (*end == '-') {
|
|
|
|
min = idx;
|
|
|
|
} else if ((*end == ',') || (*end == '\0')) {
|
|
|
|
max = idx;
|
|
|
|
if (min == RTE_MAX_LCORE)
|
|
|
|
min = idx;
|
|
|
|
for (idx = min; idx <= max; idx++) {
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
if (cfg->lcore_role[idx] != ROLE_RTE) {
|
|
|
|
cfg->lcore_role[idx] = ROLE_RTE;
|
|
|
|
lcore_config[idx].core_index = count;
|
|
|
|
count++;
|
|
|
|
}
|
2014-06-27 14:09:32 +00:00
|
|
|
}
|
|
|
|
min = RTE_MAX_LCORE;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
corelist = end + 1;
|
|
|
|
} while (*end != '\0');
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
return -1;
|
|
|
|
|
2015-01-20 18:54:43 +00:00
|
|
|
/* Update the count of enabled logical cores of the EAL configuration */
|
|
|
|
cfg->lcore_count = count;
|
|
|
|
|
2014-06-27 14:09:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-07-08 08:28:30 +00:00
|
|
|
/* Changes the lcore id of the master thread */
|
|
|
|
static int
|
|
|
|
eal_parse_master_lcore(const char *arg)
|
|
|
|
{
|
|
|
|
char *parsing_end;
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
cfg->master_lcore = (uint32_t) strtol(arg, &parsing_end, 0);
|
|
|
|
if (errno || parsing_end[0] != 0)
|
|
|
|
return -1;
|
|
|
|
if (cfg->master_lcore >= RTE_MAX_LCORE)
|
|
|
|
return -1;
|
|
|
|
master_lcore_parsed = 1;
|
2017-07-11 14:19:29 +00:00
|
|
|
|
|
|
|
/* ensure master core is not used as service core */
|
|
|
|
if (lcore_config[cfg->master_lcore].core_role == ROLE_SERVICE) {
|
2018-07-26 16:31:59 +00:00
|
|
|
RTE_LOG(ERR, EAL,
|
|
|
|
"Error: Master lcore is used as a service core\n");
|
2017-07-11 14:19:29 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-07-08 08:28:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
/*
|
|
|
|
* Parse elem, the elem could be single number/range or '(' ')' group
|
|
|
|
* 1) A single number elem, it's just a simple digit. e.g. 9
|
|
|
|
* 2) A single range elem, two digits with a '-' between. e.g. 2-6
|
|
|
|
* 3) A group elem, combines multiple 1) or 2) with '( )'. e.g (0,2-4,6)
|
|
|
|
* Within group elem, '-' used for a range separator;
|
|
|
|
* ',' used for a single number.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
eal_parse_set(const char *input, uint16_t set[], unsigned num)
|
|
|
|
{
|
|
|
|
unsigned idx;
|
|
|
|
const char *str = input;
|
|
|
|
char *end = NULL;
|
|
|
|
unsigned min, max;
|
|
|
|
|
|
|
|
memset(set, 0, num * sizeof(uint16_t));
|
|
|
|
|
|
|
|
while (isblank(*str))
|
|
|
|
str++;
|
|
|
|
|
|
|
|
/* only digit or left bracket is qualify for start point */
|
|
|
|
if ((!isdigit(*str) && *str != '(') || *str == '\0')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* process single number or single range of number */
|
|
|
|
if (*str != '(') {
|
|
|
|
errno = 0;
|
|
|
|
idx = strtoul(str, &end, 10);
|
|
|
|
if (errno || end == NULL || idx >= num)
|
|
|
|
return -1;
|
|
|
|
else {
|
|
|
|
while (isblank(*end))
|
|
|
|
end++;
|
|
|
|
|
|
|
|
min = idx;
|
|
|
|
max = idx;
|
|
|
|
if (*end == '-') {
|
|
|
|
/* process single <number>-<number> */
|
|
|
|
end++;
|
|
|
|
while (isblank(*end))
|
|
|
|
end++;
|
|
|
|
if (!isdigit(*end))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
idx = strtoul(end, &end, 10);
|
|
|
|
if (errno || end == NULL || idx >= num)
|
|
|
|
return -1;
|
|
|
|
max = idx;
|
|
|
|
while (isblank(*end))
|
|
|
|
end++;
|
|
|
|
if (*end != ',' && *end != '\0')
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*end != ',' && *end != '\0' &&
|
|
|
|
*end != '@')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (idx = RTE_MIN(min, max);
|
|
|
|
idx <= RTE_MAX(min, max); idx++)
|
|
|
|
set[idx] = 1;
|
|
|
|
|
|
|
|
return end - input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* process set within bracket */
|
|
|
|
str++;
|
|
|
|
while (isblank(*str))
|
|
|
|
str++;
|
|
|
|
if (*str == '\0')
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
min = RTE_MAX_LCORE;
|
|
|
|
do {
|
|
|
|
|
|
|
|
/* go ahead to the first digit */
|
|
|
|
while (isblank(*str))
|
|
|
|
str++;
|
|
|
|
if (!isdigit(*str))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* get the digit value */
|
|
|
|
errno = 0;
|
|
|
|
idx = strtoul(str, &end, 10);
|
|
|
|
if (errno || end == NULL || idx >= num)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* go ahead to separator '-',',' and ')' */
|
|
|
|
while (isblank(*end))
|
|
|
|
end++;
|
|
|
|
if (*end == '-') {
|
|
|
|
if (min == RTE_MAX_LCORE)
|
|
|
|
min = idx;
|
|
|
|
else /* avoid continuous '-' */
|
|
|
|
return -1;
|
|
|
|
} else if ((*end == ',') || (*end == ')')) {
|
|
|
|
max = idx;
|
|
|
|
if (min == RTE_MAX_LCORE)
|
|
|
|
min = idx;
|
|
|
|
for (idx = RTE_MIN(min, max);
|
|
|
|
idx <= RTE_MAX(min, max); idx++)
|
|
|
|
set[idx] = 1;
|
|
|
|
|
|
|
|
min = RTE_MAX_LCORE;
|
|
|
|
} else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
str = end + 1;
|
|
|
|
} while (*end != '\0' && *end != ')');
|
|
|
|
|
2016-07-27 11:25:56 +00:00
|
|
|
/*
|
|
|
|
* to avoid failure that tail blank makes end character check fail
|
|
|
|
* in eal_parse_lcores( )
|
|
|
|
*/
|
|
|
|
while (isblank(*str))
|
|
|
|
str++;
|
|
|
|
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
return str - input;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* convert from set array to cpuset bitmap */
|
|
|
|
static int
|
|
|
|
convert_to_cpuset(rte_cpuset_t *cpusetp,
|
|
|
|
uint16_t *set, unsigned num)
|
|
|
|
{
|
|
|
|
unsigned idx;
|
|
|
|
|
|
|
|
CPU_ZERO(cpusetp);
|
|
|
|
|
|
|
|
for (idx = 0; idx < num; idx++) {
|
|
|
|
if (!set[idx])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!lcore_config[idx].detected) {
|
|
|
|
RTE_LOG(ERR, EAL, "core %u "
|
|
|
|
"unavailable\n", idx);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
CPU_SET(idx, cpusetp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The format pattern: --lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
|
|
|
|
* lcores, cpus could be a single digit/range or a group.
|
|
|
|
* '(' and ')' are necessary if it's a group.
|
|
|
|
* If not supply '@cpus', the value of cpus uses the same as lcores.
|
|
|
|
* e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means start 9 EAL thread as below
|
|
|
|
* lcore 0 runs on cpuset 0x41 (cpu 0,6)
|
|
|
|
* lcore 1 runs on cpuset 0x2 (cpu 1)
|
|
|
|
* lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
|
|
|
|
* lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
|
|
|
|
* lcore 6 runs on cpuset 0x41 (cpu 0,6)
|
|
|
|
* lcore 7 runs on cpuset 0x80 (cpu 7)
|
|
|
|
* lcore 8 runs on cpuset 0x100 (cpu 8)
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
eal_parse_lcores(const char *lcores)
|
|
|
|
{
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
static uint16_t set[RTE_MAX_LCORE];
|
|
|
|
unsigned idx = 0;
|
|
|
|
unsigned count = 0;
|
|
|
|
const char *lcore_start = NULL;
|
|
|
|
const char *end = NULL;
|
|
|
|
int offset;
|
|
|
|
rte_cpuset_t cpuset;
|
2016-07-27 11:23:41 +00:00
|
|
|
int lflags;
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (lcores == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Remove all blank characters ahead and after */
|
|
|
|
while (isblank(*lcores))
|
|
|
|
lcores++;
|
|
|
|
|
|
|
|
CPU_ZERO(&cpuset);
|
|
|
|
|
|
|
|
/* Reset lcore config */
|
|
|
|
for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
|
|
|
|
cfg->lcore_role[idx] = ROLE_OFF;
|
|
|
|
lcore_config[idx].core_index = -1;
|
|
|
|
CPU_ZERO(&lcore_config[idx].cpuset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get list of cores */
|
|
|
|
do {
|
|
|
|
while (isblank(*lcores))
|
|
|
|
lcores++;
|
|
|
|
if (*lcores == '\0')
|
|
|
|
goto err;
|
|
|
|
|
2016-07-27 11:23:41 +00:00
|
|
|
lflags = 0;
|
|
|
|
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
/* record lcore_set start point */
|
|
|
|
lcore_start = lcores;
|
|
|
|
|
|
|
|
/* go across a complete bracket */
|
|
|
|
if (*lcore_start == '(') {
|
|
|
|
lcores += strcspn(lcores, ")");
|
|
|
|
if (*lcores++ == '\0')
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* scan the separator '@', ','(next) or '\0'(finish) */
|
|
|
|
lcores += strcspn(lcores, "@,");
|
|
|
|
|
|
|
|
if (*lcores == '@') {
|
|
|
|
/* explicit assign cpu_set */
|
|
|
|
offset = eal_parse_set(lcores + 1, set, RTE_DIM(set));
|
|
|
|
if (offset < 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* prepare cpu_set and update the end cursor */
|
|
|
|
if (0 > convert_to_cpuset(&cpuset,
|
|
|
|
set, RTE_DIM(set)))
|
|
|
|
goto err;
|
|
|
|
end = lcores + 1 + offset;
|
|
|
|
} else { /* ',' or '\0' */
|
|
|
|
/* haven't given cpu_set, current loop done */
|
|
|
|
end = lcores;
|
|
|
|
|
|
|
|
/* go back to check <number>-<number> */
|
|
|
|
offset = strcspn(lcore_start, "(-");
|
|
|
|
if (offset < (end - lcore_start) &&
|
|
|
|
*(lcore_start + offset) != '(')
|
|
|
|
lflags = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*end != ',' && *end != '\0')
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* parse lcore_set from start point */
|
|
|
|
if (0 > eal_parse_set(lcore_start, set, RTE_DIM(set)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* without '@', by default using lcore_set as cpu_set */
|
|
|
|
if (*lcores != '@' &&
|
|
|
|
0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* start to update lcore_set */
|
|
|
|
for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
|
|
|
|
if (!set[idx])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (cfg->lcore_role[idx] != ROLE_RTE) {
|
|
|
|
lcore_config[idx].core_index = count;
|
|
|
|
cfg->lcore_role[idx] = ROLE_RTE;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lflags) {
|
|
|
|
CPU_ZERO(&cpuset);
|
|
|
|
CPU_SET(idx, &cpuset);
|
|
|
|
}
|
|
|
|
rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
|
|
|
|
sizeof(rte_cpuset_t));
|
|
|
|
}
|
|
|
|
|
|
|
|
lcores = end + 1;
|
|
|
|
} while (*end != '\0');
|
|
|
|
|
|
|
|
if (count == 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
cfg->lcore_count = count;
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
err:
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
static int
|
|
|
|
eal_parse_syslog(const char *facility, struct internal_config *conf)
|
|
|
|
{
|
|
|
|
int i;
|
2018-04-25 03:17:46 +00:00
|
|
|
static const struct {
|
2014-09-22 08:37:59 +00:00
|
|
|
const char *name;
|
|
|
|
int value;
|
|
|
|
} map[] = {
|
|
|
|
{ "auth", LOG_AUTH },
|
|
|
|
{ "cron", LOG_CRON },
|
|
|
|
{ "daemon", LOG_DAEMON },
|
|
|
|
{ "ftp", LOG_FTP },
|
|
|
|
{ "kern", LOG_KERN },
|
|
|
|
{ "lpr", LOG_LPR },
|
|
|
|
{ "mail", LOG_MAIL },
|
|
|
|
{ "news", LOG_NEWS },
|
|
|
|
{ "syslog", LOG_SYSLOG },
|
|
|
|
{ "user", LOG_USER },
|
|
|
|
{ "uucp", LOG_UUCP },
|
|
|
|
{ "local0", LOG_LOCAL0 },
|
|
|
|
{ "local1", LOG_LOCAL1 },
|
|
|
|
{ "local2", LOG_LOCAL2 },
|
|
|
|
{ "local3", LOG_LOCAL3 },
|
|
|
|
{ "local4", LOG_LOCAL4 },
|
|
|
|
{ "local5", LOG_LOCAL5 },
|
|
|
|
{ "local6", LOG_LOCAL6 },
|
|
|
|
{ "local7", LOG_LOCAL7 },
|
|
|
|
{ NULL, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
for (i = 0; map[i].name; i++) {
|
|
|
|
if (!strcmp(facility, map[i].name)) {
|
|
|
|
conf->syslog_facility = map[i].value;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-04-25 03:17:47 +00:00
|
|
|
eal_parse_log_priority(const char *level)
|
2014-09-22 08:37:59 +00:00
|
|
|
{
|
2018-04-25 03:17:47 +00:00
|
|
|
static const char * const levels[] = {
|
|
|
|
[RTE_LOG_EMERG] = "emergency",
|
|
|
|
[RTE_LOG_ALERT] = "alert",
|
|
|
|
[RTE_LOG_CRIT] = "critical",
|
|
|
|
[RTE_LOG_ERR] = "error",
|
|
|
|
[RTE_LOG_WARNING] = "warning",
|
|
|
|
[RTE_LOG_NOTICE] = "notice",
|
|
|
|
[RTE_LOG_INFO] = "info",
|
|
|
|
[RTE_LOG_DEBUG] = "debug",
|
|
|
|
};
|
|
|
|
size_t len = strlen(level);
|
2014-09-22 08:37:59 +00:00
|
|
|
unsigned long tmp;
|
2018-04-25 03:17:47 +00:00
|
|
|
char *end;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* look for named values, skip 0 which is not a valid level */
|
|
|
|
for (i = 1; i < RTE_DIM(levels); i++) {
|
|
|
|
if (strncmp(levels[i], level, len) == 0)
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not a string, maybe it is numeric */
|
|
|
|
errno = 0;
|
|
|
|
tmp = strtoul(level, &end, 0);
|
|
|
|
|
|
|
|
/* check for errors */
|
|
|
|
if (errno != 0 || end == NULL || *end != '\0' ||
|
|
|
|
tmp >= UINT32_MAX)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
eal_parse_log_level(const char *arg)
|
|
|
|
{
|
2018-04-25 03:17:49 +00:00
|
|
|
const char *pattern = NULL;
|
|
|
|
const char *regex = NULL;
|
|
|
|
char *str, *level;
|
2018-04-25 03:17:47 +00:00
|
|
|
int priority;
|
2014-09-22 08:37:59 +00:00
|
|
|
|
2017-04-04 16:40:36 +00:00
|
|
|
str = strdup(arg);
|
|
|
|
if (str == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2018-04-25 03:17:49 +00:00
|
|
|
if ((level = strchr(str, ','))) {
|
|
|
|
regex = str;
|
|
|
|
*level++ = '\0';
|
|
|
|
} else if ((level = strchr(str, ':'))) {
|
|
|
|
pattern = str;
|
|
|
|
*level++ = '\0';
|
2017-04-04 16:40:36 +00:00
|
|
|
} else {
|
2018-04-25 03:17:49 +00:00
|
|
|
level = str;
|
2017-04-04 16:40:36 +00:00
|
|
|
}
|
|
|
|
|
2018-04-25 03:17:47 +00:00
|
|
|
priority = eal_parse_log_priority(level);
|
|
|
|
if (priority < 0) {
|
|
|
|
fprintf(stderr, "invalid log priority: %s\n", level);
|
2017-04-04 16:40:36 +00:00
|
|
|
goto fail;
|
2018-04-25 03:17:47 +00:00
|
|
|
}
|
2017-04-04 16:40:36 +00:00
|
|
|
|
2018-04-25 03:17:49 +00:00
|
|
|
if (regex) {
|
|
|
|
if (rte_log_set_level_regexp(regex, priority) < 0) {
|
|
|
|
fprintf(stderr, "cannot set log level %s,%d\n",
|
|
|
|
pattern, priority);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
if (rte_log_save_regexp(regex, priority) < 0)
|
|
|
|
goto fail;
|
|
|
|
} else if (pattern) {
|
|
|
|
if (rte_log_set_level_pattern(pattern, priority) < 0) {
|
|
|
|
fprintf(stderr, "cannot set log level %s:%d\n",
|
|
|
|
pattern, priority);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
if (rte_log_save_pattern(pattern, priority) < 0)
|
|
|
|
goto fail;
|
|
|
|
} else {
|
2018-04-25 03:17:47 +00:00
|
|
|
rte_log_set_global_level(priority);
|
2017-04-04 16:40:36 +00:00
|
|
|
}
|
2014-09-22 08:37:59 +00:00
|
|
|
|
2017-04-04 16:40:36 +00:00
|
|
|
free(str);
|
2014-09-22 08:37:59 +00:00
|
|
|
return 0;
|
2017-04-04 16:40:36 +00:00
|
|
|
|
|
|
|
fail:
|
|
|
|
free(str);
|
|
|
|
return -1;
|
2014-09-22 08:37:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static enum rte_proc_type_t
|
|
|
|
eal_parse_proc_type(const char *arg)
|
|
|
|
{
|
|
|
|
if (strncasecmp(arg, "primary", sizeof("primary")) == 0)
|
|
|
|
return RTE_PROC_PRIMARY;
|
|
|
|
if (strncasecmp(arg, "secondary", sizeof("secondary")) == 0)
|
|
|
|
return RTE_PROC_SECONDARY;
|
|
|
|
if (strncasecmp(arg, "auto", sizeof("auto")) == 0)
|
|
|
|
return RTE_PROC_AUTO;
|
|
|
|
|
|
|
|
return RTE_PROC_INVALID;
|
|
|
|
}
|
|
|
|
|
2018-10-03 20:53:12 +00:00
|
|
|
static int
|
|
|
|
eal_parse_iova_mode(const char *name)
|
|
|
|
{
|
|
|
|
int mode;
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!strcmp("pa", name))
|
|
|
|
mode = RTE_IOVA_PA;
|
|
|
|
else if (!strcmp("va", name))
|
|
|
|
mode = RTE_IOVA_VA;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
internal_config.iova_mode = mode;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
int
|
2014-09-22 08:38:00 +00:00
|
|
|
eal_parse_common_option(int opt, const char *optarg,
|
2014-09-22 08:37:59 +00:00
|
|
|
struct internal_config *conf)
|
|
|
|
{
|
2017-08-02 17:10:22 +00:00
|
|
|
static int b_used;
|
|
|
|
static int w_used;
|
2019-01-17 12:13:12 +00:00
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
2017-08-02 17:10:22 +00:00
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
switch (opt) {
|
|
|
|
/* blacklist */
|
|
|
|
case 'b':
|
2017-08-02 17:10:22 +00:00
|
|
|
if (w_used)
|
|
|
|
goto bw_used;
|
|
|
|
if (eal_option_device_add(RTE_DEVTYPE_BLACKLISTED_PCI,
|
2014-09-22 08:37:59 +00:00
|
|
|
optarg) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-08-02 17:10:22 +00:00
|
|
|
b_used = 1;
|
2014-09-22 08:37:59 +00:00
|
|
|
break;
|
|
|
|
/* whitelist */
|
|
|
|
case 'w':
|
2017-08-02 17:10:22 +00:00
|
|
|
if (b_used)
|
|
|
|
goto bw_used;
|
|
|
|
if (eal_option_device_add(RTE_DEVTYPE_WHITELISTED_PCI,
|
2014-09-22 08:37:59 +00:00
|
|
|
optarg) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-08-02 17:10:22 +00:00
|
|
|
w_used = 1;
|
2014-09-22 08:37:59 +00:00
|
|
|
break;
|
|
|
|
/* coremask */
|
|
|
|
case 'c':
|
|
|
|
if (eal_parse_coremask(optarg) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid coremask\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2018-02-02 14:51:28 +00:00
|
|
|
|
|
|
|
if (core_parsed) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option -c is ignored, because (%s) is set!\n",
|
|
|
|
(core_parsed == LCORE_OPT_LST) ? "-l" :
|
|
|
|
(core_parsed == LCORE_OPT_MAP) ? "--lcore" :
|
|
|
|
"-c");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
core_parsed = LCORE_OPT_MSK;
|
2014-09-22 08:37:59 +00:00
|
|
|
break;
|
2014-06-27 14:09:32 +00:00
|
|
|
/* corelist */
|
|
|
|
case 'l':
|
|
|
|
if (eal_parse_corelist(optarg) < 0) {
|
2019-01-17 12:13:12 +00:00
|
|
|
RTE_LOG(ERR, EAL,
|
|
|
|
"invalid core list, please check core numbers are in [0, %u] range\n",
|
|
|
|
cfg->lcore_count-1);
|
2014-06-27 14:09:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2018-02-02 14:51:28 +00:00
|
|
|
|
|
|
|
if (core_parsed) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option -l is ignored, because (%s) is set!\n",
|
|
|
|
(core_parsed == LCORE_OPT_MSK) ? "-c" :
|
|
|
|
(core_parsed == LCORE_OPT_MAP) ? "--lcore" :
|
|
|
|
"-l");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
core_parsed = LCORE_OPT_LST;
|
2014-06-27 14:09:32 +00:00
|
|
|
break;
|
2017-07-11 14:19:29 +00:00
|
|
|
/* service coremask */
|
|
|
|
case 's':
|
|
|
|
if (eal_parse_service_coremask(optarg) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid service coremask\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
2017-07-17 15:21:54 +00:00
|
|
|
/* service corelist */
|
|
|
|
case 'S':
|
|
|
|
if (eal_parse_service_corelist(optarg) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid service core list\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
2014-09-22 08:37:59 +00:00
|
|
|
/* size of memory */
|
|
|
|
case 'm':
|
|
|
|
conf->memory = atoi(optarg);
|
|
|
|
conf->memory *= 1024ULL;
|
|
|
|
conf->memory *= 1024ULL;
|
2014-11-17 09:14:10 +00:00
|
|
|
mem_parsed = 1;
|
2014-09-22 08:37:59 +00:00
|
|
|
break;
|
|
|
|
/* force number of channels */
|
|
|
|
case 'n':
|
|
|
|
conf->force_nchannel = atoi(optarg);
|
2016-03-30 15:39:16 +00:00
|
|
|
if (conf->force_nchannel == 0) {
|
2014-09-22 08:37:59 +00:00
|
|
|
RTE_LOG(ERR, EAL, "invalid channel number\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
/* force number of ranks */
|
|
|
|
case 'r':
|
|
|
|
conf->force_nrank = atoi(optarg);
|
|
|
|
if (conf->force_nrank == 0 ||
|
|
|
|
conf->force_nrank > 16) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid rank number\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
2015-11-10 14:28:14 +00:00
|
|
|
/* force loading of external driver */
|
|
|
|
case 'd':
|
|
|
|
if (eal_plugin_add(optarg) == -1)
|
|
|
|
return -1;
|
|
|
|
break;
|
2014-09-22 08:37:59 +00:00
|
|
|
case 'v':
|
|
|
|
/* since message is explicitly requested by user, we
|
|
|
|
* write message at highest log level so it can always
|
|
|
|
* be seen
|
|
|
|
* even if info or warning messages are disabled */
|
|
|
|
RTE_LOG(CRIT, EAL, "RTE Version: '%s'\n", rte_version());
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* long options */
|
2015-10-28 22:04:25 +00:00
|
|
|
case OPT_HUGE_UNLINK_NUM:
|
|
|
|
conf->hugepage_unlink = 1;
|
|
|
|
break;
|
|
|
|
|
2014-09-22 08:38:00 +00:00
|
|
|
case OPT_NO_HUGE_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
conf->no_hugetlbfs = 1;
|
2018-04-11 12:30:22 +00:00
|
|
|
/* no-huge is legacy mem */
|
|
|
|
conf->legacy_mem = 1;
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_NO_PCI_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
conf->no_pci = 1;
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_NO_HPET_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
conf->no_hpet = 1;
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_VMWARE_TSC_MAP_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
conf->vmware_tsc_map = 1;
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_NO_SHCONF_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
conf->no_shconf = 1;
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
2018-07-13 12:48:03 +00:00
|
|
|
case OPT_IN_MEMORY_NUM:
|
|
|
|
conf->in_memory = 1;
|
|
|
|
/* in-memory is a superset of noshconf and huge-unlink */
|
|
|
|
conf->no_shconf = 1;
|
|
|
|
conf->hugepage_unlink = 1;
|
|
|
|
break;
|
|
|
|
|
2014-09-22 08:38:00 +00:00
|
|
|
case OPT_PROC_TYPE_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
conf->process_type = eal_parse_proc_type(optarg);
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
2014-07-08 08:28:30 +00:00
|
|
|
case OPT_MASTER_LCORE_NUM:
|
|
|
|
if (eal_parse_master_lcore(optarg) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid parameter for --"
|
|
|
|
OPT_MASTER_LCORE "\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-09-22 08:38:00 +00:00
|
|
|
case OPT_VDEV_NUM:
|
2017-08-02 17:10:22 +00:00
|
|
|
if (eal_option_device_add(RTE_DEVTYPE_VIRTUAL,
|
2014-09-22 08:38:01 +00:00
|
|
|
optarg) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_SYSLOG_NUM:
|
2014-09-22 08:38:01 +00:00
|
|
|
if (eal_parse_syslog(optarg, conf) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid parameters for --"
|
|
|
|
OPT_SYSLOG "\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-09-22 08:38:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OPT_LOG_LEVEL_NUM: {
|
2017-04-18 14:22:22 +00:00
|
|
|
if (eal_parse_log_level(optarg) < 0) {
|
2014-09-22 08:38:01 +00:00
|
|
|
RTE_LOG(ERR, EAL,
|
|
|
|
"invalid parameters for --"
|
|
|
|
OPT_LOG_LEVEL "\n");
|
|
|
|
return -1;
|
2014-09-22 08:38:00 +00:00
|
|
|
}
|
2014-09-22 08:38:01 +00:00
|
|
|
break;
|
|
|
|
}
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
case OPT_LCORES_NUM:
|
|
|
|
if (eal_parse_lcores(optarg) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid parameter for --"
|
|
|
|
OPT_LCORES "\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2018-02-02 14:51:28 +00:00
|
|
|
|
|
|
|
if (core_parsed) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option --lcore is ignored, because (%s) is set!\n",
|
|
|
|
(core_parsed == LCORE_OPT_LST) ? "-l" :
|
|
|
|
(core_parsed == LCORE_OPT_MSK) ? "-c" :
|
|
|
|
"--lcore");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
core_parsed = LCORE_OPT_MAP;
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
break;
|
2018-04-11 12:30:22 +00:00
|
|
|
case OPT_LEGACY_MEM_NUM:
|
|
|
|
conf->legacy_mem = 1;
|
|
|
|
break;
|
2018-04-11 12:30:28 +00:00
|
|
|
case OPT_SINGLE_FILE_SEGMENTS_NUM:
|
|
|
|
conf->single_file_segments = 1;
|
|
|
|
break;
|
2018-10-03 20:53:12 +00:00
|
|
|
case OPT_IOVA_MODE_NUM:
|
|
|
|
if (eal_parse_iova_mode(optarg) < 0) {
|
|
|
|
RTE_LOG(ERR, EAL, "invalid parameters for --"
|
|
|
|
OPT_IOVA_MODE "\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
2014-09-22 08:37:59 +00:00
|
|
|
|
|
|
|
/* don't know what to do, leave this to caller */
|
|
|
|
default:
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-08-02 17:10:22 +00:00
|
|
|
bw_used:
|
|
|
|
RTE_LOG(ERR, EAL, "Options blacklist (-b) and whitelist (-w) "
|
|
|
|
"cannot be used at the same time\n");
|
|
|
|
return -1;
|
2014-09-22 08:37:59 +00:00
|
|
|
}
|
|
|
|
|
2016-12-02 17:48:56 +00:00
|
|
|
static void
|
|
|
|
eal_auto_detect_cores(struct rte_config *cfg)
|
|
|
|
{
|
|
|
|
unsigned int lcore_id;
|
|
|
|
unsigned int removed = 0;
|
|
|
|
rte_cpuset_t affinity_set;
|
|
|
|
pthread_t tid = pthread_self();
|
|
|
|
|
|
|
|
if (pthread_getaffinity_np(tid, sizeof(rte_cpuset_t),
|
|
|
|
&affinity_set) < 0)
|
|
|
|
CPU_ZERO(&affinity_set);
|
|
|
|
|
|
|
|
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
|
|
|
|
if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
|
|
|
|
!CPU_ISSET(lcore_id, &affinity_set)) {
|
|
|
|
cfg->lcore_role[lcore_id] = ROLE_OFF;
|
|
|
|
removed++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg->lcore_count -= removed;
|
|
|
|
}
|
|
|
|
|
eal: fix strdup usages in internal config
Currently, we use strdup in a few places to store command-line
parameter values for certain internal config values. There are
several issues with that.
First of all, they're never freed, so memory ends up leaking
either after EAL exit, or when these command-line options are
supplied multiple times.
Second of all, they're defined as `const char *`, so they
*cannot* be freed even if we wanted to.
Finally, strdup may return NULL, which will be stored in the
config. For most fields, NULL is a valid value, but for the
default prefix, the value is always expected to be valid.
To fix all of this, three things are done. First, we change
the definitions of these values to `char *` as opposed to
`const char *`. This does not break the ABI, and previous
code assumes constness (which is more restrictive), so it's
safe to do so.
Then, fix all usages of strdup to check return value, and add
a cleanup function that will free the memory occupied by
these strings, as well as freeing them before assigning a new
value to prevent leaks when parameter is specified multiple
times.
And finally, add an internal API to query hugefile prefix, so
that, absent of a valid value, a default value will be
returned, and also fix up all usages of hugefile prefix to
use this API instead of accessing hugefile prefix directly.
Bugzilla ID: 108
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
2019-01-10 13:38:59 +00:00
|
|
|
int
|
|
|
|
eal_cleanup_config(struct internal_config *internal_cfg)
|
|
|
|
{
|
|
|
|
if (internal_cfg->hugefile_prefix != NULL)
|
|
|
|
free(internal_cfg->hugefile_prefix);
|
|
|
|
if (internal_cfg->hugepage_dir != NULL)
|
|
|
|
free(internal_cfg->hugepage_dir);
|
|
|
|
if (internal_cfg->user_mbuf_pool_ops_name != NULL)
|
|
|
|
free(internal_cfg->user_mbuf_pool_ops_name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-20 21:57:22 +00:00
|
|
|
int
|
|
|
|
eal_adjust_config(struct internal_config *internal_cfg)
|
|
|
|
{
|
|
|
|
int i;
|
2014-07-08 08:28:30 +00:00
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
2014-11-20 21:57:22 +00:00
|
|
|
|
2016-12-02 17:48:56 +00:00
|
|
|
if (!core_parsed)
|
|
|
|
eal_auto_detect_cores(cfg);
|
|
|
|
|
2014-11-20 21:57:22 +00:00
|
|
|
if (internal_config.process_type == RTE_PROC_AUTO)
|
|
|
|
internal_config.process_type = eal_proc_type_detect();
|
|
|
|
|
2014-07-08 08:28:30 +00:00
|
|
|
/* default master lcore is the first one */
|
2017-07-11 14:19:29 +00:00
|
|
|
if (!master_lcore_parsed) {
|
2014-07-08 08:28:30 +00:00
|
|
|
cfg->master_lcore = rte_get_next_lcore(-1, 0, 0);
|
2019-01-17 13:12:57 +00:00
|
|
|
if (cfg->master_lcore >= RTE_MAX_LCORE)
|
|
|
|
return -1;
|
2017-07-11 14:19:29 +00:00
|
|
|
lcore_config[cfg->master_lcore].core_role = ROLE_RTE;
|
|
|
|
}
|
2014-07-08 08:28:30 +00:00
|
|
|
|
2014-11-20 21:57:22 +00:00
|
|
|
/* if no memory amounts were requested, this will result in 0 and
|
|
|
|
* will be overridden later, right after eal_hugepage_info_init() */
|
|
|
|
for (i = 0; i < RTE_MAX_NUMA_NODES; i++)
|
|
|
|
internal_cfg->memory += internal_cfg->socket_mem[i];
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-17 09:14:10 +00:00
|
|
|
int
|
|
|
|
eal_check_common_options(struct internal_config *internal_cfg)
|
|
|
|
{
|
|
|
|
struct rte_config *cfg = rte_eal_get_configuration();
|
|
|
|
|
2014-07-08 08:28:30 +00:00
|
|
|
if (cfg->lcore_role[cfg->master_lcore] != ROLE_RTE) {
|
|
|
|
RTE_LOG(ERR, EAL, "Master lcore is not enabled for DPDK\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-11-17 09:14:10 +00:00
|
|
|
|
|
|
|
if (internal_cfg->process_type == RTE_PROC_INVALID) {
|
|
|
|
RTE_LOG(ERR, EAL, "Invalid process type specified\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2019-01-16 12:12:53 +00:00
|
|
|
if (internal_cfg->hugefile_prefix != NULL &&
|
|
|
|
strlen(internal_cfg->hugefile_prefix) < 1) {
|
|
|
|
RTE_LOG(ERR, EAL, "Invalid length of --" OPT_FILE_PREFIX " option\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (internal_cfg->hugepage_dir != NULL &&
|
|
|
|
strlen(internal_cfg->hugepage_dir) < 1) {
|
|
|
|
RTE_LOG(ERR, EAL, "Invalid length of --" OPT_HUGE_DIR" option\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (internal_cfg->user_mbuf_pool_ops_name != NULL &&
|
|
|
|
strlen(internal_cfg->user_mbuf_pool_ops_name) < 1) {
|
|
|
|
RTE_LOG(ERR, EAL, "Invalid length of --" OPT_MBUF_POOL_OPS_NAME" option\n");
|
|
|
|
return -1;
|
|
|
|
}
|
eal: fix strdup usages in internal config
Currently, we use strdup in a few places to store command-line
parameter values for certain internal config values. There are
several issues with that.
First of all, they're never freed, so memory ends up leaking
either after EAL exit, or when these command-line options are
supplied multiple times.
Second of all, they're defined as `const char *`, so they
*cannot* be freed even if we wanted to.
Finally, strdup may return NULL, which will be stored in the
config. For most fields, NULL is a valid value, but for the
default prefix, the value is always expected to be valid.
To fix all of this, three things are done. First, we change
the definitions of these values to `char *` as opposed to
`const char *`. This does not break the ABI, and previous
code assumes constness (which is more restrictive), so it's
safe to do so.
Then, fix all usages of strdup to check return value, and add
a cleanup function that will free the memory occupied by
these strings, as well as freeing them before assigning a new
value to prevent leaks when parameter is specified multiple
times.
And finally, add an internal API to query hugefile prefix, so
that, absent of a valid value, a default value will be
returned, and also fix up all usages of hugefile prefix to
use this API instead of accessing hugefile prefix directly.
Bugzilla ID: 108
Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
2019-01-10 13:38:59 +00:00
|
|
|
if (index(eal_get_hugefile_prefix(), '%') != NULL) {
|
2014-11-17 09:14:10 +00:00
|
|
|
RTE_LOG(ERR, EAL, "Invalid char, '%%', in --"OPT_FILE_PREFIX" "
|
|
|
|
"option\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (mem_parsed && internal_cfg->force_sockets == 1) {
|
|
|
|
RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot "
|
|
|
|
"be specified at the same time\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2015-05-27 09:30:16 +00:00
|
|
|
if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot "
|
2014-11-17 09:14:10 +00:00
|
|
|
"be specified together with --"OPT_NO_HUGE"\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2018-07-13 12:48:03 +00:00
|
|
|
if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink &&
|
|
|
|
!internal_cfg->in_memory) {
|
2015-10-28 22:04:25 +00:00
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot "
|
|
|
|
"be specified together with --"OPT_NO_HUGE"\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2018-05-31 17:35:33 +00:00
|
|
|
if (internal_config.force_socket_limits && internal_config.legacy_mem) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_LIMIT
|
|
|
|
" is only supported in non-legacy memory mode\n");
|
|
|
|
}
|
2018-07-13 12:48:02 +00:00
|
|
|
if (internal_cfg->single_file_segments &&
|
2018-09-04 15:15:50 +00:00
|
|
|
internal_cfg->hugepage_unlink &&
|
|
|
|
!internal_cfg->in_memory) {
|
2018-07-13 12:48:02 +00:00
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_SINGLE_FILE_SEGMENTS" is "
|
2018-09-04 15:15:50 +00:00
|
|
|
"not compatible with --"OPT_HUGE_UNLINK"\n");
|
2018-07-13 12:48:02 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2018-09-04 15:15:43 +00:00
|
|
|
if (internal_cfg->legacy_mem &&
|
|
|
|
internal_cfg->in_memory) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible "
|
|
|
|
"with --"OPT_IN_MEMORY"\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2018-12-14 17:13:03 +00:00
|
|
|
if (internal_cfg->legacy_mem && internal_cfg->match_allocations) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible "
|
|
|
|
"with --"OPT_MATCH_ALLOCATIONS"\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (internal_cfg->no_hugetlbfs && internal_cfg->match_allocations) {
|
|
|
|
RTE_LOG(ERR, EAL, "Option --"OPT_NO_HUGE" is not compatible "
|
|
|
|
"with --"OPT_MATCH_ALLOCATIONS"\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2015-10-28 22:04:25 +00:00
|
|
|
|
2014-11-17 09:14:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-22 08:37:59 +00:00
|
|
|
void
|
|
|
|
eal_common_usage(void)
|
|
|
|
{
|
2015-09-25 20:37:16 +00:00
|
|
|
printf("[options]\n\n"
|
2014-09-22 08:37:59 +00:00
|
|
|
"EAL common options:\n"
|
2015-01-29 16:42:31 +00:00
|
|
|
" -c COREMASK Hexadecimal bitmask of cores to run on\n"
|
|
|
|
" -l CORELIST List of cores to run on\n"
|
|
|
|
" The argument format is <c1>[-c2][,c3[-c4],...]\n"
|
|
|
|
" where c1, c2, etc are core indexes between 0 and %d\n"
|
eal: new option --lcores for cpu assignment
It supports one new eal long option '--lcores' for EAL thread cpuset assignment.
The format pattern:
--lcores='<lcores[@cpus]>[<,lcores[@cpus]>...]'
lcores, cpus could be a single digit/range or a group.
'(' and ')' are necessary if it's a group.
If not supply '@cpus', the value of cpus uses the same as lcores.
e.g. '1,2@(5-7),(3-5)@(0,2),(0,6),7-8' means starting 9 EAL thread as below
lcore 0 runs on cpuset 0x41 (cpu 0,6)
lcore 1 runs on cpuset 0x2 (cpu 1)
lcore 2 runs on cpuset 0xe0 (cpu 5,6,7)
lcore 3,4,5 runs on cpuset 0x5 (cpu 0,2)
lcore 6 runs on cpuset 0x41 (cpu 0,6)
lcore 7 runs on cpuset 0x80 (cpu 7)
lcore 8 runs on cpuset 0x100 (cpu 8)
Test report: http://dpdk.org/ml/archives/dev/2015-February/013383.html
Signed-off-by: Cunming Liang <cunming.liang@intel.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
Tested-by: Qun Wan <qun.wan@intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
2015-02-17 02:08:00 +00:00
|
|
|
" --"OPT_LCORES" COREMAP Map lcore set to physical cpu set\n"
|
|
|
|
" The argument format is\n"
|
|
|
|
" '<lcores[@cpus]>[<,lcores[@cpus]>...]'\n"
|
|
|
|
" lcores and cpus list are grouped by '(' and ')'\n"
|
|
|
|
" Within the group, '-' is used for range separator,\n"
|
|
|
|
" ',' is used for single number separator.\n"
|
|
|
|
" '( )' can be omitted for single element group,\n"
|
|
|
|
" '@' can be omitted if cpus and lcores have the same value\n"
|
2017-07-11 14:19:29 +00:00
|
|
|
" -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores\n"
|
2015-01-29 16:42:31 +00:00
|
|
|
" --"OPT_MASTER_LCORE" ID Core ID that is used as master\n"
|
2017-10-06 07:45:29 +00:00
|
|
|
" --"OPT_MBUF_POOL_OPS_NAME" Pool ops name for mbuf to use\n"
|
2015-01-29 16:42:31 +00:00
|
|
|
" -n CHANNELS Number of memory channels\n"
|
|
|
|
" -m MB Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
|
|
|
|
" -r RANKS Force number of memory ranks (don't detect)\n"
|
|
|
|
" -b, --"OPT_PCI_BLACKLIST" Add a PCI device in black list.\n"
|
|
|
|
" Prevent EAL from using this PCI device. The argument\n"
|
|
|
|
" format is <domain:bus:devid.func>.\n"
|
|
|
|
" -w, --"OPT_PCI_WHITELIST" Add a PCI device in white list.\n"
|
|
|
|
" Only use the specified PCI devices. The argument format\n"
|
|
|
|
" is <[domain:]bus:devid.func>. This option can be present\n"
|
|
|
|
" several times (once per device).\n"
|
|
|
|
" [NOTE: PCI whitelist cannot be used with -b option]\n"
|
|
|
|
" --"OPT_VDEV" Add a virtual device.\n"
|
|
|
|
" The argument format is <driver><id>[,key=val,...]\n"
|
2016-10-06 10:34:22 +00:00
|
|
|
" (ex: --vdev=net_pcap0,iface=eth2).\n"
|
2018-10-03 20:53:12 +00:00
|
|
|
" --"OPT_IOVA_MODE" Set IOVA mode. 'pa' for IOVA_PA\n"
|
|
|
|
" 'va' for IOVA_VA\n"
|
2015-11-10 14:28:15 +00:00
|
|
|
" -d LIB.so|DIR Add a driver or driver directory\n"
|
|
|
|
" (can be used multiple times)\n"
|
2015-01-29 16:42:31 +00:00
|
|
|
" --"OPT_VMWARE_TSC_MAP" Use VMware TSC map instead of native RDTSC\n"
|
|
|
|
" --"OPT_PROC_TYPE" Type of this process (primary|secondary|auto)\n"
|
|
|
|
" --"OPT_SYSLOG" Set syslog facility\n"
|
2017-04-04 16:40:36 +00:00
|
|
|
" --"OPT_LOG_LEVEL"=<int> Set global log level\n"
|
2018-04-25 03:17:49 +00:00
|
|
|
" --"OPT_LOG_LEVEL"=<type-match>:<int>\n"
|
2017-04-04 16:40:36 +00:00
|
|
|
" Set specific log level\n"
|
2015-01-29 16:42:31 +00:00
|
|
|
" -v Display version information on startup\n"
|
2015-01-29 16:51:17 +00:00
|
|
|
" -h, --help This help\n"
|
2018-07-13 12:48:03 +00:00
|
|
|
" --"OPT_IN_MEMORY" Operate entirely in memory. This will\n"
|
|
|
|
" disable secondary process support\n"
|
2014-09-22 08:37:59 +00:00
|
|
|
"\nEAL options for DEBUG use only:\n"
|
2015-10-28 22:04:25 +00:00
|
|
|
" --"OPT_HUGE_UNLINK" Unlink hugepage files after init\n"
|
2015-01-29 16:42:31 +00:00
|
|
|
" --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n"
|
|
|
|
" --"OPT_NO_PCI" Disable PCI\n"
|
|
|
|
" --"OPT_NO_HPET" Disable HPET\n"
|
|
|
|
" --"OPT_NO_SHCONF" No shared config (mmap'd files)\n"
|
2014-06-27 14:09:32 +00:00
|
|
|
"\n", RTE_MAX_LCORE);
|
2018-12-20 17:06:42 +00:00
|
|
|
rte_option_usage();
|
2014-09-22 08:37:59 +00:00
|
|
|
}
|