diff options
Diffstat (limited to 'VNFs/DPPD-PROX/prox_shared.c')
-rw-r--r-- | VNFs/DPPD-PROX/prox_shared.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/VNFs/DPPD-PROX/prox_shared.c b/VNFs/DPPD-PROX/prox_shared.c new file mode 100644 index 00000000..890d564b --- /dev/null +++ b/VNFs/DPPD-PROX/prox_shared.c @@ -0,0 +1,174 @@ +/* +// Copyright (c) 2010-2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include <stdio.h> +#include <rte_hash.h> +#include <rte_hash_crc.h> +#include <rte_version.h> + +#include "quit.h" +#include "log.h" +#include "prox_shared.h" +#include "prox_globals.h" + +#define INIT_HASH_TABLE_SIZE 8192 + +struct prox_shared { + struct rte_hash *hash; + size_t size; +}; + +struct prox_shared sh_system; +struct prox_shared sh_socket[MAX_SOCKETS]; +struct prox_shared sh_core[RTE_MAX_LCORE]; + +static char* get_sh_name(void) +{ + static char name[] = "prox_sh"; + + name[0]++; + return name; +} + +struct rte_hash_parameters param = { + .key_len = 256, + .hash_func = rte_hash_crc, + .hash_func_init_val = 0, + .socket_id = 0, +}; + +static void prox_sh_create_hash(struct prox_shared *ps, size_t size) +{ + param.entries = size; + param.name = get_sh_name(); + ps->hash = rte_hash_create(¶m); + PROX_PANIC(ps->hash == NULL, "Failed to create hash table for shared data"); + ps->size = size; + if (ps->size == INIT_HASH_TABLE_SIZE) + plog_info("Shared data tracking hash table created with size %zu\n", ps->size); + else + plog_info("Shared data tracking hash table grew to %zu\n", ps->size); +} + +#if RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0) +static int copy_hash(struct rte_hash *new_hash, struct rte_hash *old_hash) +{ + const void *next_key; + void *next_data; + uint32_t iter = 0; + + while (rte_hash_iterate(old_hash, &next_key, &next_data, &iter) >= 0) { + if (rte_hash_add_key_data(new_hash, next_key, next_data) < 0) + return -1; + } + + return 0; +} +#endif + +static int prox_sh_add(struct prox_shared *ps, const char *name, void *data) +{ + char key[256] = {0}; + int ret; + + strncpy(key, name, sizeof(key)); + if (ps->size == 0) { + prox_sh_create_hash(ps, INIT_HASH_TABLE_SIZE); + } + +#if RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0) + do { + ret = rte_hash_add_key_data(ps->hash, key, data); + if (ret < 0) { + struct rte_hash *old = ps->hash; + int success; + do { + prox_sh_create_hash(ps, ps->size * 2); + success = !copy_hash(ps->hash, old); + if (success) + rte_hash_free(old); + else + rte_hash_free(ps->hash); + } while (!success); + } + } while (ret < 0); +#else + PROX_PANIC(1, "DPDK < 2.1 not fully supported"); +#endif + return 0; +} + +static void *prox_sh_find(struct prox_shared *sh, const char *name) +{ +#if RTE_VERSION >= RTE_VERSION_NUM(2,1,0,0) + char key[256] = {0}; + int ret; + void *data; + + if (!sh->hash) + return NULL; + + strncpy(key, name, sizeof(key)); + ret = rte_hash_lookup_data(sh->hash, key, &data); + if (ret >= 0) + return data; +#else + PROX_PANIC(1, "DPDK < 2.1 not fully supported"); +#endif + return NULL; +} + +int prox_sh_add_system(const char *name, void *data) +{ + return prox_sh_add(&sh_system, name, data); +} + +int prox_sh_add_socket(const int socket_id, const char *name, void *data) +{ + if (socket_id >= MAX_SOCKETS) + return -1; + + return prox_sh_add(&sh_socket[socket_id], name, data); +} + +int prox_sh_add_core(const int core_id, const char *name, void *data) +{ + if (core_id >= RTE_MAX_LCORE) + return -1; + + return prox_sh_add(&sh_core[core_id], name, data); +} + +void *prox_sh_find_system(const char *name) +{ + return prox_sh_find(&sh_system, name); +} + +void *prox_sh_find_socket(const int socket_id, const char *name) +{ + if (socket_id >= MAX_SOCKETS) + return NULL; + + return prox_sh_find(&sh_socket[socket_id], name); +} + +void *prox_sh_find_core(const int core_id, const char *name) +{ + if (core_id >= RTE_MAX_LCORE) + return NULL; + + return prox_sh_find(&sh_core[core_id], name); +} |