Commit 9ca54779 authored by Cedric Roux's avatar Cedric Roux

integrate X2 code

parent 75418f50
...@@ -46,5 +46,6 @@ MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register ...@@ -46,5 +46,6 @@ MESSAGE_DEF(X2AP_REGISTER_ENB_REQ , MESSAGE_PRIORITY_MED, x2ap_register
MESSAGE_DEF(X2AP_REGISTER_ENB_CNF , MESSAGE_PRIORITY_MED, x2ap_register_enb_cnf_t , x2ap_register_enb_cnf) 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) MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_deregistered_enb_ind_t , x2ap_deregistered_enb_ind)
/* handover messages X2AP <-> RRC */
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
MESSAGE_DEF(X2AP_HANDOVER_RESP , MESSAGE_PRIORITY_MED, x2ap_handover_resp_t , x2ap_handover_resp)
...@@ -30,10 +30,14 @@ ...@@ -30,10 +30,14 @@
#ifndef X2AP_MESSAGES_TYPES_H_ #ifndef X2AP_MESSAGES_TYPES_H_
#define X2AP_MESSAGES_TYPES_H_ #define X2AP_MESSAGES_TYPES_H_
#include "PhysCellId.h"
//-------------------------------------------------------------------------------------------// //-------------------------------------------------------------------------------------------//
// Defines to access message fields. // Defines to access message fields.
#define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req #define X2AP_REGISTER_ENB_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_req
#define X2AP_HANDOVER_REQ(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req
#define X2AP_HANDOVER_RESP(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_resp
#define X2AP_REGISTER_ENB_CNF(mSGpTR) (mSGpTR)->ittiMsg.x2ap_register_enb_cnf #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_DEREGISTERED_ENB_IND(mSGpTR) (mSGpTR)->ittiMsg.x2ap_deregistered_enb_ind
...@@ -105,4 +109,22 @@ typedef struct x2ap_deregistered_enb_ind_s { ...@@ -105,4 +109,22 @@ typedef struct x2ap_deregistered_enb_ind_s {
uint8_t nb_x2; uint8_t nb_x2;
} x2ap_deregistered_enb_ind_t; } x2ap_deregistered_enb_ind_t;
//-------------------------------------------------------------------------------------------//
// X2AP <-> RRC
typedef struct x2ap_handover_req_s {
int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */
PhysCellId_t target_physCellId;
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_req_t;
typedef struct x2ap_handover_resp_s {
int source_rnti; /* TODO: to be fixed/remove */
int source_x2id; /* TODO: to be fixed/remove */
/* TODO: this parameter has to be removed */
int target_mod_id;
} x2ap_handover_resp_t;
#endif /* X2AP_MESSAGES_TYPES_H_ */ #endif /* X2AP_MESSAGES_TYPES_H_ */
...@@ -165,7 +165,7 @@ int xer_sprint (char *string, size_t string_size, asn_TYPE_descriptor_t *td, voi ...@@ -165,7 +165,7 @@ int xer_sprint (char *string, size_t string_size, asn_TYPE_descriptor_t *td, voi
er.encoded = string_buffer.string_size; er.encoded = string_buffer.string_size;
} else { } else {
if (er.encoded > string_buffer.string_size) { if (er.encoded > string_buffer.string_size) {
LOG_E(RRC, "xer_sprint string buffer too small, got %d need %d!", string_buffer.string_size, er.encoded); //LOG_E(RRC, "xer_sprint string buffer too small, got %d need %d!", string_buffer.string_size, er.encoded);
er.encoded = string_buffer.string_size; er.encoded = string_buffer.string_size;
} }
} }
......
...@@ -166,7 +166,11 @@ typedef enum HO_STATE_e { ...@@ -166,7 +166,11 @@ typedef enum HO_STATE_e {
HO_MEASURMENT, HO_MEASURMENT,
HO_PREPARE, HO_PREPARE,
HO_CMD, // initiated by the src eNB HO_CMD, // initiated by the src eNB
HO_COMPLETE // initiated by the target eNB HO_COMPLETE, // initiated by the target eNB
HO_REQUEST,
HO_ACK,
HO_CONFIGURED,
} HO_STATE_t; } HO_STATE_t;
//#define NUMBER_OF_UE_MAX MAX_MOBILES_PER_RG //#define NUMBER_OF_UE_MAX MAX_MOBILES_PER_RG
...@@ -235,8 +239,8 @@ typedef struct e_rab_param_s { ...@@ -235,8 +239,8 @@ typedef struct e_rab_param_s {
/* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */ /* Intermediate structure for Handover management. Associated per-UE in eNB_RRC_INST */
typedef struct HANDOVER_INFO_s { typedef struct HANDOVER_INFO_s {
uint8_t ho_prepare; int ho_prepare, ho_complete;
uint8_t ho_complete; HO_STATE_t state; //current state of handover
uint8_t modid_s; //module_idP of serving cell uint8_t modid_s; //module_idP of serving cell
uint8_t modid_t; //module_idP of target cell uint8_t modid_t; //module_idP of target cell
uint16_t ueid_s; //UE index in serving cell uint16_t ueid_s; //UE index in serving cell
...@@ -245,6 +249,8 @@ typedef struct HANDOVER_INFO_s { ...@@ -245,6 +249,8 @@ typedef struct HANDOVER_INFO_s {
AS_Context_t as_context; /* They are mandatory for HO */ AS_Context_t as_context; /* They are mandatory for HO */
uint8_t buf[RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */ uint8_t buf[RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */
int size; /* size of above message in bytes */ int size; /* size of above message in bytes */
/* TODO: to remove or not? */
int source_x2id;
} HANDOVER_INFO; } HANDOVER_INFO;
#define RRC_HEADER_SIZE_MAX 64 #define RRC_HEADER_SIZE_MAX 64
......
...@@ -1812,6 +1812,31 @@ rrc_eNB_process_MeasurementReport( ...@@ -1812,6 +1812,31 @@ rrc_eNB_process_MeasurementReport(
LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult); LOG_I(RRC, "RSRQ of Source %d\n", measResults2->measResultServCell.rsrqResult);
#endif #endif
/* if the UE is not in handover mode, start handover procedure */
if (ue_context_pP->ue_context.Status != RRC_HO_EXECUTION) {
MessageDef *msg;
ue_context_pP->ue_context.Status = RRC_HO_EXECUTION;
ue_context_pP->ue_context.handover_info->state = HO_REQUEST;
rrc_eNB_generate_HandoverPreparationInformation(ctxt_pP,
ue_context_pP,
measResults2->measResultNeighCells->choice.
measResultListEUTRA.list.array[0]->physCellId);
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_REQ);
X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
measResultListEUTRA.list.array[0]->physCellId;
/* TODO: don't do that, X2AP should find the target by itself */
X2AP_HANDOVER_REQ(msg).target_mod_id = get_adjacent_cell_mod_id(X2AP_HANDOVER_REQ(msg).target_physCellId);
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
} else {
LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame,
ctxt_pP->rnti);
}
#if 0
if (ue_context_pP->ue_context.handover_info->ho_prepare != 0xF0) { if (ue_context_pP->ue_context.handover_info->ho_prepare != 0xF0) {
rrc_eNB_generate_HandoverPreparationInformation(ctxt_pP, rrc_eNB_generate_HandoverPreparationInformation(ctxt_pP,
ue_context_pP, ue_context_pP,
...@@ -1821,6 +1846,7 @@ rrc_eNB_process_MeasurementReport( ...@@ -1821,6 +1846,7 @@ rrc_eNB_process_MeasurementReport(
LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame, LOG_D(RRC, "[eNB %d] Frame %d: Ignoring MeasReport from UE %x as Handover is in progress... \n", ctxt_pP->module_id, ctxt_pP->frame,
ctxt_pP->rnti); ctxt_pP->rnti);
} }
#endif
//Look for IP address of the target eNB //Look for IP address of the target eNB
//Send Handover Request -> target eNB //Send Handover Request -> target eNB
...@@ -1899,6 +1925,46 @@ rrc_eNB_generate_HandoverPreparationInformation( ...@@ -1899,6 +1925,46 @@ rrc_eNB_generate_HandoverPreparationInformation(
} }
} }
static int global_rnti;
void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m)
{
struct rrc_eNB_ue_context_s* ue_context_target_p = NULL;
/* TODO: get proper UE rnti */
int rnti = taus() & 0xffff;
global_rnti = rnti;
ue_context_target_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[mod_id], rnti);
if (ue_context_target_p != NULL) {
LOG_E(RRC, "\nError in obtaining free UE id in target eNB for handover \n");
return;
}
ue_context_target_p = rrc_eNB_allocate_new_UE_context(&eNB_rrc_inst[mod_id]);
if (ue_context_target_p == NULL) {
LOG_E(RRC, "Cannot create new UE context\n");
return;
}
ue_context_target_p->ue_id_rnti = rnti;
ue_context_target_p->ue_context.rnti = rnti;
RB_INSERT(rrc_ue_tree_s, &eNB_rrc_inst[mod_id].rrc_ue_head, ue_context_target_p);
LOG_D(RRC, "eNB %d: Created new UE context uid %u\n", mod_id, ue_context_target_p->local_uid);
ue_context_target_p->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info)));
ue_context_target_p->ue_context.handover_info->source_x2id = m->source_x2id;
ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION;
ue_context_target_p->ue_context.handover_info->state = HO_ACK;
/* TODO: remove this hack */
ue_context_target_p->ue_context.handover_info->modid_t = mod_id;
ue_context_target_p->ue_context.handover_info->modid_s = 1-mod_id;
ue_context_target_p->ue_context.handover_info->ueid_s= m->source_rnti;
}
#if 0
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
rrc_eNB_process_handoverPreparationInformation( rrc_eNB_process_handoverPreparationInformation(
...@@ -1983,6 +2049,7 @@ rrc_eNB_process_handoverPreparationInformation( ...@@ -1983,6 +2049,7 @@ rrc_eNB_process_handoverPreparationInformation(
//rrc_create_old_crnti(ctxt_pP,ue_context_target_p->ue_context.handover_info->modid_s,0, ue_context_pP->ue_id_rnti); //rrc_create_old_crnti(ctxt_pP,ue_context_target_p->ue_context.handover_info->modid_s,0, ue_context_pP->ue_id_rnti);
} }
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void void
...@@ -1994,12 +2061,12 @@ check_handovers( ...@@ -1994,12 +2061,12 @@ check_handovers(
int result; int result;
struct rrc_eNB_ue_context_s* ue_context_p; struct rrc_eNB_ue_context_s* ue_context_p;
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head) { RB_FOREACH(ue_context_p, rrc_ue_tree_s, &eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head) {
ctxt_pP->rnti = ue_context_p->ue_id_rnti; ctxt_pP->rnti = ue_context_p->ue_id_rnti;
if (ue_context_p->ue_context.handover_info != NULL) { if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION && ue_context_p->ue_context.handover_info != NULL) {
if (ue_context_p->ue_context.handover_info->ho_prepare == 0xFF) { /* in the source, UE in HO_PREPARE mode */
if (ue_context_p->ue_context.handover_info->state == HO_PREPARE /*ho_prepare == 0xFF*/) {
LOG_D(RRC, LOG_D(RRC,
"[eNB %d] Frame %d: Incoming handover detected for new UE_id %x (source eNB %d->target eNB %d) \n", "[eNB %d] Frame %d: Incoming handover detected for new UE_id %x (source eNB %d->target eNB %d) \n",
ctxt_pP->module_id, ctxt_pP->module_id,
...@@ -2008,19 +2075,45 @@ check_handovers( ...@@ -2008,19 +2075,45 @@ check_handovers(
ctxt_pP->module_id, ctxt_pP->module_id,
ue_context_p->ue_context.handover_info->modid_t); ue_context_p->ue_context.handover_info->modid_t);
// source eNB generates rrcconnectionreconfiguration to prepare the HO // source eNB generates rrcconnectionreconfiguration to prepare the HO
LOG_I(RRC,
"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n",
ctxt_pP->module_id, ctxt_pP->frame, ue_context_p->ue_context.rnti);
/* TODO: remove this hack, this call has to be done here I think but we must do
* it before rrc_eNB_configure_rbs_handover because the SRBs are copied
* instead of coming from the X2AP message as should be done
*/
// rrc_eNB_generate_RRCConnectionReconfiguration_handover(
// ctxt_pP,
// ue_context_p,
// NULL,
// 0);
#if 0
rrc_eNB_process_handoverPreparationInformation( rrc_eNB_process_handoverPreparationInformation(
ctxt_pP, ctxt_pP,
ue_context_p); ue_context_p);
ue_context_p->ue_context.handover_info->ho_prepare = 0xF0; #endif
//ue_context_p->ue_context.handover_info->ho_prepare = 0xF0;
ue_context_p->ue_context.handover_info->state = HO_COMPLETE;
} }
if (ue_context_p->ue_context.handover_info->ho_prepare == 0xF2) { /* in the target, UE in HO_ACK mode */
if (ue_context_p->ue_context.handover_info->state == HO_ACK /*ho_prepare == 0xF2*/) {
MessageDef *msg;
// Configure target // Configure target
rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP); rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP);
ue_context_p->ue_context.handover_info->ho_prepare = 0x00; // ue_context_p->ue_context.handover_info->ho_prepare = 0x00;
ue_context_p->ue_context.handover_info->state = HO_CONFIGURED;
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_HANDOVER_RESP);
/* TODO: remove this hack */
X2AP_HANDOVER_RESP(msg).target_mod_id = 1 - ctxt_pP->module_id;
X2AP_HANDOVER_RESP(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id;
itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(ctxt_pP->module_id), msg);
} }
/* THIS CODE IS NOT RUN */
if (ue_context_p->ue_context.handover_info->ho_complete == 0xF1) { if (ue_context_p->ue_context.handover_info->ho_complete == 0xF1) {
LOG_D(RRC, LOG_D(RRC,
"[eNB %d] Frame %d: handover Command received for new UE_id %x current eNB %d target eNB: %d \n", "[eNB %d] Frame %d: handover Command received for new UE_id %x current eNB %d target eNB: %d \n",
...@@ -2057,6 +2150,21 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protoc ...@@ -2057,6 +2150,21 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s* ue_context_p, protoc
&eNB_rrc_inst[ue_context_p->ue_context.handover_info->modid_s], &eNB_rrc_inst[ue_context_p->ue_context.handover_info->modid_s],
ue_context_p->ue_context.handover_info->ueid_s); ue_context_p->ue_context.handover_info->ueid_s);
if(ue_source_context!=NULL){ if(ue_source_context!=NULL){
/* HACK - we have to call rrc_eNB_generate_RRCConnectionReconfiguration_handover before for the SRBs to be okay */
/* to be removed when X2 messages are done */
{
protocol_ctxt_t c = *ctxt_pP;
c.module_id = 0;
c.enb_flag = 1;
c.instance = 0;
c.rnti = ue_source_context->ue_context.rnti;
c.eNB_index = 0;
rrc_eNB_generate_RRCConnectionReconfiguration_handover(
&c,
ue_source_context,
NULL,
0);
}
LOG_D(RRC,"Frame: %d-Entering target: C-RNTI %x-eNB: %d-MOD_ID: %d\n",ctxt_pP->frame,ctxt_pP->rnti,ctxt_pP->eNB_index,ctxt_pP->module_id); LOG_D(RRC,"Frame: %d-Entering target: C-RNTI %x-eNB: %d-MOD_ID: %d\n",ctxt_pP->frame,ctxt_pP->rnti,ctxt_pP->eNB_index,ctxt_pP->module_id);
// E-RABS // E-RABS
// Emulating transmission/reception (just a memory copy) // Emulating transmission/reception (just a memory copy)
...@@ -2235,6 +2343,8 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( ...@@ -2235,6 +2343,8 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
rv[i] = taus() & 0xff; rv[i] = taus() & 0xff;
LOG_D(RRC, " %x.", rv[i]); LOG_D(RRC, " %x.", rv[i]);
} }
rv[0] = global_rnti&255;
rv[1] = (global_rnti>>8) & 255;
LOG_D(RRC, "[eNB %d] Frame %d : handover reparation: add target eNB SRB1 and PHYConfigDedicated reconfiguration\n", LOG_D(RRC, "[eNB %d] Frame %d : handover reparation: add target eNB SRB1 and PHYConfigDedicated reconfiguration\n",
ctxt_pP->module_id, ctxt_pP->frame); ctxt_pP->module_id, ctxt_pP->frame);
...@@ -2276,6 +2386,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( ...@@ -2276,6 +2386,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
*logicalchannelgroup = 0; *logicalchannelgroup = 0;
SRB1_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup; SRB1_ul_SpecificParameters->logicalChannelGroup = logicalchannelgroup;
ASN_SEQUENCE_ADD(&SRB_configList->list, SRB1_config);
ASN_SEQUENCE_ADD(&SRB_configList2->list, SRB1_config); ASN_SEQUENCE_ADD(&SRB_configList2->list, SRB1_config);
//2nd: now reconfigure phy config dedicated //2nd: now reconfigure phy config dedicated
...@@ -2484,8 +2595,8 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover( ...@@ -2484,8 +2595,8 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
// Configure target eNB SRB2 // Configure target eNB SRB2
/// SRB2 /// SRB2
SRB2_config = CALLOC(1, sizeof(*SRB2_config)); SRB2_config = CALLOC(1, sizeof(*SRB2_config));
SRB_configList2 = CALLOC(1, sizeof(*SRB_configList2)); //SRB_configList2 = CALLOC(1, sizeof(*SRB_configList2));
memset(SRB_configList2, 0, sizeof(*SRB_configList2)); //memset(SRB_configList2, 0, sizeof(*SRB_configList2));
SRB2_config->srb_Identity = 1; SRB2_config->srb_Identity = 1;
SRB2_rlc_config = CALLOC(1, sizeof(*SRB2_rlc_config)); SRB2_rlc_config = CALLOC(1, sizeof(*SRB2_rlc_config));
...@@ -4548,6 +4659,20 @@ rrc_enb_task( ...@@ -4548,6 +4659,20 @@ rrc_enb_task(
# endif # endif
case X2AP_HANDOVER_REQ:
LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p);
rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p));
break;
case X2AP_HANDOVER_RESP: {
struct rrc_eNB_ue_context_s *ue_context_p = rrc_eNB_get_ue_context(&eNB_rrc_inst[instance], X2AP_HANDOVER_RESP(msg_p).source_rnti);
LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p);
DevAssert(ue_context_p != NULL);
if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort();
ue_context_p->ue_context.handover_info->state = HO_PREPARE;
break;
}
/* Messages from eNB app */ /* Messages from eNB app */
case RRC_CONFIGURATION_REQ: case RRC_CONFIGURATION_REQ:
LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p); LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p);
......
...@@ -69,6 +69,14 @@ static ...@@ -69,6 +69,14 @@ static
void x2ap_eNB_handle_register_eNB(instance_t instance, void x2ap_eNB_handle_register_eNB(instance_t instance,
x2ap_register_enb_req_t *x2ap_register_eNB); x2ap_register_enb_req_t *x2ap_register_eNB);
static
void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req);
static
void x2ap_eNB_handle_handover_resp(instance_t instance,
x2ap_handover_resp_t *x2ap_handover_resp);
static static
void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p, void x2ap_eNB_register_eNB(x2ap_eNB_instance_t *instance_p,
net_ip_address_t *target_eNB_ip_addr, net_ip_address_t *target_eNB_ip_addr,
...@@ -378,6 +386,64 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, ...@@ -378,6 +386,64 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
} }
/* TODO: remove this hack, it's to map rnti to X2 ID in the source eNB, only 1 UE supported */
/* so we directly use index 0, no search no lock no nothing */
int x2id_to_source_rnti[1];
/* TODO: remove that, it's for the hack below */
#include "enb_config.h"
static
void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req)
{
/* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the target) - we need a proper way for RRC
* and X2AP to identify eNodeBs
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
* the configuration file)
* as far as I understand.. CROUX
*/
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
const Enb_properties_array_t *enb_properties = enb_config_get();
int target_enb_id = enb_properties->properties[x2ap_handover_req->target_mod_id]->eNB_id;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL);
/* store rnti at index 0 */
x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti;
x2ap_eNB_generate_x2_handover_request(instance_p, target, 0);
}
static
void x2ap_eNB_handle_handover_resp(instance_t instance,
x2ap_handover_resp_t *x2ap_handover_resp)
{
/* TODO: remove this hack (the goal is to find the correct
* eNodeB structure for the other end) - we need a proper way for RRC
* and X2AP to identify eNodeBs
* RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in
* the configuration file)
* as far as I understand.. CROUX
*/
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
const Enb_properties_array_t *enb_properties = enb_config_get();
int target_enb_id = enb_properties->properties[x2ap_handover_resp->target_mod_id]->eNB_id;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id);
DevAssert(target != NULL);
x2ap_eNB_generate_x2_handover_response(instance_p, target, x2ap_handover_resp->source_x2id);
}
void *x2ap_task(void *arg) void *x2ap_task(void *arg)
{ {
...@@ -403,6 +469,16 @@ void *x2ap_task(void *arg) ...@@ -403,6 +469,16 @@ void *x2ap_task(void *arg)
&X2AP_REGISTER_ENB_REQ(received_msg)); &X2AP_REGISTER_ENB_REQ(received_msg));
break; break;
case X2AP_HANDOVER_REQ:
x2ap_eNB_handle_handover_req(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_REQ(received_msg));
break;
case X2AP_HANDOVER_RESP:
x2ap_eNB_handle_handover_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_HANDOVER_RESP(received_msg));
break;
case SCTP_NEW_ASSOCIATION_RESP: case SCTP_NEW_ASSOCIATION_RESP:
x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), x2ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_new_association_resp); &received_msg->ittiMsg.sctp_new_association_resp);
......
...@@ -49,8 +49,8 @@ ...@@ -49,8 +49,8 @@
int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_p, 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; x2ap_message message;
X2SetupRequest_IEs_t *x2SetupRequest; X2SetupRequest_IEs_t *x2SetupRequest;
...@@ -296,3 +296,156 @@ int x2ap_eNB_set_cause (X2ap_Cause_t * cause_p, ...@@ -296,3 +296,156 @@ int x2ap_eNB_set_cause (X2ap_Cause_t * cause_p,
return 0; return 0;
} }
int x2ap_eNB_generate_x2_handover_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id)
{
/* TODO: set correct values in there */
x2ap_message message;
uint8_t *buffer;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_enb_data_p != NULL);
memset(&message, 0, sizeof(x2ap_message));
message.direction = X2AP_PDU_PR_initiatingMessage;
message.procedureCode = X2ap_ProcedureCode_id_handoverPreparation;
message.criticality = X2ap_Criticality_reject;
message.msg.x2ap_HandoverRequest_IEs.old_eNB_UE_X2AP_ID = source_x2id;
message.msg.x2ap_HandoverRequest_IEs.cause.present = X2ap_Cause_PR_radioNetwork;
message.msg.x2ap_HandoverRequest_IEs.cause.choice.radioNetwork = X2ap_CauseRadioNetwork_handover_desirable_for_radio_reasons;
MCC_MNC_TO_PLMNID(123, 456, 3, &message.msg.x2ap_HandoverRequest_IEs.targetCell_ID.pLMN_Identity);
int eci1 = 79;
ECI_TO_BIT_STRING(eci1, &message.msg.x2ap_HandoverRequest_IEs.targetCell_ID.eUTRANcellIdentifier);
MCC_MNC_TO_PLMNID(456, 123, 3, &message.msg.x2ap_HandoverRequest_IEs.gummei_id.gU_Group_ID.pLMN_Identity);
MMEGID_TO_OCTET_STRING(26, &message.msg.x2ap_HandoverRequest_IEs.gummei_id.gU_Group_ID.mME_Group_ID);
MMEC_TO_OCTET_STRING(12, &message.msg.x2ap_HandoverRequest_IEs.gummei_id.mME_Code);
message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.mME_UE_S1AP_ID = 12;
ENCRALG_TO_BIT_STRING(0,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
INTPROTALG_TO_BIT_STRING(0,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uESecurityCapabilities.integrityProtectionAlgorithms);
char KeNB_star[32] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
KENB_STAR_TO_BIT_STRING(KeNB_star,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.aS_SecurityInformation.key_eNodeB_star);
message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.aS_SecurityInformation.nextHopChainingCount = 1;
UEAGMAXBITRTD_TO_ASN_PRIMITIVES(3L,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateDownlink);
UEAGMAXBITRTU_TO_ASN_PRIMITIVES(6L,&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.uEaggregateMaximumBitRate.uEaggregateMaximumBitRateUplink);
X2ap_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item1 = calloc(1, sizeof(X2ap_E_RABs_ToBeSetup_Item_t));
e_RABs_ToBeSetup_Item1->e_RAB_ID=10;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.qCI=1;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.priorityLevel = 1;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionCapability = 0;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.pre_emptionVulnerability = 0;
e_RABs_ToBeSetup_Item1->e_RAB_Level_QoS_Parameters.allocationAndRetentionPriority.iE_Extensions = NULL;
TRLA_TO_BIT_STRING(1, &e_RABs_ToBeSetup_Item1->uL_GTPtunnelEndpoint.transportLayerAddress); // IPv4
GTP_TEID_TO_OCTET_STRING (12, &e_RABs_ToBeSetup_Item1->uL_GTPtunnelEndpoint.gTP_TEID);
X2ap_E_RABs_ToBeSetup_ListIEs_t *e_RABs_ToBeSetup_List1 = calloc(1, sizeof(X2ap_E_RABs_ToBeSetup_ListIEs_t));
ASN_SEQUENCE_ADD(e_RABs_ToBeSetup_List1, e_RABs_ToBeSetup_Item1);
x2ap_encode_x2ap_e_rabs_tobesetup_list(&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.e_RABs_ToBeSetup_List, e_RABs_ToBeSetup_List1);
#if 0
char RRC[81] = { 0x0a,0x10,0x00,0x00,0x03,0x41,0x60,0x08,0xcf,0x50,0x4a,0x0e,0x07,0x00,0x8c,0xf5,0x04,0xa0,0xe0,0x03,0xc0,0x51,0xc2,0x28,
0xb8,0x56,0xd1,0x80,0x4a,0x00,0x00,0x08,0x18,0x02,0x20,0x42,0x08,0x00,0x80,0x60,0x00,0x20,0x00,0x00,0x03,0x82,0xca,0x04,
0x06,0x14,0x08,0x0f,0x59,0x95,0x64,0x80,0x00,0x02,0x0a,0x5a,0x00,0x20,0x00,0x08,0x04,0x01,0x2f,0x39,0x57,0x96,0xde,0xc0,
0x00,0x88,0xea,0x46,0x7d,0x10,0x00,0x03,0x40 };
#endif
char RRC[] = {
0x0A,0x10,0x31,0xC5,0x20,0x00,0x05,0x00,0x10,0x40,0xC1,0xC9,0x85,0x8B,0xF8,0xDF,0xE2,0xFE,0x37,0xF8,0xBF,0x8D,0xFE,0x2F,0xE3,0x7F,0x8B,0xF8,0xDF,0xE2,0xFE,0x37,0xF7,0xF0,0xFF,0xE9,0x88,0x81,0x00,0x87,0x0C,0xA7,0x4A,0x92,0x20,0x20,0x58,0x00,0x00,0x00,0x00,0x00,0x15,0xD8,0x00,0x00,0x06,0x8B,0x02,0x00,0x02,0x90,0x21,0x59,0x70,0x00,0x00,0x72,0xA2,0x40,0x37,0xB0,0x11,0xFA,0x9C,0x0B,0x81,0x1F,0xA9,0xC0,0x83,0xEA,0x26,0xE0,0x25,0x75,0x38,0xA1,0xD8,0x84,0xF9,0x80,0x3E,0x55,0x8F,0xFD,0x15,0x35,0x86,0x1C,0x86,0xC8,0xA1,0x82,0x40,0xA1,0x35,0x00,0x00,0x00,0x24,0x10,0x92,0x80,0x02,0x00,0x00,0x10,0x2C,0x00,0x30,0x00,0x40,0xF6,0x07,0xCA,0xCB,0xB2,0x4C,0x00,0x6C,0x05,0x35,0x00,0x10,0x00,0x04,0x01,0x00,0xF7,0x52,0xAB,0xCA,0xF7,0x20,0x07,0x43,0x45,0xA0,0x1E,0xB8,0xE0,
};
OCTET_STRING_fromBuf(&message.msg.x2ap_HandoverRequest_IEs.uE_ContextInformation.rRC_Context, (char*) RRC, sizeof(RRC));
X2ap_LastVisitedCell_Item_t *lastVisitedCell_Item1 = calloc(1, sizeof(X2ap_LastVisitedCell_Item_t));
lastVisitedCell_Item1->present = X2ap_LastVisitedCell_Item_PR_e_UTRAN_Cell;
lastVisitedCell_Item1->choice.e_UTRAN_Cell.cellType.cell_Size=1;
lastVisitedCell_Item1->choice.e_UTRAN_Cell.time_UE_StayedInCell=2;
MCC_MNC_TO_PLMNID(987,765, 3, &lastVisitedCell_Item1->choice.e_UTRAN_Cell.global_Cell_ID.pLMN_Identity);
int eci2 = 55;
ECI_TO_BIT_STRING(eci2,&lastVisitedCell_Item1->choice.e_UTRAN_Cell.global_Cell_ID.eUTRANcellIdentifier);
ASN_SEQUENCE_ADD(&message.msg.x2ap_HandoverRequest_IEs.uE_HistoryInformation.list,lastVisitedCell_Item1);
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 setup request\n");
abort();
return -1;
}
/* TODO: use correct stream, 1 for the moment */
x2ap_eNB_itti_send_sctp_data_req(instance_p->instance, x2ap_enb_data_p->assoc_id, buffer, len, 1);
return ret;
}
int x2ap_eNB_generate_x2_handover_response(x2ap_eNB_instance_t *instance,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id)
{
x2ap_message message;
uint8_t *buffer;
uint32_t len;
int ret = 0;
// Generating response
memset (&message, 0, sizeof (x2ap_message));
X2ap_E_RABs_Admitted_ListIEs_t *e_RABs_Admitted_List1;
X2ap_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item1;
e_RABs_Admitted_Item1 = calloc(1, sizeof(X2ap_E_RABs_Admitted_Item_t));
e_RABs_Admitted_List1 = calloc(1, sizeof(X2ap_E_RABs_Admitted_ListIEs_t));
asn1_xer_print = 1;
asn_debug = 0;
X2ap_ProcedureCode_t procedure = X2ap_ProcedureCode_id_handoverPreparation;
X2ap_Criticality_t criticality = X2ap_Criticality_reject;
X2AP_PDU_PR present;
present = X2AP_PDU_PR_successfulOutcome;
message.procedureCode = procedure;
message.criticality= criticality;
message.direction = present;
//data is in file RRC_Context_acknowledge.txt
uint8_t RRC[63] = { 0x01,0xe9,0x00,0x90,0xa8,0x00,0x00,0x22,0x33,0xe9,0x42,0x80,0x02,0xf0,0x80,0x9e,0x20,0x23,0xc6,0x05,0x79,0x00,0xef,0x28,
0x21,0xe1,0x01,0x24,0x38,0x40,0x05,0x00,0x12,0x1c,0xa0,0x00,0x02,0x00,0x88,0x02,0x18,0x06,0x40,0x10,0xa0,0x2b,0x43,0x81,
0x1d,0xd9,0xc0,0x30,0x70,0x00,0xe0,0x21,0xc3,0x17,0x01,0x74,0x60,0x12,0x80 };
message.msg.x2ap_HandoverRequestAcknowledge_IEs.old_eNB_UE_X2AP_ID = source_x2id;
message.msg.x2ap_HandoverRequestAcknowledge_IEs.new_eNB_UE_X2AP_ID= 2001;
e_RABs_Admitted_Item1->e_RAB_ID=12;
e_RABs_Admitted_Item1->iE_Extensions = NULL;
ASN_SEQUENCE_ADD(e_RABs_Admitted_List1, e_RABs_Admitted_Item1);
memcpy(&message.msg.x2ap_HandoverRequestAcknowledge_IEs.e_RABs_Admitted_List, e_RABs_Admitted_List1, sizeof(X2ap_E_RABs_Admitted_ListIEs_t));
OCTET_STRING_fromBuf(&message.msg.x2ap_HandoverRequestAcknowledge_IEs.targeteNBtoSource_eNBTransparentContainer, (char*) RRC, sizeof(RRC));
if (x2ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
X2AP_ERROR("Failed to encode X2 handover response\n");
abort();
return -1;
}
//eNB_association->state = X2AP_ENB_STATE_READY;
/* TODO: use correct stream, 1 for the moment */
x2ap_eNB_itti_send_sctp_data_req(instance->instance, x2ap_enb_data_p->assoc_id, buffer, len, 1);
return ret;
}
...@@ -42,4 +42,13 @@ int x2ap_eNB_generate_x2_setup_failure ( uint32_t assoc_id, ...@@ -42,4 +42,13 @@ int x2ap_eNB_generate_x2_setup_failure ( uint32_t assoc_id,
X2ap_Cause_PR cause_type, X2ap_Cause_PR cause_type,
long cause_value, long cause_value,
long time_to_waitx); long time_to_waitx);
int x2ap_eNB_generate_x2_handover_request(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id);
int x2ap_eNB_generate_x2_handover_response(x2ap_eNB_instance_t *instance_p,
x2ap_eNB_data_t *x2ap_enb_data_p,
int source_x2id);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ #endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
...@@ -55,6 +55,14 @@ ...@@ -55,6 +55,14 @@
#include "conversions.h" #include "conversions.h"
#include "msc.h" #include "msc.h"
static
int x2ap_eNB_handle_handover_preparation(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message);
static
int x2ap_eNB_handle_handover_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message);
static static
int x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id, int x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id,
uint32_t stream, uint32_t stream,
...@@ -86,7 +94,7 @@ int x2ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, ...@@ -86,7 +94,7 @@ int x2ap_eNB_handle_ue_context_release_command(uint32_t assoc_id,
// x2ap_messages_callback[message.procedureCode][message.direction] // x2ap_messages_callback[message.procedureCode][message.direction]
x2ap_message_decoded_callback x2ap_messages_callback[][3] = { x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
// { x2ap_eNB_handle_handover_preparation, 0, 0 }, /* HandoverPreparation */ // { x2ap_eNB_handle_handover_preparation, 0, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverPreparation */ { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* HandoverPreparation */
{ 0, 0, 0 }, /* HandoverCancel */ { 0, 0, 0 }, /* HandoverCancel */
{ 0, 0, 0 }, /* loadIndication */ { 0, 0, 0 }, /* loadIndication */
{ x2ap_eNB_handle_error_indication, 0, 0 }, /* errorIndication */ { x2ap_eNB_handle_error_indication, 0, 0 }, /* errorIndication */
...@@ -195,6 +203,164 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown ...@@ -195,6 +203,164 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown
} }
} }
int
x2ap_eNB_handle_handover_preparation(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message)
{
X2ap_HandoverRequest_IEs_t *x2HandoverRequest;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
int ta_ret;
//uint16_t max_enb_connected;
MessageDef *m;
DevAssert (message != NULL);
x2HandoverRequest = &message->msg.x2ap_HandoverRequest_IEs;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover request on stream == 0\n");
/* TODO: send a x2 failure response */
return 0;
}
X2AP_DEBUG ("Received a new X2 handover request\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
m = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ);
/* TODO: fill the message */
extern int x2id_to_source_rnti[1];
X2AP_HANDOVER_REQ(m).source_x2id = x2HandoverRequest->old_eNB_UE_X2AP_ID;
X2AP_HANDOVER_REQ(m).source_rnti = x2id_to_source_rnti[x2HandoverRequest->old_eNB_UE_X2AP_ID];
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, m);
return 0;
#if 0
if (x2SetupRequest->globalENB_ID.eNB_ID.present == X2ap_ENB_ID_PR_home_eNB_ID) {
// Home eNB ID = 28 bits
uint8_t *eNB_id_buf = x2SetupRequest->globalENB_ID.eNB_ID.choice.home_eNB_ID.buf;
if (x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 28) {
//TODO: handle case were size != 28 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 20) + (eNB_id_buf[1] << 12) + (eNB_id_buf[2] << 4) + ((eNB_id_buf[3] & 0xf0) >> 4);
X2AP_DEBUG ("Home eNB id: %07x\n", eNB_id);
} else {
// Macro eNB = 20 bits
uint8_t *eNB_id_buf = x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.buf;
if (x2SetupRequest->globalENB_ID.eNB_ID.choice.macro_eNB_ID.size != 20) {
//TODO: handle case were size != 20 -> notify ? reject ?
}
eNB_id = (eNB_id_buf[0] << 12) + (eNB_id_buf[1] << 4) + ((eNB_id_buf[2] & 0xf0) >> 4);
X2AP_DEBUG ("macro eNB id: %05x\n", eNB_id);
}
/*
* If none of the provided PLMNs/TAC match the one configured in MME,
* * * * the x2 setup should be rejected with a cause set to Unknown PLMN.
*/
// ta_ret = x2ap_eNB_compare_ta_lists (&x2SetupRequest_p->supportedTAs);
/*
* Source and Target eNBs have no common PLMN
*/
/*
if (ta_ret != TA_LIST_RET_OK) {
X2AP_ERROR ("No Common PLMN with the target eNB, generate_x2_setup_failure\n");
return x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_misc,
X2ap_CauseMisc_unknown_PLMN,
X2ap_TimeToWait_v20s);
}
*/
X2AP_DEBUG ("Adding eNB to the list of associated eNBs\n");
if ((x2ap_eNB_data = x2ap_is_eNB_id_in_list (eNB_id)) == NULL) {
/*
* eNB has not been fount in list of associated eNB,
* * * * Add it to the tail of list and initialize data
*/
if ((x2ap_eNB_data = x2ap_is_eNB_assoc_id_in_list (assoc_id)) == NULL) {
/*
* ??
*/
return -1;
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
x2ap_eNB_data->eNB_id = eNB_id;
}
} else {
x2ap_eNB_data->state = X2AP_ENB_STATE_RESETTING;
/*
* eNB has been fount in list, consider the x2 setup request as a reset connection,
* * * * reseting any previous UE state if sctp association is != than the previous one
*/
if (x2ap_eNB_data->assoc_id != assoc_id) {
X2SetupFailure_IEs_t x2SetupFailure;
memset (&x2SetupFailure, 0, sizeof (x2SetupFailure));
/*
* Send an overload cause...
*/
X2AP_ERROR ("Rejeting x2 setup request as eNB id %d is already associated to an active sctp association" "Previous known: %d, new one: %d\n", eNB_id, x2ap_eNB_data->assoc_id, assoc_id);
x2ap_eNB_generate_x2_setup_failure (assoc_id,
X2ap_Cause_PR_protocol,
X2ap_CauseProtocol_unspecified,
-1);
return -1;
}
/*
* TODO: call the reset procedure
*/
}
return x2ap_generate_x2_setup_response (x2ap_eNB_data);
#endif
}
int
x2ap_eNB_handle_handover_response(uint32_t assoc_id,
uint32_t stream,
struct x2ap_message_s *message)
{
X2ap_HandoverRequestAcknowledge_IEs_t *x2HandoverRequestAck;
x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0;
int ta_ret;
//uint16_t max_enb_connected;
MessageDef *m;
DevAssert (message != NULL);
x2HandoverRequestAck = &message->msg.x2ap_HandoverRequestAcknowledge_IEs;
if (stream == 0) {
X2AP_ERROR ("Received new x2 handover response on stream == 0\n");
/* TODO: what to do? */
return 0;
}
X2AP_DEBUG ("Received a new X2 handover response\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
m = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_RESP);
/* TODO: fill the message */
extern int x2id_to_source_rnti[1];
X2AP_HANDOVER_RESP(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID;
X2AP_HANDOVER_RESP(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, m);
return 0;
}
int int
x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id, x2ap_eNB_handle_x2_setup_request (uint32_t assoc_id,
...@@ -674,6 +840,3 @@ int x2ap_eNB_handle_error_indication(uint32_t assoc_id, ...@@ -674,6 +840,3 @@ int x2ap_eNB_handle_error_indication(uint32_t assoc_id,
// TODO continue // TODO continue
return 0; return 0;
} }
...@@ -208,6 +208,89 @@ do { \ ...@@ -208,6 +208,89 @@ do { \
(bitstring)->buf[3] = (eci) << 4; \ (bitstring)->buf[3] = (eci) << 4; \
}while(0) }while(0)
#define MMEGID_TO_OCTET_STRING(mmegid,octetstring) \
do { \
(octetstring)->size=2; \
(octetstring)->buf=calloc (2, sizeof (uint8_t)); \
(octetstring)->buf[0] = (mmegid) >> 8; \
(octetstring)->buf[1] = (mmegid); \
}while(0)
#define MMEC_TO_OCTET_STRING(mmec, octetstring) \
do { \
(octetstring)->size=1; \
(octetstring)->buf=calloc (1, sizeof (uint8_t));\
(octetstring)->buf[0] = (mmec); \
}while(0)
#define ENCRALG_TO_BIT_STRING(encralg, bitstring) \
do { \
(bitstring)->size=2; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (1, sizeof (uint8_t)); \
(bitstring)->buf[0] = (encralg) >> 8; \
(bitstring)->buf[1] = (encralg); \
}while(0)
#define INTPROTALG_TO_BIT_STRING(intprotalg, bitstring) \
do { \
(bitstring)->size=2; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (2, sizeof (uint8_t)); \
(bitstring)->buf[0] = (intprotalg) >> 8; \
(bitstring)->buf[1] = (intprotalg); \
}while(0)
#define KENB_STAR_TO_BIT_STRING(kenbstar, bitstring) \
do { \
(bitstring)->size=32; \
(bitstring)->bits_unused=0; \
(bitstring)->buf= calloc (32, sizeof (uint8_t));\
memcpy((bitstring)->buf, kenbstar, 32*sizeof(uint8_t)); \
}while(0)
#define UEAGMAXBITRTD_TO_ASN_PRIMITIVES(uegmaxbitrtd, asnprimitives) \
do { \
(asnprimitives)->size=5; \
(asnprimitives)->buf=calloc (5, sizeof (uint8_t)); \
(asnprimitives)->buf[0] = (uegmaxbitrtd) >> 32; \
(asnprimitives)->buf[1] = (uegmaxbitrtd) >> 24; \
(asnprimitives)->buf[2] = (uegmaxbitrtd) >> 16; \
(asnprimitives)->buf[3] = (uegmaxbitrtd) >> 8; \
(asnprimitives)->buf[4] = (uegmaxbitrtd); \
}while(0)
#define UEAGMAXBITRTU_TO_ASN_PRIMITIVES(uegmaxbitrtu, asnprimitives) \
do { \
(asnprimitives)->size=5; \
(asnprimitives)->buf=calloc (5, sizeof (uint8_t)); \
(asnprimitives)->buf[0] = (uegmaxbitrtu) >> 32; \
(asnprimitives)->buf[1] = (uegmaxbitrtu) >> 24; \
(asnprimitives)->buf[2] = (uegmaxbitrtu) >> 16; \
(asnprimitives)->buf[3] = (uegmaxbitrtu) >> 8; \
(asnprimitives)->buf[4] = (uegmaxbitrtu); \
}while(0)
#define TRLA_TO_BIT_STRING(trla, bitstring) \
do { \
(bitstring)->size=4; \
(bitstring)->bits_unused=0; \
(bitstring)->buf=calloc (4, sizeof (uint8_t)); \
(bitstring)->buf[0] = (trla)>>24; \
(bitstring)->buf[1] = (trla)>>16; \
(bitstring)->buf[2] = (trla)>>8; \
(bitstring)->buf[3] = (trla); \
}while(0)
#define GTP_TEID_TO_OCTET_STRING(gtpteid, octetstring) \
do { \
(octetstring)->size=4; \
(octetstring)->buf=calloc (4, sizeof (uint8_t));\
(octetstring)->buf[0] = (gtpteid)>>24; \
(octetstring)->buf[1] = (gtpteid)>>16; \
(octetstring)->buf[2] = (gtpteid)>>8; \
(octetstring)->buf[3] = (gtpteid); \
}while(0)
#define TAC_TO_OCTET_STRING(tac, octetstring)\ #define TAC_TO_OCTET_STRING(tac, octetstring)\
do { \ do { \
......
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