---
helper/Makefile.am | 5 +-
helper/include/odp/helper/odp_table.h | 184 ++++++++++++++++++
helper/odp_hashtable.c | 342 ++++++++++++++++++++++++++++++++++
helper/odp_hashtable.h | 37 ++++
helper/odp_lineartable.c | 210 +++++++++++++++++++++
helper/odp_lineartable.h | 37 ++++
helper/odp_list_internal.h | 82 ++++++++
helper/test/Makefile.am | 5 +-
helper/test/odp_table_test.c | 119 ++++++++++++
9 files changed, 1019 insertions(+), 2 deletions(-)
mode change 100644 => 100755 helper/Makefile.am
create mode 100755 helper/include/odp/helper/odp_table.h
create mode 100755 helper/odp_hashtable.c
create mode 100755 helper/odp_hashtable.h
create mode 100755 helper/odp_lineartable.c
create mode 100755 helper/odp_lineartable.h
create mode 100755 helper/odp_list_internal.h
mode change 100644 => 100755 helper/test/Makefile.am
create mode 100755 helper/test/odp_table_test.c
diff --git a/helper/Makefile.am b/helper/Makefile.am
old mode 100644
new mode 100755
index 1a74e8e..32a6184
--- a/helper/Makefile.am
+++ b/helper/Makefile.am
@@ -17,6 +17,7 @@ helperinclude_HEADERS = \
$(srcdir)/include/odp/helper/ip.h\
$(srcdir)/include/odp/helper/ipsec.h\
$(srcdir)/include/odp/helper/tcp.h\
+ $(srcdir)/include/odp/helper/odp_table.h\
$(srcdir)/include/odp/helper/udp.h
noinst_HEADERS = \
@@ -25,6 +26,8 @@ noinst_HEADERS = \
__LIB__libodphelper_la_SOURCES = \
linux.c \
- ring.c
+ ring.c \
+ odp_hashtable.c \
+ odp_lineartable.c
lib_LTLIBRARIES = $(LIB)/libodphelper.la
diff --git a/helper/include/odp/helper/odp_table.h
b/helper/include/odp/helper/odp_table.h
new file mode 100755
index 0000000..3e9c5ab
--- /dev/null
+++ b/helper/include/odp/helper/odp_table.h
@@ -0,0 +1,184 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *
+ * ODP table
+ *
+ * This tool is part of ODP helper suite, designed to provide a standard
interface
+ * to implement different types of tables for data processing.
+ * Use case:
+ * Table is publicly used in the following scenarios in data plane:
+ * ARP Table, IP Routing Table, MAC address filtering, ACL, interworking etc.
+ * The features of the "table":
+ * 1) All these different types of "table" have the common operations:
+ * Create a table, destroy a table, add an entry (key/value pairs), delete
an entry, and lookup the value via the key.
+ * Usually these operations are software based, but also can be hardware
accelerated if cost,
+ * power consumption are not the concern in your platform.
+ * 2) Different types of "table" can use different algorithms to
add/delete/lookup the entry.
+ *
+ */
+
+#ifndef ODP_TABLE_H_
+#define ODP_TABLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ODP_TABLE_NAME_LEN 32
+
+typedef ODP_HANDLE_T(odp_table_t);
+
+/**
+* create a table
+* Generally, we suppose Tables only support key-value pair both with fixed size
+*
+* @param name
+* name of this table, max ODP_TABLE_NAME_LEN - 1
+* May be specified as NULL for anonymous table
+* @param capacity
+* Max memory usage this table use, in MBytes(for memory allocation purpose)
+* @param key_size
+* fixed size of the 'key' in bytes.
+* @param value_size
+* fixed size of the 'value' in bytes.
+* @return
+* Handle to table instance or NULL if failed
+* @note
+*/
+typedef odp_table_t (*odp_table_create)(const char *name, uint32_t capacity,
uint32_t key_size, uint32_t value_size);
+
+/**
+ * Find a table by name
+ *
+ * @param name: Name of the table
+ *
+ * @return Handle of found table
+ * @retval NULL table could not be found
+ *
+ * @note
+ * This routine cannot be used to look up an anonymous table (one created
with no name).
+ * This API supports Multiprocess
+ */
+typedef odp_table_t (*odp_table_lookup)(const char *name);
+
+/**
+ * Destroy a table previously created by odp_table_create()
+ *
+ * @param table: Handle of the table to be destroyed
+ *
+ * @retval 0 Success
+ * @retval -1 Failure
+ *
+ * @note
+ * This routine destroys a previously created pool
+ * also should free any memory allocated at creation
+ *
+ */
+typedef int (*odp_table_destroy)(odp_table_t table);
+
+/**
+ * table element add
+ *
+ * @param table: Handle of the table that the element be added
+ *
+ * @param key : address of 'key' in key-value pair.
+ * User should make sure the address and 'key_size' bytes after
are accessible
+ * @param value : address of 'value' in key-value pair
+ * User should make sure the address and 'value_size' bytes after
are accessible
+ * @retval 0 Success
+ * @retval -1 Failure
+ *
+ * @note: Add a same key again with a new value, the older value will be
covered.
+ * This API supports Multiprocess
+ */
+typedef int (*odp_table_put_value)(odp_table_t table,void* key,void *value);
+
+/**
+ * table element lookup
+ *
+ * @param table: Handle of the table that the element be added
+ *
+ * @param key : address of 'key' in key-value pair
+ * User should make sure the address and key_size bytes after are
accessible
+ *
+ * @param buffer : output The buffer address to the 'value'
+ After successfully found, the content of 'value' will be
copied to this address
+ * User should make sure the address and value_size bytes
after are accessible
+ * @param buffer_size: size of the buffer, should be equal or bigger than
value_size
+
+ * @retval 0 Success
+ * @retval -1 Failure
+ *
+ * @note: This API supports Multiprocess
+ */
+typedef int (*odp_table_get_value)(odp_table_t table,void* key,void *buffer,
uint32_t buffer_size);
+
+
+/**
+ * table element remove
+ *
+ * @param table: Handle of the table that the element will be removed from
+ *
+ * @param key : address of 'key' in key-value pair
+ * User should make sure the address and key_size bytes after are
accessible
+ *
+ * @retval 0 Success
+ * @retval -1 Failure
+ *
+ * @note: This API supports Multiprocess
+ */
+typedef int (*odp_table_remove_value)(odp_table_t table, void *key);
+
+struct odp_table_ops {
+ odp_table_create f_create; /* Table Create */
+ odp_table_lookup f_lookup; /* Table Lookup */
+ odp_table_destroy f_des; /* Table Destroy */
+ odp_table_put_value f_put; /* Value Put */
+ odp_table_get_value f_get; /* Value Get */
+ odp_table_remove_value f_remove; /* Value Remove */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/helper/odp_hashtable.c b/helper/odp_hashtable.c
new file mode 100755
index 0000000..0162e5b
--- /dev/null
+++ b/helper/odp_hashtable.c
@@ -0,0 +1,342 @@
+/* Copyright (c) 2013, Linaro Limited
+* All rights reserved.
+*
+* SPDX-License-Identifier: BSD-3-Clause
+*/
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "odp_hashtable.h"
+#include "odp_list_internal.h"
+#include "odph_debug.h"
+
+#include <odp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ODP_SUCCESS 0
+#define ODP_FAIL -1
+
+#define ODP_HASH_TABLE_MAGIC_WORD 0xABABBABA
+#define ODP_MAX_BUCKET_NUM 0x10000 /* 64k */
+
+/* inner element structure of hash table */
+typedef struct odp_hash_node{
+ list_object list_node; //list structure
+ char content[0]; //Flexible Array,memory will be alloced
when table has been created
+ //Its length is key_size+value_size,
suppose key_size = m; value_size = n;
+ // its structure is like:
+ // key_byte1 key_byte2
key_byte3...key_byten value_byte1...value_bytem
+} odp_hash_node;
+
+typedef struct{
+ uint32_t magicword; //for check
+ odp_rwlock_t *lock_pool; //multi-process support,every list
has one rw lock
+ list_head *list_head_pool; //table bucket pool,every hash
value has one list head
+ //To resolve the hash conflict
+ uint32_t key_size;
+ uint32_t value_size;
+ uint32_t head_num; //number of the list head in
list_head_pool
+ uint32_t init_cap;
+ odp_hash_node *hash_node_pool; //table element pool
+ uint32_t hash_node_num; //number of element in the
hash_node_pool
+ char rsv[7]; //for align
+ char name[ODP_TABLE_NAME_LEN]; //table name
+} odp_hash_table_imp;
+
+//odp_hash_table_imp g_stGlobalHashTables[ODP_MAX_HASH_TABLE_NUM];
+
+
+odp_table_t odp_hash_table_create(const char *name, uint32_t capacity,
uint32_t key_size, uint32_t value_size)
+{
+ int idx,i;
+ uint32_t node_num;
+ odp_hash_table_imp * hash_tbl;
+ odp_shm_t shmem;
+ uint32_t node_mem;
+ if(strlen(name) >= ODP_TABLE_NAME_LEN || capacity < 1 || capacity >=
0x1000 || key_size == 0 || value_size == 0)
+ {
+ ODPH_DBG("create para input error!\n");
+ return NULL;
+ }
+ hash_tbl = (odp_hash_table_imp *)odp_shm_addr(odp_shm_lookup(name));
+ if(hash_tbl != NULL)
+ {
+ ODPH_DBG("name already exist\n");
+ return NULL;
+ }
+ shmem = odp_shm_reserve(name,capacity<<20,64,ODP_SHM_SW_ONLY);
+ if(shmem == ODP_SHM_INVALID)
+ {
+ ODPH_DBG("shm reserve fail\n");
+ return NULL;
+ }
+ hash_tbl = (odp_hash_table_imp *)odp_shm_addr(shmem);
+
+ /* clean this block of memory */
+ memset(hash_tbl,0,capacity<<20);
+
+ hash_tbl->init_cap = capacity<<20;
+ strncpy(hash_tbl->name,name,ODP_TABLE_NAME_LEN);
+ hash_tbl->key_size = key_size;
+ hash_tbl->value_size = value_size;
+
+ /* header of this mem block is the table control struct,
+ * then the lock pool, then the list header pool
+ * the last part is the element node pool
+ */
+
+ hash_tbl->lock_pool = (odp_rwlock_t*)((char*)hash_tbl +
sizeof(odp_hash_table_imp));
+ hash_tbl->list_head_pool = (list_head*)((char*)hash_tbl->lock_pool +
ODP_MAX_BUCKET_NUM * sizeof(odp_rwlock_t));
+
+ node_mem = hash_tbl->init_cap - sizeof(odp_hash_table_imp) -
ODP_MAX_BUCKET_NUM * (sizeof(list_head) + sizeof(odp_rwlock_t));
+ node_num = node_mem / (sizeof(odp_hash_node) + key_size + value_size);
+ hash_tbl->hash_node_num = node_num;
+ hash_tbl->hash_node_pool = (odp_hash_node
*)((char*)hash_tbl->list_head_pool + ODP_MAX_BUCKET_NUM * sizeof(list_head));
+
+ /* init every list head and rw lock */
+ for(i = 0;i < ODP_MAX_BUCKET_NUM;i++)
+ {
+ INIT_LIST_HEAD(&(hash_tbl->list_head_pool[i]));
+ odp_rwlock_init((odp_rwlock_t*)&(hash_tbl->lock_pool[i]));
+ }
+
+ /* finish */
+ hash_tbl->magicword = ODP_HASH_TABLE_MAGIC_WORD;
+ return (odp_table_t)hash_tbl;
+}
+
+int odp_hash_table_destroy(odp_table_t table)
+{
+ int ret;
+ if(table != NULL)
+ {
+ odp_hash_table_imp *hash_tbl = (odp_hash_table_imp*)table;
+ if(hash_tbl->magicword != ODP_HASH_TABLE_MAGIC_WORD)
+ {
+ return ODP_FAIL;
+ }
+ ret = odp_shm_free(odp_shm_lookup(hash_tbl->name));
+ if(ret != 0)
+ {
+ ODPH_DBG("free fail\n");
+ return ret;
+ }
+ /* clean head */
+ return ODP_SUCCESS;
+ }
+ return ODP_FAIL;
+}
+
+odp_table_t odp_hash_table_lookup(const char *name)
+{
+ int idx;
+ odp_hash_table_imp * hash_tbl;
+ if(name == NULL || strlen(name) >= ODP_TABLE_NAME_LEN)
+ {
+ return NULL;
+ }
+ hash_tbl = (odp_hash_table_imp *)odp_shm_addr(odp_shm_lookup(name));
+ if(hash_tbl != NULL && strcmp(hash_tbl->name,name) == 0)
+ {
+ return (odp_table_t)hash_tbl;
+ }
+ return NULL;
+}
+/*
+ * Calculate has value by the input key and key_size
+ * This hash algorithm is the most simple one, so we choose it as an DEMO
+ * User can use any other algorithm, like CRC...
+ */
+uint16_t odp_key_hash(void *key, uint32_t key_size)
+{
+ register uint32_t hash = 0;
+ uint32_t idx = (key_size == 0 ? 1:key_size);
+ uint32_t ch;
+
+ while(idx != 0)
+ {
+ ch = (uint32_t)(*(char*)key);
+ hash = hash * 131 + ch;
+ idx--;
+ }
+ return (uint16_t)(hash & 0x0000FFFF);
+}
+
+/*
+ * Get an available node from pool
+ */
+odp_hash_node * odp_hashnode_take(odp_table_t table)
+{
+ odp_hash_table_imp *hash_tbl = (odp_hash_table_imp*)table;
+ uint32_t idx;
+ odp_hash_node *pNode;
+ for(idx = 0; idx < hash_tbl->hash_node_num;idx++)
+ {
+ /* notice: memory of one hash_node is not only sizeof(odp_hash_node)
+ * should add the size of Flexible Array
+ */
+ pNode = (odp_hash_node *)((char*)hash_tbl->hash_node_pool
+ + idx * (sizeof(odp_hash_node) + hash_tbl->key_size +
hash_tbl->value_size));
+ if(pNode->list_node.next == NULL
+ &&pNode->list_node.prev == NULL)
+ {
+ INIT_LIST_HEAD(&(pNode->list_node));
+ return pNode;
+ }
+ }
+ return NULL;
+}
+/*
+ * Release an node to the pool
+ */
+void odp_hashnode_give(odp_table_t table, odp_hash_node *node)
+{
+ odp_hash_table_imp *hash_tbl = (odp_hash_table_imp*)table;
+ if(node == NULL)
+ {
+ return;
+ }
+ list_del(&node->list_node);
+ memset(node,0,(sizeof(odp_hash_node) + hash_tbl->key_size +
hash_tbl->value_size));
+}
+
+/* should make sure the input table exists and is available */
+int odp_hash_put_value(odp_table_t table, void *key, void *value)
+{
+ odp_hash_table_imp *hash_tbl = (odp_hash_table_imp*)table;
+ uint16_t hash = 0;
+ odp_hash_node *node = NULL;
+ char* tmp = NULL;
+ if(table == NULL || key == NULL || value == NULL)
+ {
+ return ODP_FAIL;
+ }
+
+ /* hash value is just the index of the list head in pool */
+ hash = odp_key_hash(key, hash_tbl->key_size);
+
+ odp_rwlock_write_lock(&hash_tbl->lock_pool[hash]);
+ /* First, check if the key already exist */
+ LIST_FOR_EACH(node,&hash_tbl->list_head_pool[hash],odp_hash_node,list_node)
+ {
+ if(memcmp(node->content,key,hash_tbl->key_size) == 0)
+ {
+ /* copy value content to hash node*/
+ tmp = (void*)((char*)node->content + hash_tbl->key_size);
+ memcpy(tmp,value,hash_tbl->value_size);
+
+ odp_rwlock_write_unlock(&hash_tbl->lock_pool[hash]);
+
+ return ODP_SUCCESS;
+ }
+ }
+
+ /*if the key is a new one, get hash node form the pool */
+ node = odp_hashnode_take(table);
+ if(node == NULL)
+ {
+ odp_rwlock_write_unlock(&hash_tbl->lock_pool[hash]);
+ return ODP_FAIL;
+ }
+
+ /* copy both key and value content to the hash node */
+ memcpy(node->content,key,hash_tbl->key_size);
+ tmp = (void*)((char*)node->content + hash_tbl->key_size);
+ memcpy(tmp,value,hash_tbl->value_size);
+
+ /* add the node to list */
+ list_add(&node->list_node,&hash_tbl->list_head_pool[hash]);
+
+ odp_rwlock_write_unlock(&hash_tbl->lock_pool[hash]);
+ return ODP_SUCCESS;
+}
+
+/* should make sure the input table exists and is available */
+int odp_hash_get_value(odp_table_t table, void *key, void *buffer, uint32_t
buffer_size)
+{
+ odp_hash_table_imp *hash_tbl = (odp_hash_table_imp*)table;
+ uint16_t hash = 0;
+ odp_hash_node *node;
+ char* tmp = NULL;
+
+ if(table == NULL || key == NULL || buffer == NULL || buffer_size <
hash_tbl->value_size)
+ {
+ return ODP_FAIL;
+ }
+
+ /* hash value is just the index of the list head in pool */
+ hash = odp_key_hash(key, hash_tbl->key_size);
+
+ odp_rwlock_read_lock(&hash_tbl->lock_pool[hash]);
+
+ LIST_FOR_EACH(node,&hash_tbl->list_head_pool[hash],odp_hash_node,list_node)
+ {
+ /* in case of hash conflict, compare the whole key */
+ if(memcmp(node->content,key,hash_tbl->key_size) == 0)
+ {
+ /* find the target */
+ tmp = (void*)((char*)node->content + hash_tbl->key_size);
+ memcpy(buffer,tmp,hash_tbl->value_size);
+
+ odp_rwlock_read_unlock(&hash_tbl->lock_pool[hash]);
+
+ return ODP_SUCCESS;
+ }
+ }
+
+ odp_rwlock_read_unlock(&hash_tbl->lock_pool[hash]);
+
+ return ODP_FAIL;
+}
+
+/* should make sure the input table exists and is available */
+int odp_hash_remove_value(odp_table_t table, void *key)
+{
+ odp_hash_table_imp *hash_tbl = (odp_hash_table_imp*)table;
+ uint16_t hash = 0;
+ odp_hash_node *node;
+ if(table == NULL || key == NULL)
+ {
+ return ODP_FAIL;
+ }
+
+ /* hash value is just the index of the list head in pool */
+ hash = odp_key_hash(key, hash_tbl->key_size);
+
+ odp_rwlock_write_lock(&hash_tbl->lock_pool[hash]);
+
+ LIST_FOR_EACH(node,&hash_tbl->list_head_pool[hash],odp_hash_node,list_node)
+ {
+ if(memcmp(node->content,key,hash_tbl->key_size) == 0)
+ {
+ odp_hashnode_give(table,node);
+
+ odp_rwlock_write_unlock(&hash_tbl->lock_pool[hash]);
+
+ return ODP_SUCCESS;
+ }
+ }
+
+ odp_rwlock_write_unlock(&hash_tbl->lock_pool[hash]);
+
+ return ODP_SUCCESS;
+}
+
+
+struct odp_table_ops odp_hash_table_ops =
+{
+ odp_hash_table_create,
+ odp_hash_table_lookup,
+ odp_hash_table_destroy,
+ odp_hash_put_value,
+ odp_hash_get_value,
+ odp_hash_remove_value,
+};
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/helper/odp_hashtable.h b/helper/odp_hashtable.h
new file mode 100755
index 0000000..f513e3e
--- /dev/null
+++ b/helper/odp_hashtable.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP Hash table
+ */
+
+#ifndef ODP_HASH_TABLE_H_
+#define ODP_HASH_TABLE_H_
+
+#include <stdint.h>
+#include <odp/plat/strong_types.h>
+#include <odp/helper/odp_table.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern odp_table_t odp_hash_table_create(const char *name, uint32_t
capacity, uint32_t key_size,uint32_t value_size);
+ extern odp_table_t odp_hash_table_lookup(const char *name);
+ extern int odp_hash_table_destroy(odp_table_t table);
+ extern int odp_hash_put_value(odp_table_t table, void *key, void *value);
+ extern int odp_hash_get_value(odp_table_t table, void *key, void
*buffer, uint32_t buffer_size);
+ extern int odp_hash_remove_value(odp_table_t table, void *key);
+
+ extern struct odp_table_ops odp_hash_table_ops;
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/helper/odp_lineartable.c b/helper/odp_lineartable.c
new file mode 100755
index 0000000..98e72b0
--- /dev/null
+++ b/helper/odp_lineartable.c
@@ -0,0 +1,210 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "odp_lineartable.h"
+#include "odph_debug.h"
+#include <odp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ODP_SUCCESS 0
+#define ODP_FAIL -1
+#define ODP_LINEAR_TABLE_MAGIC_WORD 0xEFEFFEFE
+/* internal table struct */
+typedef struct{
+ uint32_t magicword; //for check
+ uint32_t init_cap; //capacity
+ uint32_t node_sum; //given the capacity,it shows
how many nodes can we put into this table
+ uint32_t value_size; //size of one linear table
element, including the rwlock in the head
+ void *data_array; //node pool
+ char name[ODP_TABLE_NAME_LEN];
+} odp_linear_table_imp;
+
+
+odp_table_t odp_linear_table_create(const char *name, uint32_t capacity,
uint32_t key_size, uint32_t value_size)
+{
+ int idx;
+ uint32_t node_num;
+ odp_shm_t shmem;
+ odp_linear_table_imp * linear_tbl;
+ /* Note: for linear table, key must be an uint32_t, its is fixed 4. So, we
ignore the input key_size here*/
+ (void)key_size;
+
+ if(strlen(name) >= ODP_TABLE_NAME_LEN || capacity < 1 || capacity >=
0x1000 || value_size == 0)
+ {
+ printf("create para input error or less than !");
+ return NULL;
+ }
+ /* check name confict in shm*/
+ linear_tbl = (odp_linear_table_imp *)odp_shm_addr(odp_shm_lookup(name));
+ if(linear_tbl != NULL)
+ {
+ ODPH_DBG("name already exist\n");
+ return NULL;
+ }
+
+ /* alloc memory from shm */
+ shmem = odp_shm_reserve(name,capacity<<20,64,ODP_SHM_SW_ONLY);
+ if(shmem == ODP_SHM_INVALID)
+ {
+ ODPH_DBG("shm reserve fail\n");
+ return NULL;
+ }
+ linear_tbl = (odp_linear_table_imp *)odp_shm_addr(shmem);
+
+ /* clean this block of memory */
+ memset(linear_tbl,0,capacity<<20);
+
+ linear_tbl->init_cap = capacity<20;
+
+ strncpy(linear_tbl->name,name,ODP_TABLE_NAME_LEN);
+
+ /* for linear table, the key is just the index, without confict
+ * so we just need to record the value content
+ * there is a rwlock in the head of every node
+ */
+
+ linear_tbl->value_size = value_size + sizeof(odp_rwlock_t);
+
+ node_num = linear_tbl->init_cap / linear_tbl->value_size;
+ linear_tbl->node_sum = node_num;
+
+ linear_tbl->data_array = (void*)((char*)linear_tbl +
sizeof(odp_linear_table_imp));
+
+ /* initialize rwlock*/
+ for(idx = 0;idx < linear_tbl->node_sum;idx++)
+ {
+ odp_rwlock_t* lock = (odp_rwlock_t*)((char*)linear_tbl->data_array +
idx * linear_tbl->value_size);
+ odp_rwlock_init(lock);
+ }
+
+ linear_tbl->magicword = ODP_LINEAR_TABLE_MAGIC_WORD;
+
+ return (odp_table_t)(linear_tbl);
+}
+
+int odp_linear_table_destroy(odp_table_t table)
+{
+ int ret;
+ if(table != NULL)
+ {
+ odp_linear_table_imp *linear_tbl = (odp_linear_table_imp*)table;
+ if(linear_tbl->magicword != ODP_LINEAR_TABLE_MAGIC_WORD)
+ {
+ return ODP_FAIL;
+ }
+ ret = odp_shm_free(odp_shm_lookup(linear_tbl->name));
+ if(ret != 0)
+ {
+ ODPH_DBG("free fail\n");
+ return ret;
+ }
+ /* clean head */
+ return ODP_SUCCESS;
+ }
+ return ODP_FAIL;
+}
+
+odp_table_t odp_linear_table_lookup(const char *name)
+{
+ int idx;
+ odp_linear_table_imp * linear_tbl;
+ if(name == NULL || strlen(name) >= ODP_TABLE_NAME_LEN)
+ {
+ return NULL;
+ }
+ linear_tbl = (odp_linear_table_imp *)odp_shm_addr(odp_shm_lookup(name));
+ if(linear_tbl != NULL
+ && linear_tbl->magicword == ODP_LINEAR_TABLE_MAGIC_WORD
+ && strcmp(linear_tbl->name,name) == 0)
+ {
+ return (odp_table_t)linear_tbl;
+ }
+ return NULL;
+}
+
+/* should make sure the input table exists and is available */
+int odp_lineartable_put_value(odp_table_t table, void *key, void *value)
+{
+ odp_linear_table_imp *linear_tbl = (odp_linear_table_imp*)table;
+ uint32_t ikey = 0;
+ void* entry = NULL;
+ odp_rwlock_t* lock = NULL;
+ if(table == NULL || key == NULL || value == NULL)
+ {
+ return ODP_FAIL;
+ }
+
+ ikey = *(uint32_t*)key;
+ if(ikey >= linear_tbl->node_sum)
+ {
+ return ODP_FAIL;
+ }
+
+ entry = (void *)((char*)linear_tbl->data_array + ikey *
linear_tbl->value_size);
+ lock = (odp_rwlock_t*)entry;
+ entry = (char*)entry + sizeof(odp_rwlock_t);
+
+ odp_rwlock_write_lock(lock);
+
+ memcpy(entry,value,linear_tbl->value_size - sizeof(odp_rwlock_t));
+
+ odp_rwlock_write_unlock(lock);
+
+ return ODP_SUCCESS;
+}
+
+/* should make sure the input table exists and is available */
+int odp_lineartable_get_value(odp_table_t table, void *key, void *buffer,
uint32_t buffer_size)
+{
+ odp_linear_table_imp *linear_tbl = (odp_linear_table_imp*)table;
+ uint32_t ikey = 0;
+ void* entry = NULL;
+ odp_rwlock_t* lock = NULL;
+ if(table == NULL || key == NULL || buffer == NULL)
+ {
+ return ODP_FAIL;
+ }
+
+ ikey = *(uint32_t*)key;
+ if(ikey >= linear_tbl->node_sum)
+ {
+ return ODP_FAIL;
+ }
+
+ entry = (void *)((char*)linear_tbl->data_array + ikey *
linear_tbl->value_size);
+ lock = (odp_rwlock_t*)entry;
+ entry = (char*)entry + sizeof(odp_rwlock_t);
+
+ odp_rwlock_read_lock(lock);
+
+ memcpy(buffer,entry,linear_tbl->value_size - sizeof(odp_rwlock_t));
+
+ odp_rwlock_read_unlock(lock);
+
+ return ODP_SUCCESS;
+}
+
+struct odp_table_ops odp_linear_table_ops =
+{
+odp_linear_table_create,
+odp_linear_table_lookup,
+odp_linear_table_destroy,
+odp_lineartable_put_value,
+odp_lineartable_get_value,
+NULL,
+};
+
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/helper/odp_lineartable.h b/helper/odp_lineartable.h
new file mode 100755
index 0000000..7cfa0da
--- /dev/null
+++ b/helper/odp_lineartable.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP Hash table
+ */
+
+#ifndef ODP_HASH_TABLE_H_
+#define ODP_HASH_TABLE_H_
+
+#include <stdint.h>
+#include <odp/plat/strong_types.h>
+#include <odp/helper/odp_table.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern odp_table_t odp_linear_table_create(const char *name, uint32_t
capacity,uint32_t key_size,uint32_t value_size);
+ extern odp_table_t odp_linear_table_lookup(const char *name);
+ extern int odp_linear_table_destroy(odp_table_t table);
+ extern int odp_linear_put_value(odp_table_t table, void *key, void
*value);
+ extern int odp_linear_get_value(odp_table_t table, void *key, void
*buffer,uint32_t buffer_size);
+
+ extern struct odp_table_ops odp_linear_table_ops;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/helper/odp_list_internal.h b/helper/odp_list_internal.h
new file mode 100755
index 0000000..a3743cf
--- /dev/null
+++ b/helper/odp_list_internal.h
@@ -0,0 +1,82 @@
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP list
+ */
+
+#ifndef ODP_LIST_INTER_H_
+#define ODP_LIST_INTER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct list_object {
+ struct list_object *next, *prev;
+ } list_object;
+
+ typedef list_object list_head;
+
+ static inline void INIT_LIST_HEAD(list_object *list)
+ {
+ list->next = list;
+ list->prev = list;
+
+ }
+
+ static inline void __list_add(list_object *new,list_object
*prev,list_object *next)
+ {
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+ }
+ static inline void list_add(list_object *new, struct list_object *head)
+ {
+ __list_add(new, head, head->next);
+ }
+
+ static inline void list_add_tail(struct list_object *new, struct
list_object *head)
+ {
+ __list_add(new, head->prev, head);
+ }
+
+ static inline void __list_del(struct list_object * prev, struct
list_object * next)
+ {
+ next->prev = prev;
+ prev->next = next;
+ }
+
+ static inline void list_del(struct list_object *entry)
+ {
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+ }
+
+ static inline int list_empty(const struct list_object *head)
+ {
+ return head->next == head;
+ }
+ #ifndef offsetof
+ #define offsetof(type, list_node) ((size_t) &((type *)0)->list_node)
+ #endif
+
+ #define container_of(ptr, type, list_node) ((type *)(void *)((char *)ptr -
offsetof(type,list_node)))
+
+ #define LIST_FOR_EACH(pos, list_head, type, list_node) \
+ for (pos = container_of((list_head)->next,type,list_node); \
+ &(pos->list_node) != (list_head); \
+ pos = container_of(pos->list_node.next,type,list_node))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/helper/test/Makefile.am b/helper/test/Makefile.am
old mode 100644
new mode 100755
index fbf5a9b..06ebe33
--- a/helper/test/Makefile.am
+++ b/helper/test/Makefile.am
@@ -8,7 +8,8 @@ TESTS_ENVIRONMENT += TEST_DIR=${builddir}
EXECUTABLES = odp_chksum$(EXEEXT) \
odp_thread$(EXEEXT) \
odp_process$(EXEEXT)\
- odph_pause$(EXEEXT)
+ odph_pause$(EXEEXT)\
+ odp_table_test$(EXEEXT)
COMPILE_ONLY =
@@ -29,3 +30,5 @@ odp_thread_LDADD = $(LIB)/libodphelper.la $(LIB)/libodp.la
dist_odp_process_SOURCES = odp_process.c
odp_process_LDADD = $(LIB)/libodphelper.la $(LIB)/libodp.la
odph_pause_SOURCES = odph_pause.c
+dist_odp_table_test_SOURCES = odp_table_test.c
+dist_odp_table_test_LDADD = $(LIB)/libodphelper.la $(LIB)/libodp.la
diff --git a/helper/test/odp_table_test.c b/helper/test/odp_table_test.c
new file mode 100755
index 0000000..e9f74b4
--- /dev/null
+++ b/helper/test/odp_table_test.c
@@ -0,0 +1,119 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <test_debug.h>
+#include <../odp_hashtable.h>
+#include <../odp_lineartable.h>
+#include <odp.h>
+
+extern int odp_shm_init_global(void);
+extern int odp_shm_init_local(void);
+
+int main(int argc TEST_UNUSED, char *argv[] TEST_UNUSED)
+{
+ int ret = 0;
+ odp_table_t table;
+ odp_table_t tmp_tbl;
+ struct odp_table_ops *test_ops;
+ char tmp[32];
+ char ip_addr1[] = "12345678";
+ char ip_addr2[] = "11223344";
+ char ip_addr3[] = "55667788";
+ char mac_addr1[] = "0A1122334401";
+ char mac_addr2[] = "0A1122334402";
+ char mac_addr3[] = "0B4433221101";
+ char mac_addr4[] = "0B4433221102";
+
+ ret = odp_shm_init_global();
+ if(ret != 0)
+ {
+ printf("odp_shm_init_global fail\n");
+ return 1;
+ }
+ ret = odp_shm_init_local();
+ if(ret != 0)
+ {
+ printf("odp_shm_init_local fail\n");
+ return 1;
+ }
+
+
+ printf("test hash table:\n");
+ test_ops = &odp_hash_table_ops;
+
+ table = test_ops->f_create("test",2,4,16);
+ if(table == NULL)
+ {
+ printf("table create fail\n");
+ return 1;
+ }
+ ret += test_ops->f_put(table,&ip_addr1,mac_addr1);
+
+ ret += test_ops->f_put(table,&ip_addr2,mac_addr2);
+
+ ret += test_ops->f_put(table,&ip_addr3,mac_addr3);
+
+ if(ret != 0)
+ {
+ printf("put value fail\n");
+ return 1;
+ }
+
+ ret = test_ops->f_get(table,&ip_addr1,&tmp,32);
+ if(ret != 0)
+ {
+ printf("get value fail\n");
+ return 1;
+ }
+ printf("\t1 get '123' tmp = %s,\n",tmp);
+
+ ret = test_ops->f_put(table,&ip_addr1,mac_addr4);
+ if(ret != 0)
+ {
+ printf("repeat put value fail\n");
+ return 1;
+ }
+
+ ret = test_ops->f_get(table,&ip_addr1,&tmp,32);
+ if(ret != 0 || strcmp(tmp,mac_addr4)!=0)
+ {
+ printf("get value fail\n");
+ return 1;
+ }
+
+ printf("\t2 repeat get '123' value = %s\n",tmp);
+
+ ret = test_ops->f_remove(table,&ip_addr1);
+ if(ret != 0)
+ {
+ printf("remove value fail\n");
+ return 1;
+ }
+ ret = test_ops->f_get(table,&ip_addr1,tmp,32);
+ if(ret == 0 )
+ {
+ printf("remove value fail actually\n");
+ return 1;
+ }
+ printf("\t3 remove success!\n");
+
+ tmp_tbl = test_ops->f_lookup("test");
+ if(tmp_tbl != table)
+ {
+ printf("lookup table fail!!!\n");
+ }
+ printf("\t4 lookup table success!\n");
+
+ ret = test_ops->f_des(table);
+ if(ret != 0)
+ {
+ printf("destory table fail!!!\n");
+ }
+ printf("\t5 destory table success!\n");
+
+ printf("all test finished success!!\n");
+ return 0;
+}
--
1.9.1
_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp