New configs with libconfig
git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5071 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
char* hashtble_rc_code2string(hashtbl_rc_t rcP)
|
||||
char* hashtable_rc_code2string(hashtable_rc_t rcP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
switch (rcP) {
|
||||
@@ -17,220 +17,226 @@ char* hashtble_rc_code2string(hashtbl_rc_t rcP)
|
||||
case HASH_TABLE_KEY_NOT_EXISTS: return "HASH_TABLE_KEY_NOT_EXISTS";break;
|
||||
case HASH_TABLE_KEY_ALREADY_EXISTS: return "HASH_TABLE_KEY_ALREADY_EXISTS";break;
|
||||
case HASH_TABLE_BAD_PARAMETER_HASHTABLE: return "HASH_TABLE_BAD_PARAMETER_HASHTABLE";break;
|
||||
default: return "UNKNOWN hashtbl_rc_t";
|
||||
|
||||
default: return "UNKNOWN hashtable_rc_t";
|
||||
}
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* free int function
|
||||
* hash_free_int_func() is used when this hashtable is used to store int values as data (pointer = value).
|
||||
*/
|
||||
|
||||
void hash_free_int_func(void* memoryP){}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Default hash function
|
||||
* def_hashfunc() is the default used by hashtbl_create() when the user didn't specify one.
|
||||
* def_hashfunc() is the default used by hashtable_create() when the user didn't specify one.
|
||||
* This is a simple/naive hash function which adds the key's ASCII char values. It will probably generate lots of collisions on large hash tables.
|
||||
*/
|
||||
|
||||
static hash_size_t def_hashfunc(const uint64_t keyP)
|
||||
{
|
||||
return (hash_size_t)keyP;
|
||||
return (hash_size_t)keyP;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Initialisation
|
||||
* hashtbl_create() sets up the initial structure of the hash table. The user specified size will be allocated and initialized to NULL.
|
||||
* hashtable_create() sets up the initial structure of the hash table. The user specified size will be allocated and initialized to NULL.
|
||||
* The user can also specify a hash function. If the hashfunc argument is NULL, a default hash function is used.
|
||||
* If an error occurred, NULL is returned. All other values in the returned hash_table_t pointer should be released with hashtbl_destroy().
|
||||
* If an error occurred, NULL is returned. All other values in the returned hash_table_t pointer should be released with hashtable_destroy().
|
||||
*/
|
||||
hash_table_t *hashtbl_create(hash_size_t sizeP, hash_size_t (*hashfuncP)(const uint64_t ), void (*freefuncP)(void*))
|
||||
hash_table_t *hashtable_create(hash_size_t sizeP, hash_size_t (*hashfuncP)(const uint64_t ), void (*freefuncP)(void*))
|
||||
{
|
||||
hash_table_t *hashtbl;
|
||||
hash_table_t *hashtbl;
|
||||
|
||||
if(!(hashtbl=malloc(sizeof(hash_table_t)))) return NULL;
|
||||
if(!(hashtbl=malloc(sizeof(hash_table_t)))) return NULL;
|
||||
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(hash_node_t*)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(hash_node_t*)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashtbl->size=sizeP;
|
||||
hashtbl->size=sizeP;
|
||||
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
|
||||
if(freefuncP) hashtbl->freefunc=freefuncP;
|
||||
else hashtbl->freefunc=free;
|
||||
if(freefuncP) hashtbl->freefunc=freefuncP;
|
||||
else hashtbl->freefunc=free;
|
||||
|
||||
return hashtbl;
|
||||
return hashtbl;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Cleanup
|
||||
* The hashtbl_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the hash_table_t.
|
||||
* The hashtable_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the hash_table_t.
|
||||
*/
|
||||
hashtbl_rc_t hashtbl_destroy(hash_table_t *hashtblP)
|
||||
hashtable_rc_t hashtable_destroy(hash_table_t *hashtblP)
|
||||
{
|
||||
hash_size_t n;
|
||||
hash_node_t *node, *oldnode;
|
||||
hash_size_t n;
|
||||
hash_node_t *node, *oldnode;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
if (oldnode->data) {
|
||||
hashtblP->freefunc(oldnode->data);
|
||||
}
|
||||
free(oldnode);
|
||||
}
|
||||
}
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
return HASH_TABLE_OK;
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
if (oldnode->data) {
|
||||
hashtblP->freefunc(oldnode->data);
|
||||
}
|
||||
free(oldnode);
|
||||
}
|
||||
}
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtbl_rc_t hashtbl_is_key_exists (hash_table_t *hashtblP, const uint64_t keyP)
|
||||
hashtable_rc_t hashtable_is_key_exists (hash_table_t *hashtblP, const uint64_t keyP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtbl_rc_t hashtbl_apply_funct_on_elements (hash_table_t *hashtblP, void functP(uint64_t keyP, void* dataP, void* parameterP), void* parameterP)
|
||||
hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t *hashtblP, void functP(uint64_t keyP, void* dataP, void* parameterP), void* parameterP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
hash_node_t *node = NULL;
|
||||
unsigned int i = 0;
|
||||
unsigned int num_elements = 0;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
while ((num_elements < hashtblP->num_elements) && (i < hashtblP->size)) {
|
||||
if (hashtblP->nodes[i] != NULL) {
|
||||
node=hashtblP->nodes[i];
|
||||
while(node) {
|
||||
num_elements += 1;
|
||||
functP(node->key, node->data, parameterP);
|
||||
node=node->next;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return HASH_TABLE_OK;
|
||||
hash_node_t *node = NULL;
|
||||
unsigned int i = 0;
|
||||
unsigned int num_elements = 0;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
while ((num_elements < hashtblP->num_elements) && (i < hashtblP->size)) {
|
||||
if (hashtblP->nodes[i] != NULL) {
|
||||
node=hashtblP->nodes[i];
|
||||
while(node) {
|
||||
num_elements += 1;
|
||||
functP(node->key, node->data, parameterP);
|
||||
node=node->next;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Adding a new element
|
||||
* To make sure the hash value is not bigger than size, the result of the user provided hash function is used modulo size.
|
||||
*/
|
||||
hashtbl_rc_t hashtbl_insert(hash_table_t *hashtblP, const uint64_t keyP, void *dataP)
|
||||
hashtable_rc_t hashtable_insert(hash_table_t *hashtblP, const uint64_t keyP, void *dataP)
|
||||
{
|
||||
hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
node->data=dataP;
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if(!(node=malloc(sizeof(hash_node_t)))) return -1;
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
hashtblP->nodes[hash]=node;
|
||||
hashtblP->num_elements += 1;
|
||||
return HASH_TABLE_OK;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
node->data=dataP;
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if(!(node=malloc(sizeof(hash_node_t)))) return -1;
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
hashtblP->nodes[hash]=node;
|
||||
hashtblP->num_elements += 1;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* To remove an element from the hash table, we just search for it in the linked list for that hash value,
|
||||
* and remove it if it is found. If it was not found, it is an error and -1 is returned.
|
||||
*/
|
||||
hashtbl_rc_t hashtbl_remove(hash_table_t *hashtblP, const uint64_t keyP)
|
||||
hashtable_rc_t hashtable_remove(hash_table_t *hashtblP, const uint64_t keyP)
|
||||
{
|
||||
hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash;
|
||||
hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key != keyP) {
|
||||
if(prevnode) prevnode->next=node->next;
|
||||
else hashtblP->nodes[hash]=node->next;
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
free(node);
|
||||
hashtblP->num_elements -= 1;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key != keyP) {
|
||||
if(prevnode) prevnode->next=node->next;
|
||||
else hashtblP->nodes[hash]=node->next;
|
||||
if (node->data) {
|
||||
hashtblP->freefunc(node->data);
|
||||
}
|
||||
free(node);
|
||||
hashtblP->num_elements -= 1;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Searching for an element is easy. We just search through the linked list for the corresponding hash value.
|
||||
* NULL is returned if we didn't find it.
|
||||
*/
|
||||
hashtbl_rc_t hashtbl_get(hash_table_t *hashtblP, const uint64_t keyP, void** dataP)
|
||||
hashtable_rc_t hashtable_get(hash_table_t *hashtblP, const uint64_t keyP, void** dataP)
|
||||
{
|
||||
hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
/* fprintf(stderr, "hashtbl_get() key=%s, hash=%d\n", key, hash);*/
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP)%hashtblP->size;
|
||||
/* fprintf(stderr, "hashtable_get() key=%s, hash=%d\n", key, hash);*/
|
||||
|
||||
node=hashtblP->nodes[hash];
|
||||
node=hashtblP->nodes[hash];
|
||||
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
@@ -240,40 +246,40 @@ hashtbl_rc_t hashtbl_get(hash_table_t *hashtblP, const uint64_t keyP, void** dat
|
||||
* If the number of elements are reduced, the hash table will waste memory. That is why we provide a function for resizing the table.
|
||||
* Resizing a hash table is not as easy as a realloc(). All hash values must be recalculated and each element must be inserted into its new position.
|
||||
* We create a temporary hash_table_t object (newtbl) to be used while building the new hashes.
|
||||
* This allows us to reuse hashtbl_insert() and hashtbl_remove(), when moving the elements to the new table.
|
||||
* This allows us to reuse hashtable_insert() and hashtable_remove(), when moving the elements to the new table.
|
||||
* After that, we can just free the old table and copy the elements from newtbl to hashtbl.
|
||||
*/
|
||||
|
||||
hashtbl_rc_t hashtbl_resize(hash_table_t *hashtblP, hash_size_t sizeP)
|
||||
hashtable_rc_t hashtable_resize(hash_table_t *hashtblP, hash_size_t sizeP)
|
||||
{
|
||||
hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
hash_node_t *node,*next;
|
||||
hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
hash_node_t *node,*next;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(hash_node_t*)))) return -1;
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(hash_node_t*)))) return -1;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
hashtbl_insert(&newtbl, node->key, node->data);
|
||||
// Lionel GAUTHIER: BAD CODE TO BE REWRITTEN
|
||||
hashtbl_remove(hashtblP, node->key);
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
hashtable_insert(&newtbl, node->key, node->data);
|
||||
// Lionel GAUTHIER: BAD CODE TO BE REWRITTEN
|
||||
hashtable_remove(hashtblP, node->key);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
|
||||
return HASH_TABLE_OK;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
#ifndef _HASH_TABLE_H_
|
||||
#define _HASH_TABLE_H_
|
||||
#ifndef _UTILS_COLLECTION_HASH_TABLE_H_
|
||||
#define _UTILS_COLLECTION_HASH_TABLE_H_
|
||||
#include<stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef size_t hash_size_t;
|
||||
|
||||
typedef enum hashtbl_return_code_e {
|
||||
typedef enum hashtable_return_code_e {
|
||||
HASH_TABLE_OK = 0,
|
||||
HASH_TABLE_INSERT_OVERWRITTEN_DATA = 1,
|
||||
HASH_TABLE_KEY_NOT_EXISTS = 2,
|
||||
HASH_TABLE_KEY_ALREADY_EXISTS = 3,
|
||||
HASH_TABLE_BAD_PARAMETER_HASHTABLE = 4,
|
||||
HASH_TABLE_SYSTEM_ERROR = 5,
|
||||
HASH_TABLE_CODE_MAX
|
||||
} hashtbl_rc_t;
|
||||
} hashtable_rc_t;
|
||||
|
||||
|
||||
typedef struct hash_node_s {
|
||||
uint64_t key;
|
||||
void *data;
|
||||
struct hash_node_s *next;
|
||||
uint64_t key;
|
||||
void *data;
|
||||
struct hash_node_s *next;
|
||||
} hash_node_t;
|
||||
|
||||
typedef struct hash_table_s {
|
||||
hash_size_t size;
|
||||
hash_size_t num_elements;
|
||||
struct hash_node_s **nodes;
|
||||
hash_size_t (*hashfunc)(const uint64_t);
|
||||
void (*freefunc)(void*);
|
||||
hash_size_t size;
|
||||
hash_size_t num_elements;
|
||||
struct hash_node_s **nodes;
|
||||
hash_size_t (*hashfunc)(const uint64_t);
|
||||
void (*freefunc)(void*);
|
||||
} hash_table_t;
|
||||
|
||||
char* hashtble_rc_code2string(hashtbl_rc_t rcP);
|
||||
hash_table_t *hashtbl_create (hash_size_t size, hash_size_t (*hashfunc)(const uint64_t ), void (*freefunc)(void*));
|
||||
hashtbl_rc_t hashtbl_destroy(hash_table_t *hashtbl);
|
||||
hashtbl_rc_t hashtbl_is_key_exists (hash_table_t *hashtbl, const uint64_t key);
|
||||
hashtbl_rc_t hashtbl_apply_funct_on_elements (hash_table_t *hashtblP, void funct(uint64_t keyP, void* dataP, void* parameterP), void* parameterP);
|
||||
hashtbl_rc_t hashtbl_insert (hash_table_t *hashtbl, const uint64_t key, void *data);
|
||||
hashtbl_rc_t hashtbl_remove (hash_table_t *hashtbl, const uint64_t key);
|
||||
hashtbl_rc_t hashtbl_get (hash_table_t *hashtbl, const uint64_t key, void **dataP);
|
||||
hashtbl_rc_t hashtbl_resize (hash_table_t *hashtbl, hash_size_t size);
|
||||
char* hashtable_rc_code2string(hashtable_rc_t rcP);
|
||||
void hash_free_int_func(void* memoryP);
|
||||
hash_table_t *hashtable_create (hash_size_t size, hash_size_t (*hashfunc)(const uint64_t ), void (*freefunc)(void*));
|
||||
hashtable_rc_t hashtable_destroy(hash_table_t *hashtbl);
|
||||
hashtable_rc_t hashtable_is_key_exists (hash_table_t *hashtbl, const uint64_t key);
|
||||
hashtable_rc_t hashtable_apply_funct_on_elements (hash_table_t *hashtblP, void funct(uint64_t keyP, void* dataP, void* parameterP), void* parameterP);
|
||||
hashtable_rc_t hashtable_insert (hash_table_t *hashtbl, const uint64_t key, void *data);
|
||||
hashtable_rc_t hashtable_remove (hash_table_t *hashtbl, const uint64_t key);
|
||||
hashtable_rc_t hashtable_get (hash_table_t *hashtbl, const uint64_t key, void **dataP);
|
||||
hashtable_rc_t hashtable_resize (hash_table_t *hashtbl, hash_size_t size);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,189 +8,221 @@
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Default hash function
|
||||
* def_hashfunc() is the default used by hashtbl_create() when the user didn't specify one.
|
||||
* def_hashfunc() is the default used by hashtable_create() when the user didn't specify one.
|
||||
* This is a simple/naive hash function which adds the key's ASCII char values. It will probably generate lots of collisions on large hash tables.
|
||||
*/
|
||||
|
||||
static hash_size_t def_hashfunc(const void *keyP, int key_sizeP)
|
||||
{
|
||||
hash_size_t hash=0;
|
||||
hash_size_t hash=0;
|
||||
|
||||
while(key_sizeP) hash^=((unsigned char*)keyP)[key_sizeP --];
|
||||
while(key_sizeP) hash^=((unsigned char*)keyP)[key_sizeP --];
|
||||
|
||||
return hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Initialisation
|
||||
* hashtbl_create() sets up the initial structure of the hash table. The user specified size will be allocated and initialized to NULL.
|
||||
* hashtable_create() sets up the initial structure of the hash table. The user specified size will be allocated and initialized to NULL.
|
||||
* The user can also specify a hash function. If the hashfunc argument is NULL, a default hash function is used.
|
||||
* If an error occurred, NULL is returned. All other values in the returned obj_hash_table_t pointer should be released with hashtbl_destroy().
|
||||
* If an error occurred, NULL is returned. All other values in the returned obj_hash_table_t pointer should be released with hashtable_destroy().
|
||||
*/
|
||||
obj_hash_table_t *obj_hashtbl_create(hash_size_t sizeP, hash_size_t (*hashfuncP)(const void*, int ), void (*freekeyfuncP)(void*), void (*freedatafuncP)(void*))
|
||||
obj_hash_table_t *obj_hashtable_create(hash_size_t sizeP, hash_size_t (*hashfuncP)(const void*, int ), void (*freekeyfuncP)(void*), void (*freedatafuncP)(void*))
|
||||
{
|
||||
obj_hash_table_t *hashtbl;
|
||||
obj_hash_table_t *hashtbl;
|
||||
|
||||
if(!(hashtbl=malloc(sizeof(obj_hash_table_t)))) return NULL;
|
||||
if(!(hashtbl=malloc(sizeof(obj_hash_table_t)))) return NULL;
|
||||
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(obj_hash_node_t*)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
if(!(hashtbl->nodes=calloc(sizeP, sizeof(obj_hash_node_t*)))) {
|
||||
free(hashtbl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashtbl->size=sizeP;
|
||||
hashtbl->size=sizeP;
|
||||
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
if(hashfuncP) hashtbl->hashfunc=hashfuncP;
|
||||
else hashtbl->hashfunc=def_hashfunc;
|
||||
|
||||
if(freekeyfuncP) hashtbl->freekeyfunc=freekeyfuncP;
|
||||
else hashtbl->freekeyfunc=free;
|
||||
if(freekeyfuncP) hashtbl->freekeyfunc=freekeyfuncP;
|
||||
else hashtbl->freekeyfunc=free;
|
||||
|
||||
if(freedatafuncP) hashtbl->freedatafunc=freedatafuncP;
|
||||
else hashtbl->freedatafunc=free;
|
||||
if(freedatafuncP) hashtbl->freedatafunc=freedatafuncP;
|
||||
else hashtbl->freedatafunc=free;
|
||||
|
||||
return hashtbl;
|
||||
return hashtbl;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Cleanup
|
||||
* The hashtbl_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the obj_hash_table_t.
|
||||
* The hashtable_destroy() walks through the linked lists for each possible hash value, and releases the elements. It also releases the nodes array and the obj_hash_table_t.
|
||||
*/
|
||||
hashtbl_rc_t obj_hashtbl_destroy(obj_hash_table_t *hashtblP)
|
||||
hashtable_rc_t obj_hashtable_destroy(obj_hash_table_t *hashtblP)
|
||||
{
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node, *oldnode;
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node, *oldnode;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
hashtblP->freekeyfunc(oldnode->key);
|
||||
hashtblP->freedatafunc(oldnode->data);
|
||||
free(oldnode);
|
||||
}
|
||||
}
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
return HASH_TABLE_OK;
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
node=hashtblP->nodes[n];
|
||||
while(node) {
|
||||
oldnode=node;
|
||||
node=node->next;
|
||||
hashtblP->freekeyfunc(oldnode->key);
|
||||
hashtblP->freedatafunc(oldnode->data);
|
||||
free(oldnode);
|
||||
}
|
||||
}
|
||||
free(hashtblP->nodes);
|
||||
free(hashtblP);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
hashtbl_rc_t obj_hashtbl_is_key_exists (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP)
|
||||
hashtable_rc_t obj_hashtable_is_key_exists (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP)
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
{
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
return HASH_TABLE_OK;
|
||||
} else if (node->key_size == key_sizeP) {
|
||||
if (memcmp(node->key, keyP, key_sizeP) == 0) {
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Adding a new element
|
||||
* To make sure the hash value is not bigger than size, the result of the user provided hash function is used modulo size.
|
||||
*/
|
||||
hashtbl_rc_t obj_hashtbl_insert(obj_hash_table_t *hashtblP, void* keyP, int key_sizeP, void *dataP)
|
||||
hashtable_rc_t obj_hashtable_insert(obj_hash_table_t *hashtblP, void* keyP, int key_sizeP, void *dataP)
|
||||
{
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freedatafunc(node->data);
|
||||
}
|
||||
node->data=dataP;
|
||||
// waste of memory here (keyP is lost) we should free it now
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if(!(node=malloc(sizeof(obj_hash_node_t)))) return -1;
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
hashtblP->nodes[hash]=node;
|
||||
return HASH_TABLE_OK;
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if (node->data) {
|
||||
hashtblP->freedatafunc(node->data);
|
||||
}
|
||||
node->data=dataP;
|
||||
// waste of memory here (keyP is lost) we should free it now
|
||||
return HASH_TABLE_INSERT_OVERWRITTEN_DATA;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
if(!(node=malloc(sizeof(obj_hash_node_t)))) return -1;
|
||||
node->key=keyP;
|
||||
node->data=dataP;
|
||||
if (hashtblP->nodes[hash]) {
|
||||
node->next=hashtblP->nodes[hash];
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
hashtblP->nodes[hash]=node;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* To remove an element from the hash table, we just search for it in the linked list for that hash value,
|
||||
* and remove it if it is found. If it was not found, it is an error and -1 is returned.
|
||||
*/
|
||||
hashtbl_rc_t obj_hashtbl_remove(obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP)
|
||||
hashtable_rc_t obj_hashtable_remove(obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP)
|
||||
{
|
||||
obj_hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash;
|
||||
obj_hash_node_t *node, *prevnode=NULL;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
if(prevnode) {
|
||||
prevnode->next=node->next;
|
||||
} else {
|
||||
hashtblP->nodes[hash]=node->next;
|
||||
}
|
||||
hashtblP->freekeyfunc(node->key);
|
||||
hashtblP->freedatafunc(node->data);
|
||||
free(node);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if ((node->key == keyP) || ((node->key_size == key_sizeP) && (memcmp(node->key, keyP, key_sizeP) == 0))){
|
||||
if(prevnode) {
|
||||
prevnode->next=node->next;
|
||||
} else {
|
||||
hashtblP->nodes[hash]=node->next;
|
||||
}
|
||||
hashtblP->freekeyfunc(node->key);
|
||||
hashtblP->freedatafunc(node->data);
|
||||
free(node);
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
prevnode=node;
|
||||
node=node->next;
|
||||
}
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Searching for an element is easy. We just search through the linked list for the corresponding hash value.
|
||||
* NULL is returned if we didn't find it.
|
||||
*/
|
||||
hashtbl_rc_t obj_hashtbl_get(obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP, void** dataP)
|
||||
hashtable_rc_t obj_hashtable_get(obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP, void** dataP)
|
||||
{
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
obj_hash_node_t *node;
|
||||
hash_size_t hash;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
if (hashtblP == NULL) {
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
hash=hashtblP->hashfunc(keyP, key_sizeP)%hashtblP->size;
|
||||
node=hashtblP->nodes[hash];
|
||||
while(node) {
|
||||
if(node->key == keyP) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
} else if (node->key_size == key_sizeP) {
|
||||
if (memcmp(node->key, keyP, key_sizeP) == 0) {
|
||||
*dataP = node->data;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
}
|
||||
node=node->next;
|
||||
}
|
||||
*dataP = NULL;
|
||||
return HASH_TABLE_KEY_NOT_EXISTS;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
* Function to return all keys of an object hash table
|
||||
*/
|
||||
hashtable_rc_t obj_hashtable_get_keys(obj_hash_table_t *hashtblP, void ** keysP, unsigned int *sizeP)
|
||||
{
|
||||
size_t n = 0;
|
||||
obj_hash_node_t *node = NULL;
|
||||
obj_hash_node_t *next = NULL;
|
||||
|
||||
*sizeP = 0;
|
||||
keysP = calloc(hashtblP->num_elements, sizeof(void *));
|
||||
if (keysP) {
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
keysP[*sizeP++] = node->key;
|
||||
next = node->next;
|
||||
}
|
||||
}
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
return HASH_TABLE_SYSTEM_ERROR;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
@@ -200,38 +232,37 @@ hashtbl_rc_t obj_hashtbl_get(obj_hash_table_t *hashtblP, const void* keyP, int k
|
||||
* If the number of elements are reduced, the hash table will waste memory. That is why we provide a function for resizing the table.
|
||||
* Resizing a hash table is not as easy as a realloc(). All hash values must be recalculated and each element must be inserted into its new position.
|
||||
* We create a temporary obj_hash_table_t object (newtbl) to be used while building the new hashes.
|
||||
* This allows us to reuse hashtbl_insert() and hashtbl_remove(), when moving the elements to the new table.
|
||||
* This allows us to reuse hashtable_insert() and hashtable_remove(), when moving the elements to the new table.
|
||||
* After that, we can just free the old table and copy the elements from newtbl to hashtbl.
|
||||
*/
|
||||
hashtbl_rc_t obj_hashtbl_resize(obj_hash_table_t *hashtblP, hash_size_t sizeP)
|
||||
hashtable_rc_t obj_hashtable_resize(obj_hash_table_t *hashtblP, hash_size_t sizeP)
|
||||
{
|
||||
obj_hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node,*next;
|
||||
obj_hash_table_t newtbl;
|
||||
hash_size_t n;
|
||||
obj_hash_node_t *node,*next;
|
||||
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
if (hashtblP == NULL) {
|
||||
return HASH_TABLE_BAD_PARAMETER_HASHTABLE;
|
||||
}
|
||||
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
newtbl.size = sizeP;
|
||||
newtbl.hashfunc = hashtblP->hashfunc;
|
||||
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(obj_hash_node_t*)))) return -1;
|
||||
if(!(newtbl.nodes=calloc(sizeP, sizeof(obj_hash_node_t*)))) return HASH_TABLE_SYSTEM_ERROR;
|
||||
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
obj_hashtbl_insert(&newtbl, node->key, node->key_size, node->data);
|
||||
//WARNING Lionel GAUTHIER: BAD CODE TO BE REWRITTEN
|
||||
obj_hashtbl_remove(hashtblP, node->key, node->key_size);
|
||||
}
|
||||
}
|
||||
for(n=0; n<hashtblP->size; ++n) {
|
||||
for(node=hashtblP->nodes[n]; node; node=next) {
|
||||
next = node->next;
|
||||
obj_hashtable_insert(&newtbl, node->key, node->key_size, node->data);
|
||||
obj_hashtable_remove(hashtblP, node->key, node->key_size);
|
||||
}
|
||||
}
|
||||
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
free(hashtblP->nodes);
|
||||
hashtblP->size=newtbl.size;
|
||||
hashtblP->nodes=newtbl.nodes;
|
||||
|
||||
return HASH_TABLE_OK;
|
||||
return HASH_TABLE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,28 +10,29 @@ typedef size_t hash_size_t;
|
||||
|
||||
|
||||
typedef struct obj_hash_node_s {
|
||||
int key_size;
|
||||
void *key;
|
||||
void *data;
|
||||
struct obj_hash_node_s *next;
|
||||
int key_size;
|
||||
void *key;
|
||||
void *data;
|
||||
struct obj_hash_node_s *next;
|
||||
} obj_hash_node_t;
|
||||
|
||||
typedef struct obj_hash_table_s {
|
||||
hash_size_t size;
|
||||
hash_size_t num_elements;
|
||||
struct obj_hash_node_s **nodes;
|
||||
hash_size_t (*hashfunc)(const void*, int);
|
||||
void (*freekeyfunc)(void*);
|
||||
void (*freedatafunc)(void*);
|
||||
hash_size_t size;
|
||||
hash_size_t num_elements;
|
||||
struct obj_hash_node_s **nodes;
|
||||
hash_size_t (*hashfunc)(const void*, int);
|
||||
void (*freekeyfunc)(void*);
|
||||
void (*freedatafunc)(void*);
|
||||
} obj_hash_table_t;
|
||||
|
||||
obj_hash_table_t *obj_hashtbl_create (hash_size_t size, hash_size_t (*hashfunc)(const void*, int ), void (*freekeyfunc)(void*), void (*freedatafunc)(void*));
|
||||
hashtbl_rc_t obj_hashtbl_destroy(obj_hash_table_t *hashtblP);
|
||||
hashtbl_rc_t obj_hashtbl_is_key_exists (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP);
|
||||
hashtbl_rc_t obj_hashtbl_insert (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP, void *dataP);
|
||||
hashtbl_rc_t obj_hashtbl_remove (obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP);
|
||||
hashtbl_rc_t obj_hashtbl_get (obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP, void ** dataP);
|
||||
hashtbl_rc_t obj_hashtbl_resize (obj_hash_table_t *hashtblP, hash_size_t sizeP);
|
||||
obj_hash_table_t *obj_hashtable_create (hash_size_t size, hash_size_t (*hashfunc)(const void*, int ), void (*freekeyfunc)(void*), void (*freedatafunc)(void*));
|
||||
hashtable_rc_t obj_hashtable_destroy (obj_hash_table_t *hashtblP);
|
||||
hashtable_rc_t obj_hashtable_is_key_exists (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP);
|
||||
hashtable_rc_t obj_hashtable_insert (obj_hash_table_t *hashtblP, void* keyP, int key_sizeP, void *dataP);
|
||||
hashtable_rc_t obj_hashtable_remove (obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP);
|
||||
hashtable_rc_t obj_hashtable_get (obj_hash_table_t *hashtblP, const void* keyP, int key_sizeP, void ** dataP);
|
||||
hashtable_rc_t obj_hashtable_get_keys(obj_hash_table_t *hashtblP, void ** keysP, unsigned int *sizeP);
|
||||
hashtable_rc_t obj_hashtable_resize (obj_hash_table_t *hashtblP, hash_size_t sizeP);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ AM_CFLAGS = @ADD_CFLAGS@ \
|
||||
-I$(top_srcdir)/COMMON \
|
||||
-I$(top_srcdir)/NAS/EURECOM-NAS/src/api/network \
|
||||
-I$(top_srcdir)/NAS/EURECOM-NAS/src/include \
|
||||
-I$(top_srcdir)/SGW-LITE \
|
||||
-I$(top_srcdir)/INTERTASK_INTERFACE
|
||||
|
||||
AM_YFLAGS = -d
|
||||
@@ -14,7 +15,6 @@ libutils_la_SOURCES = \
|
||||
conversions.h conversions.c \
|
||||
enum_string.h enum_string.c \
|
||||
log.c log.h \
|
||||
mme_parser.y mme_scanner.l \
|
||||
mme_config.c mme_config.h \
|
||||
mme_default_values.h \
|
||||
queue.h tree.h
|
||||
|
||||
+242
-59
@@ -38,16 +38,19 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libconfig.h>
|
||||
|
||||
#include <arpa/inet.h> /* To provide inet_addr */
|
||||
|
||||
#include "assertions.h"
|
||||
#include "mme_config.h"
|
||||
#include "spgw_config.h"
|
||||
#include "intertask_interface_conf.h"
|
||||
|
||||
mme_config_t mme_config;
|
||||
|
||||
static
|
||||
void config_init(mme_config_t *mme_config_p)
|
||||
void mme_config_init(mme_config_t *mme_config_p)
|
||||
{
|
||||
memset(mme_config_p, 0, sizeof(mme_config_t));
|
||||
|
||||
@@ -65,29 +68,15 @@ void config_init(mme_config_t *mme_config_p)
|
||||
mme_config_p->gtpv1u_config.port_number = GTPV1_U_PORT_NUMBER;
|
||||
mme_config_p->s1ap_config.port_number = S1AP_PORT_NUMBER;
|
||||
/* IP configuration */
|
||||
mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up = DEFAULT_SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP;
|
||||
mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up = inet_addr(DEFAULT_SGW_IP_ADDRESS_FOR_S1U_S12_S4_UP);
|
||||
mme_config_p->ipv4.sgw_ip_netmask_for_S1u_S12_S4_up = DEFAULT_SGW_IP_NETMASK_FOR_S1U_S12_S4_UP;
|
||||
|
||||
mme_config_p->ipv4.sgw_interface_name_for_S5_S8_up = DEFAULT_SGW_INTERFACE_NAME_FOR_S5_S8_UP;
|
||||
mme_config_p->ipv4.sgw_ip_address_for_S5_S8_up = inet_addr(DEFAULT_SGW_IP_ADDRESS_FOR_S5_S8_UP);
|
||||
mme_config_p->ipv4.sgw_ip_netmask_for_S5_S8_up = DEFAULT_SGW_IP_NETMASK_FOR_S5_S8_UP;
|
||||
|
||||
mme_config_p->ipv4.pgw_interface_name_for_SGI = DEFAULT_PGW_INTERFACE_NAME_FOR_S5_S8;
|
||||
mme_config_p->ipv4.pgw_ip_addr_for_SGI = inet_addr(DEFAULT_PGW_IP_ADDRESS_FOR_S5_S8);
|
||||
mme_config_p->ipv4.pgw_ip_netmask_for_SGI = DEFAULT_PGW_IP_NETMASK_FOR_S5_S8;
|
||||
|
||||
mme_config_p->ipv4.mme_interface_name_for_S1_MME = DEFAULT_MME_INTERFACE_NAME_FOR_S1_MME;
|
||||
mme_config_p->ipv4.mme_ip_address_for_S1_MME = inet_addr(DEFAULT_MME_IP_ADDRESS_FOR_S1_MME);
|
||||
mme_config_p->ipv4.mme_ip_netmask_for_S1_MME = DEFAULT_MME_IP_NETMASK_FOR_S1_MME;
|
||||
|
||||
mme_config_p->ipv4.mme_interface_name_for_S11 = DEFAULT_MME_INTERFACE_NAME_FOR_S11;
|
||||
mme_config_p->ipv4.mme_ip_address_for_S11 = inet_addr(DEFAULT_MME_IP_ADDRESS_FOR_S11);
|
||||
mme_config_p->ipv4.mme_ip_netmask_for_S11 = DEFAULT_MME_IP_NETMASK_FOR_S11;
|
||||
|
||||
mme_config_p->ipv4.sgw_interface_name_for_S11 = DEFAULT_SGW_INTERFACE_NAME_FOR_S11;
|
||||
mme_config_p->ipv4.sgw_ip_address_for_S11 = inet_addr(DEFAULT_SGW_IP_ADDRESS_FOR_S11);
|
||||
mme_config_p->ipv4.sgw_ip_netmask_for_S11 = DEFAULT_SGW_IP_NETMASK_FOR_S11;
|
||||
|
||||
mme_config_p->s6a_config.conf_file = S6A_CONF_FILE;
|
||||
|
||||
@@ -123,34 +112,231 @@ void config_init(mme_config_t *mme_config_p)
|
||||
|
||||
static int config_parse_file(mme_config_t *mme_config_p)
|
||||
{
|
||||
extern FILE *yyin;
|
||||
int ret = -1;
|
||||
config_t cfg;
|
||||
config_setting_t *setting_mme = NULL;
|
||||
config_setting_t *setting = NULL;
|
||||
config_setting_t *subsetting = NULL;
|
||||
config_setting_t *sub2setting = NULL;
|
||||
|
||||
if (mme_config_p == NULL)
|
||||
return ret;
|
||||
if (mme_config_p->config_file == NULL) {
|
||||
fprintf(stderr, "No Configuration file given... Attempting default values\n");
|
||||
return 0;
|
||||
long int alongint;
|
||||
int i, num;
|
||||
char *astring = NULL;
|
||||
char *address = NULL;
|
||||
char *cidr = NULL;
|
||||
|
||||
char *sgw_ip_address_for_S1u_S12_S4_up = NULL;
|
||||
char *mme_interface_name_for_S1_MME = NULL;
|
||||
char *mme_ip_address_for_S1_MME = NULL;
|
||||
char *mme_interface_name_for_S11 = NULL;
|
||||
char *mme_ip_address_for_S11 = NULL;
|
||||
char *sgw_ip_address_for_S11 = NULL;
|
||||
|
||||
config_init(&cfg);
|
||||
|
||||
if(mme_config_p->config_file != NULL)
|
||||
{
|
||||
/* Read the file. If there is an error, report it and exit. */
|
||||
if(! config_read_file(&cfg, mme_config_p->config_file))
|
||||
{
|
||||
fprintf(stdout, "ERROR: %s:%d - %s\n", mme_config_p->config_file, config_error_line(&cfg), config_error_text(&cfg));
|
||||
config_destroy(&cfg);
|
||||
AssertFatal (1 == 0, "Failed to parse MME configuration file %s!\n", mme_config_p->config_file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stdout, "ERROR No MME configuration file provided!\n");
|
||||
config_destroy(&cfg);
|
||||
AssertFatal (0, "No MME configuration file provided!\n");
|
||||
}
|
||||
|
||||
yyin = fopen(mme_config_p->config_file, "r");
|
||||
if (!yyin) {
|
||||
/* We failed to open the file */
|
||||
fprintf(stderr, "Unable to open the configuration file: %s (%d:%s)\n",
|
||||
mme_config_p->config_file, errno, strerror(errno));
|
||||
return errno;
|
||||
setting_mme = config_lookup(&cfg, MME_CONFIG_STRING_MME_CONFIG);
|
||||
if(setting_mme != NULL) {
|
||||
// GENERAL MME SETTINGS
|
||||
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_REALM, (const char **)&astring) )) {
|
||||
mme_config_p->realm = strdup(astring);
|
||||
mme_config_p->realm_length = strlen(mme_config_p->realm);
|
||||
}
|
||||
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_MAXENB, &alongint) )) {
|
||||
mme_config_p->max_eNBs = (uint32_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_MAXUE, &alongint) )) {
|
||||
mme_config_p->max_ues = (uint32_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_RELATIVE_CAPACITY, &alongint) )) {
|
||||
mme_config_p->relative_capacity = (uint8_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( setting_mme, MME_CONFIG_STRING_STATISTIC_TIMER, &alongint) )) {
|
||||
mme_config_p->mme_statistic_timer = (uint32_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_EMERGENCY_ATTACH_SUPPORTED, (const char **)&astring) )) {
|
||||
if (strcasecmp(astring , "yes") == 0)
|
||||
mme_config_p->emergency_attach_supported = 1;
|
||||
else
|
||||
mme_config_p->emergency_attach_supported = 0;
|
||||
}
|
||||
if( (config_setting_lookup_string( setting_mme, MME_CONFIG_STRING_UNAUTHENTICATED_IMSI_SUPPORTED, (const char **)&astring) )) {
|
||||
if (strcasecmp(astring , "yes") == 0)
|
||||
mme_config_p->unauthenticated_imsi_supported = 1;
|
||||
else
|
||||
mme_config_p->unauthenticated_imsi_supported = 0;
|
||||
}
|
||||
|
||||
// ITTI SETTING
|
||||
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_INTERTASK_INTERFACE_CONFIG);
|
||||
if (setting != NULL) {
|
||||
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_INTERTASK_INTERFACE_QUEUE_SIZE, &alongint) )) {
|
||||
mme_config_p->itti_config.queue_size = (uint32_t)alongint;
|
||||
}
|
||||
}
|
||||
|
||||
// S6A SETTING
|
||||
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_S6A_CONFIG);
|
||||
if (setting != NULL) {
|
||||
if( (config_setting_lookup_string( setting, MME_CONFIG_STRING_S6A_CONF_FILE_PATH, (const char **)&astring) )) {
|
||||
if (astring != NULL)
|
||||
mme_config_p->s6a_config.conf_file = strdup(astring);
|
||||
}
|
||||
}
|
||||
|
||||
// SCTP SETTING
|
||||
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_SCTP_CONFIG);
|
||||
if (setting != NULL) {
|
||||
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_SCTP_INSTREAMS, &alongint) )) {
|
||||
mme_config_p->sctp_config.in_streams = (uint16_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_SCTP_OUTSTREAMS, &alongint) )) {
|
||||
mme_config_p->sctp_config.out_streams = (uint16_t)alongint;
|
||||
}
|
||||
}
|
||||
|
||||
// S1AP SETTING
|
||||
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_S1AP_CONFIG);
|
||||
if (setting != NULL) {
|
||||
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_S1AP_OUTCOME_TIMER, &alongint) )) {
|
||||
mme_config_p->s1ap_config.outcome_drop_timer_sec = (uint8_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( setting, MME_CONFIG_STRING_SCTP_OUTSTREAMS, &alongint) )) {
|
||||
mme_config_p->sctp_config.out_streams = (uint16_t)alongint;
|
||||
}
|
||||
}
|
||||
|
||||
// GUMMEI SETTING
|
||||
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_GUMMEI_CONFIG);
|
||||
if (setting != NULL) {
|
||||
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_MME_CODE);
|
||||
if (subsetting != NULL) {
|
||||
num = config_setting_length(subsetting);
|
||||
if (mme_config_p->gummei.nb_mmec != num) {
|
||||
if (mme_config_p->gummei.mmec != NULL) {
|
||||
free(mme_config_p->gummei.mmec);
|
||||
}
|
||||
mme_config_p->gummei.mmec = calloc(num, sizeof(*mme_config_p->gummei.mmec));
|
||||
}
|
||||
mme_config_p->gummei.nb_mmec = num;
|
||||
for (i = 0; i < num; i++) {
|
||||
mme_config_p->gummei.mmec[i] = config_setting_get_int_elem(subsetting, i);
|
||||
}
|
||||
}
|
||||
|
||||
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_MME_GID);
|
||||
if (subsetting != NULL) {
|
||||
num = config_setting_length(subsetting);
|
||||
if (mme_config_p->gummei.nb_mme_gid != num) {
|
||||
if (mme_config_p->gummei.mme_gid != NULL) {
|
||||
free(mme_config_p->gummei.mme_gid);
|
||||
}
|
||||
mme_config_p->gummei.mme_gid = calloc(num, sizeof(*mme_config_p->gummei.mme_gid));
|
||||
}
|
||||
mme_config_p->gummei.nb_mme_gid = num;
|
||||
for (i = 0; i < num; i++) {
|
||||
mme_config_p->gummei.mme_gid[i] = config_setting_get_int_elem(subsetting, i);
|
||||
}
|
||||
}
|
||||
|
||||
subsetting = config_setting_get_member (setting, MME_CONFIG_STRING_PLMN);
|
||||
if (subsetting != NULL) {
|
||||
num = config_setting_length(subsetting);
|
||||
if (mme_config_p->gummei.nb_plmns != num) {
|
||||
if (mme_config_p->gummei.plmn_mcc != NULL) free(mme_config_p->gummei.plmn_mcc);
|
||||
if (mme_config_p->gummei.plmn_mnc != NULL) free(mme_config_p->gummei.plmn_mnc);
|
||||
if (mme_config_p->gummei.plmn_tac != NULL) free(mme_config_p->gummei.plmn_tac);
|
||||
|
||||
mme_config_p->gummei.plmn_mcc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mcc));
|
||||
mme_config_p->gummei.plmn_mnc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mnc));
|
||||
mme_config_p->gummei.plmn_tac = calloc(num, sizeof(*mme_config_p->gummei.plmn_tac));
|
||||
}
|
||||
mme_config_p->gummei.nb_plmns = num;
|
||||
for (i = 0; i < num; i++) {
|
||||
sub2setting = config_setting_get_elem(subsetting, i);
|
||||
if (sub2setting != NULL) {
|
||||
if( (config_setting_lookup_int( sub2setting, MME_CONFIG_STRING_MCC, &alongint) )) {
|
||||
mme_config_p->gummei.plmn_mcc[i] = (uint16_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( sub2setting, MME_CONFIG_STRING_MNC, &alongint) )) {
|
||||
mme_config_p->gummei.plmn_mnc[i] = (uint16_t)alongint;
|
||||
}
|
||||
if( (config_setting_lookup_int( sub2setting, MME_CONFIG_STRING_TAC, &alongint) )) {
|
||||
mme_config_p->gummei.plmn_tac[i] = (uint16_t)alongint;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NETWORK INTERFACE SETTING
|
||||
setting = config_setting_get_member (setting_mme, MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
|
||||
if(setting != NULL) {
|
||||
if( (
|
||||
config_setting_lookup_string( setting, MME_CONFIG_STRING_INTERFACE_NAME_FOR_S1_MME,
|
||||
(const char **)&mme_interface_name_for_S1_MME)
|
||||
&& config_setting_lookup_string( setting, MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S1_MME,
|
||||
(const char **)&mme_ip_address_for_S1_MME)
|
||||
&& config_setting_lookup_string( setting, MME_CONFIG_STRING_INTERFACE_NAME_FOR_S11_MME,
|
||||
(const char **)&mme_interface_name_for_S11)
|
||||
&& config_setting_lookup_string( setting, MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S11_MME,
|
||||
(const char **)&mme_ip_address_for_S11)
|
||||
)
|
||||
) {
|
||||
mme_config_p->ipv4.mme_interface_name_for_S1_MME = strdup(mme_interface_name_for_S1_MME);
|
||||
cidr = strdup(mme_ip_address_for_S1_MME);
|
||||
address = strtok(cidr, "/");
|
||||
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.mme_ip_address_for_S1_MME, "BAD IP ADDRESS FORMAT FOR MME S1_MME !\n" )
|
||||
free(cidr);
|
||||
|
||||
mme_config_p->ipv4.mme_interface_name_for_S11 = strdup(mme_interface_name_for_S11);
|
||||
cidr = strdup(mme_ip_address_for_S11);
|
||||
address = strtok(cidr, "/");
|
||||
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.mme_ip_address_for_S11, "BAD IP ADDRESS FORMAT FOR MME S11 !\n" )
|
||||
free(cidr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the yacc parser */
|
||||
ret = yyparse(mme_config_p);
|
||||
setting = config_lookup(&cfg, SGW_CONFIG_STRING_SGW_CONFIG);
|
||||
if(setting != NULL) {
|
||||
subsetting = config_setting_get_member (setting, SGW_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
|
||||
if(subsetting != NULL) {
|
||||
if( (
|
||||
config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP,
|
||||
(const char **)&sgw_ip_address_for_S1u_S12_S4_up)
|
||||
&& config_setting_lookup_string( subsetting, SGW_CONFIG_STRING_SGW_IPV4_ADDRESS_FOR_S11,
|
||||
(const char **)&sgw_ip_address_for_S11)
|
||||
)
|
||||
) {
|
||||
cidr = strdup(sgw_ip_address_for_S1u_S12_S4_up);
|
||||
address = strtok(cidr, "/");
|
||||
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR SGW S1u_S12_S4 !\n" )
|
||||
free(cidr);
|
||||
|
||||
/* Close the file descriptor */
|
||||
if (fclose(yyin) != 0) {
|
||||
fprintf(stderr, "Unable to close the configuration file: %s (%d:%s)\n",
|
||||
mme_config_p->config_file, errno, strerror(errno));
|
||||
return errno;
|
||||
cidr = strdup(sgw_ip_address_for_S11);
|
||||
address = strtok(cidr, "/");
|
||||
IPV4_STR_ADDR_TO_INT_NWBO ( address, mme_config_p->ipv4.sgw_ip_address_for_S11, "BAD IP ADDRESS FORMAT FOR SGW S11 !\n" )
|
||||
free(cidr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DISPLAY_ARRAY(size, format, args...) \
|
||||
@@ -178,7 +364,6 @@ static void config_display(mme_config_t *mme_config_p)
|
||||
fprintf(stdout, "- Max UEs ............: %u\n", mme_config_p->max_ues);
|
||||
fprintf(stdout, "- Emergency support ..: %s\n", mme_config_p->emergency_attach_supported == 0 ? "FALSE" : "TRUE");
|
||||
fprintf(stdout, "- Unauth IMSI support : %s\n", mme_config_p->unauthenticated_imsi_supported == 0 ? "FALSE" : "TRUE");
|
||||
fprintf(stdout, "- Max UEs ............: %u\n", mme_config_p->max_ues);
|
||||
fprintf(stdout, "- Relative capa ......: %u\n\n", mme_config_p->relative_capacity);
|
||||
fprintf(stdout, "- Statistics timer ...: %u (seconds)\n\n", mme_config_p->mme_statistic_timer);
|
||||
fprintf(stdout, "- S1-U:\n");
|
||||
@@ -186,26 +371,24 @@ static void config_display(mme_config_t *mme_config_p)
|
||||
fprintf(stdout, "- S1-MME:\n");
|
||||
fprintf(stdout, " port number ......: %d\n", mme_config_p->s1ap_config.port_number);
|
||||
fprintf(stdout, "- IP:\n");
|
||||
fprintf(stdout, " s1-u iface .......: %s\n", mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up);
|
||||
fprintf(stdout, " s1-u ip ..........: %s/%d\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up)),
|
||||
mme_config_p->ipv4.sgw_ip_netmask_for_S1u_S12_S4_up);
|
||||
fprintf(stdout, " sgi iface ........: %s\n", mme_config_p->ipv4.pgw_interface_name_for_SGI);
|
||||
fprintf(stdout, " sgi ip ...........: %s/%d\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.pgw_ip_addr_for_SGI)),
|
||||
mme_config_p->ipv4.pgw_ip_netmask_for_SGI);
|
||||
//fprintf(stdout, " s1-u iface .......: %s\n", mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up);
|
||||
//fprintf(stdout, " s1-u ip ..........: %s/%d\n",
|
||||
// inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S1u_S12_S4_up)),
|
||||
// mme_config_p->ipv4.sgw_ip_netmask_for_S1u_S12_S4_up);
|
||||
//fprintf(stdout, " sgi iface ........: %s\n", mme_config_p->ipv4.pgw_interface_name_for_SGI);
|
||||
//fprintf(stdout, " sgi ip ...........: %s/%d\n",
|
||||
// inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.pgw_ip_addr_for_SGI)),
|
||||
// mme_config_p->ipv4.pgw_ip_netmask_for_SGI);
|
||||
fprintf(stdout, " s1-MME iface .....: %s\n", mme_config_p->ipv4.mme_interface_name_for_S1_MME);
|
||||
fprintf(stdout, " s1-MME ip ........: %s/%d\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.mme_ip_address_for_S1_MME)),
|
||||
mme_config_p->ipv4.mme_ip_netmask_for_S1_MME);
|
||||
fprintf(stdout, " s11 S-GW iface ...: %s\n", mme_config_p->ipv4.sgw_interface_name_for_S11);
|
||||
fprintf(stdout, " s11 S-GW ip ......: %s/%d\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S11)),
|
||||
mme_config_p->ipv4.sgw_ip_netmask_for_S11);
|
||||
fprintf(stdout, " s1-MME ip ........: %s\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.mme_ip_address_for_S1_MME)));
|
||||
//fprintf(stdout, " s11 S-GW iface ...: %s\n", mme_config_p->ipv4.sgw_interface_name_for_S11);
|
||||
//fprintf(stdout, " s11 S-GW ip ......: %s/%d\n",
|
||||
// inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.sgw_ip_address_for_S11)),
|
||||
// mme_config_p->ipv4.sgw_ip_netmask_for_S11);
|
||||
fprintf(stdout, " s11 MME iface ....: %s\n", mme_config_p->ipv4.mme_interface_name_for_S11);
|
||||
fprintf(stdout, " s11 S-GW ip ......: %s/%d\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.mme_ip_address_for_S11)),
|
||||
mme_config_p->ipv4.mme_ip_netmask_for_S11);
|
||||
fprintf(stdout, " s11 S-GW ip ......: %s\n",
|
||||
inet_ntoa(*((struct in_addr *)&mme_config_p->ipv4.mme_ip_address_for_S11)));
|
||||
fprintf(stdout, "- ITTI:\n");
|
||||
fprintf(stdout, " queue size .......: %u (bytes)\n", mme_config_p->itti_config.queue_size);
|
||||
fprintf(stdout, " log file .........: %s\n", mme_config_p->itti_config.log_file);
|
||||
@@ -251,7 +434,7 @@ nwGtpv1uDisplayBanner(void);
|
||||
int config_parse_opt_line(int argc, char *argv[], mme_config_t *mme_config_p)
|
||||
{
|
||||
int c;
|
||||
config_init(mme_config_p);
|
||||
mme_config_init(mme_config_p);
|
||||
/* Parsing command line */
|
||||
while ((c = getopt (argc, argv, "c:hi:K:v:V")) != -1) {
|
||||
switch (c) {
|
||||
@@ -265,15 +448,15 @@ int config_parse_opt_line(int argc, char *argv[], mme_config_t *mme_config_p)
|
||||
memcpy(mme_config_p->config_file, optarg, config_file_len);
|
||||
mme_config_p->config_file[config_file_len] = '\0';
|
||||
} break;
|
||||
case 'i': {
|
||||
/*case 'i': {
|
||||
int interface_len = 0;
|
||||
|
||||
/* Copying provided interface name to use for ipv4 forwarding */
|
||||
// Copying provided interface name to use for ipv4 forwarding
|
||||
interface_len = strlen(optarg);
|
||||
mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up = calloc(interface_len + 1, sizeof(char));
|
||||
memcpy(mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up, optarg, interface_len);
|
||||
mme_config_p->ipv4.sgw_interface_name_for_S1u_S12_S4_up[interface_len] = '\0';
|
||||
} break;
|
||||
} break;*/
|
||||
case 'v': {
|
||||
mme_config_p->verbosity_level = atoi(optarg);
|
||||
} break;
|
||||
|
||||
@@ -36,6 +36,44 @@
|
||||
#ifndef MME_CONFIG_H_
|
||||
#define MME_CONFIG_H_
|
||||
|
||||
#define MME_CONFIG_STRING_MME_CONFIG "MME"
|
||||
#define MME_CONFIG_STRING_REALM "REALM"
|
||||
#define MME_CONFIG_STRING_MAXENB "MAXENB"
|
||||
#define MME_CONFIG_STRING_MAXUE "MAXUE"
|
||||
#define MME_CONFIG_STRING_RELATIVE_CAPACITY "RELATIVE_CAPACITY"
|
||||
#define MME_CONFIG_STRING_STATISTIC_TIMER "MME_STATISTIC_TIMER"
|
||||
#define MME_CONFIG_STRING_EMERGENCY_ATTACH_SUPPORTED "EMERGENCY_ATTACH_SUPPORTED"
|
||||
#define MME_CONFIG_STRING_UNAUTHENTICATED_IMSI_SUPPORTED "UNAUTHENTICATED_IMSI_SUPPORTED"
|
||||
|
||||
#define MME_CONFIG_STRING_INTERTASK_INTERFACE_CONFIG "INTERTASK_INTERFACE"
|
||||
#define MME_CONFIG_STRING_INTERTASK_INTERFACE_QUEUE_SIZE "ITTI_QUEUE_SIZE"
|
||||
|
||||
#define MME_CONFIG_STRING_S6A_CONFIG "S6A"
|
||||
#define MME_CONFIG_STRING_S6A_CONF_FILE_PATH "S6A_CONF"
|
||||
|
||||
#define MME_CONFIG_STRING_SCTP_CONFIG "SCTP"
|
||||
#define MME_CONFIG_STRING_SCTP_INSTREAMS "SCTP_INSTREAMS"
|
||||
#define MME_CONFIG_STRING_SCTP_OUTSTREAMS "SCTP_OUTSTREAMS"
|
||||
|
||||
|
||||
#define MME_CONFIG_STRING_S1AP_CONFIG "S1AP"
|
||||
#define MME_CONFIG_STRING_S1AP_OUTCOME_TIMER "S1AP_OUTCOME_TIMER"
|
||||
|
||||
#define MME_CONFIG_STRING_GUMMEI_CONFIG "GUMMEI"
|
||||
#define MME_CONFIG_STRING_MME_CODE "MME_CODE"
|
||||
#define MME_CONFIG_STRING_MME_GID "MME_GID"
|
||||
#define MME_CONFIG_STRING_PLMN "PLMN"
|
||||
#define MME_CONFIG_STRING_MCC "MCC"
|
||||
#define MME_CONFIG_STRING_MNC "MNC"
|
||||
#define MME_CONFIG_STRING_TAC "TAC"
|
||||
|
||||
#define MME_CONFIG_STRING_NETWORK_INTERFACES_CONFIG "NETWORK_INTERFACES"
|
||||
#define MME_CONFIG_STRING_INTERFACE_NAME_FOR_S1_MME "MME_INTERFACE_NAME_FOR_S1_MME"
|
||||
#define MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S1_MME "MME_IPV4_ADDRESS_FOR_S1_MME"
|
||||
#define MME_CONFIG_STRING_INTERFACE_NAME_FOR_S11_MME "MME_INTERFACE_NAME_FOR_S11_MME"
|
||||
#define MME_CONFIG_STRING_IPV4_ADDRESS_FOR_S11_MME "MME_IPV4_ADDRESS_FOR_S11_MME"
|
||||
|
||||
|
||||
typedef struct mme_config_s {
|
||||
/* Reader/writer lock for this configuration */
|
||||
pthread_rwlock_t rw_lock;
|
||||
@@ -81,33 +119,15 @@ typedef struct mme_config_s {
|
||||
uint8_t outcome_drop_timer_sec;
|
||||
} s1ap_config;
|
||||
struct {
|
||||
char *sgw_interface_name_for_S1u_S12_S4_up;
|
||||
uint32_t sgw_ip_address_for_S1u_S12_S4_up;
|
||||
int sgw_ip_netmask_for_S1u_S12_S4_up;
|
||||
|
||||
char *sgw_interface_name_for_S5_S8_up;
|
||||
uint32_t sgw_ip_address_for_S5_S8_up;
|
||||
int sgw_ip_netmask_for_S5_S8_up;
|
||||
|
||||
char *pgw_interface_name_for_S5_S8;
|
||||
uint32_t pgw_ip_address_for_S5_S8;
|
||||
int pgw_ip_netmask_for_S5_S8;
|
||||
|
||||
char *pgw_interface_name_for_SGI;
|
||||
uint32_t pgw_ip_addr_for_SGI;
|
||||
int pgw_ip_netmask_for_SGI;
|
||||
|
||||
char *mme_interface_name_for_S1_MME;
|
||||
uint32_t mme_ip_address_for_S1_MME;
|
||||
int mme_ip_netmask_for_S1_MME;
|
||||
|
||||
char *mme_interface_name_for_S11;
|
||||
uint32_t mme_ip_address_for_S11;
|
||||
int mme_ip_netmask_for_S11;
|
||||
|
||||
char *sgw_interface_name_for_S11;
|
||||
uint32_t sgw_ip_address_for_S11;
|
||||
int sgw_ip_netmask_for_S11;
|
||||
} ipv4;
|
||||
struct {
|
||||
char *conf_file;
|
||||
@@ -126,6 +146,6 @@ int config_parse_opt_line(int argc, char *argv[], mme_config_t *mme_config);
|
||||
#define config_write_lock(mMEcONFIG) pthread_rwlock_wrlock(&(mMEcONFIG)->rw_lock)
|
||||
#define config_unlock(mMEcONFIG) pthread_rwlock_unlock(&(mMEcONFIG)->rw_lock)
|
||||
|
||||
int yyparse(struct mme_config_s *mme_config_p);
|
||||
//int yyparse(struct mme_config_s *mme_config_p);
|
||||
|
||||
#endif /* MME_CONFIG_H_ */
|
||||
|
||||
@@ -93,9 +93,13 @@
|
||||
* | |cpenb0+------------------+cpmme0| |
|
||||
* | +------+ |bridge| +------+ |
|
||||
* | |upenb0+-------+ | | |
|
||||
* +-----------+------+ | | | +-----------+
|
||||
* +---|--+ |
|
||||
* | +-----------+
|
||||
* +-----------+------+ | | | +-+------+--+
|
||||
* +---|--+ |s11mme|
|
||||
* | +---+--+
|
||||
* | VLAN3 | (optional)
|
||||
* | +---+--+
|
||||
* | |s11sgw|
|
||||
* | +-+------+--+
|
||||
* | | S+P-GW |
|
||||
* | VLAN2 +------+ +--------+
|
||||
* +----------+upsgw0| |pgwsgi0 +
|
||||
@@ -132,7 +136,5 @@
|
||||
#define DEFAULT_MME_IP_ADDRESS_FOR_S1_MME ("192.168.11.1") ///< MME control plane IP address
|
||||
#define DEFAULT_MME_IP_NETMASK_FOR_S1_MME 24;
|
||||
|
||||
#define IPV4_UP_UE_SUBNET ("10.2.0.0")
|
||||
|
||||
|
||||
#endif /* MME_DEFAULT_VALUES_H_ */
|
||||
|
||||
Reference in New Issue
Block a user