X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Feal%2Fcommon%2Feal_common_options.c;h=f247a42455122195aad29956b2109ab067c6a3c4;hb=ec487c189686ee9b3b7551d3aca138cec3f91e74;hp=6ecf5fd6603ccff50c385c6e857059c7f0c8cff1;hpb=7df485eb3d56fbe5e6fcd160d33ca971bc3d3572;p=dpdk.git diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c index 6ecf5fd660..f247a42455 100644 --- a/lib/eal/common/eal_common_options.c +++ b/lib/eal/common/eal_common_options.c @@ -4,7 +4,6 @@ */ #include -#include #include #ifndef RTE_EXEC_ENV_WINDOWS #include @@ -17,7 +16,6 @@ #include #include #endif -#include #include #ifndef RTE_EXEC_ENV_WINDOWS #include @@ -74,7 +72,7 @@ eal_long_options[] = { {OPT_FILE_PREFIX, 1, NULL, OPT_FILE_PREFIX_NUM }, {OPT_HELP, 0, NULL, OPT_HELP_NUM }, {OPT_HUGE_DIR, 1, NULL, OPT_HUGE_DIR_NUM }, - {OPT_HUGE_UNLINK, 0, NULL, OPT_HUGE_UNLINK_NUM }, + {OPT_HUGE_UNLINK, 2, NULL, OPT_HUGE_UNLINK_NUM }, {OPT_IOVA_MODE, 1, NULL, OPT_IOVA_MODE_NUM }, {OPT_LCORES, 1, NULL, OPT_LCORES_NUM }, {OPT_LOG_LEVEL, 1, NULL, OPT_LOG_LEVEL_NUM }, @@ -223,9 +221,9 @@ eal_save_args(int argc, char **argv) return -1; for (i = 0; i < argc; i++) { - eal_args[i] = strdup(argv[i]); if (strcmp(argv[i], "--") == 0) break; + eal_args[i] = strdup(argv[i]); } eal_args[i++] = NULL; /* always finish with NULL */ @@ -277,7 +275,7 @@ eal_option_device_parse(void) void *tmp; int ret = 0; - TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) { + RTE_TAILQ_FOREACH_SAFE(devopt, &devopt_list, next, tmp) { if (ret == 0) { ret = rte_devargs_add(devopt->type, devopt->arg); if (ret) @@ -311,6 +309,8 @@ eal_reset_internal_config(struct internal_config *internal_cfg) internal_cfg->force_nchannel = 0; internal_cfg->hugefile_prefix = NULL; internal_cfg->hugepage_dir = NULL; + internal_cfg->hugepage_file.unlink_before_mapping = false; + internal_cfg->hugepage_file.unlink_existing = true; internal_cfg->force_sockets = 0; /* zero out the NUMA config */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) @@ -703,10 +703,50 @@ update_lcore_config(int *cores) return ret; } +static int +check_core_list(int *lcores, unsigned int count) +{ + char lcorestr[RTE_MAX_LCORE * 10]; + bool overflow = false; + int len = 0, ret; + unsigned int i; + + for (i = 0; i < count; i++) { + if (lcores[i] < RTE_MAX_LCORE) + continue; + + RTE_LOG(ERR, EAL, "lcore %d >= RTE_MAX_LCORE (%d)\n", + lcores[i], RTE_MAX_LCORE); + overflow = true; + } + if (!overflow) + return 0; + + /* + * We've encountered a core that's greater than RTE_MAX_LCORE, + * suggest using --lcores option to map lcores onto physical cores + * greater than RTE_MAX_LCORE. + */ + for (i = 0; i < count; i++) { + ret = snprintf(&lcorestr[len], sizeof(lcorestr) - len, + "%d@%d,", i, lcores[i]); + if (ret > 0) + len = len + ret; + } + if (len > 0) + lcorestr[len - 1] = 0; + RTE_LOG(ERR, EAL, "To use high physical core ids, " + "please use --lcores to map them to lcore ids below RTE_MAX_LCORE, " + "e.g. --lcores %s\n", lcorestr); + return -1; +} + static int eal_parse_coremask(const char *coremask, int *cores) { - unsigned count = 0; + const char *coremask_orig = coremask; + int lcores[RTE_MAX_LCORE]; + unsigned int count = 0; int i, j, idx; int val; char c; @@ -726,29 +766,52 @@ eal_parse_coremask(const char *coremask, int *cores) i = strlen(coremask); while ((i > 0) && isblank(coremask[i - 1])) i--; - if (i == 0) + if (i == 0) { + RTE_LOG(ERR, EAL, "No lcores in coremask: [%s]\n", + coremask_orig); return -1; + } - for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) { + for (i = i - 1; i >= 0; i--) { c = coremask[i]; if (isxdigit(c) == 0) { /* invalid characters */ + RTE_LOG(ERR, EAL, "invalid characters in coremask: [%s]\n", + coremask_orig); return -1; } val = xdigit2val(c); - for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE; j++, idx++) + for (j = 0; j < BITS_PER_HEX; j++, idx++) { if ((1 << j) & val) { - cores[idx] = count; - count++; + if (count >= RTE_MAX_LCORE) { + RTE_LOG(ERR, EAL, "Too many lcores provided. Cannot exceed RTE_MAX_LCORE (%d)\n", + RTE_MAX_LCORE); + return -1; + } + lcores[count++] = idx; } } } - for (; i >= 0; i--) - if (coremask[i] != '0') - return -1; - if (count == 0) + if (count == 0) { + RTE_LOG(ERR, EAL, "No lcores in coremask: [%s]\n", + coremask_orig); + return -1; + } + + if (check_core_list(lcores, count)) return -1; + + /* + * Now that we've got a list of cores no longer than RTE_MAX_LCORE, + * and no lcore in that list is greater than RTE_MAX_LCORE, populate + * the cores array. + */ + do { + count--; + cores[lcores[count]] = count; + } while (count != 0); + return 0; } @@ -833,7 +896,8 @@ eal_parse_service_corelist(const char *corelist) static int eal_parse_corelist(const char *corelist, int *cores) { - unsigned count = 0; + unsigned int count = 0, i; + int lcores[RTE_MAX_LCORE]; char *end = NULL; int min, max; int idx; @@ -846,7 +910,7 @@ eal_parse_corelist(const char *corelist, int *cores) corelist++; /* Get list of cores */ - min = RTE_MAX_LCORE; + min = -1; do { while (isblank(*corelist)) corelist++; @@ -856,7 +920,7 @@ eal_parse_corelist(const char *corelist, int *cores) idx = strtol(corelist, &end, 10); if (errno || end == NULL) return -1; - if (idx < 0 || idx >= RTE_MAX_LCORE) + if (idx < 0) return -1; while (isblank(*end)) end++; @@ -864,15 +928,26 @@ eal_parse_corelist(const char *corelist, int *cores) min = idx; } else if ((*end == ',') || (*end == '\0')) { max = idx; - if (min == RTE_MAX_LCORE) + if (min == -1) min = idx; for (idx = min; idx <= max; idx++) { - if (cores[idx] == -1) { - cores[idx] = count; - count++; + bool dup = false; + + /* Check if this idx is already present */ + for (i = 0; i < count; i++) { + if (lcores[i] == idx) + dup = true; + } + if (dup) + continue; + if (count >= RTE_MAX_LCORE) { + RTE_LOG(ERR, EAL, "Too many lcores provided. Cannot exceed RTE_MAX_LCORE (%d)\n", + RTE_MAX_LCORE); + return -1; } + lcores[count++] = idx; } - min = RTE_MAX_LCORE; + min = -1; } else return -1; corelist = end + 1; @@ -880,6 +955,20 @@ eal_parse_corelist(const char *corelist, int *cores) if (count == 0) return -1; + + if (check_core_list(lcores, count)) + return -1; + + /* + * Now that we've got a list of cores no longer than RTE_MAX_LCORE, + * and no lcore in that list is greater than RTE_MAX_LCORE, populate + * the cores array. + */ + do { + count--; + cores[lcores[count]] = count; + } while (count != 0); + return 0; } @@ -1507,6 +1596,28 @@ available_cores(void) return str; } +#define HUGE_UNLINK_NEVER "never" + +static int +eal_parse_huge_unlink(const char *arg, struct hugepage_file_discipline *out) +{ + if (arg == NULL || strcmp(arg, "always") == 0) { + out->unlink_before_mapping = true; + return 0; + } + if (strcmp(arg, "existing") == 0) { + /* same as not specifying the option */ + return 0; + } + if (strcmp(arg, HUGE_UNLINK_NEVER) == 0) { + RTE_LOG(WARNING, EAL, "Using --"OPT_HUGE_UNLINK"=" + HUGE_UNLINK_NEVER" may create data leaks.\n"); + out->unlink_existing = false; + return 0; + } + return -1; +} + int eal_parse_common_option(int opt, const char *optarg, struct internal_config *conf) @@ -1648,7 +1759,10 @@ eal_parse_common_option(int opt, const char *optarg, /* long options */ case OPT_HUGE_UNLINK_NUM: - conf->hugepage_unlink = 1; + if (eal_parse_huge_unlink(optarg, &conf->hugepage_file) < 0) { + RTE_LOG(ERR, EAL, "invalid --"OPT_HUGE_UNLINK" option\n"); + return -1; + } break; case OPT_NO_HUGE_NUM: @@ -1677,7 +1791,7 @@ eal_parse_common_option(int opt, const char *optarg, conf->in_memory = 1; /* in-memory is a superset of noshconf and huge-unlink */ conf->no_shconf = 1; - conf->hugepage_unlink = 1; + conf->hugepage_file.unlink_before_mapping = true; break; case OPT_PROC_TYPE_NUM: @@ -1873,12 +1987,9 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg) 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); + free(internal_cfg->hugefile_prefix); + free(internal_cfg->hugepage_dir); + free(internal_cfg->user_mbuf_pool_ops_name); return 0; } @@ -1961,7 +2072,8 @@ eal_check_common_options(struct internal_config *internal_cfg) "be specified together with --"OPT_NO_HUGE"\n"); return -1; } - if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink && + if (internal_cfg->no_hugetlbfs && + internal_cfg->hugepage_file.unlink_before_mapping && !internal_cfg->in_memory) { RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot " "be specified together with --"OPT_NO_HUGE"\n"); @@ -1972,12 +2084,18 @@ eal_check_common_options(struct internal_config *internal_cfg) " is only supported in non-legacy memory mode\n"); } if (internal_cfg->single_file_segments && - internal_cfg->hugepage_unlink && + internal_cfg->hugepage_file.unlink_before_mapping && !internal_cfg->in_memory) { RTE_LOG(ERR, EAL, "Option --"OPT_SINGLE_FILE_SEGMENTS" is " "not compatible with --"OPT_HUGE_UNLINK"\n"); return -1; } + if (!internal_cfg->hugepage_file.unlink_existing && + internal_cfg->in_memory) { + RTE_LOG(ERR, EAL, "Option --"OPT_IN_MEMORY" is not compatible " + "with --"OPT_HUGE_UNLINK"="HUGE_UNLINK_NEVER"\n"); + return -1; + } if (internal_cfg->legacy_mem && internal_cfg->in_memory) { RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible " @@ -2110,7 +2228,9 @@ eal_common_usage(void) " --"OPT_NO_TELEMETRY" Disable telemetry support\n" " --"OPT_FORCE_MAX_SIMD_BITWIDTH" Force the max SIMD bitwidth\n" "\nEAL options for DEBUG use only:\n" - " --"OPT_HUGE_UNLINK" Unlink hugepage files after init\n" + " --"OPT_HUGE_UNLINK"[=existing|always|never]\n" + " When to unlink files in hugetlbfs\n" + " ('existing' by default, no value means 'always')\n" " --"OPT_NO_HUGE" Use malloc instead of hugetlbfs\n" " --"OPT_NO_PCI" Disable PCI\n" " --"OPT_NO_HPET" Disable HPET\n"