Commit 82b4fc3b authored by Navid Nikaein's avatar Navid Nikaein

x2ap setup messaging

parent c1ba760b
......@@ -403,13 +403,15 @@ include_directories ("${X2AP_DIR}")
add_library(X2AP_ENB
${X2AP_C_DIR}/x2ap_ies_defs.h
${X2AP_DIR}/x2ap.c
${X2AP_DIR}/x2ap_eNB.c
${X2AP_DIR}/x2ap_eNB_decoder.c
${X2AP_DIR}/x2ap_eNB_encoder.c
${X2AP_DIR}/x2ap_eNB_handlers.c
${X2AP_DIR}/x2ap_eNB_handler.c
${X2AP_DIR}/x2ap_eNB_itti_messaging.c
${X2AP_DIR}/x2ap_eNB_management_procedures.c
${X2AP_DIR}/x2ap_eNB_generate_messages.c
)
# Hardware dependant options
###################################
add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4")
......@@ -469,7 +471,7 @@ include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON")
##############################################################
add_boolean_option(ENABLE_SECURITY True "Enable LTE integrity and ciphering between RRC UE and eNB")
add_boolean_option(ENABLE_USE_MME True "eNB connected to MME (INTERFACE S1-C), not standalone eNB")
add_boolean_option(ENABLE_USE_X2 True "eNB connected to eNB (INTERFACE X2)")
add_boolean_option(ENABLE_USE_X2 False "eNB connected to eNB (INTERFACE X2)")
add_boolean_option(NO_RRM True "DO WE HAVE A RADIO RESSOURCE MANAGER: NO")
add_boolean_option(USER_MODE True "????")
......@@ -1604,7 +1606,7 @@ add_executable(oaisim_nos1
target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER)
target_link_libraries (oaisim_nos1
-Wl,--start-group
RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB}
RRC_LIB X2AP_LIB X2AP_ENB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB}
-Wl,--end-group )
target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES})
......
......@@ -111,6 +111,7 @@ typedef enum cn_domain_s {
typedef struct net_ip_address_s {
unsigned ipv4:1;
unsigned ipv6:1;
unsigned active:1;
char ipv4_address[16];
char ipv6_address[40];
} net_ip_address_t;
......
......@@ -33,14 +33,18 @@
/* ENCODER */
MESSAGE_DEF(X2AP_RESET_REQUST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_reset_request_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_RESPONSE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_response_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILUIRE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
MESSAGE_DEF(X2AP_RESOURCE_STATUS_FAILURE_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_resource_status_failure_log)
/* DECODER */
/* Messages for X2AP logging */
MESSAGE_DEF(X2AP_SETUP_REQUEST_LOG , MESSAGE_PRIORITY_MED, IttiMsgText , x2ap_setup_request_log)
/* eNB application layer -> X2AP messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register_enb_req_t , x2ap_register_enb_req)
/* X2AP -> eNB application layer messages */
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf)
MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
......@@ -34,6 +34,8 @@
// Defines to access message fields.
#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req
#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf
#define X2AP_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2
......@@ -91,4 +93,16 @@ typedef struct x2ap_register_enb_req_s {
uint16_t sctp_out_streams;
} x2ap_register_enb_req_t;
//-------------------------------------------------------------------------------------------//
// X2AP -> eNB application layer messages
typedef struct x2ap_register_enb_cnf_s {
/* Nb of connected eNBs*/
uint8_t nb_x2;
} x2ap_register_enb_cnf_t;
typedef struct x2ap_deregistered_enb_ind_s {
/* Nb of connected eNBs */
uint8_t nb_x2;
} x2ap_deregistered_enb_ind_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */
......@@ -71,6 +71,10 @@ extern unsigned char NB_eNB_INST;
# define ENB_REGISTER_RETRY_DELAY 10
# endif
# if defined(ENABLE_USE_X2)
# define X2AP_ENB_REGISTER_RETRY_DELAY 10
#endif
/*------------------------------------------------------------------------------*/
static void configure_phy(module_id_t enb_id, const Enb_properties_array_t* enb_properties)
{
......@@ -271,7 +275,8 @@ static uint32_t eNB_app_register_s1(uint32_t enb_id_start, uint32_t enb_id_end,
/*------------------------------------------------------------------------------*/
# if defined(ENABLE_USE_X2)
static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end, const Enb_properties_array_t *enb_properties)
static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end,
const Enb_properties_array_t *enb_properties)
{
uint32_t enb_id;
uint32_t x2_id;
......@@ -307,7 +312,8 @@ static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end,
x2ap_register_eNB->nb_x2 = enb_properties->properties[enb_id]->nb_x2;
AssertFatal (x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS, "Too many X2 interfaces for eNB %d (%d/%d)!",
AssertFatal (x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS,
"Too many X2 interfaces for eNB %d (%d/%d)!",
enb_id, x2ap_register_eNB->nb_x2,
X2AP_MAX_NB_ENB_IP_ADDRESS);
......@@ -321,6 +327,9 @@ static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end,
strncpy (x2ap_register_eNB->target_enb_x2_ip_address[x2_id].ipv6_address,
enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].ipv6_address,
sizeof(x2ap_register_eNB->target_enb_x2_ip_address[0].ipv6_address));
// this is used to identify whether this eNb is acting as an initiator (client) or listener (server)
x2ap_register_eNB->target_enb_x2_ip_address[x2_id].active = enb_properties->properties[enb_id]->target_enb_x2_ip_address[x2_id].active;
}
x2ap_register_eNB->sctp_in_streams = enb_properties->properties[enb_id]->sctp_in_streams;
......@@ -329,6 +338,7 @@ static uint32_t eNB_app_register_x2(uint32_t enb_id_start, uint32_t enb_id_end,
x2ap_register_eNB->enb_x2_ip_address.ipv6 = 0;
x2ap_register_eNB->enb_x2_ip_address.ipv4 = 1;
addr.s_addr = enb_properties->properties[enb_id]->enb_ipv4_address_for_X2C;
str = inet_ntoa(addr);
strcpy(x2ap_register_eNB->enb_x2_ip_address.ipv4_address, str);
......@@ -359,9 +369,9 @@ void *eNB_app_task(void *args_p)
long enb_register_retry_timer_id;
# endif
# if defined(ENABLE_USE_X2)
uint32_t x2ap_register_enb_pending;
uint32_t x2ap_registered_enb;
long x2ap_enb_register_retry_timer_id;
uint32_t x2_register_enb_pending;
uint32_t x2_registered_enb;
long x2_enb_register_retry_timer_id;
# endif
uint32_t enb_id;
MessageDef *msg_p = NULL;
......@@ -406,8 +416,8 @@ void *eNB_app_task(void *args_p)
# if defined(ENABLE_USE_X2)
/* Try to register each eNB with each other */
registered_enb_x2 = 0;
register_enb_x2_pending = eNB_app_register_x2 (enb_id_start, enb_id_end, enb_properties_p);
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end, enb_properties_p);
# else
# endif
......@@ -510,29 +520,41 @@ void *eNB_app_task(void *args_p)
/* TODO handle recovering of registration */
break;
case S1AP_REGISTER_ENB_CNF:
case X2AP_REGISTER_ENB_CNF:
LOG_I(ENB_APP, "[eNB %d] Received %s: associated eNB %d\n", instance, msg_name,
X2AP_REGISTER_ENB_CNF(msg_p).nb_x2);
DevAssert(register_enb_x2_pending > 0);
register_enb_x2_pending--;
DevAssert(x2_register_enb_pending > 0);
x2_register_enb_pending--;
/* Check if at least eNB is registered with one target eNB */
if (X2AP_REGISTER_ENB_CNF(msg_p).nb_x2 > 0) {
registered_enb_x2++;
x2_registered_enb++;
}
/* Check if all register eNB requests have been processed */
if (register_enb_x2_pending == 0) {
if (registered_enb_x2 == enb_nb) {
/* If all eNB are registered, start L2L1 task */
if (x2_register_enb_pending == 0) {
if (x2_registered_enb == enb_nb) {
/* If all eNB are registered, start RRC HO task */
}else {
uint32_t not_associated_x2 = enb_nb - registered_enb;
uint32_t x2_not_associated = enb_nb - x2_registered_enb;
LOG_W(ENB_APP, " %d eNB %s not associated with the target\n",
not_associated, not_associated > 1 ? "are" : "is");
x2_not_associated, x2_not_associated > 1 ? "are" : "is");
// timer to retry
/* Restart the eNB registration process in ENB_REGISTER_RETRY_DELAY seconds */
if (timer_setup (X2AP_ENB_REGISTER_RETRY_DELAY, 0, TASK_ENB_APP,
INSTANCE_DEFAULT, TIMER_ONE_SHOT, NULL,
&x2_enb_register_retry_timer_id) < 0) {
LOG_E(ENB_APP, " Can not start eNB X2AP register: retry timer, use \"sleep\" instead!\n");
sleep(X2AP_ENB_REGISTER_RETRY_DELAY);
/* Restart the registration process */
x2_registered_enb = 0;
x2_register_enb_pending = eNB_app_register_x2 (enb_id_start, enb_id_end, enb_properties_p);
}
}
}
......
......@@ -2191,7 +2191,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
if (strcmp(active, "yes") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].active = 1;
} // else { (calloc)
} else {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].active = 0;
}
if (strcmp(preference, "ipv4") == 0) {
enb_properties.properties[enb_properties_index]->target_enb_x2_ip_address[j].ipv4 = 1;
......
......@@ -27,8 +27,8 @@
*******************************************************************************/
/*! \file x2ap.c
* \brief x2ap protocol
/*! \file x2ap_eNB.c
* \brief x2ap protocol for eNB
* \author Navid Nikaein
* \date 2014 - 2015
* \version 1.0
......@@ -44,14 +44,22 @@
#include "intertask_interface.h"
#include "x2ap.h"
#include "assertions.h"
#include "queue.h"
#include "msc.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_defs.h"
#include "x2ap_eNB_decoder.h"
#include "x2ap_eNB_handler.h"
#include "x2ap_ies_defs.h"
#include "x2ap_eNB_management_procedures.h"
#include "msc.h"
#include "assertions.h"
#include "conversions.h"
static
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB);
......@@ -69,21 +77,22 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance,
static
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p);
x2ap_eNB_data_t *x2ap_enb_data_p);
static
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p);
x2ap_eNB_data_t *x2ap_enb_data_p);
static
int x2ap_eNB_generate_x2_setup_failure(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p);
x2ap_eNB_data_t *x2ap_enb_data_p);
static
void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) {
void x2ap_eNB_handle_sctp_data_ind(instance_t instance,
sctp_data_ind_t *sctp_data_ind) {
int result;
......@@ -101,14 +110,14 @@ static
void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_mme_data_t *x2ap_enb_data_p;
x2ap_eNB_data_t *x2ap_enb_data_p;
DevAssert(sctp_new_association_resp != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
x2ap_enb_data_p = x2ap_eNB_get_eNB(instance_p, -1,
x2ap_enb_data_p = x2ap_get_eNB(instance_p, -1,
sctp_new_association_resp->ulp_cnx_id);
DevAssert(x2ap_enb_data_p != NULL);
......@@ -118,7 +127,8 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
instance,
sctp_new_association_resp->ulp_cnx_id);
x2ap_handle_x2_setup_message(x2ap_enb_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
x2ap_handle_x2_setup_message(x2ap_enb_data_p,
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
return;
}
......@@ -132,6 +142,38 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
x2ap_eNB_generate_x2_setup_request(instance_p, x2ap_enb_data_p);
}
int x2ap_eNB_init_sctp (x2ap_eNB_instance_t *instance_p,
net_ip_address_t *local_ip_addr)
{
// Create and alloc new message
MessageDef *message;
sctp_init_t *sctp_init = NULL;
DevAssert(instance_p != NULL);
DevAssert(local_ip_addr != NULL);
message = itti_alloc_new_message (TASK_X2AP, SCTP_INIT_MSG);
sctp_init = &message->ittiMsg.sctp_init;
sctp_init->port = X2AP_PORT_NUMBER;
sctp_init->ppid = X2AP_SCTP_PPID;
sctp_init->ipv4 = 1;
sctp_init->ipv6 = 0;
sctp_init->nb_ipv4_addr = 1;
memcpy(&sctp_init->ipv4_address,
local_ip_addr,
sizeof(*local_ip_addr));
/*
* SR WARNING: ipv6 multi-homing fails sometimes for localhost.
* * * * Disable it for now.
*/
sctp_init->nb_ipv6_addr = 0;
sctp_init->ipv6_address[0] = "0:0:0:0:0:0:0:1";
return itti_send_msg_to_task (TASK_SCTP, instance_p->instance, message);
}
static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_address,
......@@ -140,54 +182,55 @@ static void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
uint16_t out_streams)
{
MessageDef *message_p = NULL;
sctp_new_association_req_t *sctp_new_association_req_p = NULL;
x2ap_eNB_data_t *x2ap_enb_data_p = NULL;
MessageDef *message = NULL;
sctp_new_association_req_t *sctp_new_association_req = NULL;
x2ap_eNB_data_t *x2ap_enb_data = NULL;
DevAssert(instance_p != NULL);
DevAssert(target_eNB_ip_address != NULL);
message_p = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ);
message = itti_alloc_new_message(TASK_X2AP, SCTP_NEW_ASSOCIATION_REQ);
sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req;
sctp_new_association_req = &message->ittiMsg.sctp_new_association_req;
sctp_new_association_req_p->port = X2AP_PORT_NUMBER;
sctp_new_association_req_p->ppid = X2AP_SCTP_PPID;
sctp_new_association_req->port = X2AP_PORT_NUMBER;
sctp_new_association_req->ppid = X2AP_SCTP_PPID;
sctp_new_association_req_p->in_streams = in_streams;
sctp_new_association_req_p->out_streams = out_streams;
sctp_new_association_req->in_streams = in_streams;
sctp_new_association_req->out_streams = out_streams;
memcpy(&sctp_new_association_req_p->remote_address,
memcpy(&sctp_new_association_req->remote_address,
target_eNB_ip_address,
sizeof(*target_eNB_ip_address));
memcpy(&sctp_new_association_req_p->local_address,
memcpy(&sctp_new_association_req->local_address,
local_ip_addr,
sizeof(*local_ip_addr));
/* Create new MME descriptor */
x2ap_enb_data_p = calloc(1, sizeof(*x2ap_enb_data_p));
DevAssert(x2ap_enb_data_p != NULL);
/* Create new eNB descriptor */
x2ap_enb_data = calloc(1, sizeof(*x2ap_enb_data));
DevAssert(x2ap_enb_data != NULL);
x2ap_enb_data_p->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
sctp_new_association_req_p->ulp_cnx_id = x2ap_enb_data_p->cnx_id;
x2ap_enb_data->cnx_id = x2ap_eNB_fetch_add_global_cnx_id();
sctp_new_association_req->ulp_cnx_id = x2ap_enb_data->cnx_id;
x2ap_enb_data_p->assoc_id = -1;
x2ap_enb_data_p->x2ap_eNB_instance = instance_p;
x2ap_enb_data->assoc_id = -1;
x2ap_enb_data->x2ap_eNB_instance = instance_p;
/* Insert the new descriptor in list of known eNB
* but not yet associated.
*/
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data_p);
s1ap_mme_data_p->state = X2AP_ENB_STATE_WAITING;
instance_p->x2ap_enb_nb ++;
instance_p->x2ap_enb_pending_nb ++;
RB_INSERT(x2ap_enb_map, &instance_p->x2ap_enb_head, x2ap_enb_data);
x2ap_enb_data->state = X2AP_ENB_STATE_WAITING;
instance_p->x2_target_enb_nb ++;
instance_p->x2_target_enb_pending_nb ++;
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message);
}
static
void x2ap_eNB_handle_register_eNB(instance_t instance, x2ap_register_enb_req_t *x2ap_register_eNB)
void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB)
{
x2ap_eNB_instance_t *new_instance;
......@@ -233,16 +276,32 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, x2ap_register_enb_req_t *
x2ap_register_eNB->eNB_id);
}
DevCheck(x2ap_register_eNB->nb_mme <= X2AP_MAX_NB_ENB_IP_ADDRESS,
DevCheck(x2ap_register_eNB->nb_x2 <= X2AP_MAX_NB_ENB_IP_ADDRESS,
X2AP_MAX_NB_ENB_IP_ADDRESS, x2ap_register_eNB->nb_x2, 0);
/* Trying to connect to the provided list of eNB ip address */
for (index = 0; index < x2ap_register_eNB->nb_x2; index++) {
x2ap_eNB_register_eNB(new_instance,
&x2ap_register_eNB->target_enb_x2_ip_address[index],
&x2ap_register_eNB->enb_x2_ip_address,
x2ap_register_eNB->sctp_in_streams,
x2ap_register_eNB->sctp_out_streams);
if (x2ap_register_eNB->target_enb_x2_ip_address[index].active == 1 ){
X2AP_INFO("eNB[%d] eNB id %u acting as an initiator\n",
instance, x2ap_register_eNB->eNB_id);
x2ap_eNB_register_eNB(new_instance,
&x2ap_register_eNB->target_enb_x2_ip_address[index],
&x2ap_register_eNB->enb_x2_ip_address,
x2ap_register_eNB->sctp_in_streams,
x2ap_register_eNB->sctp_out_streams);
}
else {
/* initiate the SCTP listener */
if (x2ap_eNB_init_sctp(new_instance,&x2ap_register_eNB->enb_x2_ip_address) < 0 ) {
X2AP_ERROR ("Error while sending SCTP_INIT_MSG to SCTP \n");
return -1;
}
X2AP_INFO("eNB[%d] eNB id %u acting as a listner\n",
instance, x2ap_register_eNB->eNB_id);
}
}
}
......
......@@ -35,8 +35,8 @@
* @{
*/
#ifndef X2AP_H_
#define X2AP_H_
#ifndef X2AP_ENB_H_
#define X2AP_ENB_H_
#define X2AP_PORT_NUMBER (36422) ///< X2AP SCTP IANA ASSIGNED Port Number
#define X2AP_SCTP_PPID (27) ///< X2AP SCTP Payload Protocol Identifier (PPID)
......
This diff is collapsed.
......@@ -37,9 +37,9 @@
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
#ifndef X2AP_ENB_PDU_DECODER_H_
#define X2AP_ENB_PDU_DECODER_H_
#ifndef X2AP_ENB_DECODER_H_
#define X2AP_ENB_DECODER_H_
int x2ap_eNB_decode_pdu(x2ap_message *x2ap_message, uint8_t *buffer, uint32_t len);
#endif /* X2AP_PDU_DECODER_H_ */
#endif /* X2AP_ENB_DECODER_H_ */
......@@ -54,10 +54,15 @@ typedef enum {
/*
*/
X2AP_ENB_OVERLOAD = 0x3,
X2AP_ENB_STATE_OVERLOAD = 0x3,
X2AP_ENB_STATE_RESETTING = 0x4,
X2AP_ENB_STATE_READY = 0x5,
/* Max number of states available */
X2AP_ENB_STATE_MAX,
} s1ap_eNB_state_t;
} x2ap_eNB_state_t;
/* Served PLMN identity element */
......@@ -89,7 +94,10 @@ typedef struct x2ap_eNB_data_s {
/* This is the optional name provided by the MME */
char *eNB_name;
/* target eNB ID */
uint32_t eNB_id;
/* Current eNB load information (if any). */
//x2ap_load_state_t overload_state;
......@@ -103,7 +111,7 @@ typedef struct x2ap_eNB_data_s {
uint16_t in_streams;
uint16_t out_streams;
/* Connexion id used between SCTP/S1AP */
/* Connexion id used between SCTP/X2AP */
uint16_t cnx_id;
/* SCTP association id */
......@@ -114,17 +122,15 @@ typedef struct x2ap_eNB_data_s {
} x2ap_eNB_data_t;
typedef struct x2ap_eNB_instance_s {
/* Next s1ap eNB association.
* Only used for virtual mode.
*/
STAILQ_ENTRY(x2ap_eNB_instance_s) x2ap_eNB_entries;
/* Number of target eNBs requested by eNB (tree size) */
uint32_t x2ap_enb_nb;
uint32_t x2_target_enb_nb;
/* Number of target eNBs for which association is pending */
uint32_t x2ap_target_enb_pending_nb;
uint32_t x2_target_enb_pending_nb;
/* Number of target eNB successfully associated to eNB */
uint32_t x2ap_target_enb_associated_nb;
uint32_t x2_target_enb_associated_nb;
/* Tree of X2AP eNB associations ordered by association ID */
RB_HEAD(x2ap_enb_map, x2ap_eNB_data_s) x2ap_enb_head;
......@@ -166,15 +172,15 @@ typedef struct {
/* Nb of registered eNBs */
uint8_t nb_registered_eNBs;
/* Generate a unique connexion id used between S1AP and SCTP */
/* Generate a unique connexion id used between X2AP and SCTP */
uint16_t global_cnx_id;
} x2ap_eNB_internal_data_t;
int x2ap_eNB_compare_assoc_id(
struct x2ap_eNB_data_s *p1, struct x2ap_eNB_data_s *p2);
int x2ap_eNB_compare_assoc_id(struct x2ap_eNB_data_s *p1, struct x2ap_eNB_data_s *p2);
/* Generate the tree management functions */
RB_PROTOTYPE(x2ap_eNB_map, x2ap_eNB_data_s, entry,
RB_PROTOTYPE(x2ap_eNB_map, x2ap_eNB_data_s, 0entry,
x2ap_eNB_compare_assoc_id);
#endif /* S1AP_ENB_DEFS_H_ */
#endif /* X2AP_ENB_DEFS_H_ */
This diff is collapsed.
......@@ -30,7 +30,10 @@
#ifndef X2AP_ENB_ENCODER_H_
#define X2AP_ENB_ENCODER_H_
int x2ap_eNB_encode_pdu(s1ap_message *message, uint8_t **buffer, uint32_t *len)
#include "x2ap_common.h"
#include "x2ap_ies_defs.h"
int x2ap_eNB_encode_pdu(x2ap_message *x2ap_message_p, uint8_t **buffer, uint32_t *len)
__attribute__ ((warn_unused_result));
#endif /* X2AP_ENB_ENCODER_H_ */
......@@ -38,20 +38,21 @@
#include "intertask_interface.h"
#include "x2ap.h"
#include "x2ap_eNB.h"
#include "x2ap_eNB_generate_messages.h"
#include "msc.h"
#include "assertions.h"
static
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_t *x2ap_enb_data_p){
x2ap_eNB_data_t *x2ap_enb_data_p){
x2ap_message message;
X2SetupRequest_IEs_t *x2SetupRequest_p;
X2SetupRequest_IEs_t *x2SetupRequest;
X2ap_PLMN_Identity_t plmnIdentity;
......@@ -74,7 +75,7 @@ int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
message.procedureCode = X2ap_ProcedureCode_id_X2Setup;
message.criticality = X2ap_Criticality_reject;
x2SetupRequest_p = &message.msg.x2SetupRequest_IEs;
x2SetupRequest = &message.msg.x2SetupRequest_IEs;
memset((void *)&plmnIdentity, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_1, 0, sizeof(X2ap_PLMN_Identity_t));
......@@ -85,18 +86,18 @@ int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_enb_data_p->state = X2AP_ENB_STATE_WAITING;
//----globalENB_ID------
x2SetupRequest_p->global_ENB_ID.eNB_ID.present = X2ap_ENB_ID_PR_macro_eNB_ID;
x2SetupRequest->global_ENB_ID.eNB_ID.present = X2ap_ENB_ID_PR_macro_eNB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID);
&x2SetupRequest->global_ENB_ID.eNB_ID.choice.macroENB_ID);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&x2SetupRequest_p->global_ENB_ID.pLMNidentity);
&x2SetupRequest->global_ENB_ID.pLMNidentity);
X2AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0],
x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1],
x2SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
x2SetupRequest->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0],
x2SetupRequest->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1],
x2SetupRequest->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
//----served cells------
//----served cells------
#warning update the value of the message
served_cell->servedCellInfo.pCI = 6;
served_cell->servedCellInfo.eUTRA_Mode_Info.present = EUTRA_Mode_Info_PR_fDD;
......@@ -116,12 +117,14 @@ int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
ECI_TO_BIT_STRING(instance_p->eNB_id, &served_cell->servedCellInfo.cellId.eUTRANcellIdentifier);
TAC_TO_OCTET_STRING(instance_p->tac, &served_cell->servedCellInfo.tAC);
ASN_SEQUENCE_ADD(&x2SetupRequest_p->servedCells.list, served_cell);
ASN_SEQUENCE_ADD(&x2SetupRequest->servedCells.list, served_cell);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_SRC_ENB, MSC_X2AP_TARGET_ENB, NULL, 0, "0 X2Setup/initiatingMessage assoc_id %u", x2ap_enb_data_p->assoc_id);
/* Non UE-Associated signalling -> stream = 0 */
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_enb_data_p->assoc_id, buffer, len, 0);
......@@ -130,6 +133,94 @@ int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
}
int
x2ap_generate_x2_setup_response (x2ap_eNB_data_t * eNB_association)
{
x2ap_eNB_instance_t *instance=eNB_association->x2ap_eNB_instance;
x2ap_message message;
X2SetupResponse_IEs_t *x2SetupResponse;
X2ap_PLMN_Identity_t plmnIdentity;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_1;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_2;
X2ap_PLMN_Identity_t broadcast_plmnIdentity_3;
ServedCellItem_t *served_cell= malloc(sizeof(ServedCellItem_t));;
uint8_t *buffer;
uint32_t length;
int ret = 0;
// get the eNB instance
//
DevAssert (eNB_association != NULL);
// Generating response
memset (&message, 0, sizeof (x2ap_message));
message.direction = X2AP_PDU_PR_successfulOutcome
message.procedureCode = X2ap_ProcedureCode_id_X2Setup;
message.criticality = X2ap_Criticality_reject;
x2SetupResponse = &message.msg.x2SetupResponse_IEs;
memset((void *)&plmnIdentity, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_1, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_2, 0, sizeof(X2ap_PLMN_Identity_t));
memset((void *)&broadcast_plmnIdentity_3, 0, sizeof(X2ap_PLMN_Identity_t));
//----globalENB_ID------
x2SetupResponse->global_ENB_ID.eNB_ID.present = X2ap_ENB_ID_PR_macro_eNB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&x2SetupResponse->global_ENB_ID.eNB_ID.choice.macroENB_ID);
MCC_MNC_TO_PLMNID(instance->mcc, instance->mnc, instance->mnc_digit_length,
&x2SetupResponse->global_ENB_ID.pLMNidentity);
X2AP_INFO("%d -> %02x%02x%02x\n", instance->eNB_id,
x2SetupResponse->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0],
x2SetupResponse->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1],
x2SetupResponse->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
//----served cells------
#warning update the value of the message
served_cell->servedCellInfo.pCI = 6;
served_cell->servedCellInfo.eUTRA_Mode_Info.present = EUTRA_Mode_Info_PR_fDD;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_EARFCN = 3350;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.uL_Transmission_Bandwidth = 0;
served_cell->servedCellInfo.eUTRA_Mode_Info.choice.fDD.dL_Transmission_Bandwidth = 0;
MCC_MNC_TO_PLMNID(instance->mcc,instance->mnc,&served_cell->servedCellInfo.cellId.pLMN_Identity);
MCC_MNC_TO_PLMNID(0,0,&broadcast_plmnid_1);
MCC_MNC_TO_PLMNID(0,0,&broadcast_plmnid_2);
MCC_MNC_TO_PLMNID(0,0,&broadcast_plmnid_3);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnid_1);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnid_2);
ASN_SEQUENCE_ADD(&served_cell->servedCellInfo.broadcastPLMNs.list, &broadcast_plmnid_3);
ECI_TO_BIT_STRING(instance->eNB_id, &served_cell->servedCellInfo.cellId.eUTRANcellIdentifier);
TAC_TO_OCTET_STRING(instance->tac, &served_cell->servedCellInfo.tAC);
ASN_SEQUENCE_ADD(&x2SetupRequest->servedCells.list, served_cell);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
return -1;
}
MSC_LOG_TX_MESSAGE (MSC_X2AP_TARGET_ENB, MSC_X2AP_SRC_ENB, NULL, 0, "0 X2Setup/successfulOutcome assoc_id %u", eNB_association->assoc_id);
/*
* Non-UE signalling -> stream 0
*/
return x2ap_eNB_itti_send_sctp_req (buffer, length, eNB_association->assoc_id, 0);
}
int x2ap_eNB_generate_x2_setup_failure ( uint32_t assoc_id,
X2ap_Cause_PR cause_type,
long cause_value,
......
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that 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 OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_GENERATE_MESSAGES_H_
#define X2AP_ENB_GENERATE_MESSAGES_H_
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p);
int
x2ap_generate_x2_setup_response (x2ap_eNB_data_t * eNB_association);
int x2ap_eNB_generate_x2_setup_failure ( uint32_t assoc_id,
X2ap_Cause_PR cause_type,
long cause_value,
long time_to_waitx);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
This diff is collapsed.
......@@ -30,6 +30,8 @@
#ifndef X2AP_ENB_HANDLERS_H_
#define X2AP_ENB_HANDLERS_H_
#include "x2ap_eNB_defs.h"
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *mme_desc_p, int sctp_shutdown);
int x2ap_eNB_handle_message(uint32_t assoc_id, int32_t stream,
......
......@@ -47,28 +47,8 @@ void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uin
itti_send_msg_to_task(TASK_SCTP, instance, message_p);
}
/*
void x2ap_eNB_itti_send_nas_downlink_ind(instance_t instance,
uint16_t ue_initial_id,
uint32_t eNB_ue_s1ap_id,
uint8_t *nas_pdu,
uint32_t nas_pdu_length)
{
MessageDef *message_p;
x2ap_rrc_t *x2ap_rrc;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_RRC);
x2ap_rrc = &message_p->ittiMsg.x2ap_rrc;
x2ap_rrc->ue_initial_id = ue_initial_id;
x2ap_rrc->eNB_ue_x2ap_id = eNB_ue_x2ap_id;
x2ap_rrc->rrc_pdu.buffer = rrc_pdu;
x2ap_rrc->rrc_pdu.length = rrc_pdu_length;
itti_send_msg_to_task(TASK_RRC_ENB, instance, message_p);
}
*/
void x2ap_eNB_itti_send_sctp_close_association(instance_t instance, int32_t assoc_id)
{
MessageDef *message_p = NULL;
......
/*******************************************************************************
OpenAirInterface
Copyright(c) 1999 - 2014 Eurecom
OpenAirInterface is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenAirInterface is distributed in the hope that 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 OpenAirInterface.The full GNU General Public License is
included in this distribution in the file called "COPYING". If not,
see <http://www.gnu.org/licenses/>.
Contact Information
OpenAirInterface Admin: openair_admin@eurecom.fr
OpenAirInterface Tech : openair_tech@eurecom.fr
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.
*******************************************************************************/
#ifndef X2AP_ENB_ITTI_MESSAGING_H_
#define X2AP_ENB_ITTI_MESSAGING_H_
void x2ap_eNB_itti_send_sctp_data_req(instance_t instance, int32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream);
void x2ap_eNB_itti_send_sctp_close_association(instance_t instance,
int32_t assoc_id);
#endif /* X2AP_ENB_ITTI_MESSAGING_H_ */
......@@ -38,7 +38,20 @@
#include "x2ap_common.h"
#include "x2ap_eNB_defs.h"
#include "x2ap.h"
#include "x2ap_eNB.h"
#define X2AP_DEBUG_LIST
#ifdef X2AP_DEBUG_LIST
# define X2AP_eNB_LIST_OUT(x, args...) X2AP_DEBUG("[eNB]%*s"x"\n", 4*indent, "", ##args)
#else
# define X2AP_eNB_LIST_OUT(x, args...)
#endif
STAILQ_HEAD (x2ap_eNB_list_s, x2ap_eNB_data_s)
x2ap_eNB_list_head;
static int indent = 0;
x2ap_eNB_internal_data_t x2ap_eNB_internal_data;
......@@ -88,9 +101,9 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p)
new_instance_p, x2ap_eNB_entries);
}
struct s1ap_eNB_mme_data_s *x2ap_eNB_get_taregt_eNB(
x2ap_eNB_instance_t *instance_p,
int32_t assoc_id, uint16_t cnx_id)
struct x2ap_eNB_data_s *x2ap_get_eNB(x2ap_eNB_instance_t *instance_p,
int32_t assoc_id,
uint16_t cnx_id)
{
struct x2ap_eNB_data_s temp;
struct x2ap_eNB_data_s *found;
......@@ -116,6 +129,7 @@ struct s1ap_eNB_mme_data_s *x2ap_eNB_get_taregt_eNB(
return NULL;
}
x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
{
x2ap_eNB_instance_t *temp = NULL;
......@@ -130,3 +144,58 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
return NULL;
}
/// utility functions
void
x2ap_dump_eNB_list (void) {
x2ap_eNB_data_t *eNB_ref;
STAILQ_FOREACH (eNB_ref, &x2ap_eNB_list_head, x2ap_eNB_entries) {
x2ap_dump_eNB (eNB_ref);
}
}
void x2ap_dump_eNB ( x2ap_eNB_data_t * eNB_ref)
{
if (eNB_ref == NULL) {
return;
}
eNB_LIST_OUT ("");
eNB_LIST_OUT ("eNB name: %s", eNB_ref->eNB_name == NULL ? "not present" : eNB_ref->eNB_name);
eNB_LIST_OUT ("eNB ID: %07x", eNB_ref->eNB_id);
indent++;
eNB_LIST_OUT ("SCTP assoc id: %d", eNB_ref->assoc_id);
eNB_LIST_OUT ("SCTP instreams: %d", eNB_ref->instreams);
eNB_LIST_OUT ("SCTP outstreams: %d", eNB_ref->outstreams);
indent--;
}
x2ap_eNB_data_t * x2ap_is_eNB_id_in_list (const uint32_t eNB_id)
{
x2ap_eNB_data_t *eNB_ref;
STAILQ_FOREACH (eNB_ref, &x2ap_eNB_list_head, x2ap_eNB_entries) {
if (eNB_ref->eNB_id == eNB_id) {
return eNB_ref;
}
}
return NULL;
}
x2ap_eNB_data_t * x2ap_is_eNB_assoc_id_in_list (const uint32_t sctp_assoc_id)
{
x2ap_eNB_data_t *eNB_ref;
STAILQ_FOREACH (eNB_ref, &x2ap_eNB_list_head, x2ap_eNB_entries) {
if (eNB_ref->sctp_assoc_id == sctp_assoc_id) {
return eNB_ref;
}
}
return NULL;
}
......@@ -42,4 +42,8 @@ uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
void x2ap_eNB_prepare_internal_data(void);
x2ap_eNB_data_t* x2ap_is_eNB_id_in_list(uint32_t eNB_id);
x2ap_eNB_data_t* x2ap_is_eNB_assoc_id_in_list(uint32_t sctp_assoc_id);
#endif /* X2AP_ENB_MANAGEMENT_PROCEDURES_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment