diff --git a/openair2/ENB_APP/Makefile.inc b/openair2/ENB_APP/Makefile.inc index 4b79c096f59f4eb899d2cb6fa579245f726c8e00..7bb09035cd22c8dc6ef89528554bc2e96663ff7b 100644 --- a/openair2/ENB_APP/Makefile.inc +++ b/openair2/ENB_APP/Makefile.inc @@ -1,6 +1,6 @@ ENB_APP_DIR = $(OPENAIR2_TOP)/ENB_APP -ENB_APP_OBJS = $(ENB_APP_DIR)/enb_app.o +ENB_APP_OBJS = $(ENB_APP_DIR)/enb_app.o $(ENB_APP_DIR)/enb_config.o ENB_APP_incl = \ -I$(ENB_APP_DIR) diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 3832bb6a04cacdd971603802d7c640a91ff33b15..059be2dfb0b3d20bbeedd61031a0a40ffc3d4c73 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -31,6 +31,7 @@ #include <string.h> #include "enb_app.h" +#include "enb_config.h" #include "assertions.h" #include "log.h" @@ -48,6 +49,7 @@ # endif extern unsigned char NB_eNB_INST; +extern char *g_conf_config_file_name; #endif #if defined(ENABLE_ITTI) @@ -57,159 +59,14 @@ extern unsigned char NB_eNB_INST; # define ENB_REGISTER_RETRY_DELAY 10 # endif -typedef struct mme_ip_address_s { - unsigned ipv4:1; - unsigned ipv6:1; - char *ipv4_address; - char *ipv6_address; -} mme_ip_address_t; - -typedef struct Enb_properties_s { - /* Unique eNB_id to identify the eNB within EPC. - * For macro eNB ids this field should be 20 bits long. - * For home eNB ids this field should be 28 bits long. - */ - uint32_t eNB_id; - - /* The type of the cell */ - enum cell_type_e cell_type; - - /* Optional name for the cell - * NOTE: the name can be NULL (i.e no name) and will be cropped to 150 - * characters. - */ - char *eNB_name; - - /* Tracking area code */ - uint16_t tac; - - /* Mobile Country Code - * Mobile Network Code - */ - uint16_t mcc; - uint16_t mnc; - - /* Default Paging DRX of the eNB as defined in TS 36.304 */ - paging_drx_t default_drx; - - /* Nb of MME to connect to */ - uint8_t nb_mme; - /* List of MME to connect to */ - mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS]; -} Enb_properties_t; - /*------------------------------------------------------------------------------*/ # if defined(ENABLE_USE_MME) static uint32_t enb_nb = 1; /* Default number of eNB */ # endif -/* eNB 0 properties */ -static Enb_properties_t enb_0_properties = -{ - 347472, - CELL_MACRO_ENB, - "eNB_Eurecom_0", - 1, /* Tracking area code, 0x0000 and 0xfffe are reserved values */ - 208, /* Mobile Country Code */ -#ifdef EXMIMO_IOT - 92, /* Mobile Network Code */ -#else - 10, /* Mobile Network Code */ -#endif - PAGING_DRX_256, - 1, /* There are 2 addresses defined, but use only one by default */ - { - { - 1, - 0, - "192.168.12.87", - "2001:660:5502:12:30da:829a:2343:b6cf" - }, - { - 1, - 0, - "192.168.12.86", - "" - } - } -}; -/* eNB 1 properties */ -static Enb_properties_t enb_1_properties = -{ - 347473, - CELL_MACRO_ENB, - "eNB_Eurecom_1", - 1, - 208, - 92, - PAGING_DRX_256, - 1, /* There are 2 addresses defined, but use only one by default */ - { - { - 1, - 0, - "192.168.12.87", - "2001:660:5502:12:30da:829a:2343:b6cf" - }, - { - 1, - 0, - "192.168.12.88", - "" - } - } -}; - -/* eNB 2 properties */ -static Enb_properties_t enb_2_properties = -{ - 347474, - CELL_MACRO_ENB, - "eNB_Eurecom_2", - 1, - 208, - 92, - PAGING_DRX_256, - 1, - { - { - 1, - 0, - "192.168.12.87", - "2001:660:5502:12:30da:829a:2343:b6cf" - }, - } -}; - -/* eNB 3 properties */ -static Enb_properties_t enb_3_properties = -{ - 347475, - CELL_MACRO_ENB, - "eNB_Eurecom_3", - 1, - 208, - 92, - PAGING_DRX_256, - 1, - { - { - 1, - 0, - "192.168.12.87", - "2001:660:5502:12:30da:829a:2343:b6cf" - }, - } -}; - -static Enb_properties_t *enb_properties[] = -{ - &enb_0_properties, - &enb_1_properties, - &enb_2_properties, - &enb_3_properties, -}; +extern Enb_properties_t *g_enb_properties[]; +extern int g_num_enb_properties; /*------------------------------------------------------------------------------*/ static void configure_rrc(void) @@ -228,10 +85,10 @@ static void configure_rrc(void) { msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); - RRC_CONFIGURATION_REQ (msg_p).cell_identity = enb_properties[eNB_id]->eNB_id; - RRC_CONFIGURATION_REQ (msg_p).tac = enb_properties[eNB_id]->tac; - RRC_CONFIGURATION_REQ (msg_p).mcc = enb_properties[eNB_id]->mcc; - RRC_CONFIGURATION_REQ (msg_p).mnc = enb_properties[eNB_id]->mnc; + RRC_CONFIGURATION_REQ (msg_p).cell_identity = g_enb_properties[eNB_id]->eNB_id; + RRC_CONFIGURATION_REQ (msg_p).tac = g_enb_properties[eNB_id]->tac; + RRC_CONFIGURATION_REQ (msg_p).mcc = g_enb_properties[eNB_id]->mcc; + RRC_CONFIGURATION_REQ (msg_p).mnc = g_enb_properties[eNB_id]->mnc; itti_send_msg_to_task (TASK_RRC_ENB, eNB_id, msg_p); } @@ -253,7 +110,8 @@ static uint32_t eNB_app_register() DevCheck(eNB_id_end <= NUMBER_OF_eNB_MAX, eNB_id_end, NUMBER_OF_eNB_MAX, 0); # endif - DevCheck(eNB_id_end <= (sizeof(enb_properties) / sizeof(enb_properties[0])), eNB_id_end, (sizeof(enb_properties) / sizeof(enb_properties[0])), 0); + //DevCheck(eNB_id_end <= (sizeof(g_enb_properties) / sizeof(g_enb_properties[0])), eNB_id_end, (sizeof(g_enb_properties) / sizeof(g_enb_properties[0])), 0); + DevCheck((eNB_id_end - eNB_id_start) == g_num_enb_properties, eNB_id_end - eNB_id_start, g_num_enb_properties, 0); for (eNB_id = eNB_id_start; (eNB_id < eNB_id_end) ; eNB_id++) { @@ -266,12 +124,12 @@ static uint32_t eNB_app_register() /* Overwrite default eNB ID */ hash = s1ap_generate_eNB_id (); - enb_properties[eNB_id]->eNB_id = eNB_id + (hash & 0xFFFF8); + g_enb_properties[eNB_id]->eNB_id = eNB_id + (hash & 0xFFFF8); if (EPC_MODE_ENABLED) { /* Overwrite default IP v4 address by value from command line */ - enb_properties[eNB_id]->mme_ip_address[0].ipv4_address = EPC_MODE_MME_ADDRESS; + g_enb_properties[eNB_id]->mme_ip_address[0].ipv4_address = EPC_MODE_MME_ADDRESS; } /* note: there is an implicit relationship between the data structure and the message name */ @@ -280,26 +138,26 @@ static uint32_t eNB_app_register() s1ap_register_eNB = &S1AP_REGISTER_ENB_REQ(msg_p); /* Some default/random parameters */ - s1ap_register_eNB->eNB_id = enb_properties[eNB_id]->eNB_id; - s1ap_register_eNB->cell_type = enb_properties[eNB_id]->cell_type; - s1ap_register_eNB->eNB_name = enb_properties[eNB_id]->eNB_name; - s1ap_register_eNB->tac = enb_properties[eNB_id]->tac; - s1ap_register_eNB->mcc = enb_properties[eNB_id]->mcc; - s1ap_register_eNB->mnc = enb_properties[eNB_id]->mnc; - s1ap_register_eNB->default_drx = enb_properties[eNB_id]->default_drx; - - s1ap_register_eNB->nb_mme = enb_properties[eNB_id]->nb_mme; + s1ap_register_eNB->eNB_id = g_enb_properties[eNB_id]->eNB_id; + s1ap_register_eNB->cell_type = g_enb_properties[eNB_id]->cell_type; + s1ap_register_eNB->eNB_name = g_enb_properties[eNB_id]->eNB_name; + s1ap_register_eNB->tac = g_enb_properties[eNB_id]->tac; + s1ap_register_eNB->mcc = g_enb_properties[eNB_id]->mcc; + s1ap_register_eNB->mnc = g_enb_properties[eNB_id]->mnc; + s1ap_register_eNB->default_drx = g_enb_properties[eNB_id]->default_drx; + + s1ap_register_eNB->nb_mme = g_enb_properties[eNB_id]->nb_mme; DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, eNB_id, s1ap_register_eNB->nb_mme, S1AP_MAX_NB_MME_IP_ADDRESS); for (mme_id = 0; mme_id < s1ap_register_eNB->nb_mme; mme_id++) { - s1ap_register_eNB->mme_ip_address[mme_id].ipv4 = enb_properties[eNB_id]->mme_ip_address[mme_id].ipv4; - s1ap_register_eNB->mme_ip_address[mme_id].ipv6 = enb_properties[eNB_id]->mme_ip_address[mme_id].ipv6; + s1ap_register_eNB->mme_ip_address[mme_id].ipv4 = g_enb_properties[eNB_id]->mme_ip_address[mme_id].ipv4; + s1ap_register_eNB->mme_ip_address[mme_id].ipv6 = g_enb_properties[eNB_id]->mme_ip_address[mme_id].ipv6; strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv4_address, - enb_properties[eNB_id]->mme_ip_address[mme_id].ipv4_address, + g_enb_properties[eNB_id]->mme_ip_address[mme_id].ipv4_address, sizeof(s1ap_register_eNB->mme_ip_address[0].ipv4_address)); strncpy (s1ap_register_eNB->mme_ip_address[mme_id].ipv6_address, - enb_properties[eNB_id]->mme_ip_address[mme_id].ipv6_address, + g_enb_properties[eNB_id]->mme_ip_address[mme_id].ipv6_address, sizeof(s1ap_register_eNB->mme_ip_address[0].ipv6_address)); } @@ -333,6 +191,7 @@ void *eNB_app_task(void *args_p) # if defined(ENABLE_USE_MME) # if defined(OAI_EMU) enb_nb = oai_emulation.info.nb_enb_local; + enb_config_init(g_conf_config_file_name); # endif # endif diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c new file mode 100755 index 0000000000000000000000000000000000000000..d1223fe28c264ca098804d510e0225b88547e6d4 --- /dev/null +++ b/openair2/ENB_APP/enb_config.c @@ -0,0 +1,208 @@ +/******************************************************************************* + + Eurecom OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information + Openair Admin: openair_admin@eurecom.fr + Openair Tech : openair_tech@eurecom.fr + Forums : http://forums.eurecom.fr/openairinterface + Address : EURECOM, Campus SophiaTech, 450 Route des Chappes + 06410 Biot FRANCE + + *******************************************************************************/ + +#include <string.h> +#include <libconfig.h> + +#include "log.h" +#include "assertions.h" +#include "enb_config.h" +#if defined(ENABLE_ITTI) +# include "intertask_interface.h" +# if defined(ENABLE_USE_MME) +# include "s1ap_eNB.h" +# include "sctp_eNB_task.h" +# endif +#endif + +#include "LAYER2/MAC/extern.h" + +// Hard to find a defined value for max enb... +#define MAX_ENB 16 +Enb_properties_t *g_enb_properties[MAX_ENB]; +int g_num_enb_properties = 0; + +int enb_config_init(char* lib_config_file_name_pP) { + + config_t cfg; + config_setting_t *setting; + config_setting_t *setting_mme_addresses; + config_setting_t *setting_mme_address; + config_setting_t *setting_enb; + int num_enbs, num_mme_address, i, j, parse_error, enb_properties_index; + long int enb_id; + const char* cell_type; + long int tac; + const char* enb_name; + long int mcc; + long int mnc; + const char* default_drx; + char* ipv4; + char* ipv6; + char* active; + char* preference; + char* active_enb[MAX_ENB]; + + + memset((char*)g_enb_properties, 0 , MAX_ENB * sizeof(Enb_properties_t*)); + memset((char*)active_enb, 0 , MAX_ENB * sizeof(char*)); + + config_init(&cfg); + + /* Read the file. If there is an error, report it and exit. */ + if(! config_read_file(&cfg, lib_config_file_name_pP)) + { + LOG_E(ENB_APP, "%s:%d - %s\n", lib_config_file_name_pP, config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + AssertFatal (1 == 0, "Failed to parse config file %s!\n", lib_config_file_name_pP); + } + + + // Get list of active eNBs, (only these will be configured) + g_num_enb_properties = 0; + setting = config_lookup(&cfg, ENB_CONFIG_STRING_ACTIVE_ENBS); + if(setting != NULL) + { + num_enbs = config_setting_length(setting); + for (i = 0; i < num_enbs; i++) { + setting_enb = config_setting_get_elem(setting, i); + active_enb[i] = config_setting_get_string (setting_enb); + AssertFatal (active_enb[i] != NULL, + "Failed to parse config file %s, %uth attribute %s \n", + lib_config_file_name_pP, i, ENB_CONFIG_STRING_ACTIVE_ENBS); + active_enb[i] = strdup(active_enb[i]); + g_num_enb_properties += 1; + } + } + + /* Output a list of all eNBs. */ + setting = config_lookup(&cfg, ENB_CONFIG_STRING_ENB_LIST); + if(setting != NULL) + { + enb_properties_index = 0; + parse_error = 0; + num_enbs = config_setting_length(setting); + for (i = 0; i < num_enbs; i++) { + setting_enb = config_setting_get_elem(setting, i); + if( !( + config_setting_lookup_int (setting_enb, ENB_CONFIG_STRING_ENB_ID, &enb_id) + && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE, &cell_type) + && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_ENB_NAME, &enb_name) + && config_setting_lookup_int (setting_enb, ENB_CONFIG_STRING_TRACKING_AREA_CODE, &tac) + && config_setting_lookup_int (setting_enb, ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE, &mcc) + && config_setting_lookup_int (setting_enb, ENB_CONFIG_STRING_MOBILE_NETWORK_CODE, &mnc) + && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_DEFAULT_PAGING_DRX, &default_drx) + ) + ) { + parse_error = 1; + AssertFatal (parse_error == 0, + "Failed to parse config file %s, %u th enb\n", + lib_config_file_name_pP, i); + } + // search if in active list + for (j=0; j < g_num_enb_properties; j++) { + if (strcmp(active_enb[j], enb_name) == 0) { + g_enb_properties[enb_properties_index] = calloc(1, sizeof(Enb_properties_t)); + + g_enb_properties[enb_properties_index]->eNB_id = enb_id; + if (strcmp(cell_type, "CELL_MACRO_ENB") == 0) { + g_enb_properties[enb_properties_index]->cell_type = CELL_MACRO_ENB; + } else if (strcmp(cell_type, "CELL_HOME_ENB") == 0) { + g_enb_properties[enb_properties_index]->cell_type = CELL_HOME_ENB; + } else { + AssertFatal (1 == 0, + "Failed to parse config file %s, enb %d unknown value for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n", + lib_config_file_name_pP, i); + } + g_enb_properties[enb_properties_index]->eNB_name = strdup(enb_name); + g_enb_properties[enb_properties_index]->tac = (uint16_t)tac; + g_enb_properties[enb_properties_index]->mcc = (uint16_t)mcc; + g_enb_properties[enb_properties_index]->mnc = (uint16_t)mnc; + + if (strcmp(default_drx, "PAGING_DRX_32") == 0) { + g_enb_properties[enb_properties_index]->default_drx = PAGING_DRX_32; + } else if (strcmp(default_drx, "PAGING_DRX_64") == 0) { + g_enb_properties[enb_properties_index]->default_drx = PAGING_DRX_64; + } else if (strcmp(default_drx, "PAGING_DRX_128") == 0) { + g_enb_properties[enb_properties_index]->default_drx = PAGING_DRX_128; + } else if (strcmp(default_drx, "PAGING_DRX_256") == 0) { + g_enb_properties[enb_properties_index]->default_drx = PAGING_DRX_256; + } else { + AssertFatal (1 == 0, + "Failed to parse config file %s, enb %d unknown value for default_drx choice: PAGING_DRX_32..PAGING_DRX_256 !\n", + lib_config_file_name_pP, i); + } + AssertFatal (parse_error == 0, "Failed to parse config file %s, enb %d\n", lib_config_file_name_pP, i); + + setting_mme_addresses = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_MME_IP_ADDRESS); + num_mme_address = config_setting_length(setting_mme_addresses); + g_enb_properties[enb_properties_index]->nb_mme = 0; + for (j = 0; j < num_mme_address; j++) { + setting_mme_address = config_setting_get_elem(setting_mme_addresses, j); + if( !( + config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IPV4_ADDRESS, (const char **)&ipv4) + && config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IPV6_ADDRESS, (const char **)&ipv6) + && config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE, (const char **)&active) + && config_setting_lookup_string(setting_mme_address, ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE, (const char **)&preference) + ) + ) { + parse_error = 1; + AssertFatal (parse_error == 0, + "Failed to parse config file %s, %u th enb %u th mme address\n", + lib_config_file_name_pP, i, j); + } + g_enb_properties[enb_properties_index]->nb_mme += 1; + + g_enb_properties[enb_properties_index]->mme_ip_address[j].ipv4_address = strdup(ipv4); + g_enb_properties[enb_properties_index]->mme_ip_address[j].ipv6_address = strdup(ipv6); + if (strcmp(active, "yes") == 0) { + g_enb_properties[enb_properties_index]->mme_ip_address[j].active = 1; + } // else { (calloc) + + if (strcmp(preference, "ipv4") == 0) { + g_enb_properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1; + } else if (strcmp(preference, "ipv6") == 0) { + g_enb_properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1; + } else if (strcmp(preference, "no") == 0) { + g_enb_properties[enb_properties_index]->mme_ip_address[j].ipv4 = 1; + g_enb_properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1; + } + } + enb_properties_index += 1; + break; + } + } + } + } + AssertFatal (enb_properties_index == g_num_enb_properties, + "Failed to parse config file %s, mismatch between %u active eNBs and %u corresponding defined eNBs!\n", + lib_config_file_name_pP, g_num_enb_properties, enb_properties_index); + return 0; +} diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h new file mode 100755 index 0000000000000000000000000000000000000000..a5b6e749bb622eeccc4df67c51e2d33ebb8e8af6 --- /dev/null +++ b/openair2/ENB_APP/enb_config.h @@ -0,0 +1,100 @@ +/******************************************************************************* + + Eurecom OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + This program is free software; you can redistribute it and/or modify it + under the terms and conditions of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + This program is distributed in the hope it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". + + Contact Information + Openair Admin: openair_admin@eurecom.fr + Openair Tech : openair_tech@eurecom.fr + Forums : http://forums.eurecom.fr/openairinterface + Address : EURECOM, Campus SophiaTech, 450 Route des Chappes + 06410 Biot FRANCE + +*******************************************************************************/ + +#ifndef ENB_CONFIG_H_ +#define ENB_CONFIG_H_ + +#include "commonDef.h" +#include "s1ap_messages_types.h" + + +#define ENB_CONFIG_STRING_ACTIVE_ENBS "Active_eNBs" +#define ENB_CONFIG_STRING_ENB_LIST "eNBs" +#define ENB_CONFIG_STRING_ENB_ID "eNB_ID" +#define ENB_CONFIG_STRING_CELL_TYPE "cell_type" +#define ENB_CONFIG_STRING_ENB_NAME "eNB_name" +#define ENB_CONFIG_STRING_TRACKING_AREA_CODE "tracking_area_code" +#define ENB_CONFIG_STRING_MOBILE_COUNTRY_CODE "mobile_country_code" +#define ENB_CONFIG_STRING_MOBILE_NETWORK_CODE "mobile_network_code" +#define ENB_CONFIG_STRING_DEFAULT_PAGING_DRX "default_paging_drx" +#define ENB_CONFIG_STRING_MME_IP_ADDRESS "mme_ip_address" +#define ENB_CONFIG_STRING_MME_IPV4_ADDRESS "ipv4" +#define ENB_CONFIG_STRING_MME_IPV6_ADDRESS "ipv6" +#define ENB_CONFIG_STRING_MME_IP_ADDRESS_ACTIVE "active" +#define ENB_CONFIG_STRING_MME_IP_ADDRESS_PREFERENCE "preference" + + + +typedef struct mme_ip_address_s { + unsigned ipv4:1; + unsigned ipv6:1; + unsigned active:1; + char *ipv4_address; + char *ipv6_address; +} mme_ip_address_t; + +typedef struct Enb_properties_s { + /* Unique eNB_id to identify the eNB within EPC. + * For macro eNB ids this field should be 20 bits long. + * For home eNB ids this field should be 28 bits long. + */ + uint32_t eNB_id; + + /* The type of the cell */ + enum cell_type_e cell_type; + + /* Optional name for the cell + * NOTE: the name can be NULL (i.e no name) and will be cropped to 150 + * characters. + */ + char *eNB_name; + + /* Tracking area code */ + uint16_t tac; + + /* Mobile Country Code + * Mobile Network Code + */ + uint16_t mcc; + uint16_t mnc; + + /* Default Paging DRX of the eNB as defined in TS 36.304 */ + paging_drx_t default_drx; + + /* Nb of MME to connect to */ + uint8_t nb_mme; + /* List of MME to connect to */ + mme_ip_address_t mme_ip_address[S1AP_MAX_NB_MME_IP_ADDRESS]; +} Enb_properties_t; + + +int enb_config_init(char* lib_config_file_name_pP); + +#endif /* ENB_CONFIG_H_ */