#include <sys/stat.h>
#include <dirent.h>
+#include <rte_string_fns.h>
#include <rte_eal.h>
#include <rte_log.h>
#include <rte_lcore.h>
+#include <rte_memory.h>
#include <rte_tailq.h>
#include <rte_version.h>
#include <rte_devargs.h>
}
devopt->type = type;
- ret = snprintf(devopt->arg, optlen, "%s", optarg);
+ ret = strlcpy(devopt->arg, optarg, optlen);
if (ret < 0) {
RTE_LOG(ERR, EAL, "Unable to copy device option\n");
free(devopt);
internal_cfg->create_uio_dev = 0;
internal_cfg->iova_mode = RTE_IOVA_DC;
internal_cfg->user_mbuf_pool_ops_name = NULL;
+ CPU_ZERO(&internal_cfg->ctrl_cpuset);
internal_cfg->init_complete = 0;
}
while ((dent = readdir(d)) != NULL) {
struct stat sb;
- snprintf(sopath, PATH_MAX-1, "%s/%s", path, dent->d_name);
- sopath[PATH_MAX-1] = 0;
+ snprintf(sopath, sizeof(sopath), "%s/%s", path, dent->d_name);
if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
continue;
return -1;
}
- if (!lcore_config[idx].detected) {
+ if (eal_cpu_detected(idx) == 0) {
RTE_LOG(ERR, EAL,
"lcore %u unavailable\n", idx);
return -1;
}
static int
-eal_parse_coremask(const char *coremask)
+update_lcore_config(int *cores)
{
struct rte_config *cfg = rte_eal_get_configuration();
- int i, j, idx = 0;
+ unsigned int count = 0;
+ unsigned int i;
+ int ret = 0;
+
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
+ if (cores[i] != -1) {
+ if (eal_cpu_detected(i) == 0) {
+ RTE_LOG(ERR, EAL, "lcore %u unavailable\n", i);
+ ret = -1;
+ continue;
+ }
+ cfg->lcore_role[i] = ROLE_RTE;
+ count++;
+ } else {
+ cfg->lcore_role[i] = ROLE_OFF;
+ }
+ lcore_config[i].core_index = cores[i];
+ }
+ if (!ret)
+ cfg->lcore_count = count;
+ return ret;
+}
+
+static int
+eal_parse_coremask(const char *coremask, int *cores)
+{
unsigned count = 0;
- char c;
+ int i, j, idx;
int val;
+ char c;
- if (eal_service_cores_parsed())
- RTE_LOG(WARNING, EAL,
- "Service cores parsed before dataplane cores. "
- "Please ensure -c is before -s or -S\n");
+ for (idx = 0; idx < RTE_MAX_LCORE; idx++)
+ cores[idx] = -1;
+ idx = 0;
- if (coremask == NULL)
- return -1;
/* Remove all blank characters ahead and after .
* Remove 0x/0X if exists.
*/
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;
- }
-
- cfg->lcore_role[idx] = ROLE_RTE;
- lcore_config[idx].core_index = count;
+ cores[idx] = count;
count++;
- } else {
- cfg->lcore_role[idx] = ROLE_OFF;
- lcore_config[idx].core_index = -1;
}
}
}
for (; i >= 0; i--)
if (coremask[i] != '0')
return -1;
- for (; idx < RTE_MAX_LCORE; idx++) {
- cfg->lcore_role[idx] = ROLE_OFF;
- lcore_config[idx].core_index = -1;
- }
if (count == 0)
return -1;
- /* Update the count of enabled logical cores of the EAL configuration */
- cfg->lcore_count = count;
return 0;
}
}
static int
-eal_parse_corelist(const char *corelist)
+eal_parse_corelist(const char *corelist, int *cores)
{
- struct rte_config *cfg = rte_eal_get_configuration();
- int i, idx = 0;
unsigned count = 0;
char *end = NULL;
int min, max;
+ int idx;
- if (eal_service_cores_parsed())
- RTE_LOG(WARNING, EAL,
- "Service cores parsed before dataplane cores. "
- "Please ensure -l is before -s or -S\n");
-
- if (corelist == NULL)
- return -1;
+ for (idx = 0; idx < RTE_MAX_LCORE; idx++)
+ cores[idx] = -1;
- /* Remove all blank characters ahead and after */
+ /* Remove all blank characters ahead */
while (isblank(*corelist))
corelist++;
- i = strlen(corelist);
- while ((i > 0) && isblank(corelist[i - 1]))
- i--;
-
- /* Reset config */
- for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
- cfg->lcore_role[idx] = ROLE_OFF;
- lcore_config[idx].core_index = -1;
- }
/* Get list of cores */
min = RTE_MAX_LCORE;
return -1;
errno = 0;
idx = strtol(corelist, &end, 10);
- if (idx < 0 || idx >= (int)cfg->lcore_count)
- return -1;
if (errno || end == NULL)
return -1;
+ if (idx < 0 || idx >= RTE_MAX_LCORE)
+ return -1;
while (isblank(*end))
end++;
if (*end == '-') {
if (min == RTE_MAX_LCORE)
min = idx;
for (idx = min; idx <= max; idx++) {
- if (cfg->lcore_role[idx] != ROLE_RTE) {
- cfg->lcore_role[idx] = ROLE_RTE;
- lcore_config[idx].core_index = count;
+ if (cores[idx] == -1) {
+ cores[idx] = count;
count++;
}
}
if (count == 0)
return -1;
-
- /* Update the count of enabled logical cores of the EAL configuration */
- cfg->lcore_count = count;
-
return 0;
}
if (!set[idx])
continue;
- if (!lcore_config[idx].detected) {
+ if (eal_cpu_detected(idx) == 0) {
RTE_LOG(ERR, EAL, "core %u "
"unavailable\n", idx);
return -1;
return 0;
}
+static int
+eal_parse_base_virtaddr(const char *arg)
+{
+ char *end;
+ uint64_t addr;
+
+ errno = 0;
+ addr = strtoull(arg, &end, 16);
+
+ /* check for errors */
+ if ((errno != 0) || (arg[0] == '\0') || end == NULL || (*end != '\0'))
+ return -1;
+
+ /* make sure we don't exceed 32-bit boundary on 32-bit target */
+#ifndef RTE_ARCH_64
+ if (addr >= UINTPTR_MAX)
+ return -1;
+#endif
+
+ /* align the addr on 16M boundary, 16MB is the minimum huge page
+ * size on IBM Power architecture. If the addr is aligned to 16MB,
+ * it can align to 2MB for x86. So this alignment can also be used
+ * on x86 and other architectures.
+ */
+ internal_config.base_virtaddr =
+ RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M);
+
+ return 0;
+}
+
+/* caller is responsible for freeing the returned string */
+static char *
+available_cores(void)
+{
+ char *str = NULL;
+ int previous;
+ int sequence;
+ char *tmp;
+ int idx;
+
+ /* find the first available cpu */
+ for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
+ if (eal_cpu_detected(idx) == 0)
+ continue;
+ break;
+ }
+ if (idx >= RTE_MAX_LCORE)
+ return NULL;
+
+ /* first sequence */
+ if (asprintf(&str, "%d", idx) < 0)
+ return NULL;
+ previous = idx;
+ sequence = 0;
+
+ for (idx++ ; idx < RTE_MAX_LCORE; idx++) {
+ if (eal_cpu_detected(idx) == 0)
+ continue;
+
+ if (idx == previous + 1) {
+ previous = idx;
+ sequence = 1;
+ continue;
+ }
+
+ /* finish current sequence */
+ if (sequence) {
+ if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
+ free(str);
+ return NULL;
+ }
+ free(str);
+ str = tmp;
+ }
+
+ /* new sequence */
+ if (asprintf(&tmp, "%s,%d", str, idx) < 0) {
+ free(str);
+ return NULL;
+ }
+ free(str);
+ str = tmp;
+ previous = idx;
+ sequence = 0;
+ }
+
+ /* finish last sequence */
+ if (sequence) {
+ if (asprintf(&tmp, "%s-%d", str, previous) < 0) {
+ free(str);
+ return NULL;
+ }
+ free(str);
+ str = tmp;
+ }
+
+ return str;
+}
+
int
eal_parse_common_option(int opt, const char *optarg,
struct internal_config *conf)
{
static int b_used;
static int w_used;
- struct rte_config *cfg = rte_eal_get_configuration();
switch (opt) {
/* blacklist */
w_used = 1;
break;
/* coremask */
- case 'c':
- if (eal_parse_coremask(optarg) < 0) {
- RTE_LOG(ERR, EAL, "invalid coremask\n");
+ case 'c': {
+ int lcore_indexes[RTE_MAX_LCORE];
+
+ if (eal_service_cores_parsed())
+ RTE_LOG(WARNING, EAL,
+ "Service cores parsed before dataplane cores. Please ensure -c is before -s or -S\n");
+ if (eal_parse_coremask(optarg, lcore_indexes) < 0) {
+ RTE_LOG(ERR, EAL, "invalid coremask syntax\n");
+ return -1;
+ }
+ if (update_lcore_config(lcore_indexes) < 0) {
+ char *available = available_cores();
+
+ RTE_LOG(ERR, EAL,
+ "invalid coremask, please check specified cores are part of %s\n",
+ available);
+ free(available);
return -1;
}
core_parsed = LCORE_OPT_MSK;
break;
+ }
/* corelist */
- case 'l':
- if (eal_parse_corelist(optarg) < 0) {
+ case 'l': {
+ int lcore_indexes[RTE_MAX_LCORE];
+
+ if (eal_service_cores_parsed())
+ RTE_LOG(WARNING, EAL,
+ "Service cores parsed before dataplane cores. Please ensure -l is before -s or -S\n");
+
+ if (eal_parse_corelist(optarg, lcore_indexes) < 0) {
+ RTE_LOG(ERR, EAL, "invalid core list syntax\n");
+ return -1;
+ }
+ if (update_lcore_config(lcore_indexes) < 0) {
+ char *available = available_cores();
+
RTE_LOG(ERR, EAL,
- "invalid core list, please check core numbers are in [0, %u] range\n",
- cfg->lcore_count-1);
+ "invalid core list, please check specified cores are part of %s\n",
+ available);
+ free(available);
return -1;
}
core_parsed = LCORE_OPT_LST;
break;
+ }
/* service coremask */
case 's':
if (eal_parse_service_coremask(optarg) < 0) {
return -1;
}
break;
+ case OPT_BASE_VIRTADDR_NUM:
+ if (eal_parse_base_virtaddr(optarg) < 0) {
+ RTE_LOG(ERR, EAL, "invalid parameter for --"
+ OPT_BASE_VIRTADDR "\n");
+ return -1;
+ }
+ break;
/* don't know what to do, leave this to caller */
default:
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)
+ if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+ &affinity_set))
CPU_ZERO(&affinity_set);
for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
cfg->lcore_count -= removed;
}
+static void
+compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
+{
+ rte_cpuset_t *cpuset = &internal_cfg->ctrl_cpuset;
+ rte_cpuset_t default_set;
+ unsigned int lcore_id;
+
+ for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+ if (rte_lcore_has_role(lcore_id, ROLE_OFF))
+ continue;
+ RTE_CPU_OR(cpuset, cpuset, &lcore_config[lcore_id].cpuset);
+ }
+ RTE_CPU_NOT(cpuset, cpuset);
+
+ if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
+ &default_set))
+ CPU_ZERO(&default_set);
+
+ RTE_CPU_AND(cpuset, cpuset, &default_set);
+
+ /* if no remaining cpu, use master lcore cpu affinity */
+ if (!CPU_COUNT(cpuset)) {
+ memcpy(cpuset, &lcore_config[rte_get_master_lcore()].cpuset,
+ sizeof(*cpuset));
+ }
+}
+
int
eal_cleanup_config(struct internal_config *internal_cfg)
{
lcore_config[cfg->master_lcore].core_role = ROLE_RTE;
}
+ compute_ctrl_threads_cpuset(internal_cfg);
+
/* 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++)
"with --"OPT_MATCH_ALLOCATIONS"\n");
return -1;
}
+ if (internal_cfg->legacy_mem && internal_cfg->memory == 0) {
+ RTE_LOG(NOTICE, EAL, "Static memory layout is selected, "
+ "amount of reserved memory can be adjusted with "
+ "-m or --"OPT_SOCKET_MEM"\n");
+ }
return 0;
}
" -h, --help This help\n"
" --"OPT_IN_MEMORY" Operate entirely in memory. This will\n"
" disable secondary process support\n"
+ " --"OPT_BASE_VIRTADDR" Base virtual address\n"
"\nEAL options for DEBUG use only:\n"
" --"OPT_HUGE_UNLINK" Unlink hugepage files after init\n"
" --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n"