From 359d54d7a384c12e0b4d0514939d082138163905 Mon Sep 17 00:00:00 2001 From: wuchangsheng Date: Sat, 25 Dec 2021 15:54:12 +0800 Subject: [PATCH] 7 --- config/rte_config.h | 3 +- lib/eal/common/eal_common_config.c | 43 +++++- lib/eal/common/eal_common_dynmem.c | 67 +++++++- lib/eal/common/eal_common_fbarray.c | 106 +++++++++++-- lib/eal/common/eal_common_memory.c | 90 +++++++++-- lib/eal/common/eal_common_options.c | 179 +++++++++++++--------- lib/eal/common/eal_filesystem.h | 58 ++++++- lib/eal/common/eal_internal_cfg.h | 4 +- lib/eal/common/eal_memalloc.h | 7 + lib/eal/common/eal_options.h | 11 +- lib/eal/common/eal_private.h | 27 +++- lib/eal/include/rte_eal.h | 10 +- lib/eal/include/rte_fbarray.h | 6 + lib/eal/include/rte_memory.h | 20 ++- lib/eal/linux/eal.c | 230 +++++++++++++++++++++++++--- lib/eal/linux/eal_hugepage_info.c | 2 +- lib/eal/linux/eal_memalloc.c | 128 +++++++++++++--- lib/eal/linux/eal_memory.c | 104 ++++++++++--- lib/ring/rte_ring.h | 75 +++++++++ 19 files changed, 978 insertions(+), 192 deletions(-) diff --git a/config/rte_config.h b/config/rte_config.h index cab4390a97..d2f192ee9b 100644 --- a/config/rte_config.h +++ b/config/rte_config.h @@ -34,7 +34,8 @@ #define RTE_MAX_MEM_MB_PER_LIST 32768 #define RTE_MAX_MEMSEG_PER_TYPE 32768 #define RTE_MAX_MEM_MB_PER_TYPE 65536 -#define RTE_MAX_MEMZONE 2560 +#define RTE_MAX_MEMZONE 65535 +#define RTE_MAX_SECONDARY 256 #define RTE_MAX_TAILQ 32 #define RTE_LOG_DP_LEVEL RTE_LOG_INFO #define RTE_BACKTRACE 1 diff --git a/lib/eal/common/eal_common_config.c b/lib/eal/common/eal_common_config.c index 1c4c4dd585..fe3db184b7 100644 --- a/lib/eal/common/eal_common_config.c +++ b/lib/eal/common/eal_common_config.c @@ -22,18 +22,29 @@ static char runtime_dir[PATH_MAX]; /* internal configuration */ static struct internal_config internal_config; -const char * +/****** APIs for libnet ******/ +static char sec_runtime_dir[RTE_MAX_SECONDARY][PATH_MAX]; +static struct rte_config sec_rte_config[RTE_MAX_SECONDARY]; +static struct internal_config sec_internal_config[RTE_MAX_SECONDARY]; + +char * rte_eal_get_runtime_dir(void) { return runtime_dir; } -int -eal_set_runtime_dir(char *run_dir, size_t size) +char * +rte_eal_sec_get_runtime_dir(const int sec_idx) +{ + return sec_runtime_dir[sec_idx]; +} + +static int +set_runtime_dir(char *dst_dir, char *src_dir, size_t size) { size_t str_size; - str_size = strlcpy(runtime_dir, run_dir, size); + str_size = strlcpy(dst_dir, src_dir, size); if (str_size >= size) { RTE_LOG(ERR, EAL, "Runtime directory string too long\n"); return -1; @@ -42,6 +53,18 @@ eal_set_runtime_dir(char *run_dir, size_t size) return 0; } +int +eal_sec_set_runtime_dir(char *run_dir, size_t size, const int sec_idx) +{ + return set_runtime_dir(sec_runtime_dir[sec_idx], run_dir, size); +} + +int +eal_set_runtime_dir(char *run_dir, size_t size) +{ + return set_runtime_dir(runtime_dir, run_dir, size); +} + /* Return a pointer to the configuration structure */ struct rte_config * rte_eal_get_configuration(void) @@ -49,6 +72,18 @@ rte_eal_get_configuration(void) return &rte_config; } +struct rte_config * +rte_eal_sec_get_configuration(const int sec_idx) +{ + return &sec_rte_config[sec_idx]; +} + +struct internal_config * +rte_eal_sec_get_internal_config(const int sec_idx) +{ + return &sec_internal_config[sec_idx]; +} + /* Return a pointer to the internal configuration structure */ struct internal_config * eal_get_internal_configuration(void) diff --git a/lib/eal/common/eal_common_dynmem.c b/lib/eal/common/eal_common_dynmem.c index 7c5437ddfa..eff78c14d9 100644 --- a/lib/eal/common/eal_common_dynmem.c +++ b/lib/eal/common/eal_common_dynmem.c @@ -16,6 +16,50 @@ /** @file Functions common to EALs that support dynamic memory allocation. */ +static int +eal_sec_set_num_pages(struct internal_config *internal_conf, + struct hugepage_info *used_hp) +{ + int ret; + int hp_sz_idx; + uint64_t memory[RTE_MAX_NUMA_NODES]; + + if (!internal_conf || !used_hp) { + return -1; + } + + for (hp_sz_idx = 0; + hp_sz_idx < (int) internal_conf->num_hugepage_sizes; + hp_sz_idx++) { + struct hugepage_info *hpi; + hpi = &internal_conf->hugepage_info[hp_sz_idx]; + used_hp[hp_sz_idx].hugepage_sz = hpi->hugepage_sz; + } + + for (hp_sz_idx = 0; hp_sz_idx < RTE_MAX_NUMA_NODES; hp_sz_idx++) + memory[hp_sz_idx] = internal_conf->socket_mem[hp_sz_idx]; + + ret = eal_dynmem_calc_num_pages_per_socket(memory, + internal_conf->hugepage_info, used_hp, + internal_conf->num_hugepage_sizes); + + return ret; +} + +static int +eal_sec_get_num_pages(const struct hugepage_info *used_hp, + uint64_t hugepage_sz, int socket) +{ + int hp_sz_idx; + + for (hp_sz_idx = 0; hp_sz_idx < MAX_HUGEPAGE_SIZES; hp_sz_idx++) { + if (used_hp[hp_sz_idx].hugepage_sz == hugepage_sz) + return used_hp[hp_sz_idx].num_pages[socket]; + } + + return 0; +} + int eal_dynmem_memseg_lists_init(void) { @@ -29,6 +73,7 @@ eal_dynmem_memseg_lists_init(void) uint64_t max_mem, max_mem_per_type; unsigned int max_seglists_per_type; unsigned int n_memtypes, cur_type; + struct hugepage_info used_hp[MAX_HUGEPAGE_SIZES]; struct internal_config *internal_conf = eal_get_internal_configuration(); @@ -36,6 +81,14 @@ eal_dynmem_memseg_lists_init(void) if (internal_conf->no_hugetlbfs) return 0; + if (internal_conf->map_perfect) { + memset(used_hp, 0, sizeof(used_hp)); + ret = eal_sec_set_num_pages(internal_conf, used_hp); + if (ret == -1) { + RTE_LOG(ERR, EAL, "Cannot get num pages\n"); + } + } + /* * figuring out amount of memory we're going to have is a long and very * involved process. the basic element we're operating with is a memory @@ -132,6 +185,7 @@ eal_dynmem_memseg_lists_init(void) struct memtype *type = &memtypes[cur_type]; uint64_t max_mem_per_list, pagesz; int socket_id; + unsigned int need_n_segs, cur_n_segs; pagesz = type->page_sz; socket_id = type->socket_id; @@ -175,8 +229,17 @@ eal_dynmem_memseg_lists_init(void) "n_segs:%i socket_id:%i hugepage_sz:%" PRIu64 "\n", n_seglists, n_segs, socket_id, pagesz); + if (internal_conf->map_perfect) + need_n_segs = eal_sec_get_num_pages(used_hp, pagesz, socket_id); + else + need_n_segs = n_segs; + /* create all segment lists */ - for (cur_seglist = 0; cur_seglist < n_seglists; cur_seglist++) { + for (cur_seglist = 0; cur_seglist < n_seglists && need_n_segs > 0; cur_seglist++) { + cur_n_segs = RTE_MIN(need_n_segs, n_segs); + if (internal_conf->map_perfect) + need_n_segs -= cur_n_segs; + if (msl_idx >= RTE_MAX_MEMSEG_LISTS) { RTE_LOG(ERR, EAL, "No more space in memseg lists, please increase %s\n", @@ -185,7 +248,7 @@ eal_dynmem_memseg_lists_init(void) } msl = &mcfg->memsegs[msl_idx++]; - if (eal_memseg_list_init(msl, pagesz, n_segs, + if (eal_memseg_list_init(msl, pagesz, cur_n_segs, socket_id, cur_seglist, true)) goto out; diff --git a/lib/eal/common/eal_common_fbarray.c b/lib/eal/common/eal_common_fbarray.c index 3a28a53247..9c125c104c 100644 --- a/lib/eal/common/eal_common_fbarray.c +++ b/lib/eal/common/eal_common_fbarray.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include @@ -830,8 +832,9 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, return -1; } -int -rte_fbarray_attach(struct rte_fbarray *arr) +static int +__rte_fbarray_attach(struct rte_fbarray *arr, const char *runtime_dir, + const struct internal_config *internal_conf) { struct mem_area *ma = NULL, *tmp = NULL; size_t page_sz, mmap_len; @@ -867,13 +870,15 @@ rte_fbarray_attach(struct rte_fbarray *arr) mmap_len = calc_data_size(page_sz, arr->elt_sz, arr->len); - /* check the tailq - maybe user has already mapped this address space */ - rte_spinlock_lock(&mem_area_lock); + if (!internal_conf->pri_and_sec) { + /* check the tailq - maybe user has already mapped this address space */ + rte_spinlock_lock(&mem_area_lock); - TAILQ_FOREACH(tmp, &mem_area_tailq, next) { - if (overlap(tmp, arr->data, mmap_len)) { - rte_errno = EEXIST; - goto fail; + TAILQ_FOREACH(tmp, &mem_area_tailq, next) { + if (overlap(tmp, arr->data, mmap_len)) { + rte_errno = EEXIST; + goto fail; + } } } @@ -883,7 +888,7 @@ rte_fbarray_attach(struct rte_fbarray *arr) if (data == NULL) goto fail; - eal_get_fbarray_path(path, sizeof(path), arr->name); + eal_sec_get_fbarray_path(path, sizeof(path), arr->name, runtime_dir); fd = eal_file_open(path, EAL_OPEN_READWRITE); if (fd < 0) { @@ -897,16 +902,27 @@ rte_fbarray_attach(struct rte_fbarray *arr) if (resize_and_map(fd, path, data, mmap_len)) goto fail; + if (internal_conf->pri_and_sec) { + if (flock(fd, LOCK_UN)) { + rte_errno = errno; + goto fail; + } + close(fd); + fd = -1; + } + /* store our new memory area */ ma->addr = data; ma->fd = fd; /* keep fd until detach/destroy */ ma->len = mmap_len; - TAILQ_INSERT_TAIL(&mem_area_tailq, ma, next); + if (!internal_conf->pri_and_sec) { + TAILQ_INSERT_TAIL(&mem_area_tailq, ma, next); - /* we're done */ + /* we're done */ - rte_spinlock_unlock(&mem_area_lock); + rte_spinlock_unlock(&mem_area_lock); + } return 0; fail: if (data) @@ -918,6 +934,31 @@ rte_fbarray_attach(struct rte_fbarray *arr) return -1; } +int +rte_fbarray_attach(struct rte_fbarray *arr) +{ + const struct internal_config *internal_conf = eal_get_internal_configuration(); + return __rte_fbarray_attach(arr, rte_eal_get_runtime_dir(), internal_conf); +} + +int +rte_sec_fbarray_attach(struct rte_fbarray *arr, + const int switch_pri_and_sec, const int sec_idx) +{ + struct internal_config *internal_conf = NULL; + char *runtime_dir = NULL; + + if (!switch_pri_and_sec) { + runtime_dir = rte_eal_get_runtime_dir(); + internal_conf = eal_get_internal_configuration(); + } else { + runtime_dir = rte_eal_sec_get_runtime_dir(sec_idx); + internal_conf = rte_eal_sec_get_internal_config(sec_idx); + } + + return __rte_fbarray_attach(arr, runtime_dir, internal_conf); +} + int rte_fbarray_detach(struct rte_fbarray *arr) { @@ -1057,6 +1098,47 @@ rte_fbarray_destroy(struct rte_fbarray *arr) return ret; } +int +rte_sec_fbarray_destroy(struct rte_fbarray *arr, + const int sec_idx) +{ + int fd, ret; + char path[PATH_MAX]; + + if (arr == NULL) { + rte_errno = EINVAL; + return -1; + } + + size_t page_sz = rte_mem_page_size(); + if (page_sz == (size_t)-1) + return -1; + + size_t mmap_len = calc_data_size(page_sz, arr->elt_sz, arr->len); + rte_mem_unmap(arr->data, mmap_len); + + /* try deleting the file */ + eal_sec_get_fbarray_path(path, sizeof(path), arr->name, rte_eal_sec_get_runtime_dir(sec_idx)); + + fd = open(path, O_RDONLY); + if (fd < 0) { + RTE_LOG(ERR, EAL, "Could not open fbarray file: %s\n", strerror(errno)); + return -1; + } + if (flock(fd, LOCK_EX | LOCK_NB)) { + RTE_LOG(DEBUG, EAL, "Cannot destroy fbarray - another process is using it\n"); + rte_errno = EBUSY; + ret = -1; + } else { + ret = 0; + unlink(path); + memset(arr, 0, sizeof(*arr)); + } + close(fd); + + return ret; +} + void * rte_fbarray_get(const struct rte_fbarray *arr, unsigned int idx) { diff --git a/lib/eal/common/eal_common_memory.c b/lib/eal/common/eal_common_memory.c index 616db5ce31..884996faf2 100644 --- a/lib/eal/common/eal_common_memory.c +++ b/lib/eal/common/eal_common_memory.c @@ -307,9 +307,9 @@ virt2memseg(const void *addr, const struct rte_memseg_list *msl) } static struct rte_memseg_list * -virt2memseg_list(const void *addr) +virt2memseg_list(const void *addr, const struct rte_config *rte_cfg) { - struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; + struct rte_mem_config *mcfg = rte_cfg->mem_config; struct rte_memseg_list *msl; int msl_idx; @@ -331,7 +331,13 @@ virt2memseg_list(const void *addr) struct rte_memseg_list * rte_mem_virt2memseg_list(const void *addr) { - return virt2memseg_list(addr); + return virt2memseg_list(addr, rte_eal_get_configuration()); +} + +struct rte_memseg_list * +rte_sec_mem_virt2memseg_list(const void *addr, const struct rte_config *rte_cfg) +{ + return virt2memseg_list(addr, rte_cfg); } struct virtiova { @@ -386,11 +392,25 @@ rte_mem_iova2virt(rte_iova_t iova) return vi.virt; } +static struct rte_memseg * +__rte_mem_virt2memseg(const void *addr, const struct rte_memseg_list *msl, + const struct rte_config *rte_cfg) +{ + return virt2memseg(addr, msl != NULL ? msl : + rte_sec_mem_virt2memseg_list(addr, rte_cfg)); +} + struct rte_memseg * rte_mem_virt2memseg(const void *addr, const struct rte_memseg_list *msl) { - return virt2memseg(addr, msl != NULL ? msl : - rte_mem_virt2memseg_list(addr)); + return __rte_mem_virt2memseg(addr, msl, rte_eal_get_configuration()); +} + +struct rte_memseg * +rte_sec_mem_virt2memseg(const void *addr, const struct rte_memseg_list *msl, + const struct rte_config *rte_cfg) +{ + return __rte_mem_virt2memseg(addr, msl, rte_cfg); } static int @@ -1069,12 +1089,14 @@ rte_eal_memory_detach(void) } /* init memory subsystem */ -int -rte_eal_memory_init(void) +static int +__rte_eal_memory_init(__attribute__((__unused__)) const char *runtime_dir, + const struct internal_config *internal_conf, + struct rte_config *rte_cfg, + const int switch_pri_and_sec, + const int sec_idx) { - struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; - const struct internal_config *internal_conf = - eal_get_internal_configuration(); + struct rte_mem_config *mcfg = rte_cfg->mem_config; int retval; RTE_LOG(DEBUG, EAL, "Setting up physically contiguous memory...\n"); @@ -1083,17 +1105,18 @@ rte_eal_memory_init(void) return -1; /* lock mem hotplug here, to prevent races while we init */ - rte_mcfg_mem_read_lock(); + rte_rwlock_read_lock(&mcfg->memory_hotplug_lock); - if (rte_eal_memseg_init() < 0) + if (rte_eal_memseg_init(switch_pri_and_sec, sec_idx) < 0) goto fail; - if (eal_memalloc_init() < 0) - goto fail; + if (!internal_conf->pri_and_sec) + if (eal_memalloc_init() < 0) + goto fail; - retval = rte_eal_process_type() == RTE_PROC_PRIMARY ? + retval = rte_cfg->process_type == RTE_PROC_PRIMARY ? rte_eal_hugepage_init() : - rte_eal_hugepage_attach(); + rte_eal_hugepage_attach(switch_pri_and_sec, sec_idx); if (retval < 0) goto fail; @@ -1102,10 +1125,43 @@ rte_eal_memory_init(void) return 0; fail: - rte_mcfg_mem_read_unlock(); + rte_rwlock_read_unlock(&mcfg->memory_hotplug_lock); return -1; } +int +rte_eal_memory_init(void) +{ + const int unused_idx = -1; + const struct internal_config *internal_conf = + eal_get_internal_configuration(); + + return __rte_eal_memory_init(rte_eal_get_runtime_dir(), + internal_conf, rte_eal_get_configuration(), + false, unused_idx); +} + +int +rte_eal_sec_memory_init(const int sec_idx) +{ + int ret; + struct rte_config *rte_cfg = rte_eal_sec_get_configuration(sec_idx); + + ret = __rte_eal_memory_init(rte_eal_sec_get_runtime_dir(sec_idx), + rte_eal_sec_get_internal_config(sec_idx), rte_cfg, + true, sec_idx); + + rte_rwlock_read_unlock(&rte_cfg->mem_config->memory_hotplug_lock); + + return ret; +} + +int +rte_eal_sec_memory_cleanup(const int sec_idx) +{ + return eal_sec_memalloc_destroy(sec_idx); +} + #ifndef RTE_EXEC_ENV_WINDOWS #define EAL_MEMZONE_LIST_REQ "/eal/memzone_list" #define EAL_MEMZONE_INFO_REQ "/eal/memzone_info" diff --git a/lib/eal/common/eal_common_options.c b/lib/eal/common/eal_common_options.c index 1cfdd75f3b..ba3b19ee6e 100644 --- a/lib/eal/common/eal_common_options.c +++ b/lib/eal/common/eal_common_options.c @@ -105,6 +105,7 @@ eal_long_options[] = { {OPT_TELEMETRY, 0, NULL, OPT_TELEMETRY_NUM }, {OPT_NO_TELEMETRY, 0, NULL, OPT_NO_TELEMETRY_NUM }, {OPT_FORCE_MAX_SIMD_BITWIDTH, 1, NULL, OPT_FORCE_MAX_SIMD_BITWIDTH_NUM}, + {OPT_MAP_PERFECT, 0, NULL, OPT_MAP_PERFECT_NUM }, {0, 0, NULL, 0 } }; @@ -301,54 +302,66 @@ eal_get_hugefile_prefix(void) return HUGEFILE_PREFIX_DEFAULT; } +const char * +eal_sec_get_hugefile_prefix(const int sec_idx) +{ + struct internal_config *internal_conf = + rte_eal_sec_get_internal_config(sec_idx); + + if (internal_conf->hugefile_prefix != NULL) + return internal_conf->hugefile_prefix; + return HUGEFILE_PREFIX_DEFAULT; +} + void -eal_reset_internal_config(struct internal_config *internal_cfg) +eal_reset_internal_config(struct internal_config *internal_conf) { int i; - internal_cfg->memory = 0; - internal_cfg->force_nrank = 0; - internal_cfg->force_nchannel = 0; - internal_cfg->hugefile_prefix = NULL; - internal_cfg->hugepage_dir = NULL; - internal_cfg->force_sockets = 0; + internal_conf->memory = 0; + internal_conf->force_nrank = 0; + internal_conf->force_nchannel = 0; + internal_conf->hugefile_prefix = NULL; + internal_conf->hugepage_dir = NULL; + internal_conf->force_sockets = 0; /* zero out the NUMA config */ for (i = 0; i < RTE_MAX_NUMA_NODES; i++) - internal_cfg->socket_mem[i] = 0; - internal_cfg->force_socket_limits = 0; + internal_conf->socket_mem[i] = 0; + internal_conf->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; + internal_conf->socket_limit[i] = 0; /* zero out hugedir descriptors */ for (i = 0; i < MAX_HUGEPAGE_SIZES; i++) { - memset(&internal_cfg->hugepage_info[i], 0, - sizeof(internal_cfg->hugepage_info[0])); - internal_cfg->hugepage_info[i].lock_descriptor = -1; + memset(&internal_conf->hugepage_info[i], 0, + sizeof(internal_conf->hugepage_info[0])); + internal_conf->hugepage_info[i].lock_descriptor = -1; } - internal_cfg->base_virtaddr = 0; + internal_conf->base_virtaddr = 0; #ifdef LOG_DAEMON - internal_cfg->syslog_facility = LOG_DAEMON; + internal_conf->syslog_facility = LOG_DAEMON; #endif /* if set to NONE, interrupt mode is determined automatically */ - internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE; - memset(internal_cfg->vfio_vf_token, 0, - sizeof(internal_cfg->vfio_vf_token)); + internal_conf->vfio_intr_mode = RTE_INTR_MODE_NONE; + memset(internal_conf->vfio_vf_token, 0, + sizeof(internal_conf->vfio_vf_token)); #ifdef RTE_LIBEAL_USE_HPET - internal_cfg->no_hpet = 0; + internal_conf->no_hpet = 0; #else - internal_cfg->no_hpet = 1; + internal_conf->no_hpet = 1; #endif - internal_cfg->vmware_tsc_map = 0; - 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; - internal_cfg->max_simd_bitwidth.bitwidth = RTE_VECT_DEFAULT_SIMD_BITWIDTH; - internal_cfg->max_simd_bitwidth.forced = 0; + internal_conf->vmware_tsc_map = 0; + internal_conf->create_uio_dev = 0; + internal_conf->iova_mode = RTE_IOVA_DC; + internal_conf->user_mbuf_pool_ops_name = NULL; + CPU_ZERO(&internal_conf->ctrl_cpuset); + internal_conf->init_complete = 0; + internal_conf->map_perfect = 0; + internal_conf->max_simd_bitwidth.bitwidth = RTE_VECT_DEFAULT_SIMD_BITWIDTH; + internal_conf->max_simd_bitwidth.forced = 0; } static int @@ -1496,12 +1509,10 @@ eal_parse_simd_bitwidth(const char *arg) } static int -eal_parse_base_virtaddr(const char *arg) +eal_parse_base_virtaddr(const char *arg, struct internal_config *conf) { char *end; uint64_t addr; - struct internal_config *internal_conf = - eal_get_internal_configuration(); errno = 0; addr = strtoull(arg, &end, 16); @@ -1521,7 +1532,7 @@ eal_parse_base_virtaddr(const char *arg) * it can align to 2MB for x86. So this alignment can also be used * on x86 and other architectures. */ - internal_conf->base_virtaddr = + conf->base_virtaddr = RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M); return 0; @@ -1877,7 +1888,7 @@ eal_parse_common_option(int opt, const char *optarg, } break; case OPT_BASE_VIRTADDR_NUM: - if (eal_parse_base_virtaddr(optarg) < 0) { + if (eal_parse_base_virtaddr(optarg, conf) < 0) { RTE_LOG(ERR, EAL, "invalid parameter for --" OPT_BASE_VIRTADDR "\n"); return -1; @@ -1933,9 +1944,9 @@ eal_auto_detect_cores(struct rte_config *cfg) } static void -compute_ctrl_threads_cpuset(struct internal_config *internal_cfg) +compute_ctrl_threads_cpuset(struct internal_config *internal_conf) { - rte_cpuset_t *cpuset = &internal_cfg->ctrl_cpuset; + rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset; rte_cpuset_t default_set; unsigned int lcore_id; @@ -1960,25 +1971,23 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg) } int -eal_cleanup_config(struct internal_config *internal_cfg) +eal_cleanup_config(struct internal_config *internal_conf) { - 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); + if (internal_conf->hugefile_prefix != NULL) + free(internal_conf->hugefile_prefix); + if (internal_conf->hugepage_dir != NULL) + free(internal_conf->hugepage_dir); + if (internal_conf->user_mbuf_pool_ops_name != NULL) + free(internal_conf->user_mbuf_pool_ops_name); return 0; } int -eal_adjust_config(struct internal_config *internal_cfg) +eal_adjust_config(struct internal_config *internal_conf) { int i; struct rte_config *cfg = rte_eal_get_configuration(); - struct internal_config *internal_conf = - eal_get_internal_configuration(); if (!core_parsed) eal_auto_detect_cores(cfg); @@ -1994,44 +2003,64 @@ eal_adjust_config(struct internal_config *internal_cfg) lcore_config[cfg->main_lcore].core_role = ROLE_RTE; } - compute_ctrl_threads_cpuset(internal_cfg); + compute_ctrl_threads_cpuset(internal_conf); /* 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]; + internal_conf->memory += internal_conf->socket_mem[i]; return 0; } int -eal_check_common_options(struct internal_config *internal_cfg) +eal_sec_adjust_config(struct internal_config *internal_conf) { - struct rte_config *cfg = rte_eal_get_configuration(); - const struct internal_config *internal_conf = - eal_get_internal_configuration(); + struct internal_config *internal_conf_head; + internal_conf->process_type = RTE_PROC_SECONDARY; + + internal_conf_head = rte_eal_sec_get_internal_config(0); + for (int i = 0; i < RTE_MAX_SECONDARY; ++i) { + if (!internal_conf_head[i].pri_and_sec) + continue; + if (internal_conf == &internal_conf_head[i]) + continue; + if (!strcmp(internal_conf_head[i].hugefile_prefix, internal_conf->hugefile_prefix)) + return -EALREADY; + } + + for (int i = 0; i < RTE_MAX_NUMA_NODES; i++) + internal_conf->memory += internal_conf->socket_mem[i]; - if (cfg->lcore_role[cfg->main_lcore] != ROLE_RTE) { + return 0; +} + +int +eal_check_common_options(struct internal_config *internal_conf, + struct rte_config *cfg) +{ + if (!internal_conf->pri_and_sec && + cfg->lcore_role[cfg->main_lcore] != ROLE_RTE) { RTE_LOG(ERR, EAL, "Main lcore is not enabled for DPDK\n"); return -1; } - if (internal_cfg->process_type == RTE_PROC_INVALID) { + if (internal_conf->process_type == RTE_PROC_INVALID) { RTE_LOG(ERR, EAL, "Invalid process type specified\n"); return -1; } - if (internal_cfg->hugefile_prefix != NULL && - strlen(internal_cfg->hugefile_prefix) < 1) { + if (internal_conf->hugefile_prefix != NULL && + strlen(internal_conf->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) { + if (internal_conf->hugepage_dir != NULL && + strlen(internal_conf->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) { + if (internal_conf->user_mbuf_pool_ops_name != NULL && + strlen(internal_conf->user_mbuf_pool_ops_name) < 1) { RTE_LOG(ERR, EAL, "Invalid length of --" OPT_MBUF_POOL_OPS_NAME" option\n"); return -1; } @@ -2040,18 +2069,18 @@ eal_check_common_options(struct internal_config *internal_cfg) "option\n"); return -1; } - if (mem_parsed && internal_cfg->force_sockets == 1) { + if (mem_parsed && internal_conf->force_sockets == 1) { RTE_LOG(ERR, EAL, "Options -m and --"OPT_SOCKET_MEM" cannot " "be specified at the same time\n"); return -1; } - if (internal_cfg->no_hugetlbfs && internal_cfg->force_sockets == 1) { + if (internal_conf->no_hugetlbfs && internal_conf->force_sockets == 1) { RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_MEM" cannot " "be specified together with --"OPT_NO_HUGE"\n"); return -1; } - if (internal_cfg->no_hugetlbfs && internal_cfg->hugepage_unlink && - !internal_cfg->in_memory) { + if (internal_conf->no_hugetlbfs && internal_conf->hugepage_unlink && + !internal_conf->in_memory) { RTE_LOG(ERR, EAL, "Option --"OPT_HUGE_UNLINK" cannot " "be specified together with --"OPT_NO_HUGE"\n"); return -1; @@ -2060,35 +2089,43 @@ eal_check_common_options(struct internal_config *internal_cfg) RTE_LOG(ERR, EAL, "Option --"OPT_SOCKET_LIMIT " is only supported in non-legacy memory mode\n"); } - if (internal_cfg->single_file_segments && - internal_cfg->hugepage_unlink && - !internal_cfg->in_memory) { + if (internal_conf->single_file_segments && + internal_conf->hugepage_unlink && + !internal_conf->in_memory) { RTE_LOG(ERR, EAL, "Option --"OPT_SINGLE_FILE_SEGMENTS" is " "not compatible with --"OPT_HUGE_UNLINK"\n"); return -1; } - if (internal_cfg->legacy_mem && - internal_cfg->in_memory) { + if (internal_conf->legacy_mem && + internal_conf->in_memory) { RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" is not compatible " "with --"OPT_IN_MEMORY"\n"); return -1; } - if (internal_cfg->legacy_mem && internal_cfg->match_allocations) { + if (internal_conf->legacy_mem && internal_conf->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) { + if (internal_conf->no_hugetlbfs && internal_conf->match_allocations) { RTE_LOG(ERR, EAL, "Option --"OPT_NO_HUGE" is not compatible " "with --"OPT_MATCH_ALLOCATIONS"\n"); return -1; } - if (internal_cfg->legacy_mem && internal_cfg->memory == 0) { + if (internal_conf->legacy_mem && internal_conf->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"); } + if (internal_conf->map_perfect || internal_conf->pri_and_sec) { + if (!internal_conf->legacy_mem || internal_conf->in_memory || internal_conf->no_hugetlbfs) { + RTE_LOG(ERR, EAL, "Option --"OPT_LEGACY_MEM" or "OPT_IN_MEMORY" or "OPT_NO_HUGE" " + "is not compatible with --"OPT_MAP_PERFECT" and "OPT_PRI_AND_SEC"\n"); + return -1; + } + } + return 0; } diff --git a/lib/eal/common/eal_filesystem.h b/lib/eal/common/eal_filesystem.h index 5d21f07c20..719678772f 100644 --- a/lib/eal/common/eal_filesystem.h +++ b/lib/eal/common/eal_filesystem.h @@ -23,7 +23,7 @@ /* sets up platform-specific runtime data dir */ int -eal_create_runtime_dir(void); +eal_create_runtime_dir(const int sec_idx); int eal_clean_runtime_dir(void); @@ -32,17 +32,32 @@ eal_clean_runtime_dir(void); const char * eal_get_hugefile_prefix(void); +const char * +eal_sec_get_hugefile_prefix(const int sec_idx); + #define RUNTIME_CONFIG_FNAME "config" static inline const char * -eal_runtime_config_path(void) +__eal_runtime_config_path(const char *runtime_dir) { static char buffer[PATH_MAX]; /* static so auto-zeroed */ - snprintf(buffer, sizeof(buffer), "%s/%s", rte_eal_get_runtime_dir(), + snprintf(buffer, sizeof(buffer), "%s/%s", runtime_dir, RUNTIME_CONFIG_FNAME); return buffer; } +static inline const char * +eal_runtime_config_path(void) +{ + return __eal_runtime_config_path(rte_eal_get_runtime_dir()); +} + +static inline const char * +eal_sec_runtime_config_path(const char *runtime_dir) +{ + return __eal_runtime_config_path(runtime_dir); +} + /** Path of primary/secondary communication unix socket file. */ #define MP_SOCKET_FNAME "mp_socket" static inline const char * @@ -57,12 +72,29 @@ eal_mp_socket_path(void) #define FBARRAY_NAME_FMT "%s/fbarray_%s" static inline const char * -eal_get_fbarray_path(char *buffer, size_t buflen, const char *name) { - snprintf(buffer, buflen, FBARRAY_NAME_FMT, rte_eal_get_runtime_dir(), +__eal_get_fbarray_path(char *buffer, size_t buflen, const char *name, + const char *runtime_dir) +{ + snprintf(buffer, buflen, FBARRAY_NAME_FMT, runtime_dir, name); return buffer; } +static inline const char * +eal_get_fbarray_path(char *buffer, size_t buflen, const char *name) +{ + return __eal_get_fbarray_path(buffer, buflen, name, + rte_eal_get_runtime_dir()); +} + +static inline const char * +eal_sec_get_fbarray_path(char *buffer, size_t buflen, + const char *name, const char *runtime_dir) +{ + return __eal_get_fbarray_path(buffer, buflen, name, + runtime_dir); +} + /** Path of hugepage info file. */ #define HUGEPAGE_INFO_FNAME "hugepage_info" static inline const char * @@ -78,15 +110,27 @@ eal_hugepage_info_path(void) /** Path of hugepage data file. */ #define HUGEPAGE_DATA_FNAME "hugepage_data" static inline const char * -eal_hugepage_data_path(void) +__eal_hugepage_data_path(const char *runtime_dir) { static char buffer[PATH_MAX]; /* static so auto-zeroed */ - snprintf(buffer, sizeof(buffer), "%s/%s", rte_eal_get_runtime_dir(), + snprintf(buffer, sizeof(buffer), "%s/%s", runtime_dir, HUGEPAGE_DATA_FNAME); return buffer; } +static inline const char * +eal_hugepage_data_path(void) +{ + return __eal_hugepage_data_path(rte_eal_get_runtime_dir()); +} + +static inline const char * +eal_sec_hugepage_data_path(const char *runtime_dir) +{ + return __eal_hugepage_data_path(runtime_dir); +} + /** String format for hugepage map files. */ #define HUGEFILE_FMT "%s/%smap_%d" static inline const char * diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h index d6c0470eb8..8c326f2f87 100644 --- a/lib/eal/common/eal_internal_cfg.h +++ b/lib/eal/common/eal_internal_cfg.h @@ -94,8 +94,10 @@ struct internal_config { unsigned int no_telemetry; /**< true to disable Telemetry */ struct simd_bitwidth max_simd_bitwidth; /**< max simd bitwidth path to use */ + volatile unsigned pri_and_sec; + volatile unsigned map_perfect; }; -void eal_reset_internal_config(struct internal_config *internal_cfg); +void eal_reset_internal_config(struct internal_config *internal_conf); #endif /* EAL_INTERNAL_CFG_H */ diff --git a/lib/eal/common/eal_memalloc.h b/lib/eal/common/eal_memalloc.h index ebc3a6f6c1..19ccee7891 100644 --- a/lib/eal/common/eal_memalloc.h +++ b/lib/eal/common/eal_memalloc.h @@ -83,6 +83,10 @@ eal_memalloc_get_seg_fd(int list_idx, int seg_idx); int eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd); +int +eal_sec_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd, + const int switch_pri_and_sec, const int sec_idx); + /* returns 0 or -errno */ int eal_memalloc_set_seg_list_fd(int list_idx, int fd); @@ -96,4 +100,7 @@ eal_memalloc_init(void); int eal_memalloc_cleanup(void); +int +eal_sec_memalloc_destroy(const int sec_idx); + #endif /* EAL_MEMALLOC_H */ diff --git a/lib/eal/common/eal_options.h b/lib/eal/common/eal_options.h index 8e4f7202a2..95625c4002 100644 --- a/lib/eal/common/eal_options.h +++ b/lib/eal/common/eal_options.h @@ -87,6 +87,10 @@ enum { OPT_NO_TELEMETRY_NUM, #define OPT_FORCE_MAX_SIMD_BITWIDTH "force-max-simd-bitwidth" OPT_FORCE_MAX_SIMD_BITWIDTH_NUM, +#define OPT_PRI_AND_SEC "pri-and-sec" + OPT_PRI_AND_SEC_NUM, +#define OPT_MAP_PERFECT "map-perfect" + OPT_MAP_PERFECT_NUM, OPT_LONG_MAX_NUM }; @@ -97,9 +101,10 @@ extern const struct option eal_long_options[]; int eal_parse_common_option(int opt, const char *argv, struct internal_config *conf); int eal_option_device_parse(void); -int eal_adjust_config(struct internal_config *internal_cfg); -int eal_cleanup_config(struct internal_config *internal_cfg); -int eal_check_common_options(struct internal_config *internal_cfg); +int eal_adjust_config(struct internal_config *internal_conf); +int eal_sec_adjust_config(struct internal_config *internal_conf); +int eal_cleanup_config(struct internal_config *internal_conf); +int eal_check_common_options(struct internal_config *internal_conf, struct rte_config *cfg); void eal_common_usage(void); enum rte_proc_type_t eal_proc_type_detect(void); int eal_plugins_init(void); diff --git a/lib/eal/common/eal_private.h b/lib/eal/common/eal_private.h index 36bcc0b5a4..ac8af18773 100644 --- a/lib/eal/common/eal_private.h +++ b/lib/eal/common/eal_private.h @@ -103,7 +103,8 @@ int rte_eal_cpu_init(void); * @return * 0 on success, negative on error */ -int rte_eal_memseg_init(void); +//int rte_eal_memseg_init(void); +int rte_eal_memseg_init(const int switch_pri_and_sec, const int sec_idx); /** * Map memory @@ -117,6 +118,9 @@ int rte_eal_memseg_init(void); */ int rte_eal_memory_init(void); +int rte_eal_sec_memory_init(const int sec_idx); +int rte_eal_sec_memory_cleanup(const int sec_idx); + /** * Configure timers * @@ -413,7 +417,8 @@ int rte_eal_hugepage_init(void); * * This function is private to the EAL. */ -int rte_eal_hugepage_attach(void); +//int rte_eal_hugepage_attach(void); +int rte_eal_hugepage_attach(const int switch_pri_and_sec, const int sec_idx); /** * Detaches all memory mappings from a process. @@ -689,6 +694,9 @@ eal_mem_set_dump(void *virt, size_t size, bool dump); int eal_set_runtime_dir(char *run_dir, size_t size); +int +eal_sec_set_runtime_dir(char *run_dir, size_t size, const int sec_idx); + /** * Get the internal configuration structure. * @@ -738,4 +746,19 @@ int eal_asprintf(char **buffer, const char *format, ...); eal_asprintf(buffer, format, ##__VA_ARGS__) #endif + +/****** APIs for libnet ******/ +#include + +struct rte_memseg * +rte_sec_mem_virt2memseg(const void *addr, const struct rte_memseg_list *msl, + const struct rte_config *rte_cfg); + +struct rte_memseg_list * +rte_sec_mem_virt2memseg_list(const void *addr, const struct rte_config *rte_cfg); + +int +rte_sec_memseg_list_walk_thread_unsafe(rte_memseg_list_walk_t func, void *arg, + struct rte_config *rte_cfg); + #endif /* _EAL_PRIVATE_H_ */ diff --git a/lib/eal/include/rte_eal.h b/lib/eal/include/rte_eal.h index 5a34a6acd9..c3259a4af3 100644 --- a/lib/eal/include/rte_eal.h +++ b/lib/eal/include/rte_eal.h @@ -472,9 +472,17 @@ rte_eal_mbuf_user_pool_ops(void); * @return * The runtime directory path of DPDK */ -const char * +char * rte_eal_get_runtime_dir(void); +/****** APIs for libnet ******/ +char *rte_eal_sec_get_runtime_dir(const int sec_idx); +struct rte_config *rte_eal_sec_get_configuration(const int sec_idx); +struct internal_config *rte_eal_sec_get_internal_config(const int sec_idx); + +int rte_eal_sec_attach(int argc, char **argv); +int rte_eal_sec_detach(const char *file_prefix, int length); + #ifdef __cplusplus } #endif diff --git a/lib/eal/include/rte_fbarray.h b/lib/eal/include/rte_fbarray.h index c64868711e..e35a0cc0b4 100644 --- a/lib/eal/include/rte_fbarray.h +++ b/lib/eal/include/rte_fbarray.h @@ -99,6 +99,10 @@ rte_fbarray_init(struct rte_fbarray *arr, const char *name, unsigned int len, int rte_fbarray_attach(struct rte_fbarray *arr); +int +rte_sec_fbarray_attach(struct rte_fbarray *arr, + const int switch_pri_and_sec, const int sec_idx); + /** * Deallocate resources for an already allocated and correctly set up @@ -120,6 +124,8 @@ rte_fbarray_attach(struct rte_fbarray *arr); int rte_fbarray_destroy(struct rte_fbarray *arr); +int +rte_sec_fbarray_destroy(struct rte_fbarray *arr, const int sec_idx); /** * Deallocate resources for an already allocated and correctly set up diff --git a/lib/eal/include/rte_memory.h b/lib/eal/include/rte_memory.h index 6d018629ae..bf4c6098e3 100644 --- a/lib/eal/include/rte_memory.h +++ b/lib/eal/include/rte_memory.h @@ -143,7 +143,12 @@ rte_mem_iova2virt(rte_iova_t iova); */ struct rte_memseg * rte_mem_virt2memseg(const void *virt, const struct rte_memseg_list *msl); - +/* +__rte_experimental +struct rte_memseg * +rte_sec_mem_virt2memseg(const void *addr, const struct rte_memseg_list *msl, + const struct rte_config *rte_cfg); +*/ /** * Get memseg list corresponding to virtual memory address. * @@ -154,7 +159,11 @@ rte_mem_virt2memseg(const void *virt, const struct rte_memseg_list *msl); */ struct rte_memseg_list * rte_mem_virt2memseg_list(const void *virt); - +/* +__rte_experimental +struct rte_memseg_list * +rte_sec_mem_virt2memseg_list(const void *addr, const struct rte_config *rte_cfg); +*/ /** * Memseg walk function prototype. * @@ -268,7 +277,12 @@ rte_memseg_list_walk(rte_memseg_list_walk_t func, void *arg); */ int rte_memseg_walk_thread_unsafe(rte_memseg_walk_t func, void *arg); - +/* +__rte_experimental +int +rte_sec_memseg_list_walk_thread_unsafe(rte_memseg_list_walk_t func, void *arg, + struct rte_config *rte_cfg); +*/ /** * Walk each VA-contiguous area without performing any locking. * diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c index 47c2186bee..a3afa80d99 100644 --- a/lib/eal/linux/eal.c +++ b/lib/eal/linux/eal.c @@ -88,8 +88,10 @@ int rte_cycles_vmware_tsc_map; static const char *default_runtime_dir = "/var/run"; +static unsigned int sec_count = 0; + int -eal_create_runtime_dir(void) +eal_create_runtime_dir(const int sec_idx) { const char *directory = default_runtime_dir; const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); @@ -113,8 +115,9 @@ eal_create_runtime_dir(void) } /* create prefix-specific subdirectory under DPDK runtime dir */ - ret = snprintf(run_dir, sizeof(run_dir), "%s/%s", - tmp, eal_get_hugefile_prefix()); + const char *prefix = (sec_idx < 0) ? eal_get_hugefile_prefix() : + eal_sec_get_hugefile_prefix(sec_idx); + ret = snprintf(run_dir, sizeof(run_dir), "%s/%s", tmp, prefix); if (ret < 0 || ret == sizeof(run_dir)) { RTE_LOG(ERR, EAL, "Error creating prefix-specific runtime path name\n"); return -1; @@ -137,7 +140,9 @@ eal_create_runtime_dir(void) return -1; } - if (eal_set_runtime_dir(run_dir, sizeof(run_dir))) + ret = (sec_idx < 0) ? eal_set_runtime_dir(run_dir, sizeof(run_dir)) : + eal_sec_set_runtime_dir(run_dir, sizeof(run_dir), sec_idx); + if (ret) return -1; return 0; @@ -355,21 +360,22 @@ rte_eal_config_create(void) /* attach to an existing shared memory config */ static int -rte_eal_config_attach(void) +__rte_eal_config_attach(const int mmap_flags, int *mem_cfg_fd, + const char *runtime_dir, + const struct internal_config *internal_conf, + struct rte_config *rte_cfg) { - struct rte_config *config = rte_eal_get_configuration(); struct rte_mem_config *mem_config; - const struct internal_config *internal_conf = - eal_get_internal_configuration(); + int mcfg_fd = *mem_cfg_fd; - const char *pathname = eal_runtime_config_path(); + const char *pathname = eal_sec_runtime_config_path(runtime_dir); if (internal_conf->no_shconf) return 0; - if (mem_cfg_fd < 0){ - mem_cfg_fd = open(pathname, O_RDWR); - if (mem_cfg_fd < 0) { + if (mcfg_fd < 0){ + mcfg_fd = open(pathname, O_RDWR); + if (mcfg_fd < 0) { RTE_LOG(ERR, EAL, "Cannot open '%s' for rte_mem_config\n", pathname); return -1; @@ -378,20 +384,32 @@ rte_eal_config_attach(void) /* map it as read-only first */ mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config), - PROT_READ, MAP_SHARED, mem_cfg_fd, 0); + mmap_flags, MAP_SHARED, mcfg_fd, 0); if (mem_config == MAP_FAILED) { - close(mem_cfg_fd); - mem_cfg_fd = -1; + close(mcfg_fd); + mcfg_fd = -1; RTE_LOG(ERR, EAL, "Cannot mmap memory for rte_config! error %i (%s)\n", errno, strerror(errno)); return -1; } - config->mem_config = mem_config; + rte_cfg->mem_config = mem_config; + *mem_cfg_fd = mcfg_fd; return 0; } +static int +rte_eal_config_attach(void) +{ + const struct internal_config *internal_conf = eal_get_internal_configuration(); + + return __rte_eal_config_attach(PROT_READ, &mem_cfg_fd, + rte_eal_get_runtime_dir(), internal_conf, + rte_eal_get_configuration()); +} + + /* reattach the shared config at exact memory location primary process has it */ static int rte_eal_config_reattach(void) @@ -508,6 +526,45 @@ rte_config_init(void) return 0; } +static void +rte_sec_config_init(const int sec_idx) +{ + int mem_cfg_fd = -1; + int mmap_flags = PROT_READ | PROT_WRITE; + + struct rte_config *rte_cfg = rte_eal_sec_get_configuration(sec_idx); + struct internal_config *internal_conf = rte_eal_sec_get_internal_config(sec_idx); + + rte_cfg->process_type = internal_conf->process_type; + + __rte_eal_config_attach(mmap_flags, &mem_cfg_fd, + rte_eal_sec_get_runtime_dir(sec_idx), + internal_conf, rte_cfg); + + close(mem_cfg_fd); +} + +static int +eal_sec_config_cleanup(const int sec_idx) +{ + int ret; + struct rte_config *lc_rte_cfg = rte_eal_sec_get_configuration(sec_idx); + struct internal_config *lc_internal_cfg = rte_eal_sec_get_internal_config(sec_idx); + char *lc_runtime_dir = rte_eal_sec_get_runtime_dir(sec_idx); + + ret = munmap(lc_rte_cfg->mem_config, sizeof(*lc_rte_cfg->mem_config)); + if (ret < 0) { + RTE_LOG(ERR, EAL, "Failed to unmap config memory!\n"); + return -1; + } + + memset(lc_rte_cfg, 0, sizeof(*lc_rte_cfg)); + memset(lc_internal_cfg, 0, sizeof(*lc_internal_cfg)); + memset(lc_runtime_dir, 0, PATH_MAX); + + return 0; +} + /* Unlocks hugepage directories that were locked by eal_hugepage_info_init */ static void eal_hugedirs_unlock(void) @@ -548,6 +605,7 @@ eal_usage(const char *prgname) " --"OPT_LEGACY_MEM" Legacy memory mode (no dynamic allocation, contiguous segments)\n" " --"OPT_SINGLE_FILE_SEGMENTS" Put all hugepage memory in single files\n" " --"OPT_MATCH_ALLOCATIONS" Free hugepages exactly as allocated\n" + " --"OPT_MAP_PERFECT" Map virtual addresses according to configured hugepage size\n" "\n"); /* Allow the application to print its usage message too if hook is set */ if (hook) { @@ -678,7 +736,9 @@ eal_log_level_parse(int argc, char **argv) /* Parse the argument given in the command line of the application */ static int -eal_parse_args(int argc, char **argv) +__eal_parse_args(int argc, char **argv, const int sec_idx, + struct internal_config *internal_conf, + struct rte_config *rte_cfg) { int opt, ret; char **argvopt; @@ -687,8 +747,6 @@ eal_parse_args(int argc, char **argv) const int old_optind = optind; const int old_optopt = optopt; char * const old_optarg = optarg; - struct internal_config *internal_conf = - eal_get_internal_configuration(); argvopt = argv; optind = 1; @@ -816,6 +874,9 @@ eal_parse_args(int argc, char **argv) case OPT_MATCH_ALLOCATIONS_NUM: internal_conf->match_allocations = 1; break; + case OPT_MAP_PERFECT_NUM: + internal_conf->map_perfect = 1; + break; default: if (opt < OPT_LONG_MIN_NUM && isprint(opt)) { @@ -837,7 +898,7 @@ eal_parse_args(int argc, char **argv) } /* create runtime data directory. In no_shconf mode, skip any errors */ - if (eal_create_runtime_dir() < 0) { + if (eal_create_runtime_dir(sec_idx) < 0) { if (internal_conf->no_shconf == 0) { RTE_LOG(ERR, EAL, "Cannot create runtime directory\n"); ret = -1; @@ -846,13 +907,18 @@ eal_parse_args(int argc, char **argv) RTE_LOG(WARNING, EAL, "No DPDK runtime directory created\n"); } - if (eal_adjust_config(internal_conf) != 0) { - ret = -1; - goto out; + if (!internal_conf->pri_and_sec) { + ret = eal_adjust_config(internal_conf); + if (ret != 0) + goto out; + } else { + ret = eal_sec_adjust_config(internal_conf); + if (ret != 0) + goto out; } /* sanity checks */ - if (eal_check_common_options(internal_conf) != 0) { + if (eal_check_common_options(internal_conf, rte_cfg) != 0) { eal_usage(prgname); ret = -1; goto out; @@ -871,6 +937,24 @@ eal_parse_args(int argc, char **argv) return ret; } +static int +eal_parse_args(int argc, char **argv) +{ + struct internal_config *internal_conf = eal_get_internal_configuration(); + + return __eal_parse_args(argc, argv, -1, + internal_conf, + rte_eal_get_configuration()); +} + +static int +eal_sec_parse_args(int argc, char **argv, const int sec_idx) +{ + return __eal_parse_args(argc, argv, sec_idx, + rte_eal_sec_get_internal_config(sec_idx), + rte_eal_sec_get_configuration(sec_idx)); +} + static int check_socket(const struct rte_memseg_list *msl, void *arg) { @@ -1437,3 +1521,101 @@ rte_eal_check_module(const char *module_name) /* Module has been found */ return 1; } + + +/****** APIs for libnet ******/ +int +rte_eal_sec_attach(int argc, char **argv) +{ + int ret; + int sec_idx = -1; + struct internal_config *lc_internal_conf = NULL; + + if (sec_count >= RTE_MAX_SECONDARY) { + RTE_LOG(ERR, EAL, "Too many secondary processes: %d.\n", sec_count); + rte_errno = EINVAL; + return -1; + } + + for (int i = 0; i < RTE_MAX_SECONDARY; ++i) { + lc_internal_conf = rte_eal_sec_get_internal_config(i); + if (lc_internal_conf->pri_and_sec == 0) { + lc_internal_conf->pri_and_sec = 1; + sec_idx = i; + break; + } + } + + eal_reset_internal_config(lc_internal_conf); + + ret = eal_sec_parse_args(argc, argv, sec_idx); + if (ret < 0) { + if (ret == -EALREADY) { + RTE_LOG(ERR, EAL, "file_refix %s already called initialization.\n", + lc_internal_conf->hugefile_prefix); + rte_errno = EALREADY; + } else { + RTE_LOG(ERR, EAL, "Invalid 'command line' arguments.\n"); + rte_errno = EINVAL; + } + return -1; + } + + rte_sec_config_init(sec_idx); + + ret = rte_eal_sec_memory_init(sec_idx); + if (ret < 0) { + RTE_LOG(ERR, EAL, "Cannot init memory\n"); + rte_errno = ENOMEM; + return -1; + } + + sec_count++; + return 0; +} + +int +rte_eal_sec_detach(const char *file_prefix, int length) +{ + int ret; + int sec_idx = -1; + struct internal_config *lc_internal_conf = NULL; + + if (!file_prefix || length <= 0) { + RTE_LOG(ERR, EAL, "Invalid 'file_prefix or length' arguments.\n"); + rte_errno = EINVAL; + return -1; + } + + for (int i = 0; i < RTE_MAX_SECONDARY; ++i) { + lc_internal_conf = rte_eal_sec_get_internal_config(i); + if (lc_internal_conf->pri_and_sec == 0) + continue; + if (!strncmp(lc_internal_conf->hugefile_prefix, file_prefix, length)) { + sec_idx = i; + break; + } + } + if (sec_idx == -1) { + RTE_LOG(ERR, EAL, "Cannot find file_prefix %s.\n", file_prefix); + rte_errno = EINVAL; + return -1; + } + + ret = rte_eal_sec_memory_cleanup(sec_idx); + if (ret < 0) { + RTE_LOG(ERR, EAL, "Cannot cleanup memory\n"); + rte_errno = ENOMEM; + return -1; + } + + ret = eal_sec_config_cleanup(sec_idx); + if (ret < 0) { + RTE_LOG(ERR, EAL, "Cannot cleanup hugepage sharefile.\n"); + rte_errno = EACCES; + return -1; + } + + sec_count--; + return 0; +} diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c index 9fb0e968db..41acf180ee 100644 --- a/lib/eal/linux/eal_hugepage_info.c +++ b/lib/eal/linux/eal_hugepage_info.c @@ -389,7 +389,7 @@ calc_num_pages(struct hugepage_info *hpi, struct dirent *dirent) */ total_pages = 0; /* we also don't want to do this for legacy init */ - if (!internal_conf->legacy_mem) + if (!internal_conf->legacy_mem || internal_conf->map_perfect) for (i = 0; i < rte_socket_count(); i++) { int socket = rte_socket_id_by_idx(i); unsigned int num_pages = diff --git a/lib/eal/linux/eal_memalloc.c b/lib/eal/linux/eal_memalloc.c index fc354f4a17..dac9098c8c 100644 --- a/lib/eal/linux/eal_memalloc.c +++ b/lib/eal/linux/eal_memalloc.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "eal_filesystem.h" #include "eal_internal_cfg.h" @@ -95,12 +96,14 @@ static int fallocate_supported = -1; /* unknown */ * they will be initialized at startup, and filled as we allocate/deallocate * segments. */ -static struct { +struct fd_list{ int *fds; /**< dynamically allocated array of segment lock fd's */ int memseg_list_fd; /**< memseg list fd */ int len; /**< total length of the array */ int count; /**< entries used in an array */ -} fd_list[RTE_MAX_MEMSEG_LISTS]; +}; +static struct fd_list fd_list[RTE_MAX_MEMSEG_LISTS]; +static struct fd_list sec_fd_list[RTE_MAX_SECONDARY][RTE_MAX_MEMSEG_LISTS]; /** local copy of a memory map, used to synchronize memory hotplug in MP */ static struct rte_memseg_list local_memsegs[RTE_MAX_MEMSEG_LISTS]; @@ -1462,7 +1465,7 @@ secondary_msl_destroy_walk(const struct rte_memseg_list *msl, } static int -alloc_list(int list_idx, int len) +__alloc_list(int list_idx, int len, struct fd_list *fd_ls) { int *data; int i; @@ -1470,7 +1473,7 @@ alloc_list(int list_idx, int len) eal_get_internal_configuration(); /* single-file segments mode does not need fd list */ - if (!internal_conf->single_file_segments) { + if (!internal_conf->single_file_segments) { // sec todo /* ensure we have space to store fd per each possible segment */ data = malloc(sizeof(int) * len); if (data == NULL) { @@ -1480,24 +1483,36 @@ alloc_list(int list_idx, int len) /* set all fd's as invalid */ for (i = 0; i < len; i++) data[i] = -1; - fd_list[list_idx].fds = data; - fd_list[list_idx].len = len; + fd_ls[list_idx].fds = data; + fd_ls[list_idx].len = len; } else { - fd_list[list_idx].fds = NULL; - fd_list[list_idx].len = 0; + fd_ls[list_idx].fds = NULL; + fd_ls[list_idx].len = 0; } - fd_list[list_idx].count = 0; - fd_list[list_idx].memseg_list_fd = -1; + fd_ls[list_idx].count = 0; + fd_ls[list_idx].memseg_list_fd = -1; return 0; } +static int +alloc_list(int list_idx, int len) +{ + return __alloc_list(list_idx, len, fd_list); +} + +static int +sec_alloc_list(int list_idx, int len, struct fd_list *fd_ls) +{ + return __alloc_list(list_idx, len, fd_ls); +} + static int destroy_list(int list_idx) { const struct internal_config *internal_conf = - eal_get_internal_configuration(); + eal_get_internal_configuration(); /* single-file segments mode does not need fd list */ if (!internal_conf->single_file_segments) { @@ -1552,29 +1567,54 @@ fd_list_destroy_walk(const struct rte_memseg_list *msl, void *arg __rte_unused) return destroy_list(msl_idx); } -int -eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd) +static int +__eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd, + const struct rte_config *rte_cfg, struct fd_list *fd_ls) { - struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; - const struct internal_config *internal_conf = - eal_get_internal_configuration(); - + struct rte_mem_config *mcfg = rte_cfg->mem_config; + const struct internal_config *internal_conf = eal_get_internal_configuration(); + /* single file segments mode doesn't support individual segment fd's */ - if (internal_conf->single_file_segments) + if (internal_conf->single_file_segments) // sec todo return -ENOTSUP; /* if list is not allocated, allocate it */ - if (fd_list[list_idx].len == 0) { + if (fd_ls[list_idx].len == 0) { int len = mcfg->memsegs[list_idx].memseg_arr.len; - if (alloc_list(list_idx, len) < 0) + if (sec_alloc_list(list_idx, len, fd_ls) < 0) return -ENOMEM; } - fd_list[list_idx].fds[seg_idx] = fd; + fd_ls[list_idx].fds[seg_idx] = fd; return 0; } +int +eal_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd) +{ + return __eal_memalloc_set_seg_fd(list_idx, seg_idx, fd, + rte_eal_get_configuration(), fd_list); +} + +int +eal_sec_memalloc_set_seg_fd(int list_idx, int seg_idx, int fd, + const int switch_pri_and_sec, const int sec_idx) +{ + struct rte_config *rte_cfg = NULL; + struct fd_list *fd_ls = NULL; + + if (!switch_pri_and_sec) { + rte_cfg = rte_eal_get_configuration(); + fd_ls = &fd_list[0]; + } else { + rte_cfg = rte_eal_sec_get_configuration(sec_idx); + fd_ls = &sec_fd_list[sec_idx][0]; + } + + return __eal_memalloc_set_seg_fd(list_idx, seg_idx, fd, rte_cfg, fd_ls); +} + int eal_memalloc_set_seg_list_fd(int list_idx, int fd) { @@ -1749,3 +1789,49 @@ eal_memalloc_init(void) return -1; return 0; } + +static int +fd_sec_list_destroy_walk(const struct rte_memseg_list *msl, const int sec_idx) +{ + struct rte_mem_config *mcfg = rte_eal_sec_get_configuration(sec_idx)->mem_config; + struct fd_list *fd_ls = sec_fd_list[sec_idx]; + int list_idx; + + list_idx = msl - mcfg->memsegs; + if (fd_ls[list_idx].len != 0) { + free(fd_ls[list_idx].fds); + /* We have closed fd, seeing in function of eal_legacy_hugepage_attach. */ + //close(fd_ls[list_idx].fds[seg_idx]); + } + memset(&fd_ls[list_idx], 0, sizeof(fd_ls[list_idx])); + + return 0; +} + +int +eal_sec_memalloc_destroy(const int sec_idx) +{ + struct rte_mem_config *mcfg = rte_eal_sec_get_configuration(sec_idx)->mem_config; + int i, ret = 0; + + for (i = 0; i < RTE_MAX_MEMSEG_LISTS; i++) { + struct rte_memseg_list *msl = &mcfg->memsegs[i]; + + if (msl->base_va == NULL) + continue; + + if (fd_sec_list_destroy_walk(msl, sec_idx)) { + RTE_LOG(ERR, EAL, "Failed to clear secondary fd_list.\n"); + return -1; + } + + ret = rte_sec_fbarray_destroy(&msl->memseg_arr, sec_idx); + if (ret) + return ret; + + rte_mem_unmap(msl->base_va, msl->len); + memset(msl, 0, sizeof(*msl)); + } + + return 0; +} diff --git a/lib/eal/linux/eal_memory.c b/lib/eal/linux/eal_memory.c index 03a4f2dd2d..4d78a47e0a 100644 --- a/lib/eal/linux/eal_memory.c +++ b/lib/eal/linux/eal_memory.c @@ -992,6 +992,7 @@ static int remap_needed_hugepages(struct hugepage_file *hugepages, int n_pages) { int cur_page, seg_start_page, new_memseg, ret; + const struct internal_config *internal_conf = eal_get_internal_configuration(); seg_start_page = 0; for (cur_page = 0; cur_page < n_pages; cur_page++) { @@ -1017,10 +1018,10 @@ remap_needed_hugepages(struct hugepage_file *hugepages, int n_pages) * address to lower address. Here, physical addresses are in * descending order. */ - else if ((prev->physaddr - cur->physaddr) != cur->size) + else if (!internal_conf->map_perfect && (prev->physaddr - cur->physaddr) != cur->size) new_memseg = 1; #else - else if ((cur->physaddr - prev->physaddr) != cur->size) + else if (!internal_conf->map_perfect && (cur->physaddr - prev->physaddr) != cur->size) new_memseg = 1; #endif @@ -1235,6 +1236,24 @@ eal_legacy_hugepage_init(void) for (i = 0; i < (int) internal_conf->num_hugepage_sizes; i++) { /* meanwhile, also initialize used_hp hugepage sizes in used_hp */ used_hp[i].hugepage_sz = internal_conf->hugepage_info[i].hugepage_sz; + + if (internal_conf->map_perfect) { + int sys_num_pages = 0; + int need_num_pages = 0; + struct rte_memseg_list *msl; + + for (j = 0; j < RTE_MAX_NUMA_NODES; j++) { + sys_num_pages += internal_conf->hugepage_info[i].num_pages[j]; + } + + for (j = 0; j < RTE_MAX_MEMSEG_LISTS; j++) { + msl = &mcfg->memsegs[j]; + if (internal_conf->hugepage_info[i].hugepage_sz == msl->page_sz) + need_num_pages += msl->memseg_arr.len; + } + + internal_conf->hugepage_info[i].num_pages[0] = RTE_MIN(sys_num_pages, need_num_pages); + } nr_hugepages += internal_conf->hugepage_info[i].num_pages[0]; } @@ -1316,8 +1335,13 @@ eal_legacy_hugepage_init(void) goto fail; } - qsort(&tmp_hp[hp_offset], hpi->num_pages[0], - sizeof(struct hugepage_file), cmp_physaddr); + /* continuous physical memory does not bring performance improvements, + * so no sorting is performed for quick startup. + */ + if (!internal_conf->map_perfect) { + qsort(&tmp_hp[hp_offset], hpi->num_pages[0], + sizeof(struct hugepage_file), cmp_physaddr); + } /* we have processed a num of hugepages of this size, so inc offset */ hp_offset += hpi->num_pages[0]; @@ -1502,9 +1526,9 @@ getFileSize(int fd) * in order to form a contiguous block in the virtual memory space */ static int -eal_legacy_hugepage_attach(void) +eal_legacy_hugepage_attach(const int switch_pri_and_sec, const int sec_idx) { - struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; + struct rte_mem_config *mcfg = NULL; struct hugepage_file *hp = NULL; unsigned int num_hp = 0; unsigned int i = 0; @@ -1512,6 +1536,22 @@ eal_legacy_hugepage_attach(void) off_t size = 0; int fd, fd_hugepage = -1; + struct rte_config *rte_cfg = NULL; + struct internal_config *internal_conf = NULL; + char *runtime_dir = NULL; + + if (!switch_pri_and_sec) { + runtime_dir = rte_eal_get_runtime_dir(); + rte_cfg = rte_eal_get_configuration(); + internal_conf = eal_get_internal_configuration(); + } else { + runtime_dir = rte_eal_sec_get_runtime_dir(sec_idx); + rte_cfg = rte_eal_sec_get_configuration(sec_idx); + internal_conf = rte_eal_sec_get_internal_config(sec_idx); + } + + mcfg = rte_cfg->mem_config; + if (aslr_enabled() > 0) { RTE_LOG(WARNING, EAL, "WARNING: Address Space Layout Randomization " "(ASLR) is enabled in the kernel.\n"); @@ -1519,10 +1559,10 @@ eal_legacy_hugepage_attach(void) "into secondary processes\n"); } - fd_hugepage = open(eal_hugepage_data_path(), O_RDONLY); + fd_hugepage = open(eal_sec_hugepage_data_path(runtime_dir), O_RDONLY); if (fd_hugepage < 0) { RTE_LOG(ERR, EAL, "Could not open %s\n", - eal_hugepage_data_path()); + eal_sec_hugepage_data_path(runtime_dir)); goto error; } @@ -1530,7 +1570,7 @@ eal_legacy_hugepage_attach(void) hp = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd_hugepage, 0); if (hp == MAP_FAILED) { RTE_LOG(ERR, EAL, "Could not mmap %s\n", - eal_hugepage_data_path()); + eal_sec_hugepage_data_path(runtime_dir)); goto error; } @@ -1577,13 +1617,13 @@ eal_legacy_hugepage_attach(void) } /* find segment data */ - msl = rte_mem_virt2memseg_list(map_addr); + msl = rte_sec_mem_virt2memseg_list(map_addr, rte_cfg); if (msl == NULL) { RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg list\n", __func__); goto mmap_error; } - ms = rte_mem_virt2memseg(map_addr, msl); + ms = rte_sec_mem_virt2memseg(map_addr, msl, rte_cfg); if (ms == NULL) { RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg\n", __func__); @@ -1598,8 +1638,16 @@ eal_legacy_hugepage_attach(void) goto mmap_error; } + /* No hugefile lock is required in PRI_AND_SEC mode, close it + * to avoid opening too much fd. + */ + if (internal_conf->pri_and_sec) { + close(fd); + fd = -1; + } + /* store segment fd internally */ - if (eal_memalloc_set_seg_fd(msl_idx, ms_idx, fd) < 0) + if (eal_sec_memalloc_set_seg_fd(msl_idx, ms_idx, fd, switch_pri_and_sec, sec_idx) < 0) RTE_LOG(ERR, EAL, "Could not store segment fd: %s\n", rte_strerror(rte_errno)); } @@ -1648,13 +1696,17 @@ rte_eal_hugepage_init(void) } int -rte_eal_hugepage_attach(void) +rte_eal_hugepage_attach(const int switch_pri_and_sec, const int sec_idx) { - const struct internal_config *internal_conf = - eal_get_internal_configuration(); + struct internal_config *internal_conf; + + if (!switch_pri_and_sec) + internal_conf = eal_get_internal_configuration(); + else + internal_conf = rte_eal_sec_get_internal_config(sec_idx); return internal_conf->legacy_mem ? - eal_legacy_hugepage_attach() : + eal_legacy_hugepage_attach(switch_pri_and_sec, sec_idx) : eal_hugepage_attach(); } @@ -1873,9 +1925,10 @@ memseg_primary_init(void) } static int -memseg_secondary_init(void) +memseg_secondary_init(struct rte_config *rte_cfg, + const int switch_pri_and_sec, const int sec_idx) { - struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; + struct rte_mem_config *mcfg = rte_cfg->mem_config; int msl_idx = 0; struct rte_memseg_list *msl; @@ -1887,7 +1940,7 @@ memseg_secondary_init(void) if (msl->memseg_arr.len == 0) continue; - if (rte_fbarray_attach(&msl->memseg_arr)) { + if (rte_sec_fbarray_attach(&msl->memseg_arr, switch_pri_and_sec, sec_idx)) { RTE_LOG(ERR, EAL, "Cannot attach to primary process memseg lists\n"); return -1; } @@ -1903,11 +1956,18 @@ memseg_secondary_init(void) } int -rte_eal_memseg_init(void) +rte_eal_memseg_init(const int switch_pri_and_sec, const int sec_idx) { /* increase rlimit to maximum */ struct rlimit lim; + struct rte_config *rte_cfg = NULL; + if (!switch_pri_and_sec) { + rte_cfg = rte_eal_get_configuration(); + } else { + rte_cfg = rte_eal_sec_get_configuration(sec_idx); + } + #ifndef RTE_EAL_NUMA_AWARE_HUGEPAGES const struct internal_config *internal_conf = eal_get_internal_configuration(); @@ -1935,11 +1995,11 @@ rte_eal_memseg_init(void) } #endif - return rte_eal_process_type() == RTE_PROC_PRIMARY ? + return rte_cfg->process_type == RTE_PROC_PRIMARY ? #ifndef RTE_ARCH_64 memseg_primary_init_32() : #else memseg_primary_init() : #endif - memseg_secondary_init(); + memseg_secondary_init(rte_cfg, switch_pri_and_sec, sec_idx); } diff --git a/lib/ring/rte_ring.h b/lib/ring/rte_ring.h index da17ed6d7c..ef18a2b39b 100644 --- a/lib/ring/rte_ring.h +++ b/lib/ring/rte_ring.h @@ -802,6 +802,81 @@ rte_ring_dequeue_burst(struct rte_ring *r, void **obj_table, n, available); } +/****** APIs for libnet ******/ +static __rte_always_inline unsigned +rte_ring_cn_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n) +{ + const uint32_t old_head = r->prod.tail; + rte_smp_rmb(); + + const uint32_t entries = r->cons.head - old_head; + if (n > entries) { + n = entries; + } + if (unlikely(n == 0)) { + return 0; + } + + r->prod.head = old_head + n; + rte_smp_rmb(); + + __rte_ring_dequeue_elems(r, old_head, obj_table, sizeof(void *), n); + return n; +} + +static __rte_always_inline void +rte_ring_cn_enqueue(struct rte_ring *r) +{ + rte_smp_wmb(); + r->prod.tail = r->prod.head; +} + +static __rte_always_inline unsigned +rte_ring_en_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n) +{ + const uint32_t old_tail = r->cons.tail; + rte_smp_rmb(); + + const uint32_t entries = r->prod.tail - old_tail; + if (n > entries) { + n = entries; + } + if (unlikely(n == 0)) { + return 0; + } + + const uint32_t new_tail = old_tail + n; + rte_smp_rmb(); + + __rte_ring_dequeue_elems(r, old_tail, obj_table, sizeof(void *), n); + rte_smp_rmb(); + + r->cons.tail = new_tail; + return n; +} + +static __rte_always_inline unsigned +rte_ring_en_enqueue_bulk(struct rte_ring *r, void **obj_table, unsigned int n) +{ + const uint32_t capacity = r->capacity; + const uint32_t old_head = r->cons.head; + rte_smp_rmb(); + + const uint32_t entries = capacity + r->cons.tail - old_head; + if (n > entries) { + return 0; + } + + const uint32_t new_head = old_head + n; + rte_smp_rmb(); + + __rte_ring_enqueue_elems(r, old_head, obj_table, sizeof(void *), n); + rte_smp_wmb(); + + r->cons.head = new_head; + return n; +} + #ifdef __cplusplus } #endif -- 2.27.0