Commit 9b127482 authored by Raphael Defosseux's avatar Raphael Defosseux

Merge remote-tracking branch 'origin/x2' into develop_integration_2019_w10

parents ea0e313f 5bf595a0
...@@ -469,6 +469,7 @@ add_library(X2AP_ENB ...@@ -469,6 +469,7 @@ add_library(X2AP_ENB
${X2AP_DIR}/x2ap_eNB_itti_messaging.c ${X2AP_DIR}/x2ap_eNB_itti_messaging.c
${X2AP_DIR}/x2ap_eNB_management_procedures.c ${X2AP_DIR}/x2ap_eNB_management_procedures.c
${X2AP_DIR}/x2ap_eNB_generate_messages.c ${X2AP_DIR}/x2ap_eNB_generate_messages.c
${X2AP_DIR}/x2ap_ids.c
) )
add_dependencies(X2AP_ENB rrc_flag x2_flag) add_dependencies(X2AP_ENB rrc_flag x2_flag)
......
...@@ -72,3 +72,6 @@ MESSAGE_DEF(NAS_CONN_ESTABLI_CNF, MESSAGE_PRIORITY_MED, NasConnEstab ...@@ -72,3 +72,6 @@ MESSAGE_DEF(NAS_CONN_ESTABLI_CNF, MESSAGE_PRIORITY_MED, NasConnEstab
MESSAGE_DEF(NAS_CONN_RELEASE_IND, MESSAGE_PRIORITY_MED, NasConnReleaseInd, nas_conn_release_ind) MESSAGE_DEF(NAS_CONN_RELEASE_IND, MESSAGE_PRIORITY_MED, NasConnReleaseInd, nas_conn_release_ind)
MESSAGE_DEF(NAS_UPLINK_DATA_CNF, MESSAGE_PRIORITY_MED, NasUlDataCnf, nas_ul_data_cnf) MESSAGE_DEF(NAS_UPLINK_DATA_CNF, MESSAGE_PRIORITY_MED, NasUlDataCnf, nas_ul_data_cnf)
MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, NasDlDataInd, nas_dl_data_ind) MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, NasDlDataInd, nas_dl_data_ind)
// eNB: realtime -> RRC messages
MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process)
...@@ -81,6 +81,8 @@ ...@@ -81,6 +81,8 @@
#define NAS_UPLINK_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_cnf #define NAS_UPLINK_DATA_CNF(mSGpTR) (mSGpTR)->ittiMsg.nas_ul_data_cnf
#define NAS_DOWNLINK_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_ind #define NAS_DOWNLINK_DATA_IND(mSGpTR) (mSGpTR)->ittiMsg.nas_dl_data_ind
#define RRC_SUBFRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.rrc_subframe_process
//-------------------------------------------------------------------------------------------// //-------------------------------------------------------------------------------------------//
typedef struct RrcStateInd_s { typedef struct RrcStateInd_s {
Rrc_State_t state; Rrc_State_t state;
...@@ -399,4 +401,10 @@ typedef nas_release_ind_t NasConnReleaseInd; ...@@ -399,4 +401,10 @@ typedef nas_release_ind_t NasConnReleaseInd;
typedef ul_info_transfer_cnf_t NasUlDataCnf; typedef ul_info_transfer_cnf_t NasUlDataCnf;
typedef dl_info_transfer_ind_t NasDlDataInd; typedef dl_info_transfer_ind_t NasDlDataInd;
// eNB: realtime -> RRC messages
typedef struct rrc_subframe_process_s {
protocol_ctxt_t ctxt;
int CC_id;
} RrcSubframeProcess;
#endif /* RRC_MESSAGES_TYPES_H_ */ #endif /* RRC_MESSAGES_TYPES_H_ */
...@@ -40,3 +40,6 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_der ...@@ -40,3 +40,6 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_der
/* handover messages X2AP <-> RRC */ /* handover messages X2AP <-> RRC */
MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req) MESSAGE_DEF(X2AP_HANDOVER_REQ , MESSAGE_PRIORITY_MED, x2ap_handover_req_t , x2ap_handover_req)
MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack) MESSAGE_DEF(X2AP_HANDOVER_REQ_ACK , MESSAGE_PRIORITY_MED, x2ap_handover_req_ack_t , x2ap_handover_req_ack)
/* handover messages X2AP <-> S1AP */
MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release)
...@@ -33,11 +33,21 @@ ...@@ -33,11 +33,21 @@
#define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack #define X2AP_HANDOVER_REQ_ACK(mSGpTR) (mSGpTR)->ittiMsg.x2ap_handover_req_ack
#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
#define X2AP_UE_CONTEXT_RELEASE(mSGpTR) (mSGpTR)->ittiMsg.x2ap_ue_context_release
#define X2AP_MAX_NB_ENB_IP_ADDRESS 2 #define X2AP_MAX_NB_ENB_IP_ADDRESS 2
// eNB application layer -> X2AP messages // eNB application layer -> X2AP messages
/* X2AP UE CONTEXT RELEASE */
typedef struct x2ap_ue_context_release_s {
/* used for X2AP->RRC in source and RRC->X2AP in target */
int rnti;
int source_assoc_id;
} x2ap_ue_context_release_t;
typedef struct x2ap_register_enb_req_s { typedef struct x2ap_register_enb_req_s {
/* Unique eNB_id to identify the eNB within EPC. /* Unique eNB_id to identify the eNB within EPC.
* For macro eNB ids this field should be 20 bits long. * For macro eNB ids this field should be 20 bits long.
...@@ -128,12 +138,12 @@ typedef struct x2ap_lastvisitedcell_info_s { ...@@ -128,12 +138,12 @@ typedef struct x2ap_lastvisitedcell_info_s {
uint64_t time_UE_StayedInCell; uint64_t time_UE_StayedInCell;
}x2ap_lastvisitedcell_info_t; }x2ap_lastvisitedcell_info_t;
//used for src
typedef struct x2ap_handover_req_s { typedef struct x2ap_handover_req_s {
int source_rnti; /* TODO: to be fixed/remove */ /* used for RRC->X2AP in source eNB */
int source_x2id; /* TODO: to be fixed/remove */ int rnti;
int old_eNB_ue_x2ap_id; /* used for X2AP->RRC in target eNB */
int x2_id;
LTE_PhysCellId_t target_physCellId; LTE_PhysCellId_t target_physCellId;
...@@ -167,15 +177,17 @@ typedef struct x2ap_handover_req_s { ...@@ -167,15 +177,17 @@ typedef struct x2ap_handover_req_s {
uint8_t rrc_buffer[1024 /* arbitrary, big enough */]; uint8_t rrc_buffer[1024 /* arbitrary, big enough */];
int rrc_buffer_size; int rrc_buffer_size;
/* TODO: this parameter has to be removed */ int target_assoc_id;
int target_mod_id;
} x2ap_handover_req_t; } x2ap_handover_req_t;
typedef struct x2ap_handover_req_ack_s { typedef struct x2ap_handover_req_ack_s {
int source_rnti; /* TODO: to be fixed/remove */ /* used for RRC->X2AP in target and X2AP->RRC in source */
int source_x2id; /* TODO: to be fixed/remove */ int rnti;
/* TODO: this parameter has to be removed */
int target_mod_id; /* used for RRC->X2AP in target */
int x2_id_target;
int source_assoc_id;
uint8_t nb_e_rabs_tobesetup; uint8_t nb_e_rabs_tobesetup;
......
...@@ -2043,7 +2043,9 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { ...@@ -2043,7 +2043,9 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) {
if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) { if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1; X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 0;
} else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) { } else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 0;
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1; X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
} else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) { } else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1; X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
......
...@@ -883,7 +883,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, ...@@ -883,7 +883,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP,
rntiP, -1 rntiP, -1
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
, ,
-1 0
#endif #endif
)) == -1) )) == -1)
{ {
......
...@@ -343,7 +343,8 @@ typedef enum HO_STATE_e { ...@@ -343,7 +343,8 @@ typedef enum HO_STATE_e {
HO_COMPLETE, // initiated by the target eNB HO_COMPLETE, // initiated by the target eNB
HO_REQUEST, HO_REQUEST,
HO_ACK, HO_ACK,
HO_CONFIGURED HO_CONFIGURED,
HO_RELEASE
} HO_STATE_t; } HO_STATE_t;
typedef enum SL_TRIGGER_e { typedef enum SL_TRIGGER_e {
...@@ -450,12 +451,14 @@ typedef struct HANDOVER_INFO_s { ...@@ -450,12 +451,14 @@ typedef struct HANDOVER_INFO_s {
HO_STATE_t state; //current state of handover HO_STATE_t state; //current state of handover
uint32_t modid_s; //module_idP of serving cell uint32_t modid_s; //module_idP of serving cell
uint32_t modid_t; //module_idP of target cell uint32_t modid_t; //module_idP of target cell
int assoc_id;
uint8_t ueid_s; //UE index in serving cell uint8_t ueid_s; //UE index in serving cell
uint8_t ueid_t; //UE index in target cell uint8_t ueid_t; //UE index in target cell
LTE_AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */ LTE_AS_Config_t as_config; /* these two parameters are taken from 36.331 section 10.2.2: HandoverPreparationInformation-r8-IEs */
LTE_AS_Context_t as_context; /* They are mandatory for HO */ LTE_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 */
int x2_id; /* X2AP UE ID in the target eNB */
} HANDOVER_INFO; } HANDOVER_INFO;
#define RRC_HEADER_SIZE_MAX 64 #define RRC_HEADER_SIZE_MAX 64
......
...@@ -105,6 +105,9 @@ extern uint16_t two_tier_hexagonal_cellIds[7]; ...@@ -105,6 +105,9 @@ extern uint16_t two_tier_hexagonal_cellIds[7];
mui_t rrc_eNB_mui = 0; mui_t rrc_eNB_mui = 0;
extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw); extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
extern int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, security_capabilities_t *security_capabilities_pP);
extern void process_eNB_security_key (const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, uint8_t *security_key_pP);
extern int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl, const bool is_rel8_only, uint8_t * kenb_star);
void void
openair_rrc_on( openair_rrc_on(
...@@ -778,7 +781,8 @@ rrc_eNB_free_mem_UE_context( ...@@ -778,7 +781,8 @@ rrc_eNB_free_mem_UE_context(
ue_context_pP->ue_context.measGapConfig = NULL; ue_context_pP->ue_context.measGapConfig = NULL;
}*/ }*/
if (ue_context_pP->ue_context.handover_info) { if (ue_context_pP->ue_context.handover_info) {
ASN_STRUCT_FREE(asn_DEF_LTE_Handover, ue_context_pP->ue_context.handover_info); /* TODO: be sure free is enough here (check memory leaks) */
free(ue_context_pP->ue_context.handover_info);
ue_context_pP->ue_context.handover_info = NULL; ue_context_pP->ue_context.handover_info = NULL;
} }
...@@ -846,7 +850,9 @@ rrc_eNB_free_UE( ...@@ -846,7 +850,9 @@ rrc_eNB_free_UE(
LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 21, radio connection with ue lost\n", LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 21, radio connection with ue lost\n",
enb_mod_idP, enb_mod_idP,
rnti); rnti);
#if defined(ENABLE_USE_MME)
rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21);
#endif
// send cause 21: radio connection with ue lost // send cause 21: radio connection with ue lost
/* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered) /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered)
* If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before
...@@ -862,7 +868,9 @@ rrc_eNB_free_UE( ...@@ -862,7 +868,9 @@ rrc_eNB_free_UE(
LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 20, user inactivity\n", LOG_I(RRC, "[eNB %d] S1AP_UE_CONTEXT_RELEASE_REQ sent for RNTI %x, cause 20, user inactivity\n",
enb_mod_idP, enb_mod_idP,
rnti); rnti);
#if defined(ENABLE_USE_MME)
rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 20); rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 20);
#endif
// send cause 20: user inactivity // send cause 20: user inactivity
return; return;
} }
...@@ -1035,7 +1043,9 @@ rrc_eNB_process_RRCConnectionSetupComplete( ...@@ -1035,7 +1043,9 @@ rrc_eNB_process_RRCConnectionSetupComplete(
if (EPC_MODE_ENABLED == 1) { if (EPC_MODE_ENABLED == 1) {
// Forward message to S1AP layer // Forward message to S1AP layer
#if defined(ENABLE_USE_MME)
rrc_eNB_send_S1AP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcConnectionSetupComplete); rrc_eNB_send_S1AP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcConnectionSetupComplete);
#endif
} else { } else {
// RRC loop back (no S1AP), send SecurityModeCommand to UE // RRC loop back (no S1AP), send SecurityModeCommand to UE
rrc_eNB_generate_SecurityModeCommand(ctxt_pP, ue_context_pP); rrc_eNB_generate_SecurityModeCommand(ctxt_pP, ue_context_pP);
...@@ -3800,6 +3810,9 @@ rrc_eNB_process_MeasurementReport( ...@@ -3800,6 +3810,9 @@ rrc_eNB_process_MeasurementReport(
int neighboring_cells=-1; int neighboring_cells=-1;
int ncell_index = 0; int ncell_index = 0;
long ncell_max = -150; long ncell_max = -150;
uint32_t earfcn_dl;
uint8_t KeNB_star[32] = { 0 };
T(T_ENB_RRC_MEASUREMENT_REPORT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), T(T_ENB_RRC_MEASUREMENT_REPORT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
...@@ -3917,8 +3930,7 @@ rrc_eNB_process_MeasurementReport( ...@@ -3917,8 +3930,7 @@ rrc_eNB_process_MeasurementReport(
ue_context_pP, ue_context_pP,
X2AP_HANDOVER_REQ(msg).rrc_buffer, X2AP_HANDOVER_REQ(msg).rrc_buffer,
&X2AP_HANDOVER_REQ(msg).rrc_buffer_size); &X2AP_HANDOVER_REQ(msg).rrc_buffer_size);
X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti; X2AP_HANDOVER_REQ(msg).rnti = ctxt_pP->rnti;
X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = 0;
X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice. X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
measResultListEUTRA.list.array[ncell_index]->physCellId; measResultListEUTRA.list.array[ncell_index]->physCellId;
X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc; X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc;
...@@ -3929,9 +3941,11 @@ rrc_eNB_process_MeasurementReport( ...@@ -3929,9 +3941,11 @@ rrc_eNB_process_MeasurementReport(
// Don't know how to get this ID? // Don't know how to get this ID?
X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id; X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ue_context_pP->ue_context.mme_ue_s1ap_id;
X2AP_HANDOVER_REQ(msg).security_capabilities = ue_context_pP->ue_context.security_capabilities; X2AP_HANDOVER_REQ(msg).security_capabilities = ue_context_pP->ue_context.security_capabilities;
memcpy (X2AP_HANDOVER_REQ(msg).kenb, // compute keNB*
ue_context_pP->ue_context.kenb, earfcn_dl = (uint32_t)to_earfcn_DL(RC.rrc[ctxt_pP->module_id]->carrier[0].eutra_band, RC.rrc[ctxt_pP->module_id]->carrier[0].dl_CarrierFreq,
32); RC.rrc[ctxt_pP->module_id]->carrier[0].N_RB_DL);
derive_keNB_star(ue_context_pP->ue_context.kenb, X2AP_HANDOVER_REQ(msg).target_physCellId, earfcn_dl, true, KeNB_star);
memcpy(X2AP_HANDOVER_REQ(msg).kenb, KeNB_star, 32);
X2AP_HANDOVER_REQ(msg).kenb_ncc = ue_context_pP->ue_context.kenb_ncc; X2AP_HANDOVER_REQ(msg).kenb_ncc = ue_context_pP->ue_context.kenb_ncc;
//X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr; //X2AP_HANDOVER_REQ(msg).ue_ambr=ue_context_pP->ue_context.ue_ambr;
X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ue_context_pP->ue_context.setup_e_rabs; X2AP_HANDOVER_REQ(msg).nb_e_rabs_tobesetup = ue_context_pP->ue_context.setup_e_rabs;
...@@ -3973,114 +3987,15 @@ rrc_eNB_generate_HandoverPreparationInformation( ...@@ -3973,114 +3987,15 @@ rrc_eNB_generate_HandoverPreparationInformation(
*_size = ho_size; *_size = ho_size;
} }
#if 0
//-----------------------------------------------------------------------------
void
rrc_eNB_generate_HandoverPreparationInformation(
const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP,
LTE_PhysCellId_t targetPhyId
)
//-----------------------------------------------------------------------------
{
struct rrc_eNB_ue_context_s *ue_context_target_p = NULL;
//uint8_t UE_id_target = -1;
uint8_t mod_id_target = get_adjacent_cell_mod_id(targetPhyId);
HANDOVER_INFO *handoverInfo = CALLOC(1, sizeof(*handoverInfo));
/*
uint8_t buffer[100];
uint8_t size;
struct LTE_PhysicalConfigDedicated **physicalConfigDedicated = &RC.rrc[enb_mod_idP]->physicalConfigDedicated[ue_mod_idP];
RadioResourceConfigDedicated_t *radioResourceConfigDedicated = CALLOC(1,sizeof(RadioResourceConfigDedicated_t));
*/
T(T_ENB_RRC_HANDOVER_PREPARATION_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
handoverInfo->as_config.antennaInfoCommon.antennaPortsCount = 0; //Not used 0- but check value
handoverInfo->as_config.sourceDl_CarrierFreq = 36090; //Verify!
memcpy((void *)&handoverInfo->as_config.sourceMasterInformationBlock,
(void *)&RC.rrc[ctxt_pP->module_id]->carrier[0] /* CROUX TBC */.mib, sizeof(LTE_MasterInformationBlock_t));
memcpy((void *)&handoverInfo->as_config.sourceMeasConfig,
(void *)ue_context_pP->ue_context.measConfig, sizeof(LTE_MeasConfig_t));
// FIXME handoverInfo not used...
free( handoverInfo );
handoverInfo = 0;
//to be configured
memset((void *)&ue_context_pP->ue_context.handover_info->as_config.sourceSecurityAlgorithmConfig,
0, sizeof(LTE_SecurityAlgorithmConfig_t));
memcpy((void *)&ue_context_pP->ue_context.handover_info->as_config.sourceSystemInformationBlockType1,
(void *)&RC.rrc[ctxt_pP->module_id]->carrier[0] /* CROUX TBC */.SIB1, sizeof(LTE_SystemInformationBlockType1_t));
memcpy((void *)&ue_context_pP->ue_context.handover_info->as_config.sourceSystemInformationBlockType2,
(void *)&RC.rrc[ctxt_pP->module_id]->carrier[0] /* CROUX TBC */.SIB23, sizeof(LTE_SystemInformationBlockType2_t));
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo =
CALLOC(1, sizeof(LTE_ReestablishmentInfo_t));
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->sourcePhysCellId =
RC.rrc[ctxt_pP->module_id]->carrier[0] /* CROUX TBC */.physCellId;
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->targetCellShortMAC_I.buf = NULL; // Check values later
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->targetCellShortMAC_I.size = 0;
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->targetCellShortMAC_I.bits_unused = 0;
ue_context_pP->ue_context.handover_info->as_context.reestablishmentInfo->additionalReestabInfoList = NULL;
ue_context_pP->ue_context.handover_info->ho_prepare = 0xFF; //0xF0;
ue_context_pP->ue_context.handover_info->ho_complete = 0;
if (mod_id_target != 0xFF) {
//UE_id_target = rrc_find_free_ue_index(modid_target);
ue_context_target_p =
rrc_eNB_get_ue_context(
RC.rrc[mod_id_target],
ue_context_pP->ue_context.rnti);
/*UE_id_target = rrc_eNB_get_next_free_UE_index(
mod_id_target,
RC.rrc[ctxt_pP->module_id]->Info.UE_list[ue_mod_idP]); //this should return a new index*/
if (ue_context_target_p == NULL) { // if not already in target cell
ue_context_target_p = rrc_eNB_allocate_new_UE_context(RC.rrc[ctxt_pP->module_id]);
ue_context_target_p->ue_id_rnti = ue_context_pP->ue_context.rnti; // LG: should not be the same
ue_context_target_p->ue_context.rnti = ue_context_target_p->ue_id_rnti; // idem
LOG_I(RRC,
"[eNB %d] Frame %d : Emulate sending HandoverPreparationInformation msg from eNB source %d to eNB target %ld: source UE_id %x target UE_id %x source_modId: %d target_modId: %d\n",
ctxt_pP->module_id,
ctxt_pP->frame,
RC.rrc[ctxt_pP->module_id]->carrier[0] /* CROUX TBC */.physCellId,
targetPhyId,
ue_context_pP->ue_context.rnti,
ue_context_target_p->ue_id_rnti,
ctxt_pP->module_id,
mod_id_target);
ue_context_target_p->ue_context.handover_info =
CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info)));
memcpy((void *)&ue_context_target_p->ue_context.handover_info->as_context,
(void *)&ue_context_pP->ue_context.handover_info->as_context,
sizeof(LTE_AS_Context_t));
memcpy((void *)&ue_context_target_p->ue_context.handover_info->as_config,
(void *)&ue_context_pP->ue_context.handover_info->as_config,
sizeof(LTE_AS_Config_t));
ue_context_target_p->ue_context.handover_info->ho_prepare = 0x00;// 0xFF;
ue_context_target_p->ue_context.handover_info->ho_complete = 0;
ue_context_pP->ue_context.handover_info->modid_t = mod_id_target;
ue_context_pP->ue_context.handover_info->ueid_s = ue_context_pP->ue_context.rnti;
ue_context_pP->ue_context.handover_info->modid_s = ctxt_pP->module_id;
ue_context_target_p->ue_context.handover_info->modid_t = mod_id_target;
ue_context_target_p->ue_context.handover_info->modid_s = ctxt_pP->module_id;
ue_context_target_p->ue_context.handover_info->ueid_t = ue_context_target_p->ue_context.rnti;
} else {
LOG_E(RRC, "\nError in obtaining free UE id in target eNB %ld for handover \n", targetPhyId);
}
} else {
LOG_E(RRC, "\nError in obtaining Module ID of target eNB for handover \n");
}
}
#endif
void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m) { void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_req_t *m) {
struct rrc_eNB_ue_context_s *ue_context_target_p = NULL; struct rrc_eNB_ue_context_s *ue_context_target_p = NULL;
/* TODO: get proper UE rnti */ /* TODO: get proper UE rnti */
int rnti = taus() & 0xffff; int rnti = taus() & 0xffff;
int i; int i;
//global_rnti = rnti; //global_rnti = rnti;
//HandoverPreparationInformation_t *ho = NULL; LTE_HandoverPreparationInformation_t *ho = NULL;
//HandoverPreparationInformation_r8_IEs_t *ho_info; LTE_HandoverPreparationInformation_r8_IEs_t *ho_info;
//asn_dec_rval_t dec_rval; asn_dec_rval_t dec_rval;
ue_context_target_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); ue_context_target_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti);
if (ue_context_target_p != NULL) { if (ue_context_target_p != NULL) {
...@@ -4100,30 +4015,30 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re ...@@ -4100,30 +4015,30 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re
RB_INSERT(rrc_ue_tree_s, &RC.rrc[mod_id]->rrc_ue_head, ue_context_target_p); RB_INSERT(rrc_ue_tree_s, &RC.rrc[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); 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 = 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.Status = RRC_HO_EXECUTION;
ue_context_target_p->ue_context.handover_info->state = HO_ACK; ue_context_target_p->ue_context.handover_info->state = HO_ACK;
/* TODO: remove this hack */ ue_context_target_p->ue_context.handover_info->x2_id = m->x2_id;
//ue_context_target_p->ue_context.handover_info->modid_t = mod_id; ue_context_target_p->ue_context.handover_info->assoc_id = m->target_assoc_id;
ue_context_target_p->ue_context.handover_info->modid_t = m->target_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;
memset (ue_context_target_p->ue_context.nh, 0, 32); memset (ue_context_target_p->ue_context.nh, 0, 32);
ue_context_target_p->ue_context.nh_ncc = -1; ue_context_target_p->ue_context.nh_ncc = -1;
memcpy (ue_context_target_p->ue_context.kenb, m->kenb, 32); memcpy (ue_context_target_p->ue_context.kenb, m->kenb, 32);
ue_context_target_p->ue_context.kenb_ncc = m->kenb_ncc; ue_context_target_p->ue_context.kenb_ncc = m->kenb_ncc;
ue_context_target_p->ue_context.security_capabilities.encryption_algorithms = m->security_capabilities.encryption_algorithms; ue_context_target_p->ue_context.security_capabilities.encryption_algorithms = m->security_capabilities.encryption_algorithms;
ue_context_target_p->ue_context.security_capabilities.integrity_algorithms = m->security_capabilities.integrity_algorithms; ue_context_target_p->ue_context.security_capabilities.integrity_algorithms = m->security_capabilities.integrity_algorithms;
/*
dec_rval = uper_decode(NULL, dec_rval = uper_decode(NULL,
&asn_DEF_HandoverPreparationInformation, &asn_DEF_LTE_HandoverPreparationInformation,
(void **)&ho, (void **)&ho,
m->rrc_buffer, m->rrc_buffer,
m->rrc_buffer_size, 0, 0); m->rrc_buffer_size, 0, 0);
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_LTE_HandoverPreparationInformation, ho);
}
if (dec_rval.code != RC_OK || if (dec_rval.code != RC_OK ||
ho->criticalExtensions.present != HandoverPreparationInformation__criticalExtensions_PR_c1 || ho->criticalExtensions.present != LTE_HandoverPreparationInformation__criticalExtensions_PR_c1 ||
ho->criticalExtensions.choice.c1.present != HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8) { ho->criticalExtensions.choice.c1.present != LTE_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8) {
LOG_E(RRC, "could not decode Handover Preparation\n"); LOG_E(RRC, "could not decode Handover Preparation\n");
abort(); abort();
} }
...@@ -4132,13 +4047,13 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re ...@@ -4132,13 +4047,13 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re
if (ue_context_target_p->ue_context.UE_Capability) { if (ue_context_target_p->ue_context.UE_Capability) {
LOG_I(RRC, "freeing old UE capabilities for UE %x\n", rnti); LOG_I(RRC, "freeing old UE capabilities for UE %x\n", rnti);
ASN_STRUCT_FREE(asn_DEF_UE_EUTRA_Capability, ASN_STRUCT_FREE(asn_DEF_LTE_UE_EUTRA_Capability,
ue_context_target_p->ue_context.UE_Capability); ue_context_target_p->ue_context.UE_Capability);
ue_context_target_p->ue_context.UE_Capability = 0; ue_context_target_p->ue_context.UE_Capability = 0;
} }
dec_rval = uper_decode(NULL, dec_rval = uper_decode(NULL,
&asn_DEF_UE_EUTRA_Capability, &asn_DEF_LTE_UE_EUTRA_Capability,
(void **)&ue_context_target_p->ue_context.UE_Capability, (void **)&ue_context_target_p->ue_context.UE_Capability,
ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.buf, ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.buf,
ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size, 0, 0); ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size, 0, 0);
...@@ -4146,16 +4061,16 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re ...@@ -4146,16 +4061,16 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re
ue_context_target_p->ue_context.UE_Capability_size = ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size; ue_context_target_p->ue_context.UE_Capability_size = ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size;
if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) { if ( LOG_DEBUGFLAG(DEBUG_ASN1) ) {
xer_fprint(stdout, &asn_DEF_UE_EUTRA_Capability, ue_context_target_p->ue_context.UE_Capability); xer_fprint(stdout, &asn_DEF_LTE_UE_EUTRA_Capability, ue_context_target_p->ue_context.UE_Capability);
} }
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
LOG_E(RRC, "Failed to decode UE capabilities (%zu bytes)\n", dec_rval.consumed); LOG_E(RRC, "Failed to decode UE capabilities (%zu bytes)\n", dec_rval.consumed);
ASN_STRUCT_FREE(asn_DEF_UE_EUTRA_Capability, ASN_STRUCT_FREE(asn_DEF_LTE_UE_EUTRA_Capability,
ue_context_target_p->ue_context.UE_Capability); ue_context_target_p->ue_context.UE_Capability);
ue_context_target_p->ue_context.UE_Capability = 0; ue_context_target_p->ue_context.UE_Capability = 0;
} }
*/
ue_context_target_p->ue_context.nb_of_e_rabs = m->nb_e_rabs_tobesetup; ue_context_target_p->ue_context.nb_of_e_rabs = m->nb_e_rabs_tobesetup;
ue_context_target_p->ue_context.setup_e_rabs = m->nb_e_rabs_tobesetup; ue_context_target_p->ue_context.setup_e_rabs = m->nb_e_rabs_tobesetup;
ue_context_target_p->ue_context.mme_ue_s1ap_id = m->mme_ue_s1ap_id; ue_context_target_p->ue_context.mme_ue_s1ap_id = m->mme_ue_s1ap_id;
...@@ -4211,27 +4126,43 @@ void rrc_eNB_process_handoverCommand( ...@@ -4211,27 +4126,43 @@ void rrc_eNB_process_handoverCommand(
ue_context->ue_context.handover_info->size = size; ue_context->ue_context.handover_info->size = size;
} }
#if 0 #if defined(ENABLE_USE_MME)
//----------------------------------------------------------------------------- void rrc_eNB_handover_ue_context_release(
void protocol_ctxt_t *const ctxt_pP,
rrc_eNB_process_handoverPreparationInformation( struct rrc_eNB_ue_context_s *ue_context_p) {
const protocol_ctxt_t *const ctxt_pP, int e_rab = 0;
rrc_eNB_ue_context_t *const ue_context_pP //MessageDef *msg_release_p = NULL;
) MessageDef *msg_delete_tunnels_p = NULL;
//----------------------------------------------------------------------------- uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
{
T(T_ENB_RRC_HANDOVER_PREPARATION_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame), //msg_release_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE);
T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); //itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_release_p);
LOG_I(RRC, s1ap_ue_context_release(ctxt_pP->instance, ue_context_p->ue_context.eNB_ue_s1ap_id);
"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending LTE_RRCConnectionReconfiguration to UE %d \n",
ctxt_pP->module_id, ctxt_pP->frame, ue_context_pP->ue_context.rnti); //MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
rrc_eNB_generate_RRCConnectionReconfiguration_handover( msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
ctxt_pP, memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
ue_context_pP,
NULL, GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
0);
for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
ue_context_p->ue_context.enb_gtp_ebi[e_rab];
// erase data
ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0;
}
itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL;
rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id);
if (rrc_ue_s1ap_ids != NULL) {
rrc_eNB_S1AP_remove_ue_ids(RC.rrc[ctxt_pP->module_id], rrc_ue_s1ap_ids);
}
} }
#endif #endif /* defined(ENABLE_USE_MME) */
void void
check_handovers( check_handovers(
...@@ -4239,7 +4170,6 @@ check_handovers( ...@@ -4239,7 +4170,6 @@ check_handovers(
) )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ {
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, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) { RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[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;
...@@ -4256,19 +4186,15 @@ check_handovers( ...@@ -4256,19 +4186,15 @@ check_handovers(
LOG_I(RRC, LOG_I(RRC,
"[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n", "[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); ctxt_pP->module_id, ctxt_pP->frame, ue_context_p->ue_context.rnti);
result = pdcp_data_req(ctxt_pP, rrc_data_req(
SRB_FLAG_YES, ctxt_pP,
DCCH, DCCH,
rrc_eNB_mui++, rrc_eNB_mui++,
SDU_CONFIRM_NO, SDU_CONFIRM_NO,
ue_context_p->ue_context.handover_info->size, ue_context_p->ue_context.handover_info->size,
ue_context_p->ue_context.handover_info->buf, ue_context_p->ue_context.handover_info->buf,
PDCP_TRANSMISSION_MODE_CONTROL PDCP_TRANSMISSION_MODE_CONTROL);
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,NULL, NULL
#endif
);
AssertFatal(result == TRUE, "PDCP data request failed!\n");
ue_context_p->ue_context.handover_info->state = HO_COMPLETE; ue_context_p->ue_context.handover_info->state = HO_COMPLETE;
LOG_I(RRC, "RRC Sends RRCConnectionReconfiguration to UE %d at frame %d and subframe %d \n", ue_context_p->ue_context.rnti, ctxt_pP->frame,ctxt_pP->subframe); LOG_I(RRC, "RRC Sends RRCConnectionReconfiguration to UE %d at frame %d and subframe %d \n", ue_context_p->ue_context.rnti, ctxt_pP->frame,ctxt_pP->subframe);
} }
...@@ -4282,10 +4208,10 @@ check_handovers( ...@@ -4282,10 +4208,10 @@ check_handovers(
rrc_eNB_generate_HO_RRCConnectionReconfiguration(ctxt_pP, ue_context_p, X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, rrc_eNB_generate_HO_RRCConnectionReconfiguration(ctxt_pP, ue_context_p, X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer,
&X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size); &X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size);
rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP); rrc_eNB_configure_rbs_handover(ue_context_p,ctxt_pP);
/* TODO: remove this hack */
//X2AP_HANDOVER_REQ_ACK(msg).target_mod_id = 1 - ctxt_pP->module_id; X2AP_HANDOVER_REQ_ACK(msg).rnti = ue_context_p->ue_context.rnti;
X2AP_HANDOVER_REQ_ACK(msg).target_mod_id = ue_context_p->ue_context.handover_info->modid_t; X2AP_HANDOVER_REQ_ACK(msg).x2_id_target = ue_context_p->ue_context.handover_info->x2_id;
//X2AP_HANDOVER_REQ_ACK(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id; X2AP_HANDOVER_REQ_ACK(msg).source_assoc_id = ue_context_p->ue_context.handover_info->assoc_id;
/* Call admission control not implemented yet */ /* Call admission control not implemented yet */
X2AP_HANDOVER_REQ_ACK(msg).nb_e_rabs_tobesetup = ue_context_p->ue_context.setup_e_rabs; X2AP_HANDOVER_REQ_ACK(msg).nb_e_rabs_tobesetup = ue_context_p->ue_context.setup_e_rabs;
...@@ -4300,70 +4226,6 @@ check_handovers( ...@@ -4300,70 +4226,6 @@ check_handovers(
} }
} }
#if 0
//-----------------------------------------------------------------------------
void
check_handovers(
protocol_ctxt_t *const ctxt_pP
)
//-----------------------------------------------------------------------------
{
int result;
struct rrc_eNB_ue_context_s *ue_context_p;
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &RC.rrc[ctxt_pP->module_id]->rrc_ue_head) {
ctxt_pP->rnti = ue_context_p->ue_id_rnti;
if (ue_context_p->ue_context.handover_info != NULL) {
if (ue_context_p->ue_context.handover_info->ho_prepare == 0xFF) {
LOG_D(RRC,
"[eNB %d] Frame %d: Incoming handover detected for new UE_idx %d (source eNB %d->target eNB %d) \n",
ctxt_pP->module_id,
ctxt_pP->frame,
ctxt_pP->rnti,
ctxt_pP->module_id,
ue_context_p->ue_context.handover_info->modid_t);
// source eNB generates LTE_RRCConnectionreconfiguration to prepare the HO
rrc_eNB_process_handoverPreparationInformation(
ctxt_pP,
ue_context_p);
ue_context_p->ue_context.handover_info->ho_prepare = 0xF1;
}
if (ue_context_p->ue_context.handover_info->ho_complete == 0xF1) {
LOG_D(RRC,
"[eNB %d] Frame %d: handover Command received for new UE_id %x current eNB %d target eNB: %d \n",
ctxt_pP->module_id,
ctxt_pP->frame,
ctxt_pP->rnti,
ctxt_pP->module_id,
ue_context_p->ue_context.handover_info->modid_t);
//rrc_eNB_process_handoverPreparationInformation(enb_mod_idP,frameP,i);
result = pdcp_data_req(ctxt_pP,
SRB_FLAG_YES,
DCCH,
rrc_eNB_mui++,
SDU_CONFIRM_NO,
ue_context_p->ue_context.handover_info->size,
ue_context_p->ue_context.handover_info->buf,
PDCP_TRANSMISSION_MODE_CONTROL
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
,NULL, NULL
#endif
);
//AssertFatal(result == TRUE, "PDCP data request failed!\n");
if(result != TRUE) {
LOG_I(RRC, "PDCP data request failed!\n");
return;
}
ue_context_p->ue_context.handover_info->ho_complete = 0xF2;
}
}
}
}
#endif
void void
rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP, rrc_eNB_ue_context_t *const ue_context_pP,
...@@ -5306,6 +5168,21 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc ...@@ -5306,6 +5168,21 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc
, 0, 0 , 0, 0
#endif #endif
); );
#if defined(ENABLE_USE_MME)
rrc_eNB_process_security (
ctxt_pP,
ue_context_p,
&ue_context_p->ue_context.security_capabilities);
process_eNB_security_key (
ctxt_pP,
ue_context_p,
ue_context_p->ue_context.kenb);
rrc_pdcp_config_security(
ctxt_pP,
ue_context_p,
FALSE);
#endif
// Add a new user (called during the HO procedure) // Add a new user (called during the HO procedure)
LOG_I(RRC, "rrc_eNB_target_add_ue_handover module_id %d rnti %d\n", ctxt_pP->module_id, ctxt_pP->rnti); LOG_I(RRC, "rrc_eNB_target_add_ue_handover module_id %d rnti %d\n", ctxt_pP->module_id, ctxt_pP->rnti);
// Configure MAC for the target // Configure MAC for the target
...@@ -7709,9 +7586,11 @@ rrc_eNB_decode_dcch( ...@@ -7709,9 +7586,11 @@ rrc_eNB_decode_dcch(
if (EPC_MODE_ENABLED) { if (EPC_MODE_ENABLED) {
if (EPC_MODE_ENABLED == 1) { if (EPC_MODE_ENABLED == 1) {
#if defined(ENABLE_USE_MME)
rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP,
ue_context_p, ue_context_p,
ul_dcch_msg); ul_dcch_msg);
#endif
} }
} else { } else {
ue_context_p->ue_context.nb_of_e_rabs = 1; ue_context_p->ue_context.nb_of_e_rabs = 1;
...@@ -7759,9 +7638,11 @@ rrc_eNB_decode_dcch( ...@@ -7759,9 +7638,11 @@ rrc_eNB_decode_dcch(
sdu_sizeP); sdu_sizeP);
if (EPC_MODE_ENABLED == 1) { if (EPC_MODE_ENABLED == 1) {
#if defined(ENABLE_USE_MME)
rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP, rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP,
ue_context_p, ue_context_p,
ul_dcch_msg); ul_dcch_msg);
#endif
} }
break; break;
...@@ -7898,76 +7779,326 @@ void rrc_enb_init(void) { ...@@ -7898,76 +7779,326 @@ void rrc_enb_init(void) {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void *rrc_enb_process_itti_msg(void *notUsed) { void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id)
MessageDef *msg_p; {
const char *msg_name_p; int32_t current_timestamp_ms = 0;
instance_t instance; int32_t ref_timestamp_ms = 0;
int result; struct timeval ts;
SRB_INFO *srb_info_p; struct rrc_eNB_ue_context_s *ue_context_p = NULL;
int CC_id; struct rrc_eNB_ue_context_s *ue_to_be_removed = NULL;
#ifdef LOCALIZATION
double estimated_distance = 0;
protocol_ctxt_t ctxt; protocol_ctxt_t ctxt;
// Wait for a message #endif
itti_receive_msg(TASK_RRC_ENB, &msg_p); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_IN);
msg_name_p = ITTI_MSG_NAME(msg_p); check_handovers(ctxt_pP); // counter, get the value and aggregate
instance = ITTI_MSG_INSTANCE(msg_p); // check for UL failure or for UE to be released
LOG_I(RRC,"Received message %s\n",msg_name_p); RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
ctxt_pP->rnti = ue_context_p->ue_id_rnti;
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(RRC, " *** Exiting RRC thread\n");
itti_exit_task();
break;
case MESSAGE_TEST: if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe == 0)) {
LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p); if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
break; LOG_I(RRC, "UE rnti %x: S-TMSI %x failure timer %d/8\n",
ue_context_p->ue_context.rnti,
ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
ue_context_p->ue_context.ul_failure_timer);
} else {
LOG_I(RRC, "UE rnti %x failure timer %d/8\n",
ue_context_p->ue_context.rnti,
ue_context_p->ue_context.ul_failure_timer);
}
}
/* Messages from MAC */ if (ue_context_p->ue_context.ul_failure_timer > 0) {
case RRC_MAC_CCCH_DATA_IND: ue_context_p->ue_context.ul_failure_timer++;
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance,
ENB_FLAG_YES,
RRC_MAC_CCCH_DATA_IND(msg_p).rnti,
msg_p->ittiMsgHeader.lte_time.frame,
msg_p->ittiMsgHeader.lte_time.slot);
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received %s\n",
PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt),
msg_name_p);
CC_id = RRC_MAC_CCCH_DATA_IND(msg_p).CC_id;
srb_info_p = &RC.rrc[instance]->carrier[CC_id].Srb0;
LOG_I(RRC,"Decoding CCCH : inst %d, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n",
instance,CC_id,&ctxt, RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size);
if (RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size >= RRC_BUFFER_SIZE_MAX) { if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
LOG_I(RRC, "CCCH message has size %d > %d\n",RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size,RRC_BUFFER_SIZE_MAX); // remove UE after 20 seconds after MAC (or else) has indicated UL failure
break; LOG_I(RRC, "Removing UE %x instance, because of uplink failure timer timeout\n",
ue_context_p->ue_context.rnti);
ue_to_be_removed = ue_context_p;
break; // break RB_FOREACH
}
} }
memcpy(srb_info_p->Rx_buffer.Payload, if (ue_context_p->ue_context.ue_release_timer_s1 > 0) {
RRC_MAC_CCCH_DATA_IND(msg_p).sdu, ue_context_p->ue_context.ue_release_timer_s1++;
RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size);
srb_info_p->Rx_buffer.payload_size = RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size;
rrc_eNB_decode_ccch(&ctxt, srb_info_p, CC_id);
break;
/* Messages from PDCP */ if (ue_context_p->ue_context.ue_release_timer_s1 >= ue_context_p->ue_context.ue_release_timer_thres_s1) {
case RRC_DCCH_DATA_IND: LOG_I(RRC, "Removing UE %x instance, because of UE_CONTEXT_RELEASE_COMMAND not received after %d ms from sending request\n",
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, ue_context_p->ue_context.rnti,
instance, ue_context_p->ue_context.ue_release_timer_thres_s1);
ENB_FLAG_YES,
RRC_DCCH_DATA_IND(msg_p).rnti, if (EPC_MODE_ENABLED)
msg_p->ittiMsgHeader.lte_time.frame, rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p);
msg_p->ittiMsgHeader.lte_time.slot); else
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received on DCCH %d %s\n", ue_to_be_removed = ue_context_p;
PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt),
RRC_DCCH_DATA_IND(msg_p).dcch_index, ue_context_p->ue_context.ue_release_timer_s1 = 0;
msg_name_p); break; // break RB_FOREACH
rrc_eNB_decode_dcch(&ctxt, } // end if timer_s1 timeout
RRC_DCCH_DATA_IND(msg_p).dcch_index, } // end if timer_s1 > 0 (S1 UE_CONTEXT_RELEASE_REQ ongoing)
RRC_DCCH_DATA_IND(msg_p).sdu_p,
RRC_DCCH_DATA_IND(msg_p).sdu_size); if (ue_context_p->ue_context.ue_release_timer_rrc > 0) {
// Message buffer has been processed, free it now. ue_context_p->ue_context.ue_release_timer_rrc++;
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_IND(msg_p).sdu_p);
if (ue_context_p->ue_context.ue_release_timer_rrc >= ue_context_p->ue_context.ue_release_timer_thres_rrc) {
LOG_I(RRC, "Removing UE %x instance after UE_CONTEXT_RELEASE_Complete (ue_release_timer_rrc timeout)\n",
ue_context_p->ue_context.rnti);
ue_context_p->ue_context.ue_release_timer_rrc = 0;
ue_to_be_removed = ue_context_p;
break; // break RB_FOREACH
}
}
#if defined(ENABLE_USE_MME)
if (ue_context_p->ue_context.handover_info != NULL) {
if (ue_context_p->ue_context.handover_info->state == HO_RELEASE) {
ue_to_be_removed = ue_context_p;
rrc_eNB_handover_ue_context_release(ctxt_pP, ue_context_p);
break; //break RB_FOREACH (why to break ?)
}
}
#endif
pthread_mutex_lock(&rrc_release_freelist);
if (rrc_release_info.num_UEs > 0) {
uint16_t release_total = 0;
for (uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
if (rrc_release_info.RRC_release_ctrl[release_num].flag > 0) {
release_total++;
}
if ((rrc_release_info.RRC_release_ctrl[release_num].flag > 2) &&
(rrc_release_info.RRC_release_ctrl[release_num].rnti == ue_context_p->ue_context.rnti)) {
ue_context_p->ue_context.ue_release_timer_rrc = 1;
ue_context_p->ue_context.ue_release_timer_thres_rrc = 100;
if (EPC_MODE_ENABLED) {
int e_rab = 0;
MessageDef *msg_complete_p = NULL;
MessageDef *msg_delete_tunnels_p = NULL;
uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
if (rrc_release_info.RRC_release_ctrl[release_num].flag == 4) { // if timer_s1 == 0
MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_S1AP_ENB, NULL, 0,
"0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
eNB_ue_s1ap_id);
msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_complete_p);
}
MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
// do not wait response
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
ue_context_p->ue_context.enb_gtp_ebi[e_rab];
// erase data
ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0;
}
itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL;
rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id);
if (rrc_ue_s1ap_ids != NULL) {
rrc_eNB_S1AP_remove_ue_ids(RC.rrc[ctxt_pP->module_id], rrc_ue_s1ap_ids);
}
} /* EPC_MODE_ENABLED */
rrc_release_info.RRC_release_ctrl[release_num].flag = 0;
rrc_release_info.num_UEs--;
break; // break for (release_num)
} // end if ((rrc_release_info.RRC_release_ctrl[release_num].flag > 2) && ...
if (release_total >= rrc_release_info.num_UEs) {
break; // break for (release_num)
}
} // end for (release_num)
} // end if (rrc_release_info.num_UEs > 0)
pthread_mutex_unlock(&rrc_release_freelist);
if ((ue_context_p->ue_context.ue_rrc_inactivity_timer > 0) && (RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres > 0)) {
ue_context_p->ue_context.ue_rrc_inactivity_timer++; // (un)comment this line to (de)activate the RRC inactivity timer
if (ue_context_p->ue_context.ue_rrc_inactivity_timer >= RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres) {
LOG_I(RRC, "Removing UE %x instance because of rrc_inactivity_timer timeout\n",
ue_context_p->ue_context.rnti);
ue_to_be_removed = ue_context_p;
break; // break RB_FOREACH
}
}
if (ue_context_p->ue_context.ue_reestablishment_timer > 0) {
ue_context_p->ue_context.ue_reestablishment_timer++;
if (ue_context_p->ue_context.ue_reestablishment_timer >= ue_context_p->ue_context.ue_reestablishment_timer_thres) {
LOG_I(RRC, "Removing UE %x instance because of reestablishment_timer timeout\n",
ue_context_p->ue_context.rnti);
ue_context_p->ue_context.ul_failure_timer = 20000; // lead to send S1 UE_CONTEXT_RELEASE_REQ
ue_to_be_removed = ue_context_p;
ue_context_p->ue_context.ue_reestablishment_timer = 0;
break; // break RB_FOREACH
}
}
if (ue_context_p->ue_context.ue_release_timer > 0) {
ue_context_p->ue_context.ue_release_timer++;
if (ue_context_p->ue_context.ue_release_timer >= ue_context_p->ue_context.ue_release_timer_thres) {
LOG_I(RRC, "Removing UE %x instance because of RRC Connection Setup timer timeout\n",
ue_context_p->ue_context.rnti);
/*
* TODO: Naming problem here: ue_release_timer seems to have been used when RRC Connection Release was sent.
* It is no more the case.
* The timer should be renamed.
*/
ue_to_be_removed = ue_context_p;
ue_context_p->ue_context.ue_release_timer = 0;
break; // break RB_FOREACH
}
}
} // end RB_FOREACH
if (ue_to_be_removed) {
if ((ue_to_be_removed->ue_context.ul_failure_timer >= 20000) ||
((ue_to_be_removed->ue_context.ue_rrc_inactivity_timer >= RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres) &&
(RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres > 0))) {
ue_to_be_removed->ue_context.ue_release_timer_s1 = 1;
ue_to_be_removed->ue_context.ue_release_timer_thres_s1 = 100;
ue_to_be_removed->ue_context.ue_release_timer = 0;
ue_to_be_removed->ue_context.ue_reestablishment_timer = 0;
}
rrc_eNB_free_UE(ctxt_pP->module_id, ue_to_be_removed);
if (ue_to_be_removed->ue_context.ul_failure_timer >= 20000) {
ue_to_be_removed->ue_context.ul_failure_timer = 0;
}
if ((ue_to_be_removed->ue_context.ue_rrc_inactivity_timer >= RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres) &&
(RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres > 0)) {
ue_to_be_removed->ue_context.ue_rrc_inactivity_timer = 0; //reset timer after S1 command UE context release request is sent
}
}
#ifdef RRC_LOCALIZATION
/* for the localization, only primary CC_id might be relevant*/
gettimeofday(&ts, NULL);
current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
ref_timestamp_ms = RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms;
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
ctxt = *ctxt_pP;
ctxt.rnti = ue_context_p->ue_context.rnti;
estimated_distance = rrc_get_estimated_ue_distance(&ctxt, CC_id, RC.rrc[ctxt_pP->module_id]->loc_type);
if ((current_timestamp_ms - ref_timestamp_ms > RC.rrc[ctxt_pP->module_id]->aggregation_period_ms) &&
estimated_distance != -1) {
LOG_D(LOCALIZE, "RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
ctxt.rnti,
ctxt_pP->module_id,
current_timestamp_ms,
ctxt_pP->frame,
estimated_distance);
LOG_D(LOCALIZE, "RRC status %d\n",
ue_context_p->ue_context.Status);
push_front(&RC.rrc[ctxt_pP->module_id]->loc_list, estimated_distance);
RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms = current_timestamp_ms;
} // end if
} // end RB_FOREACH
#endif
(void)ts; /* remove gcc warning "unused variable" */
(void)ref_timestamp_ms; /* remove gcc warning "unused variable" */
(void)current_timestamp_ms; /* remove gcc warning "unused variable" */
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_OUT);
}
//-----------------------------------------------------------------------------
void *rrc_enb_process_itti_msg(void *notUsed) {
MessageDef *msg_p;
const char *msg_name_p;
instance_t instance;
int result;
SRB_INFO *srb_info_p;
int CC_id;
protocol_ctxt_t ctxt;
memset(&ctxt, 0, sizeof(ctxt));
// Wait for a message
itti_receive_msg(TASK_RRC_ENB, &msg_p);
msg_name_p = ITTI_MSG_NAME(msg_p);
instance = ITTI_MSG_INSTANCE(msg_p);
/* RRC_SUBFRAME_PROCESS is sent every subframe, do not log it */
if (ITTI_MSG_ID(msg_p) != RRC_SUBFRAME_PROCESS)
LOG_I(RRC,"Received message %s\n",msg_name_p);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(RRC, " *** Exiting RRC thread\n");
itti_exit_task();
break;
case MESSAGE_TEST:
LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p);
break;
/* Messages from MAC */
case RRC_MAC_CCCH_DATA_IND:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance,
ENB_FLAG_YES,
RRC_MAC_CCCH_DATA_IND(msg_p).rnti,
msg_p->ittiMsgHeader.lte_time.frame,
msg_p->ittiMsgHeader.lte_time.slot);
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received %s\n",
PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt),
msg_name_p);
CC_id = RRC_MAC_CCCH_DATA_IND(msg_p).CC_id;
srb_info_p = &RC.rrc[instance]->carrier[CC_id].Srb0;
LOG_I(RRC,"Decoding CCCH : inst %d, CC_id %d, ctxt %p, sib_info_p->Rx_buffer.payload_size %d\n",
instance,CC_id,&ctxt, RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size);
if (RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size >= RRC_BUFFER_SIZE_MAX) {
LOG_I(RRC, "CCCH message has size %d > %d\n",RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size,RRC_BUFFER_SIZE_MAX);
break;
}
memcpy(srb_info_p->Rx_buffer.Payload,
RRC_MAC_CCCH_DATA_IND(msg_p).sdu,
RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size);
srb_info_p->Rx_buffer.payload_size = RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size;
rrc_eNB_decode_ccch(&ctxt, srb_info_p, CC_id);
break;
/* Messages from PDCP */
case RRC_DCCH_DATA_IND:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
instance,
ENB_FLAG_YES,
RRC_DCCH_DATA_IND(msg_p).rnti,
msg_p->ittiMsgHeader.lte_time.frame,
msg_p->ittiMsgHeader.lte_time.slot);
LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received on DCCH %d %s\n",
PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt),
RRC_DCCH_DATA_IND(msg_p).dcch_index,
msg_name_p);
rrc_eNB_decode_dcch(&ctxt,
RRC_DCCH_DATA_IND(msg_p).dcch_index,
RRC_DCCH_DATA_IND(msg_p).sdu_p,
RRC_DCCH_DATA_IND(msg_p).sdu_size);
// Message buffer has been processed, free it now.
result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_IND(msg_p).sdu_p);
if (result != EXIT_SUCCESS) { if (result != EXIT_SUCCESS) {
LOG_I(RRC, "Failed to free memory (%d)!\n",result); LOG_I(RRC, "Failed to free memory (%d)!\n",result);
...@@ -8015,18 +8146,17 @@ void *rrc_enb_process_itti_msg(void *notUsed) { ...@@ -8015,18 +8146,17 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance); rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND(msg_p, msg_name_p, instance);
break; break;
case GTPV1U_ENB_DELETE_TUNNEL_RESP: case GTPV1U_ENB_DELETE_TUNNEL_RESP: {
rrc_eNB_ue_context_t *ue = rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti);
/* Nothing to do. Apparently everything is done in S1AP processing */ if (ue != NULL
//LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n", && ue->ue_context.ue_release_timer_rrc > 0
//instance, msg_name_p); && (ue->ue_context.handover_info == NULL || ue->ue_context.handover_info->state != HO_RELEASE)) {
if (rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti) ue->ue_context.ue_release_timer_rrc = ue->ue_context.ue_release_timer_thres_rrc;
&& rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc > 0) {
rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_rrc =
rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti)->ue_context.ue_release_timer_thres_rrc;
} }
break; break;
}
case S1AP_PATH_SWITCH_REQ_ACK: case S1AP_PATH_SWITCH_REQ_ACK:
LOG_I(RRC, "[eNB %d] received path switch ack %s\n", instance, msg_name_p); LOG_I(RRC, "[eNB %d] received path switch ack %s\n", instance, msg_name_p);
...@@ -8034,16 +8164,20 @@ void *rrc_enb_process_itti_msg(void *notUsed) { ...@@ -8034,16 +8164,20 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
break; break;
case X2AP_HANDOVER_REQ: case X2AP_HANDOVER_REQ:
LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s at frame %d subframe %d\n", instance, msg_name_p, LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s\n", instance, msg_name_p);
ctxt.frame, ctxt.subframe);
rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p)); rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p));
break; break;
case X2AP_HANDOVER_REQ_ACK: { case X2AP_HANDOVER_REQ_ACK: {
struct rrc_eNB_ue_context_s *ue_context_p = NULL; struct rrc_eNB_ue_context_s *ue_context_p = NULL;
ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], ctxt.rnti); ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_HANDOVER_REQ_ACK(msg_p).rnti);
LOG_I(RRC, "[eNB %d] source eNB receives the X2 HO ACK %s at frame %d subframe %d \n", instance, msg_name_p, if (ue_context_p == NULL) {
ctxt.frame,ctxt.subframe); /* is it possible? */
LOG_E(RRC, "could not find UE (rnti %x) while processing X2AP_HANDOVER_REQ_ACK\n",
X2AP_HANDOVER_REQ_ACK(msg_p).rnti);
exit(1);
}
LOG_I(RRC, "[eNB %d] source eNB receives the X2 HO ACK %s\n", instance, msg_name_p);
DevAssert(ue_context_p != NULL); DevAssert(ue_context_p != NULL);
if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort(); if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort();
...@@ -8053,12 +8187,28 @@ void *rrc_enb_process_itti_msg(void *notUsed) { ...@@ -8053,12 +8187,28 @@ void *rrc_enb_process_itti_msg(void *notUsed) {
break; break;
} }
case X2AP_UE_CONTEXT_RELEASE: {
struct rrc_eNB_ue_context_s *ue_context_p = NULL;
ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_UE_CONTEXT_RELEASE(msg_p).rnti);
LOG_I(RRC, "[eNB %d] source eNB receives the X2 UE CONTEXT RELEASE %s\n", instance, msg_name_p);
DevAssert(ue_context_p != NULL);
if (ue_context_p->ue_context.handover_info->state != HO_COMPLETE) abort();
ue_context_p->ue_context.handover_info->state = HO_RELEASE;
break;
}
/* Messages from eNB app */ /* Messages from eNB app */
case RRC_CONFIGURATION_REQ: case RRC_CONFIGURATION_REQ:
LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p,&RRC_CONFIGURATION_REQ(msg_p)); LOG_I(RRC, "[eNB %d] Received %s : %p\n", instance, msg_name_p,&RRC_CONFIGURATION_REQ(msg_p));
openair_rrc_eNB_configuration(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p)); openair_rrc_eNB_configuration(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p));
break; break;
case RRC_SUBFRAME_PROCESS:
rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id);
break;
default: default:
LOG_E(RRC, "[eNB %d] Received unexpected message %s\n", instance, msg_name_p); LOG_E(RRC, "[eNB %d] Received unexpected message %s\n", instance, msg_name_p);
break; break;
...@@ -8434,236 +8584,11 @@ rrc_rx_tx( ...@@ -8434,236 +8584,11 @@ rrc_rx_tx(
) )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
{ {
int32_t current_timestamp_ms = 0; MessageDef *message_p;
int32_t ref_timestamp_ms = 0; message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_SUBFRAME_PROCESS);
struct timeval ts; RRC_SUBFRAME_PROCESS(message_p).ctxt = *ctxt_pP;
struct rrc_eNB_ue_context_s *ue_context_p = NULL; RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id;
struct rrc_eNB_ue_context_s *ue_to_be_removed = NULL; itti_send_msg_to_task(TASK_RRC_ENB, ctxt_pP->module_id, message_p);
#ifdef LOCALIZATION
double estimated_distance = 0;
protocol_ctxt_t ctxt;
#endif
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_IN);
check_handovers(ctxt_pP); // counter, get the value and aggregate
// check for UL failure or for UE to be released
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
ctxt_pP->rnti = ue_context_p->ue_id_rnti;
if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe == 0)) {
if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
LOG_I(RRC, "UE rnti %x: S-TMSI %x failure timer %d/8\n",
ue_context_p->ue_context.rnti,
ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
ue_context_p->ue_context.ul_failure_timer);
} else {
LOG_I(RRC, "UE rnti %x failure timer %d/8\n",
ue_context_p->ue_context.rnti,
ue_context_p->ue_context.ul_failure_timer);
}
}
if (ue_context_p->ue_context.ul_failure_timer > 0) {
ue_context_p->ue_context.ul_failure_timer++;
if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
// remove UE after 20 seconds after MAC (or else) has indicated UL failure
LOG_I(RRC, "Removing UE %x instance, because of uplink failure timer timeout\n",
ue_context_p->ue_context.rnti);
ue_to_be_removed = ue_context_p;
break; // break RB_FOREACH
}
}
if (ue_context_p->ue_context.ue_release_timer_s1 > 0) {
ue_context_p->ue_context.ue_release_timer_s1++;
if (ue_context_p->ue_context.ue_release_timer_s1 >= ue_context_p->ue_context.ue_release_timer_thres_s1) {
LOG_I(RRC, "Removing UE %x instance, because of UE_CONTEXT_RELEASE_COMMAND not received after %d ms from sending request\n",
ue_context_p->ue_context.rnti,
ue_context_p->ue_context.ue_release_timer_thres_s1);
if (EPC_MODE_ENABLED)
rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p);
else
ue_to_be_removed = ue_context_p;
ue_context_p->ue_context.ue_release_timer_s1 = 0;
break; // break RB_FOREACH
} // end if timer_s1 timeout
} // end if timer_s1 > 0 (S1 UE_CONTEXT_RELEASE_REQ ongoing)
if (ue_context_p->ue_context.ue_release_timer_rrc > 0) {
ue_context_p->ue_context.ue_release_timer_rrc++;
if (ue_context_p->ue_context.ue_release_timer_rrc >= ue_context_p->ue_context.ue_release_timer_thres_rrc) {
LOG_I(RRC, "Removing UE %x instance after UE_CONTEXT_RELEASE_Complete (ue_release_timer_rrc timeout)\n",
ue_context_p->ue_context.rnti);
ue_context_p->ue_context.ue_release_timer_rrc = 0;
ue_to_be_removed = ue_context_p;
break; // break RB_FOREACH
}
}
pthread_mutex_lock(&rrc_release_freelist);
if (rrc_release_info.num_UEs > 0) {
uint16_t release_total = 0;
for (uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
if (rrc_release_info.RRC_release_ctrl[release_num].flag > 0) {
release_total++;
}
if ((rrc_release_info.RRC_release_ctrl[release_num].flag > 2) &&
(rrc_release_info.RRC_release_ctrl[release_num].rnti == ue_context_p->ue_context.rnti)) {
ue_context_p->ue_context.ue_release_timer_rrc = 1;
ue_context_p->ue_context.ue_release_timer_thres_rrc = 100;
if (EPC_MODE_ENABLED) {
int e_rab = 0;
MessageDef *msg_complete_p = NULL;
MessageDef *msg_delete_tunnels_p = NULL;
uint32_t eNB_ue_s1ap_id = ue_context_p->ue_context.eNB_ue_s1ap_id;
if (rrc_release_info.RRC_release_ctrl[release_num].flag == 4) { // if timer_s1 == 0
MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_S1AP_ENB, NULL, 0,
"0 S1AP_UE_CONTEXT_RELEASE_COMPLETE eNB_ue_s1ap_id 0x%06"PRIX32" ",
eNB_ue_s1ap_id);
msg_complete_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE_COMPLETE);
S1AP_UE_CONTEXT_RELEASE_COMPLETE(msg_complete_p).eNB_ue_s1ap_id = eNB_ue_s1ap_id;
itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_complete_p);
}
MSC_LOG_TX_MESSAGE(MSC_RRC_ENB, MSC_GTPU_ENB, NULL,0, "0 GTPV1U_ENB_DELETE_TUNNEL_REQ rnti %x ", eNB_ue_s1ap_id);
msg_delete_tunnels_p = itti_alloc_new_message(TASK_RRC_ENB, GTPV1U_ENB_DELETE_TUNNEL_REQ);
memset(&GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p)));
// do not wait response
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti;
for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) {
GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] =
ue_context_p->ue_context.enb_gtp_ebi[e_rab];
// erase data
ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0;
memset(&ue_context_p->ue_context.enb_gtp_addrs[e_rab], 0, sizeof(ue_context_p->ue_context.enb_gtp_addrs[e_rab]));
ue_context_p->ue_context.enb_gtp_ebi[e_rab] = 0;
}
itti_send_msg_to_task(TASK_GTPV1_U, ctxt_pP->module_id, msg_delete_tunnels_p);
struct rrc_ue_s1ap_ids_s *rrc_ue_s1ap_ids = NULL;
rrc_ue_s1ap_ids = rrc_eNB_S1AP_get_ue_ids(RC.rrc[ctxt_pP->module_id], 0, eNB_ue_s1ap_id);
if (rrc_ue_s1ap_ids != NULL) {
rrc_eNB_S1AP_remove_ue_ids(RC.rrc[ctxt_pP->module_id], rrc_ue_s1ap_ids);
}
} /* EPC_MODE_ENABLED */
rrc_release_info.RRC_release_ctrl[release_num].flag = 0;
rrc_release_info.num_UEs--;
break; // break for (release_num)
} // end if ((rrc_release_info.RRC_release_ctrl[release_num].flag > 2) && ...
if (release_total >= rrc_release_info.num_UEs) {
break; // break for (release_num)
}
} // end for (release_num)
} // end if (rrc_release_info.num_UEs > 0)
pthread_mutex_unlock(&rrc_release_freelist);
if ((ue_context_p->ue_context.ue_rrc_inactivity_timer > 0) && (RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres > 0)) {
ue_context_p->ue_context.ue_rrc_inactivity_timer++; // (un)comment this line to (de)activate the RRC inactivity timer
if (ue_context_p->ue_context.ue_rrc_inactivity_timer >= RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres) {
LOG_I(RRC, "Removing UE %x instance because of rrc_inactivity_timer timeout\n",
ue_context_p->ue_context.rnti);
ue_to_be_removed = ue_context_p;
break; // break RB_FOREACH
}
}
if (ue_context_p->ue_context.ue_reestablishment_timer > 0) {
ue_context_p->ue_context.ue_reestablishment_timer++;
if (ue_context_p->ue_context.ue_reestablishment_timer >= ue_context_p->ue_context.ue_reestablishment_timer_thres) {
LOG_I(RRC, "Removing UE %x instance because of reestablishment_timer timeout\n",
ue_context_p->ue_context.rnti);
ue_context_p->ue_context.ul_failure_timer = 20000; // lead to send S1 UE_CONTEXT_RELEASE_REQ
ue_to_be_removed = ue_context_p;
ue_context_p->ue_context.ue_reestablishment_timer = 0;
break; // break RB_FOREACH
}
}
if (ue_context_p->ue_context.ue_release_timer > 0) {
ue_context_p->ue_context.ue_release_timer++;
if (ue_context_p->ue_context.ue_release_timer >= ue_context_p->ue_context.ue_release_timer_thres) {
LOG_I(RRC, "Removing UE %x instance because of RRC Connection Setup timer timeout\n",
ue_context_p->ue_context.rnti);
/*
* TODO: Naming problem here: ue_release_timer seems to have been used when RRC Connection Release was sent.
* It is no more the case.
* The timer should be renamed.
*/
ue_to_be_removed = ue_context_p;
ue_context_p->ue_context.ue_release_timer = 0;
break; // break RB_FOREACH
}
}
} // end RB_FOREACH
if (ue_to_be_removed) {
if ((ue_to_be_removed->ue_context.ul_failure_timer >= 20000) ||
((ue_to_be_removed->ue_context.ue_rrc_inactivity_timer >= RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres) &&
(RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres > 0))) {
ue_to_be_removed->ue_context.ue_release_timer_s1 = 1;
ue_to_be_removed->ue_context.ue_release_timer_thres_s1 = 100;
ue_to_be_removed->ue_context.ue_release_timer = 0;
ue_to_be_removed->ue_context.ue_reestablishment_timer = 0;
}
rrc_eNB_free_UE(ctxt_pP->module_id, ue_to_be_removed);
if (ue_to_be_removed->ue_context.ul_failure_timer >= 20000) {
ue_to_be_removed->ue_context.ul_failure_timer = 0;
}
if ((ue_to_be_removed->ue_context.ue_rrc_inactivity_timer >= RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres) &&
(RC.rrc[ctxt_pP->module_id]->configuration.rrc_inactivity_timer_thres > 0)) {
ue_to_be_removed->ue_context.ue_rrc_inactivity_timer = 0; //reset timer after S1 command UE context release request is sent
}
}
#ifdef RRC_LOCALIZATION
/* for the localization, only primary CC_id might be relevant*/
gettimeofday(&ts, NULL);
current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
ref_timestamp_ms = RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms;
RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(RC.rrc[ctxt_pP->module_id]->rrc_ue_head)) {
ctxt = *ctxt_pP;
ctxt.rnti = ue_context_p->ue_context.rnti;
estimated_distance = rrc_get_estimated_ue_distance(&ctxt, CC_id, RC.rrc[ctxt_pP->module_id]->loc_type);
if ((current_timestamp_ms - ref_timestamp_ms > RC.rrc[ctxt_pP->module_id]->aggregation_period_ms) &&
estimated_distance != -1) {
LOG_D(LOCALIZE, "RRC [UE/id %d -> eNB/id %d] timestamp %d frame %d estimated r = %f\n",
ctxt.rnti,
ctxt_pP->module_id,
current_timestamp_ms,
ctxt_pP->frame,
estimated_distance);
LOG_D(LOCALIZE, "RRC status %d\n",
ue_context_p->ue_context.Status);
push_front(&RC.rrc[ctxt_pP->module_id]->loc_list, estimated_distance);
RC.rrc[ctxt_pP->module_id]->reference_timestamp_ms = current_timestamp_ms;
} // end if
} // end RB_FOREACH
#endif
(void)ts; /* remove gcc warning "unused variable" */
(void)ref_timestamp_ms; /* remove gcc warning "unused variable" */
(void)current_timestamp_ms; /* remove gcc warning "unused variable" */
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX, VCD_FUNCTION_OUT);
return RRC_OK; return RRC_OK;
} }
...@@ -426,7 +426,7 @@ static e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_inte ...@@ -426,7 +426,7 @@ static e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_inte
*\param security_capabilities The security capabilities received from S1AP. *\param security_capabilities The security capabilities received from S1AP.
*\return TRUE if at least one algorithm has been changed else FALSE. *\return TRUE if at least one algorithm has been changed else FALSE.
*/ */
static int int
rrc_eNB_process_security( rrc_eNB_process_security(
const protocol_ctxt_t *const ctxt_pP, const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP, rrc_eNB_ue_context_t *const ue_context_pP,
...@@ -477,7 +477,7 @@ rrc_eNB_process_security( ...@@ -477,7 +477,7 @@ rrc_eNB_process_security(
*\param security_key_pP The security key received from S1AP. *\param security_key_pP The security key received from S1AP.
*/ */
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
static void process_eNB_security_key ( void process_eNB_security_key (
const protocol_ctxt_t *const ctxt_pP, const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP, rrc_eNB_ue_context_t *const ue_context_pP,
uint8_t *security_key_pP uint8_t *security_key_pP
...@@ -1958,7 +1958,7 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP, ...@@ -1958,7 +1958,7 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr = create_tunnel_resp.enb_addr; S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr = create_tunnel_resp.enb_addr;
LOG_I (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d): nb_of_e_rabs %d, e_rab_id %d, teid: %u, addr: %d.%d.%d.%d \n ", LOG_I (RRC,"enb_gtp_addr (msg index %d, e_rab index %d, status %d): nb_of_e_rabs %d, e_rab_id %d, teid: %u, addr: %d.%d.%d.%d \n ",
e_rabs_done, e_rab, ue_context_pP->ue_context.e_rab[inde_list[e_rab]].status, e_rabs_done, e_rab, ue_context_pP->ue_context.e_rab[inde_list[e_rab]].status,
ue_context_pP->ue_context.nb_of_e_rabs, S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id, S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].e_rab_id,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].gtp_teid, S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].gtp_teid,
S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[0], S1AP_PATH_SWITCH_REQ (msg_p).e_rabs_tobeswitched[e_rab].eNB_addr.buffer[0],
...@@ -1970,7 +1970,7 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP, ...@@ -1970,7 +1970,7 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP,
// NN: add conditions for e_rabs_failed // NN: add conditions for e_rabs_failed
if (e_rabs_done > 0) { if (e_rabs_done > 0) {
LOG_I(RRC,"S1AP_PATH_SWITCH_REQ: sending the message: nb_of_erabstobeswitched %d, total e_rabs %d, index %d\n", LOG_I(RRC,"S1AP_PATH_SWITCH_REQ: sending the message: nb_of_erabstobeswitched %d, total e_rabs %d, index %d\n",
ue_context_pP->ue_context.nb_of_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab); S1AP_PATH_SWITCH_REQ (msg_p).nb_of_e_rabs, ue_context_pP->ue_context.setup_e_rabs, e_rab);
MSC_LOG_TX_MESSAGE( MSC_LOG_TX_MESSAGE(
MSC_RRC_ENB, MSC_RRC_ENB,
MSC_S1AP_ENB, MSC_S1AP_ENB,
...@@ -2017,46 +2017,64 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg ...@@ -2017,46 +2017,64 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg
ue_context_p->ue_context.mme_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).mme_ue_s1ap_id; ue_context_p->ue_context.mme_ue_s1ap_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).mme_ue_s1ap_id;
/* Save e RAB information for later */ /* Save e RAB information for later */
{ {
ue_context_p->ue_context.nb_release_of_e_rabs = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobereleased;
for (i = 0; for (i = 0;
i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg
i++) { i++) {
// assume that we are releasing all the DRBs // assume that we are releasing all the DRBs
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_TORELEASE; ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_REESTABLISHED;
if (ue_context_p->ue_context.nb_release_of_e_rabs==0) {
LOG_I(RRC,"Bearer re-established with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
}
} }
//memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req)); //memset(&create_tunnel_req, 0 , sizeof(create_tunnel_req));
//uint8_t nb_e_rabs_tobeswitched = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobeswitched; uint8_t nb_e_rabs_tobeswitched = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobeswitched;
// keep the previous bearer // keep the previous bearer
// the index for the rec // the index for the rec
if (nb_e_rabs_tobeswitched>0) {
int e_rab_switch_index=0;
for (i = 0; for (i = 0;
i < 1;//nb_e_rabs_tobeswitched; // go over total number of e_rabs received through x2_ho_req msg i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg
i++) { i++) {
LOG_I(RRC,"Bearer re-established with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
/* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */ /* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */
ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_REESTABLISHED; if (ue_context_p->ue_context.e_rab[i].param.e_rab_id == S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[e_rab_switch_index].e_rab_id) {
//ue_context_p->ue_context.e_rab[i].param.e_rab_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].e_rab_id; ue_context_p->ue_context.e_rab[i].param.e_rab_id = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[e_rab_switch_index].e_rab_id;
//ue_context_p->ue_context.e_rab[i].param.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].sgw_addr; ue_context_p->ue_context.e_rab[i].param.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[e_rab_switch_index].sgw_addr;
//ue_context_p->ue_context.e_rab[i].param.gtp_teid = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].gtp_teid; ue_context_p->ue_context.e_rab[i].param.gtp_teid = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[e_rab_switch_index].gtp_teid;
/* Tunnel must have been already created in X2_HO_REQ procedure */ e_rab_switch_index++;
}
}
} }
ue_context_p->ue_context.setup_e_rabs=i;
ue_context_p->ue_context.nb_of_e_rabs=i;
} }
ue_context_p->ue_context.ue_ambr=S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_ambr; ue_context_p->ue_context.ue_ambr=S1AP_PATH_SWITCH_REQ_ACK (msg_p).ue_ambr;
ue_context_p->ue_context.nb_release_of_e_rabs = S1AP_PATH_SWITCH_REQ_ACK (msg_p).nb_e_rabs_tobereleased;
memset(&delete_tunnel_req, 0, sizeof(delete_tunnel_req));
ue_context_p->ue_context.setup_e_rabs = ue_context_p->ue_context.setup_e_rabs - ue_context_p->ue_context.nb_release_of_e_rabs;
ue_context_p->ue_context.nb_of_e_rabs = ue_context_p->ue_context.nb_of_e_rabs - ue_context_p->ue_context.nb_release_of_e_rabs;
memset(&delete_tunnel_req, 0 , sizeof(delete_tunnel_req));
if (ue_context_p->ue_context.nb_release_of_e_rabs>0) {
int e_rab_release_index=0;
for (i = 0; for (i = 0;
i < ue_context_p->ue_context.nb_release_of_e_rabs; i < ue_context_p->ue_context.setup_e_rabs;
i++) { i++) {
if (ue_context_p->ue_context.e_rab[i].param.e_rab_id == S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[e_rab_release_index].e_rab_id) {
LOG_I(RRC,"Bearer released with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id); LOG_I(RRC,"Bearer released with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
ue_context_p->ue_context.e_rabs_tobereleased[i]=S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id; ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_TORELEASE;
delete_tunnel_req.eps_bearer_id[i] = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[i].e_rab_id; ue_context_p->ue_context.e_rabs_tobereleased[e_rab_release_index]=S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[e_rab_release_index].e_rab_id;
delete_tunnel_req.eps_bearer_id[e_rab_release_index] = S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobereleased[e_rab_release_index].e_rab_id;
e_rab_release_index++;
}
else {
LOG_I(RRC,"Bearer re-established with ID: %d\n", ue_context_p->ue_context.e_rab[i].param.e_rab_id);
}
}
} }
if (ue_context_p->ue_context.nb_release_of_e_rabs>0) { if (ue_context_p->ue_context.nb_release_of_e_rabs>0){
delete_tunnel_req.rnti= ue_context_p->ue_context.rnti; delete_tunnel_req.rnti= ue_context_p->ue_context.rnti;
delete_tunnel_req.num_erab= ue_context_p->ue_context.nb_release_of_e_rabs; delete_tunnel_req.num_erab= ue_context_p->ue_context.nb_release_of_e_rabs;
/* this could also be done through ITTI message */ /* this could also be done through ITTI message */
...@@ -2071,7 +2089,57 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg ...@@ -2071,7 +2089,57 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg
memcpy ( ue_context_p->ue_context.next_security_key, memcpy ( ue_context_p->ue_context.next_security_key,
S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key, S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key,
SECURITY_KEY_LENGTH); SECURITY_KEY_LENGTH);
rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(&ctxt, ue_context_p);
return (0); return (0);
} }
} }
int rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP) {
MessageDef *msg_p = NULL;
msg_p = itti_alloc_new_message (TASK_RRC_ENB, X2AP_UE_CONTEXT_RELEASE);
X2AP_UE_CONTEXT_RELEASE (msg_p).rnti = ue_context_pP->ue_context.rnti;
X2AP_UE_CONTEXT_RELEASE (msg_p).source_assoc_id = ue_context_pP->ue_context.handover_info->assoc_id;
itti_send_msg_to_task (TASK_X2AP, ctxt_pP->instance, msg_p);
return (0);
}
int s1ap_ue_context_release(instance_t instance, const uint32_t eNB_ue_s1ap_id){
s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL;
struct s1ap_eNB_ue_context_s *ue_context_p = NULL;
s1ap_eNB_instance_p = s1ap_eNB_get_instance(instance);
DevAssert(s1ap_eNB_instance_p != NULL);
if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p,
eNB_ue_s1ap_id)) == NULL) {
/* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */
LOG_W(RRC,"Failed to find ue context associated with eNB ue s1ap id: %u\n",
eNB_ue_s1ap_id);
return -1;
}
// release UE context
struct s1ap_eNB_ue_context_s *ue_context2_p = NULL;
if ((ue_context2_p = RB_REMOVE(s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head, ue_context_p))
!= NULL) {
LOG_W(RRC,"Removed UE context eNB_ue_s1ap_id %u\n",
ue_context2_p->eNB_ue_s1ap_id);
s1ap_eNB_free_ue_context(ue_context2_p);
} else {
LOG_W(RRC,"Removing UE context eNB_ue_s1ap_id %u: did not find context\n",
ue_context_p->eNB_ue_s1ap_id);
}
/*RB_FOREACH(ue_context_p, s1ap_ue_map, &s1ap_eNB_instance_p->s1ap_ue_head) {
S1AP_WARN("in s1ap_ue_map: UE context eNB_ue_s1ap_id %u mme_ue_s1ap_id %u state %u\n",
ue_context_p->eNB_ue_s1ap_id, ue_context_p->mme_ue_s1ap_id,
ue_context_p->ue_state);
}*/
return 0;
}
...@@ -270,4 +270,8 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP, ...@@ -270,4 +270,8 @@ int rrc_eNB_send_PATH_SWITCH_REQ(const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP); rrc_eNB_ue_context_t *const ue_context_pP);
int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance); int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg_name, instance_t instance);
int rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(const protocol_ctxt_t* const ctxt_pP, rrc_eNB_ue_context_t* const ue_context_pP);
int s1ap_ue_context_release(instance_t instance, const uint32_t eNB_ue_s1ap_id);
#endif /* RRC_ENB_S1AP_H_ */ #endif /* RRC_ENB_S1AP_H_ */
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "x2ap_eNB_handler.h" #include "x2ap_eNB_handler.h"
#include "x2ap_eNB_generate_messages.h" #include "x2ap_eNB_generate_messages.h"
#include "x2ap_common.h" #include "x2ap_common.h"
#include "x2ap_ids.h"
#include "queue.h" #include "queue.h"
#include "assertions.h" #include "assertions.h"
...@@ -79,6 +80,11 @@ static ...@@ -79,6 +80,11 @@ static
void x2ap_eNB_handle_handover_req_ack(instance_t instance, void x2ap_eNB_handle_handover_req_ack(instance_t instance,
x2ap_handover_req_ack_t *x2ap_handover_req_ack); x2ap_handover_req_ack_t *x2ap_handover_req_ack);
static
void x2ap_eNB_ue_context_release(instance_t instance,
x2ap_ue_context_release_t *x2ap_ue_context_release);
static 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; int result;
...@@ -130,7 +136,7 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa ...@@ -130,7 +136,7 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
sctp_new_association_resp->sctp_state, sctp_new_association_resp->sctp_state,
instance, instance,
sctp_new_association_resp->ulp_cnx_id); sctp_new_association_resp->ulp_cnx_id);
x2ap_handle_x2_setup_message(x2ap_enb_data_p, x2ap_handle_x2_setup_message(instance_p, x2ap_enb_data_p,
sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN);
return; return;
} }
...@@ -294,6 +300,8 @@ void x2ap_eNB_handle_register_eNB(instance_t instance, ...@@ -294,6 +300,8 @@ void x2ap_eNB_handle_register_eNB(instance_t instance,
new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length; new_instance->mnc_digit_length = x2ap_register_eNB->mnc_digit_length;
new_instance->num_cc = x2ap_register_eNB->num_cc; new_instance->num_cc = x2ap_register_eNB->num_cc;
x2ap_id_manager_init(&new_instance->id_manager);
for (int i = 0; i< x2ap_register_eNB->num_cc; i++) { for (int i = 0; i< x2ap_register_eNB->num_cc; i++) {
new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i];
new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i];
...@@ -371,30 +379,31 @@ static ...@@ -371,30 +379,31 @@ static
void x2ap_eNB_handle_handover_req(instance_t instance, void x2ap_eNB_handle_handover_req(instance_t instance,
x2ap_handover_req_t *x2ap_handover_req) 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_instance_t *instance_p;
x2ap_eNB_data_t *target; x2ap_eNB_data_t *target;
x2ap_id_manager *id_manager;
int ue_id;
int target_enb_id = x2ap_handover_req->target_physCellId; int target_pci = x2ap_handover_req->target_physCellId;
instance_p = x2ap_eNB_pci_get_instance(target_enb_id); instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL); DevAssert(instance_p != NULL);
//instance_p = x2ap_eNB_get_instance(instance); target = x2ap_is_eNB_pci_in_list(target_pci);
//DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(instance_p->eNB_id);
DevAssert(target != NULL); DevAssert(target != NULL);
/* store rnti at index 0 */ /* allocate x2ap ID */
//x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti; id_manager = &instance_p->id_manager;
x2ap_eNB_generate_x2_handover_request(target, x2ap_handover_req); ue_id = x2ap_allocate_new_id(id_manager);
if (ue_id == -1) {
X2AP_ERROR("could not allocate a new X2AP UE ID\n");
/* TODO: cancel handover: send (to be defined) message to RRC */
exit(1);
}
/* id_source is ue_id, id_target is unknown yet */
x2ap_set_ids(id_manager, ue_id, x2ap_handover_req->rnti, ue_id, -1);
x2ap_eNB_generate_x2_handover_request(instance_p, target, x2ap_handover_req, ue_id);
} }
static static
...@@ -410,17 +419,49 @@ void x2ap_eNB_handle_handover_req_ack(instance_t instance, ...@@ -410,17 +419,49 @@ void x2ap_eNB_handle_handover_req_ack(instance_t instance,
*/ */
x2ap_eNB_instance_t *instance_p; x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target; x2ap_eNB_data_t *target;
int target_enb_id = x2ap_handover_req_ack->target_mod_id; int source_assoc_id = x2ap_handover_req_ack->source_assoc_id;
int ue_id;
int id_source;
int id_target;
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
target = x2ap_get_eNB(NULL, source_assoc_id, 0);
DevAssert(target != NULL);
/* rnti is a new information, save it */
ue_id = x2ap_handover_req_ack->x2_id_target;
id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
id_target = ue_id;
x2ap_set_ids(&instance_p->id_manager, ue_id, x2ap_handover_req_ack->rnti, id_source, id_target);
x2ap_eNB_generate_x2_handover_request_ack(instance_p, target, x2ap_handover_req_ack);
}
static
void x2ap_eNB_ue_context_release(instance_t instance,
x2ap_ue_context_release_t *x2ap_ue_context_release)
{
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *target;
int source_assoc_id = x2ap_ue_context_release->source_assoc_id;
int ue_id;
instance_p = x2ap_eNB_get_instance(instance); instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL); DevAssert(instance_p != NULL);
target = x2ap_is_eNB_id_in_list(target_enb_id); target = x2ap_get_eNB(NULL, source_assoc_id, 0);
DevAssert(target != NULL); DevAssert(target != NULL);
x2ap_eNB_generate_x2_handover_request_ack(target, x2ap_handover_req_ack); x2ap_eNB_generate_x2_ue_context_release(instance_p, target, x2ap_ue_context_release);
//x2ap_eNB_generate_x2_handover_req_ack(instance_p, target, x2ap_handover_req_ack->source_x2id,
//x2ap_handover_req_ack->rrc_buffer, x2ap_handover_req_ack->rrc_buffer_size); /* free the X2AP UE ID */
ue_id = x2ap_find_id_from_rnti(&instance_p->id_manager, x2ap_ue_context_release->rnti);
if (ue_id == -1) {
X2AP_ERROR("could not find UE %x\n", x2ap_ue_context_release->rnti);
exit(1);
}
x2ap_release_id(&instance_p->id_manager, ue_id);
} }
void *x2ap_task(void *arg) { void *x2ap_task(void *arg) {
...@@ -454,6 +495,11 @@ void *x2ap_task(void *arg) { ...@@ -454,6 +495,11 @@ void *x2ap_task(void *arg) {
&X2AP_HANDOVER_REQ_ACK(received_msg)); &X2AP_HANDOVER_REQ_ACK(received_msg));
break; break;
case X2AP_UE_CONTEXT_RELEASE:
x2ap_eNB_ue_context_release(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&X2AP_UE_CONTEXT_RELEASE(received_msg));
break;
case SCTP_INIT_MSG_MULTI_CNF: case SCTP_INIT_MSG_MULTI_CNF:
x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg),
&received_msg->ittiMsg.sctp_init_msg_multi_cnf); &received_msg->ittiMsg.sctp_init_msg_multi_cnf);
......
...@@ -48,6 +48,10 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu) ...@@ -48,6 +48,10 @@ static int x2ap_eNB_decode_initiating_message(X2AP_X2AP_PDU_t *pdu)
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu); //asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break; break;
case X2AP_ProcedureCode_id_uEContextRelease:
//asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_X2AP_X2AP_PDU, pdu);
X2AP_INFO("x2ap_eNB_decode_initiating_message!\n");
break;
default: default:
X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n", X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n",
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include "sctp_eNB_defs.h" #include "sctp_eNB_defs.h"
#include "x2ap_ids.h"
#ifndef X2AP_ENB_DEFS_H_ #ifndef X2AP_ENB_DEFS_H_
#define X2AP_ENB_DEFS_H_ #define X2AP_ENB_DEFS_H_
...@@ -114,6 +116,10 @@ typedef struct x2ap_eNB_data_s { ...@@ -114,6 +116,10 @@ typedef struct x2ap_eNB_data_s {
/* SCTP association id */ /* SCTP association id */
int32_t assoc_id; int32_t assoc_id;
/* Nid cells */
uint32_t Nid_cell[MAX_NUM_CCs];
int num_cc;
/* Only meaningfull in virtual mode */ /* Only meaningfull in virtual mode */
struct x2ap_eNB_instance_s *x2ap_eNB_instance; struct x2ap_eNB_instance_s *x2ap_eNB_instance;
} x2ap_eNB_data_t; } x2ap_eNB_data_t;
...@@ -163,7 +169,6 @@ typedef struct x2ap_eNB_instance_s { ...@@ -163,7 +169,6 @@ typedef struct x2ap_eNB_instance_s {
uint32_t downlink_frequency[MAX_NUM_CCs]; uint32_t downlink_frequency[MAX_NUM_CCs];
int32_t uplink_frequency_offset[MAX_NUM_CCs]; int32_t uplink_frequency_offset[MAX_NUM_CCs];
uint32_t Nid_cell[MAX_NUM_CCs]; uint32_t Nid_cell[MAX_NUM_CCs];
uint32_t Nid_target_cell[MAX_NUM_CCs];
int16_t N_RB_DL[MAX_NUM_CCs]; int16_t N_RB_DL[MAX_NUM_CCs];
lte_frame_type_t frame_type[MAX_NUM_CCs]; lte_frame_type_t frame_type[MAX_NUM_CCs];
uint32_t fdd_earfcn_DL[MAX_NUM_CCs]; uint32_t fdd_earfcn_DL[MAX_NUM_CCs];
...@@ -177,6 +182,8 @@ typedef struct x2ap_eNB_instance_s { ...@@ -177,6 +182,8 @@ typedef struct x2ap_eNB_instance_s {
uint16_t sctp_out_streams; uint16_t sctp_out_streams;
uint32_t enb_port_for_X2C; uint32_t enb_port_for_X2C;
int multi_sd; int multi_sd;
x2ap_id_manager id_manager;
} x2ap_eNB_instance_t; } x2ap_eNB_instance_t;
typedef struct { typedef struct {
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "x2ap_eNB_generate_messages.h" #include "x2ap_eNB_generate_messages.h"
#include "x2ap_eNB_encoder.h" #include "x2ap_eNB_encoder.h"
#include "x2ap_eNB_decoder.h" #include "x2ap_eNB_decoder.h"
#include "x2ap_ids.h"
#include "x2ap_eNB_itti_messaging.h" #include "x2ap_eNB_itti_messaging.h"
...@@ -180,7 +181,7 @@ int x2ap_eNB_generate_x2_setup_request( ...@@ -180,7 +181,7 @@ int x2ap_eNB_generate_x2_setup_request(
return ret; return ret;
} }
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p) int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p)
{ {
X2AP_X2AP_PDU_t pdu; X2AP_X2AP_PDU_t pdu;
X2AP_X2SetupResponse_t *out; X2AP_X2SetupResponse_t *out;
...@@ -189,18 +190,12 @@ int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p) ...@@ -189,18 +190,12 @@ int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p)
ServedCells__Member *servedCellMember; ServedCells__Member *servedCellMember;
X2AP_GU_Group_ID_t *gu; X2AP_GU_Group_ID_t *gu;
x2ap_eNB_instance_t *instance_p;
uint8_t *buffer; uint8_t *buffer;
uint32_t len; uint32_t len;
int ret = 0; int ret = 0;
DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
DevAssert(instance_p != NULL); DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
/* Prepare the X2AP message to encode */ /* Prepare the X2AP message to encode */
memset(&pdu, 0, sizeof(pdu)); memset(&pdu, 0, sizeof(pdu));
...@@ -414,8 +409,8 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, ...@@ -414,8 +409,8 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
return 0; return 0;
} }
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_t *x2ap_handover_req) x2ap_handover_req_t *x2ap_handover_req, int ue_id)
{ {
X2AP_X2AP_PDU_t pdu; X2AP_X2AP_PDU_t pdu;
...@@ -425,19 +420,12 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -425,19 +420,12 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item; X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item;
X2AP_LastVisitedCell_Item_t *lastVisitedCell_Item; X2AP_LastVisitedCell_Item_t *lastVisitedCell_Item;
x2ap_eNB_instance_t *instance_p;
uint8_t *buffer; uint8_t *buffer;
uint32_t len; uint32_t len;
int ret = 0; int ret = 0;
DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance;
DevAssert(instance_p != NULL); DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL);
/* Prepare the X2AP handover message to encode */ /* Prepare the X2AP handover message to encode */
memset(&pdu, 0, sizeof(pdu)); memset(&pdu, 0, sizeof(pdu));
...@@ -452,7 +440,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -452,7 +440,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID; ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject; ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_X2AP_ID; ie->value.present = X2AP_HandoverRequest_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = x2ap_handover_req->old_eNB_ue_x2ap_id; ie->value.choice.UE_X2AP_ID = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
...@@ -471,7 +459,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -471,7 +459,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
ie->value.present = X2AP_HandoverRequest_IEs__value_PR_ECGI; ie->value.present = X2AP_HandoverRequest_IEs__value_PR_ECGI;
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&ie->value.choice.ECGI.pLMN_Identity); &ie->value.choice.ECGI.pLMN_Identity);
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier); MACRO_ENB_ID_TO_CELL_IDENTITY(x2ap_eNB_data_p->eNB_id, 0, &ie->value.choice.ECGI.eUTRANcellIdentifier);
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
...@@ -576,7 +564,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -576,7 +564,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p,
return ret; return ret;
} }
int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p, int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_ack_t *x2ap_handover_req_ack) x2ap_handover_req_ack_t *x2ap_handover_req_ack)
{ {
...@@ -585,19 +573,20 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -585,19 +573,20 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
X2AP_HandoverRequestAcknowledge_IEs_t *ie; X2AP_HandoverRequestAcknowledge_IEs_t *ie;
X2AP_E_RABs_Admitted_ItemIEs_t *e_RABS_Admitted_ItemIEs; X2AP_E_RABs_Admitted_ItemIEs_t *e_RABS_Admitted_ItemIEs;
X2AP_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item; X2AP_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item;
int ue_id;
x2ap_eNB_instance_t *instance_p; int id_source;
int id_target;
uint8_t *buffer; uint8_t *buffer;
uint32_t len; uint32_t len;
int ret = 0; int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL); DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */ ue_id = x2ap_handover_req_ack->x2_id_target;
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance; id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
id_target = ue_id;
DevAssert(instance_p != NULL);
/* Prepare the X2AP handover message to encode */ /* Prepare the X2AP handover message to encode */
memset(&pdu, 0, sizeof(pdu)); memset(&pdu, 0, sizeof(pdu));
...@@ -612,15 +601,15 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -612,15 +601,15 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID; ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_ignore; ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID; ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0; ie->value.choice.UE_X2AP_ID = id_source;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t)); ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID; ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_ignore; ie->criticality = X2AP_Criticality_ignore;
ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID; ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID_1;
ie->value.choice.UE_X2AP_ID = 0; ie->value.choice.UE_X2AP_ID_1 = id_target;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
...@@ -668,25 +657,30 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p, ...@@ -668,25 +657,30 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p,
return ret; return ret;
} }
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p) int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p, x2ap_ue_context_release_t *x2ap_ue_context_release)
{ {
X2AP_X2AP_PDU_t pdu; X2AP_X2AP_PDU_t pdu;
X2AP_UEContextRelease_t *out; X2AP_UEContextRelease_t *out;
X2AP_UEContextRelease_IEs_t *ie; X2AP_UEContextRelease_IEs_t *ie;
int ue_id;
x2ap_eNB_instance_t *instance_p; int id_source;
int id_target;
uint8_t *buffer; uint8_t *buffer;
uint32_t len; uint32_t len;
int ret = 0; int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(x2ap_eNB_data_p != NULL); DevAssert(x2ap_eNB_data_p != NULL);
/* get the eNB instance */ ue_id = x2ap_find_id_from_rnti(&instance_p->id_manager, x2ap_ue_context_release->rnti);
instance_p = x2ap_eNB_data_p->x2ap_eNB_instance; if (ue_id == -1) {
X2AP_ERROR("could not find UE %x\n", x2ap_ue_context_release->rnti);
DevAssert(instance_p != NULL); exit(1);
}
id_source = x2ap_id_get_id_source(&instance_p->id_manager, ue_id);
id_target = ue_id;
/* Prepare the X2AP ue context relase message to encode */ /* Prepare the X2AP ue context relase message to encode */
memset(&pdu, 0, sizeof(pdu)); memset(&pdu, 0, sizeof(pdu));
...@@ -701,15 +695,15 @@ int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p) ...@@ -701,15 +695,15 @@ int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p)
ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID; ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject; ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID; ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID;
ie->value.choice.UE_X2AP_ID = 0; ie->value.choice.UE_X2AP_ID = id_source;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
/* mandatory */ /* mandatory */
ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t)); ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t));
ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID; ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID;
ie->criticality = X2AP_Criticality_reject; ie->criticality = X2AP_Criticality_reject;
ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID; ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID_1;
ie->value.choice.UE_X2AP_ID = 0; ie->value.choice.UE_X2AP_ID_1 = id_target;
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
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);
int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p); int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p);
int x2ap_eNB_generate_x2_setup_failure(instance_t instance, int x2ap_eNB_generate_x2_setup_failure(instance_t instance,
uint32_t assoc_id, uint32_t assoc_id,
...@@ -47,12 +47,13 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, ...@@ -47,12 +47,13 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p,
X2AP_Cause_PR cause_type, X2AP_Cause_PR cause_type,
long cause_value); long cause_value);
int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_t *x2ap_handover_req); x2ap_handover_req_t *x2ap_handover_req, int ue_id);
int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p, int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_handover_req_ack_t *x2ap_handover_req_ack); x2ap_handover_req_ack_t *x2ap_handover_req_ack);
int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_data_t *x2ap_eNB_data_p); int x2ap_eNB_generate_x2_ue_context_release (x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *x2ap_eNB_data_p,
x2ap_ue_context_release_t *x2ap_ue_context_release);
#endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */ #endif /* X2AP_ENB_GENERATE_MESSAGES_H_ */
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "x2ap_eNB_defs.h" #include "x2ap_eNB_defs.h"
#include "x2ap_eNB_handler.h" #include "x2ap_eNB_handler.h"
#include "x2ap_eNB_decoder.h" #include "x2ap_eNB_decoder.h"
#include "x2ap_ids.h"
#include "x2ap_eNB_management_procedures.h" #include "x2ap_eNB_management_procedures.h"
#include "x2ap_eNB_generate_messages.h" #include "x2ap_eNB_generate_messages.h"
...@@ -71,6 +72,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance, ...@@ -71,6 +72,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
uint32_t stream, uint32_t stream,
X2AP_X2AP_PDU_t *pdu); X2AP_X2AP_PDU_t *pdu);
static
int x2ap_eNB_handle_ue_context_release (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu);
/* Handlers matrix. Only eNB related procedure present here */ /* Handlers matrix. Only eNB related procedure present here */
x2ap_message_decoded_callback x2ap_messages_callback[][3] = { x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */ { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */
...@@ -78,7 +85,7 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { ...@@ -78,7 +85,7 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = {
{ 0, 0, 0 }, /* loadIndication */ { 0, 0, 0 }, /* loadIndication */
{ 0, 0, 0 }, /* errorIndication */ { 0, 0, 0 }, /* errorIndication */
{ 0, 0, 0 }, /* snStatusTransfer */ { 0, 0, 0 }, /* snStatusTransfer */
{ 0, 0, 0 }, /* uEContextRelease */ { x2ap_eNB_handle_ue_context_release, 0, 0 }, /* uEContextRelease */
{ x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */ { x2ap_eNB_handle_x2_setup_request, x2ap_eNB_handle_x2_setup_response, x2ap_eNB_handle_x2_setup_failure }, /* x2Setup */
{ 0, 0, 0 }, /* reset */ { 0, 0, 0 }, /* reset */
{ 0, 0, 0 }, /* eNBConfigurationUpdate */ { 0, 0, 0 }, /* eNBConfigurationUpdate */
...@@ -112,7 +119,7 @@ static char *x2ap_direction_String[] = { ...@@ -112,7 +119,7 @@ static char *x2ap_direction_String[] = {
return(x2ap_direction_String[x2ap_dir]); return(x2ap_direction_String[x2ap_dir]);
} }
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown) void x2ap_handle_x2_setup_message(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown)
{ {
if (sctp_shutdown) { if (sctp_shutdown) {
/* A previously connected eNB has been shutdown */ /* A previously connected eNB has been shutdown */
...@@ -121,38 +128,38 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown ...@@ -121,38 +128,38 @@ void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *enb_desc_p, int sctp_shutdown
if (enb_desc_p->state == X2AP_ENB_STATE_CONNECTED) { if (enb_desc_p->state == X2AP_ENB_STATE_CONNECTED) {
enb_desc_p->state = X2AP_ENB_STATE_DISCONNECTED; enb_desc_p->state = X2AP_ENB_STATE_DISCONNECTED;
if (enb_desc_p->x2ap_eNB_instance-> x2_target_enb_associated_nb > 0) { if (instance_p-> x2_target_enb_associated_nb > 0) {
/* Decrease associated eNB number */ /* Decrease associated eNB number */
enb_desc_p->x2ap_eNB_instance-> x2_target_enb_associated_nb --; instance_p-> x2_target_enb_associated_nb --;
} }
/* If there are no more associated eNB, inform eNB app */ /* If there are no more associated eNB, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb == 0) { if (instance_p->x2_target_enb_associated_nb == 0) {
MessageDef *message_p; MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND); message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND);
X2AP_DEREGISTERED_ENB_IND(message_p).nb_x2 = 0; X2AP_DEREGISTERED_ENB_IND(message_p).nb_x2 = 0;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p); itti_send_msg_to_task(TASK_ENB_APP, instance_p->instance, message_p);
} }
} }
} else { } else {
/* Check that at least one setup message is pending */ /* Check that at least one setup message is pending */
DevCheck(enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0, DevCheck(instance_p->x2_target_enb_pending_nb > 0,
enb_desc_p->x2ap_eNB_instance->instance, instance_p->instance,
enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb, 0); instance_p->x2_target_enb_pending_nb, 0);
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0) { if (instance_p->x2_target_enb_pending_nb > 0) {
/* Decrease pending messages number */ /* Decrease pending messages number */
enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb --; instance_p->x2_target_enb_pending_nb --;
} }
/* If there are no more pending messages, inform eNB app */ /* If there are no more pending messages, inform eNB app */
if (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb == 0) { if (instance_p->x2_target_enb_pending_nb == 0) {
MessageDef *message_p; MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_X2AP, X2AP_REGISTER_ENB_CNF); message_p = itti_alloc_new_message(TASK_X2AP, X2AP_REGISTER_ENB_CNF);
X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb; X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = instance_p->x2_target_enb_associated_nb;
itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p); itti_send_msg_to_task(TASK_ENB_APP, instance_p->instance, message_p);
} }
} }
} }
...@@ -276,6 +283,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, ...@@ -276,6 +283,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
X2AP_X2SetupRequest_IEs_t *ie; X2AP_X2SetupRequest_IEs_t *ie;
ServedCells__Member *servedCellMember; ServedCells__Member *servedCellMember;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0; uint32_t eNB_id = 0;
...@@ -358,8 +366,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, ...@@ -358,8 +366,7 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
*/ */
X2AP_ERROR("Rejecting 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_ERROR("Rejecting 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);
DevAssert(x2ap_eNB_data->x2ap_eNB_instance != NULL); x2ap_eNB_generate_x2_setup_failure (instance,
x2ap_eNB_generate_x2_setup_failure (x2ap_eNB_data->x2ap_eNB_instance->instance,
assoc_id, assoc_id,
X2AP_Cause_PR_protocol, X2AP_Cause_PR_protocol,
X2AP_CauseProtocol_unspecified, X2AP_CauseProtocol_unspecified,
...@@ -374,19 +381,22 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, ...@@ -374,19 +381,22 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance,
/* Set proper pci */ /* Set proper pci */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest,
X2AP_ProtocolIE_ID_id_ServedCells, true); X2AP_ProtocolIE_ID_id_ServedCells, true);
if (ie == NULL ) { if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1; return -1;
} else if (ie->value.choice.ServedCells.list.count > 0) { }
x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count; if (ie->value.choice.ServedCells.list.count > 0) {
x2ap_eNB_data->num_cc = ie->value.choice.ServedCells.list.count;
for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) { for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i]; servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI; x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI;
} }
} }
return x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data); instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
return x2ap_eNB_generate_x2_setup_response(instance_p, x2ap_eNB_data);
} }
static static
...@@ -400,6 +410,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, ...@@ -400,6 +410,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
X2AP_X2SetupResponse_IEs_t *ie; X2AP_X2SetupResponse_IEs_t *ie;
ServedCells__Member *servedCellMember; ServedCells__Member *servedCellMember;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
uint32_t eNB_id = 0; uint32_t eNB_id = 0;
...@@ -478,15 +489,16 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, ...@@ -478,15 +489,16 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
/* Set proper pci */ /* Set proper pci */
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse,
X2AP_ProtocolIE_ID_id_ServedCells, true); X2AP_ProtocolIE_ID_id_ServedCells, true);
if (ie == NULL ) { if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1; return -1;
} else if (ie->value.choice.ServedCells.list.count > 0) { }
x2ap_eNB_data->x2ap_eNB_instance->num_cc = ie->value.choice.ServedCells.list.count;
if (ie->value.choice.ServedCells.list.count > 0) {
x2ap_eNB_data->num_cc = ie->value.choice.ServedCells.list.count;
for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) { for (int i=0; i<ie->value.choice.ServedCells.list.count;i++) {
servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i]; servedCellMember = (ServedCells__Member *)ie->value.choice.ServedCells.list.array[i];
x2ap_eNB_data->x2ap_eNB_instance->Nid_target_cell[i] = servedCellMember->servedCellInfo.pCI; x2ap_eNB_data->Nid_cell[i] = servedCellMember->servedCellInfo.pCI;
} }
} }
...@@ -496,8 +508,12 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, ...@@ -496,8 +508,12 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance,
* Mark the association as connected. * Mark the association as connected.
*/ */
x2ap_eNB_data->state = X2AP_ENB_STATE_READY; x2ap_eNB_data->state = X2AP_ENB_STATE_READY;
x2ap_eNB_data->x2ap_eNB_instance->x2_target_enb_associated_nb ++;
x2ap_handle_x2_setup_message(x2ap_eNB_data, 0); instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
instance_p->x2_target_enb_associated_nb ++;
x2ap_handle_x2_setup_message(instance_p, x2ap_eNB_data, 0);
return 0; return 0;
} }
...@@ -512,6 +528,7 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, ...@@ -512,6 +528,7 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
X2AP_X2SetupFailure_t *x2SetupFailure; X2AP_X2SetupFailure_t *x2SetupFailure;
X2AP_X2SetupFailure_IEs_t *ie; X2AP_X2SetupFailure_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
DevAssert(pdu != NULL); DevAssert(pdu != NULL);
...@@ -552,7 +569,11 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, ...@@ -552,7 +569,11 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance,
} }
x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING; x2ap_eNB_data->state = X2AP_ENB_STATE_WAITING;
x2ap_handle_x2_setup_message(x2ap_eNB_data, 0);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
x2ap_handle_x2_setup_message(instance_p, x2ap_eNB_data, 0);
return 0; return 0;
} }
...@@ -570,8 +591,10 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, ...@@ -570,8 +591,10 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
X2AP_E_RABs_ToBeSetup_ItemIEs_t *e_RABS_ToBeSetup_ItemIEs; X2AP_E_RABs_ToBeSetup_ItemIEs_t *e_RABS_ToBeSetup_ItemIEs;
X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item; X2AP_E_RABs_ToBeSetup_Item_t *e_RABs_ToBeSetup_Item;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg; MessageDef *msg;
int ue_id;
DevAssert (pdu != NULL); DevAssert (pdu != NULL);
x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest; x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest;
...@@ -587,19 +610,30 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, ...@@ -587,19 +610,30 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL); DevAssert(x2ap_eNB_data != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ); msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ);
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true); X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
//X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti;
//X2AP_HANDOVER_REQ(m).source_x2id = x2HandoverRequest->old_eNB_UE_X2AP_ID;
if (ie == NULL ) { if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1; return -1;
} else {
X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = ie->value.choice.UE_X2AP_ID;
} }
/* allocate a new X2AP UE ID */
ue_id = x2ap_allocate_new_id(&instance_p->id_manager);
if (ue_id == -1) {
X2AP_ERROR("could not allocate a new X2AP UE ID\n");
/* TODO: cancel handover: send HO preparation failure to source eNB */
exit(1);
}
/* rnti is unknown yet, must not be set to -1, 0 is fine */
x2ap_set_ids(&instance_p->id_manager, ue_id, 0, ie->value.choice.UE_X2AP_ID, ue_id);
X2AP_HANDOVER_REQ(msg).x2_id = ue_id;
//X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice. //X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice.
//measResultListEUTRA.list.array[ncell_index]->physCellId; //measResultListEUTRA.list.array[ncell_index]->physCellId;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest,
...@@ -619,7 +653,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, ...@@ -619,7 +653,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
} }
X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID; X2AP_HANDOVER_REQ(msg).mme_ue_s1ap_id = ie->value.choice.UE_ContextInformation.mME_UE_S1AP_ID;
X2AP_HANDOVER_REQ(msg).target_mod_id = x2ap_eNB_data->x2ap_eNB_instance->eNB_id;
/* TODO: properly store Target Cell ID */
X2AP_HANDOVER_REQ(msg).target_assoc_id = assoc_id;
X2AP_HANDOVER_REQ(msg).security_capabilities.encryption_algorithms = X2AP_HANDOVER_REQ(msg).security_capabilities.encryption_algorithms =
BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms); BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms);
X2AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms = X2AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms =
...@@ -671,10 +709,10 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, ...@@ -671,10 +709,10 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance,
if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/) if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s*/)
{ printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); } { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); }
memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size); memcpy(X2AP_HANDOVER_REQ(msg).rrc_buffer, c->buf, c->size);
X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size; X2AP_HANDOVER_REQ(msg).rrc_buffer_size = c->size;
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg); itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
return 0; return 0;
} }
...@@ -688,8 +726,13 @@ int x2ap_eNB_handle_handover_response (instance_t instance, ...@@ -688,8 +726,13 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
X2AP_HandoverRequestAcknowledge_t *x2HandoverRequestAck; X2AP_HandoverRequestAcknowledge_t *x2HandoverRequestAck;
X2AP_HandoverRequestAcknowledge_IEs_t *ie; X2AP_HandoverRequestAcknowledge_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data; x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg; MessageDef *msg;
int ue_id;
int id_source;
int id_target;
int rnti;
DevAssert (pdu != NULL); DevAssert (pdu != NULL);
x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge; x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge;
...@@ -705,12 +748,44 @@ int x2ap_eNB_handle_handover_response (instance_t instance, ...@@ -705,12 +748,44 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0); x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL); DevAssert(x2ap_eNB_data != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK); msg = itti_alloc_new_message(TASK_X2AP, X2AP_HANDOVER_REQ_ACK);
/* TODO: fill the message */
//extern int x2id_to_source_rnti[1]; X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
//X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID; X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
//X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID];
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_source = ie->value.choice.UE_X2AP_ID;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_target = ie->value.choice.UE_X2AP_ID_1;
ue_id = id_source;
if (id_source != x2ap_id_get_id_source(&instance_p->id_manager, ue_id)) {
X2AP_ERROR("incorrect X2AP IDs for UE (old ID %d new ID %d)\n", id_source, id_target);
exit(1);
}
rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
/* id_target is a new information, store it */
x2ap_set_ids(&instance_p->id_manager, ue_id, rnti, id_source, id_target);
X2AP_HANDOVER_REQ_ACK(msg).rnti = rnti;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck,
X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true); X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true);
...@@ -723,6 +798,81 @@ int x2ap_eNB_handle_handover_response (instance_t instance, ...@@ -723,6 +798,81 @@ int x2ap_eNB_handle_handover_response (instance_t instance,
memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size); memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size);
X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size; X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size;
itti_send_msg_to_task(TASK_RRC_ENB, x2ap_eNB_data->x2ap_eNB_instance->instance, msg); itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
return 0;
}
static
int x2ap_eNB_handle_ue_context_release (instance_t instance,
uint32_t assoc_id,
uint32_t stream,
X2AP_X2AP_PDU_t *pdu)
{
X2AP_UEContextRelease_t *x2UEContextRelease;
X2AP_UEContextRelease_IEs_t *ie;
x2ap_eNB_instance_t *instance_p;
x2ap_eNB_data_t *x2ap_eNB_data;
MessageDef *msg;
int ue_id;
int id_source;
int id_target;
DevAssert (pdu != NULL);
x2UEContextRelease = &pdu->choice.initiatingMessage.value.choice.UEContextRelease;
if (stream == 0) {
X2AP_ERROR ("Received new x2 ue context release on stream == 0\n");
/* TODO: send a x2 failure response */
return 0;
}
X2AP_DEBUG ("Received a new X2 ue context release\n");
x2ap_eNB_data = x2ap_get_eNB(NULL, assoc_id, 0);
DevAssert(x2ap_eNB_data != NULL);
instance_p = x2ap_eNB_get_instance(instance);
DevAssert(instance_p != NULL);
msg = itti_alloc_new_message(TASK_X2AP, X2AP_UE_CONTEXT_RELEASE);
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_UEContextRelease_IEs_t, ie, x2UEContextRelease,
X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_source = ie->value.choice.UE_X2AP_ID;
X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_UEContextRelease_IEs_t, ie, x2UEContextRelease,
X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID, true);
if (ie == NULL ) {
X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__);
return -1;
}
id_target = ie->value.choice.UE_X2AP_ID_1;
ue_id = id_source;
if (id_target != x2ap_id_get_id_target(&instance_p->id_manager, ue_id)) {
X2AP_ERROR("UE context release: bad id_target for UE %x (id_source %d) expected %d got %d\n",
x2ap_id_get_rnti(&instance_p->id_manager, ue_id),
id_source,
x2ap_id_get_id_target(&instance_p->id_manager, ue_id),
id_target);
}
X2AP_UE_CONTEXT_RELEASE(msg).rnti = x2ap_id_get_rnti(&instance_p->id_manager, ue_id);
itti_send_msg_to_task(TASK_RRC_ENB, instance_p->instance, msg);
x2ap_release_id(&instance_p->id_manager, ue_id);
return 0; return 0;
} }
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "x2ap_eNB_defs.h" #include "x2ap_eNB_defs.h"
void x2ap_handle_x2_setup_message(x2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown); void x2ap_handle_x2_setup_message(x2ap_eNB_instance_t *instance_p, x2ap_eNB_data_t *eNB_desc_p, int sctp_shutdown);
int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream, int x2ap_eNB_handle_message(instance_t instance, uint32_t assoc_id, int32_t stream,
const uint8_t * const data, const uint32_t data_length); const uint8_t * const data, const uint32_t data_length);
......
...@@ -169,23 +169,6 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance) ...@@ -169,23 +169,6 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance)
return NULL; return NULL;
} }
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci)
{
x2ap_eNB_instance_t *temp = NULL;
STAILQ_FOREACH(temp, &x2ap_eNB_internal_data.x2ap_eNB_instances_head,
x2ap_eNB_entries) {
for (int i=0; i<temp->num_cc;i++) {
if (temp->Nid_target_cell[i] == pci) {
/* Matching occurence */
return temp;
}
}
}
return NULL;
}
/// utility functions /// utility functions
void x2ap_dump_eNB (x2ap_eNB_data_t * eNB_ref); void x2ap_dump_eNB (x2ap_eNB_data_t * eNB_ref);
...@@ -222,6 +205,22 @@ void x2ap_dump_eNB (x2ap_eNB_data_t * eNB_ref) { ...@@ -222,6 +205,22 @@ void x2ap_dump_eNB (x2ap_eNB_data_t * eNB_ref) {
indent--; indent--;
} }
x2ap_eNB_data_t * x2ap_is_eNB_pci_in_list (const uint32_t pci)
{
x2ap_eNB_instance_t *inst;
struct x2ap_eNB_data_s *elm;
STAILQ_FOREACH(inst, &x2ap_eNB_internal_data.x2ap_eNB_instances_head, x2ap_eNB_entries) {
RB_FOREACH(elm, x2ap_enb_map, &inst->x2ap_enb_head) {
for (int i = 0; i<elm->num_cc; i++) {
if (elm->Nid_cell[i] == pci) {
return elm;
}
}
}
}
return NULL;
}
x2ap_eNB_data_t * x2ap_is_eNB_id_in_list (const uint32_t eNB_id) x2ap_eNB_data_t * x2ap_is_eNB_id_in_list (const uint32_t eNB_id)
{ {
......
...@@ -37,8 +37,6 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p); ...@@ -37,8 +37,6 @@ void x2ap_eNB_insert_new_instance(x2ap_eNB_instance_t *new_instance_p);
x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id); x2ap_eNB_instance_t *x2ap_eNB_get_instance(uint8_t mod_id);
x2ap_eNB_instance_t *x2ap_eNB_pci_get_instance(uint32_t pci);
uint16_t x2ap_eNB_fetch_add_global_cnx_id(void); uint16_t x2ap_eNB_fetch_add_global_cnx_id(void);
void x2ap_eNB_prepare_internal_data(void); void x2ap_eNB_prepare_internal_data(void);
...@@ -47,6 +45,8 @@ x2ap_eNB_data_t* x2ap_is_eNB_id_in_list(uint32_t eNB_id); ...@@ -47,6 +45,8 @@ 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); x2ap_eNB_data_t* x2ap_is_eNB_assoc_id_in_list(uint32_t sctp_assoc_id);
x2ap_eNB_data_t* x2ap_is_eNB_pci_in_list (const uint32_t pci);
struct x2ap_eNB_data_s *x2ap_get_eNB(x2ap_eNB_instance_t *instance_p, struct x2ap_eNB_data_s *x2ap_get_eNB(x2ap_eNB_instance_t *instance_p,
int32_t assoc_id, int32_t assoc_id,
uint16_t cnx_id); uint16_t cnx_id);
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "x2ap_ids.h"
#include <string.h>
void x2ap_id_manager_init(x2ap_id_manager *m)
{
int i;
memset(m, 0, sizeof(x2ap_id_manager));
for (i = 0; i < X2AP_MAX_IDS; i++)
m->ids[i].rnti = -1;
}
int x2ap_allocate_new_id(x2ap_id_manager *m)
{
int i;
for (i = 0; i < X2AP_MAX_IDS; i++)
if (m->ids[i].rnti == -1) {
m->ids[i].rnti = 0;
m->ids[i].id_source = -1;
m->ids[i].id_target = -1;
return i;
}
return -1;
}
void x2ap_release_id(x2ap_id_manager *m, int id)
{
m->ids[id].rnti = -1;
}
int x2ap_find_id(x2ap_id_manager *m, int id_source, int id_target)
{
int i;
for (i = 0; i < X2AP_MAX_IDS; i++)
if (m->ids[i].rnti != -1 &&
m->ids[i].id_source == id_source &&
m->ids[i].id_target == id_target)
return i;
return -1;
}
int x2ap_find_id_from_rnti(x2ap_id_manager *m, int rnti)
{
int i;
for (i = 0; i < X2AP_MAX_IDS; i++)
if (m->ids[i].rnti == rnti)
return i;
return -1;
}
void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target)
{
m->ids[ue_id].rnti = rnti;
m->ids[ue_id].id_source = id_source;
m->ids[ue_id].id_target = id_target;
}
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].id_source;
}
int x2ap_id_get_id_target(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].id_target;
}
int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id)
{
return m->ids[ue_id].rnti;
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef X2AP_IDS_H_
#define X2AP_IDS_H_
#define X2AP_MAX_IDS 16
typedef struct {
int rnti; /* -1 when free */
int id_source;
int id_target;
} x2ap_id;
typedef struct {
x2ap_id ids[X2AP_MAX_IDS];
} x2ap_id_manager;
void x2ap_id_manager_init(x2ap_id_manager *m);
int x2ap_allocate_new_id(x2ap_id_manager *m);
void x2ap_release_id(x2ap_id_manager *m, int id);
int x2ap_find_id(x2ap_id_manager *, int id_source, int id_target);
int x2ap_find_id_from_rnti(x2ap_id_manager *, int rnti);
void x2ap_set_ids(x2ap_id_manager *m, int ue_id, int rnti, int id_source, int id_target);
int x2ap_id_get_id_source(x2ap_id_manager *m, int ue_id);
int x2ap_id_get_id_target(x2ap_id_manager *m, int ue_id);
int x2ap_id_get_rnti(x2ap_id_manager *m, int ue_id);
#endif /* X2AP_IDS_H_ */
...@@ -38,7 +38,7 @@ int sctp_itti_send_init_msg_multi_cnf(task_id_t task_id, instance_t instance, in ...@@ -38,7 +38,7 @@ int sctp_itti_send_init_msg_multi_cnf(task_id_t task_id, instance_t instance, in
return itti_send_msg_to_task(task_id, instance, message_p); return itti_send_msg_to_task(task_id, instance, message_p);
} }
int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t *buffer, int sctp_itti_send_new_message_ind(task_id_t task_id, instance_t instance, uint32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream) uint32_t buffer_length, uint16_t stream)
{ {
MessageDef *message_p; MessageDef *message_p;
...@@ -57,7 +57,7 @@ int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t ...@@ -57,7 +57,7 @@ int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t
sctp_data_ind_p->buffer_length = buffer_length; sctp_data_ind_p->buffer_length = buffer_length;
sctp_data_ind_p->assoc_id = assoc_id; sctp_data_ind_p->assoc_id = assoc_id;
return itti_send_msg_to_task(task_id, INSTANCE_DEFAULT, message_p); return itti_send_msg_to_task(task_id, instance, message_p);
} }
int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance, int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance,
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
int sctp_itti_send_init_msg_multi_cnf(task_id_t task_id, instance_t instance, int multi_sd); int sctp_itti_send_init_msg_multi_cnf(task_id_t task_id, instance_t instance, int multi_sd);
int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t *buffer, int sctp_itti_send_new_message_ind(task_id_t task_id, instance_t instance, uint32_t assoc_id, uint8_t *buffer,
uint32_t buffer_length, uint16_t stream); uint32_t buffer_length, uint16_t stream);
int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance, int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance,
......
...@@ -324,7 +324,12 @@ sctp_handle_new_association_req_multi( ...@@ -324,7 +324,12 @@ sctp_handle_new_association_req_multi(
} }
} }
ns = sctp_peeloff(sd,assoc_id); ns = sctp_peeloff(sd, assoc_id);
if (ns == -1) {
perror("sctp_peeloff");
printf("sctp_peeloff: sd=%d assoc_id=%d\n", sd, assoc_id);
exit(1);
}
sctp_cnx = calloc(1, sizeof(*sctp_cnx)); sctp_cnx = calloc(1, sizeof(*sctp_cnx));
...@@ -1003,7 +1008,7 @@ sctp_eNB_read_from_socket( ...@@ -1003,7 +1008,7 @@ sctp_eNB_read_from_socket(
sinfo.sinfo_assoc_id, sctp_cnx->sd, n, ntohs(addr.sin_port), sinfo.sinfo_assoc_id, sctp_cnx->sd, n, ntohs(addr.sin_port),
sinfo.sinfo_stream, ntohl(sinfo.sinfo_ppid)); sinfo.sinfo_stream, ntohl(sinfo.sinfo_ppid));
sctp_itti_send_new_message_ind(sctp_cnx->task_id, sctp_itti_send_new_message_ind(sctp_cnx->task_id, sctp_cnx->instance,
sinfo.sinfo_assoc_id, sinfo.sinfo_assoc_id,
buffer, n, sinfo.sinfo_stream); buffer, n, sinfo.sinfo_stream);
} }
......
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