diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 6c176a75c24a1c1945d84791e377d12aed305b59..a1b4955b21212ae2dad2c10b37ba0d88556f25b7 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -469,6 +469,7 @@ add_library(X2AP_ENB ${X2AP_DIR}/x2ap_eNB_itti_messaging.c ${X2AP_DIR}/x2ap_eNB_management_procedures.c ${X2AP_DIR}/x2ap_eNB_generate_messages.c + ${X2AP_DIR}/x2ap_ids.c ) add_dependencies(X2AP_ENB rrc_flag x2_flag) diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 08ea93f427add5aa6dbd032e54180848cb3e85da..40005459666864367edcbc5eee52917950d48d27 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -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_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) + +// eNB: realtime -> RRC messages +MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index f6e2216c1ba848233d85dd7b5206dc1f83f40d02..3880604e61f730203c7f665c5c6cd9da23f05e33 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -81,6 +81,8 @@ #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 RRC_SUBFRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.rrc_subframe_process + //-------------------------------------------------------------------------------------------// typedef struct RrcStateInd_s { Rrc_State_t state; @@ -399,4 +401,10 @@ typedef nas_release_ind_t NasConnReleaseInd; typedef ul_info_transfer_cnf_t NasUlDataCnf; 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_ */ diff --git a/openair2/COMMON/x2ap_messages_def.h b/openair2/COMMON/x2ap_messages_def.h index d5555c183989b4573501e005620fba7b57302787..65fa9c801dee5279383d0cbeefe57406fc682fb4 100644 --- a/openair2/COMMON/x2ap_messages_def.h +++ b/openair2/COMMON/x2ap_messages_def.h @@ -40,3 +40,6 @@ MESSAGE_DEF(X2AP_DEREGISTERED_ENB_IND , MESSAGE_PRIORITY_MED, x2ap_der /* handover messages X2AP <-> RRC */ 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) + +/* handover messages X2AP <-> S1AP */ +MESSAGE_DEF(X2AP_UE_CONTEXT_RELEASE , MESSAGE_PRIORITY_MED, x2ap_ue_context_release_t , x2ap_ue_context_release) diff --git a/openair2/COMMON/x2ap_messages_types.h b/openair2/COMMON/x2ap_messages_types.h index 7cdd0ff0ff37a605e59604a0186e951ae6d47463..38429b712edc64caf6557a7bc98a710e308586da 100644 --- a/openair2/COMMON/x2ap_messages_types.h +++ b/openair2/COMMON/x2ap_messages_types.h @@ -33,11 +33,21 @@ #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_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 // 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 { /* Unique eNB_id to identify the eNB within EPC. * For macro eNB ids this field should be 20 bits long. @@ -128,12 +138,12 @@ typedef struct x2ap_lastvisitedcell_info_s { uint64_t time_UE_StayedInCell; }x2ap_lastvisitedcell_info_t; -//used for src typedef struct x2ap_handover_req_s { - int source_rnti; /* TODO: to be fixed/remove */ - int source_x2id; /* TODO: to be fixed/remove */ + /* used for RRC->X2AP in source eNB */ + int rnti; - int old_eNB_ue_x2ap_id; + /* used for X2AP->RRC in target eNB */ + int x2_id; LTE_PhysCellId_t target_physCellId; @@ -167,15 +177,17 @@ typedef struct x2ap_handover_req_s { uint8_t rrc_buffer[1024 /* arbitrary, big enough */]; int rrc_buffer_size; - /* TODO: this parameter has to be removed */ - int target_mod_id; + int target_assoc_id; } x2ap_handover_req_t; typedef struct x2ap_handover_req_ack_s { - int source_rnti; /* TODO: to be fixed/remove */ - int source_x2id; /* TODO: to be fixed/remove */ - /* TODO: this parameter has to be removed */ - int target_mod_id; + /* used for RRC->X2AP in target and X2AP->RRC in source */ + int rnti; + + /* used for RRC->X2AP in target */ + int x2_id_target; + + int source_assoc_id; uint8_t nb_e_rabs_tobesetup; diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 478f14f07c7a239174b54df7852768a5d21c90c6..d4439ab349defe28e370bc8b85b92c36224c1160 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -1923,162 +1923,164 @@ int RCconfig_X2(MessageDef *msg_p, uint32_t i) { if (ENBParamList.numelt > 0) { for (k = 0; k < ENBParamList.numelt; k++) { - if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) { - // Calculate a default eNB ID + if (ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr == NULL) { + // Calculate a default eNB ID if (EPC_MODE_ENABLED) { - uint32_t hash; - hash = s1ap_generate_eNB_id (); - enb_id = k + (hash & 0xFFFF8); + uint32_t hash; + hash = s1ap_generate_eNB_id (); + enb_id = k + (hash & 0xFFFF8); } else { - enb_id = k; + enb_id = k; } - } else { - enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr); - } - - // search if in active list - for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) { - if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) { - paramdef_t PLMNParams[] = PLMNPARAMS_DESC; - paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0}; - /* map parameter checking array instances to parameter definition array instances */ - checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK; - - for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I) - PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]); - - paramdef_t X2Params[] = X2PARAMS_DESC; - paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0}; - paramdef_t SCTPParams[] = SCTPPARAMS_DESC; - paramdef_t NETParams[] = NETPARAMS_DESC; - /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */ - /* this is most probably a problem with the config module */ - char aprefix[MAX_OPTNAME_SIZE*80 + 8]; - sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k); - /* Some default/random parameters */ - X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id; - - if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) { - X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB; - } else if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) { - X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB; - } else { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n", - RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr)); - } - - X2AP_REGISTER_ENB_REQ (msg_p).eNB_name = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)); - X2AP_REGISTER_ENB_REQ (msg_p).tac = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr; - config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix); - - if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) - AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n", - PLMNParamList.numelt); - - if (PLMNParamList.numelt > 1) - LOG_W(X2AP, "X2AP currently handles only one PLMN, ignoring the others!\n"); - - X2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][ENB_MOBILE_COUNTRY_CODE_IDX].uptr; - X2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][ENB_MOBILE_NETWORK_CODE_IDX].uptr; - X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][ENB_MNC_DIGIT_LENGTH].u8ptr; - AssertFatal(X2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3 - || X2AP_REGISTER_ENB_REQ(msg_p).mnc < 100, - "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n", - X2AP_REGISTER_ENB_REQ(msg_p).mnc); - /* CC params */ - config_getlist(&CCsParamList, NULL, 0, aprefix); - X2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt; - - if (CCsParamList.numelt > 0) { - //char ccspath[MAX_OPTNAME_SIZE*2 + 16]; - for (J = 0; J < CCsParamList.numelt ; J++) { - sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J); - config_get(CCsParams, sizeof(CCsParams)/sizeof(paramdef_t), aprefix); - X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = ccparams_lte.eutra_band; - X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) ccparams_lte.downlink_frequency; - X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) ccparams_lte.uplink_frequency_offset; - X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= ccparams_lte.Nid_cell; - - if (ccparams_lte.Nid_cell>503) { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n", - RC.config_file_name, k, ccparams_lte.Nid_cell); - } - - X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= ccparams_lte.N_RB_DL; - - if ((ccparams_lte.N_RB_DL!=6) && (ccparams_lte.N_RB_DL!=15) && (ccparams_lte.N_RB_DL!=25) && (ccparams_lte.N_RB_DL!=50) && (ccparams_lte.N_RB_DL!=75) && (ccparams_lte.N_RB_DL!=100)) { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n", - RC.config_file_name, k, ccparams_lte.N_RB_DL); - } - - if (strcmp(ccparams_lte.frame_type, "FDD") == 0) { - X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD; - } else if (strcmp(ccparams_lte.frame_type, "TDD") == 0) { - X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; - } else { - AssertFatal (0, - "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n", - RC.config_file_name, k, ccparams_lte.frame_type); - } - - X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL); - X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL); - } - } - - sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k); - config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix); - AssertFatal(X2ParamList.numelt <= X2AP_MAX_NB_ENB_IP_ADDRESS, - "value of X2ParamList.numelt %d must be lower than X2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase X2AP_MAX_NB_ENB_IP_ADDRESS\n", - X2ParamList.numelt,X2AP_MAX_NB_ENB_IP_ADDRESS); - X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 = 0; - - for (l = 0; l < X2ParamList.numelt; l++) { - X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 += 1; - strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr)); - strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6_address,*(X2ParamList.paramarray[l][ENB_X2_IPV6_ADDRESS_IDX].strptr)); - - 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; - } 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].ipv6 = 1; - } 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].ipv6 = 1; - } - } - - // SCTP SETTING - X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; - X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; + } else { + enb_id = *(ENBParamList.paramarray[k][ENB_ENB_ID_IDX].uptr); + } + + // search if in active list + for (j = 0; j < ENBSParams[ENB_ACTIVE_ENBS_IDX].numelt; j++) { + if (strcmp(ENBSParams[ENB_ACTIVE_ENBS_IDX].strlistptr[j], *(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)) == 0) { + paramdef_t PLMNParams[] = PLMNPARAMS_DESC; + paramlist_def_t PLMNParamList = {ENB_CONFIG_STRING_PLMN_LIST, NULL, 0}; + /* map parameter checking array instances to parameter definition array instances */ + checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK; + + for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I) + PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]); + + paramdef_t X2Params[] = X2PARAMS_DESC; + paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0}; + paramdef_t SCTPParams[] = SCTPPARAMS_DESC; + paramdef_t NETParams[] = NETPARAMS_DESC; + /* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */ + /* this is most probably a problem with the config module */ + char aprefix[MAX_OPTNAME_SIZE*80 + 8]; + sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k); + /* Some default/random parameters */ + X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = enb_id; + + if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_MACRO_ENB") == 0) { + X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_ENB; + } else if (strcmp(*(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr), "CELL_HOME_ENB") == 0) { + X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_HOME_ENB; + } else { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n", + RC.config_file_name, i, *(ENBParamList.paramarray[k][ENB_CELL_TYPE_IDX].strptr)); + } + + X2AP_REGISTER_ENB_REQ (msg_p).eNB_name = strdup(*(ENBParamList.paramarray[k][ENB_ENB_NAME_IDX].strptr)); + X2AP_REGISTER_ENB_REQ (msg_p).tac = *ENBParamList.paramarray[k][ENB_TRACKING_AREA_CODE_IDX].uptr; + config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix); + + if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) + AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n", + PLMNParamList.numelt); + + if (PLMNParamList.numelt > 1) + LOG_W(X2AP, "X2AP currently handles only one PLMN, ignoring the others!\n"); + + X2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][ENB_MOBILE_COUNTRY_CODE_IDX].uptr; + X2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][ENB_MOBILE_NETWORK_CODE_IDX].uptr; + X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][ENB_MNC_DIGIT_LENGTH].u8ptr; + AssertFatal(X2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3 + || X2AP_REGISTER_ENB_REQ(msg_p).mnc < 100, + "MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n", + X2AP_REGISTER_ENB_REQ(msg_p).mnc); + /* CC params */ + config_getlist(&CCsParamList, NULL, 0, aprefix); + X2AP_REGISTER_ENB_REQ (msg_p).num_cc = CCsParamList.numelt; + + if (CCsParamList.numelt > 0) { + //char ccspath[MAX_OPTNAME_SIZE*2 + 16]; + for (J = 0; J < CCsParamList.numelt ; J++) { + sprintf(aprefix, "%s.[%i].%s.[%i]", ENB_CONFIG_STRING_ENB_LIST, k, ENB_CONFIG_STRING_COMPONENT_CARRIERS, J); + config_get(CCsParams, sizeof(CCsParams)/sizeof(paramdef_t), aprefix); + X2AP_REGISTER_ENB_REQ (msg_p).eutra_band[J] = ccparams_lte.eutra_band; + X2AP_REGISTER_ENB_REQ (msg_p).downlink_frequency[J] = (uint32_t) ccparams_lte.downlink_frequency; + X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = (unsigned int) ccparams_lte.uplink_frequency_offset; + X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= ccparams_lte.Nid_cell; + + if (ccparams_lte.Nid_cell>503) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for Nid_cell choice: 0...503 !\n", + RC.config_file_name, k, ccparams_lte.Nid_cell); + } + + X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= ccparams_lte.N_RB_DL; + + if ((ccparams_lte.N_RB_DL!=6) && (ccparams_lte.N_RB_DL!=15) && (ccparams_lte.N_RB_DL!=25) && (ccparams_lte.N_RB_DL!=50) && (ccparams_lte.N_RB_DL!=75) && (ccparams_lte.N_RB_DL!=100)) { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for N_RB_DL choice: 6,15,25,50,75,100 !\n", + RC.config_file_name, k, ccparams_lte.N_RB_DL); + } + + if (strcmp(ccparams_lte.frame_type, "FDD") == 0) { + X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = FDD; + } else if (strcmp(ccparams_lte.frame_type, "TDD") == 0) { + X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD; + } else { + AssertFatal (0, + "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for frame_type choice: FDD or TDD !\n", + RC.config_file_name, k, ccparams_lte.frame_type); + } + + X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_DL[J] = to_earfcn_DL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency, ccparams_lte.N_RB_DL); + X2AP_REGISTER_ENB_REQ (msg_p).fdd_earfcn_UL[J] = to_earfcn_UL(ccparams_lte.eutra_band, ccparams_lte.downlink_frequency + ccparams_lte.uplink_frequency_offset, ccparams_lte.N_RB_DL); + } + } + + sprintf(aprefix,"%s.[%i]",ENB_CONFIG_STRING_ENB_LIST,k); + config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix); + AssertFatal(X2ParamList.numelt <= X2AP_MAX_NB_ENB_IP_ADDRESS, + "value of X2ParamList.numelt %d must be lower than X2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase X2AP_MAX_NB_ENB_IP_ADDRESS\n", + X2ParamList.numelt,X2AP_MAX_NB_ENB_IP_ADDRESS); + X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 = 0; + + for (l = 0; l < X2ParamList.numelt; l++) { + X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 += 1; + strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr)); + strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6_address,*(X2ParamList.paramarray[l][ENB_X2_IPV6_ADDRESS_IDX].strptr)); + + 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].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; + } 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].ipv6 = 1; + } + } + + // SCTP SETTING + X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; + X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; if (EPC_MODE_ENABLED) { - sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG); - config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); - X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr); - X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr); - } - - sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - // NETWORK_INTERFACES - config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); - X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C = (uint32_t)*(NETParams[ENB_PORT_FOR_X2C_IDX].uptr); - - if ((NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr == NULL) || (X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C == 0)) { - LOG_E(RRC,"Add eNB IPv4 address and/or port for X2C in the CONF file!\n"); - exit(1); + sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_SCTP_CONFIG); + config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix); + X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[ENB_SCTP_INSTREAMS_IDX].uptr); + X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[ENB_SCTP_OUTSTREAMS_IDX].uptr); } - cidr = *(NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr); - address = strtok(cidr, "/"); - X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv6 = 0; - X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4 = 1; - strcpy(X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4_address, address); - } - } + sprintf(aprefix,"%s.[%i].%s",ENB_CONFIG_STRING_ENB_LIST,k,ENB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); + // NETWORK_INTERFACES + config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix); + X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C = (uint32_t)*(NETParams[ENB_PORT_FOR_X2C_IDX].uptr); + + if ((NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr == NULL) || (X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C == 0)) { + LOG_E(RRC,"Add eNB IPv4 address and/or port for X2C in the CONF file!\n"); + exit(1); + } + + cidr = *(NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr); + address = strtok(cidr, "/"); + X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv6 = 0; + X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4 = 1; + strcpy(X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4_address, address); + } + } } } } diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 1a334a36b9a3c32434c55b0800279119832cfd61..312edea2c17b751f84d266bb3392c9475886ffe3 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -883,7 +883,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, rntiP, -1 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) , - -1 + 0 #endif )) == -1) { diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 38fc7b7262ced788cd273a94fa97c96acea93abd..22a9332a58c5842e81ac89ce1d1e71c6a99b786d 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -343,7 +343,8 @@ typedef enum HO_STATE_e { HO_COMPLETE, // initiated by the target eNB HO_REQUEST, HO_ACK, - HO_CONFIGURED + HO_CONFIGURED, + HO_RELEASE } HO_STATE_t; typedef enum SL_TRIGGER_e { @@ -450,12 +451,14 @@ typedef struct HANDOVER_INFO_s { HO_STATE_t state; //current state of handover uint32_t modid_s; //module_idP of serving 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_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_Context_t as_context; /* They are mandatory for HO */ uint8_t buf[RRC_BUF_SIZE]; /* ASN.1 encoded handoverCommandMessage */ int size; /* size of above message in bytes */ + int x2_id; /* X2AP UE ID in the target eNB */ } HANDOVER_INFO; #define RRC_HEADER_SIZE_MAX 64 diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 3503956b108746292fbb28eacea58b1fe0c821d4..95048d763ea079ab28fd02129d8d697c4e8d28a6 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -105,6 +105,9 @@ extern uint16_t two_tier_hexagonal_cellIds[7]; mui_t rrc_eNB_mui = 0; 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 openair_rrc_on( @@ -778,7 +781,8 @@ rrc_eNB_free_mem_UE_context( ue_context_pP->ue_context.measGapConfig = NULL; }*/ 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; } @@ -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", enb_mod_idP, 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); +#endif // send cause 21: radio connection with ue lost /* 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 @@ -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", enb_mod_idP, 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); +#endif // send cause 20: user inactivity return; } @@ -1035,7 +1043,9 @@ rrc_eNB_process_RRCConnectionSetupComplete( if (EPC_MODE_ENABLED == 1) { // Forward message to S1AP layer +#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_NAS_FIRST_REQ(ctxt_pP, ue_context_pP, rrcConnectionSetupComplete); +#endif } else { // RRC loop back (no S1AP), send SecurityModeCommand to UE rrc_eNB_generate_SecurityModeCommand(ctxt_pP, ue_context_pP); @@ -3800,6 +3810,9 @@ rrc_eNB_process_MeasurementReport( int neighboring_cells=-1; int ncell_index = 0; 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_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti)); @@ -3917,8 +3930,7 @@ rrc_eNB_process_MeasurementReport( ue_context_pP, X2AP_HANDOVER_REQ(msg).rrc_buffer, &X2AP_HANDOVER_REQ(msg).rrc_buffer_size); - X2AP_HANDOVER_REQ(msg).source_rnti = ctxt_pP->rnti; - X2AP_HANDOVER_REQ(msg).old_eNB_ue_x2ap_id = 0; + X2AP_HANDOVER_REQ(msg).rnti = ctxt_pP->rnti; X2AP_HANDOVER_REQ(msg).target_physCellId = measResults2->measResultNeighCells->choice. measResultListEUTRA.list.array[ncell_index]->physCellId; X2AP_HANDOVER_REQ(msg).ue_gummei.mcc = ue_context_pP->ue_context.ue_gummei.mcc; @@ -3929,9 +3941,11 @@ rrc_eNB_process_MeasurementReport( // 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).security_capabilities = ue_context_pP->ue_context.security_capabilities; - memcpy (X2AP_HANDOVER_REQ(msg).kenb, - ue_context_pP->ue_context.kenb, - 32); + // compute 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, + 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).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; @@ -3973,114 +3987,15 @@ rrc_eNB_generate_HandoverPreparationInformation( *_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) { struct rrc_eNB_ue_context_s *ue_context_target_p = NULL; /* TODO: get proper UE rnti */ int rnti = taus() & 0xffff; int i; //global_rnti = rnti; - //HandoverPreparationInformation_t *ho = NULL; - //HandoverPreparationInformation_r8_IEs_t *ho_info; - //asn_dec_rval_t dec_rval; + LTE_HandoverPreparationInformation_t *ho = NULL; + LTE_HandoverPreparationInformation_r8_IEs_t *ho_info; + asn_dec_rval_t dec_rval; ue_context_target_p = rrc_eNB_get_ue_context(RC.rrc[mod_id], rnti); if (ue_context_target_p != NULL) { @@ -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); LOG_D(RRC, "eNB %d: Created new UE context uid %u\n", mod_id, ue_context_target_p->local_uid); ue_context_target_p->ue_context.handover_info = CALLOC(1, sizeof(*(ue_context_target_p->ue_context.handover_info))); - //ue_context_target_p->ue_context.handover_info->source_x2id = m->source_x2id; ue_context_target_p->ue_context.Status = RRC_HO_EXECUTION; ue_context_target_p->ue_context.handover_info->state = HO_ACK; - /* TODO: remove this hack */ - //ue_context_target_p->ue_context.handover_info->modid_t = mod_id; - ue_context_target_p->ue_context.handover_info->modid_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; + ue_context_target_p->ue_context.handover_info->x2_id = m->x2_id; + ue_context_target_p->ue_context.handover_info->assoc_id = m->target_assoc_id; memset (ue_context_target_p->ue_context.nh, 0, 32); ue_context_target_p->ue_context.nh_ncc = -1; 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.security_capabilities.encryption_algorithms = m->security_capabilities.encryption_algorithms; ue_context_target_p->ue_context.security_capabilities.integrity_algorithms = m->security_capabilities.integrity_algorithms; - /* + dec_rval = uper_decode(NULL, - &asn_DEF_HandoverPreparationInformation, + &asn_DEF_LTE_HandoverPreparationInformation, (void **)&ho, m->rrc_buffer, 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 || - ho->criticalExtensions.present != HandoverPreparationInformation__criticalExtensions_PR_c1 || - ho->criticalExtensions.choice.c1.present != HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8) { + ho->criticalExtensions.present != LTE_HandoverPreparationInformation__criticalExtensions_PR_c1 || + ho->criticalExtensions.choice.c1.present != LTE_HandoverPreparationInformation__criticalExtensions__c1_PR_handoverPreparationInformation_r8) { LOG_E(RRC, "could not decode Handover Preparation\n"); abort(); } @@ -4132,13 +4047,13 @@ void rrc_eNB_process_handoverPreparationInformation(int mod_id, x2ap_handover_re if (ue_context_target_p->ue_context.UE_Capability) { 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 = 0; } 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, ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.buf, 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 ue_context_target_p->ue_context.UE_Capability_size = ho_info->ue_RadioAccessCapabilityInfo.list.array[0]->ueCapabilityRAT_Container.size; 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)) { 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 = 0; } - */ + 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.mme_ue_s1ap_id = m->mme_ue_s1ap_id; @@ -4211,27 +4126,43 @@ void rrc_eNB_process_handoverCommand( ue_context->ue_context.handover_info->size = size; } -#if 0 -//----------------------------------------------------------------------------- -void -rrc_eNB_process_handoverPreparationInformation( - const protocol_ctxt_t *const ctxt_pP, - rrc_eNB_ue_context_t *const ue_context_pP -) -//----------------------------------------------------------------------------- -{ - 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)); - LOG_I(RRC, - "[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); - rrc_eNB_generate_RRCConnectionReconfiguration_handover( - ctxt_pP, - ue_context_pP, - NULL, - 0); +#if defined(ENABLE_USE_MME) +void rrc_eNB_handover_ue_context_release( +protocol_ctxt_t *const ctxt_pP, +struct rrc_eNB_ue_context_s *ue_context_p) { + int e_rab = 0; + //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; + + //msg_release_p = itti_alloc_new_message(TASK_RRC_ENB, S1AP_UE_CONTEXT_RELEASE); + //itti_send_msg_to_task(TASK_S1AP, ctxt_pP->module_id, msg_release_p); + s1ap_ue_context_release(ctxt_pP->instance, ue_context_p->ue_context.eNB_ue_s1ap_id); + + //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(>PV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p), 0, sizeof(GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p))); + + 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); + } } -#endif +#endif /* defined(ENABLE_USE_MME) */ void check_handovers( @@ -4239,7 +4170,6 @@ check_handovers( ) //----------------------------------------------------------------------------- { - 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; @@ -4256,19 +4186,15 @@ check_handovers( LOG_I(RRC, "[eNB %d] Frame %d : Logical Channel UL-DCCH, processing RRCHandoverPreparationInformation, sending RRCConnectionReconfiguration to UE %d \n", ctxt_pP->module_id, ctxt_pP->frame, ue_context_p->ue_context.rnti); - 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"); + rrc_data_req( + ctxt_pP, + 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); + 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); } @@ -4282,10 +4208,10 @@ check_handovers( 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); 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).target_mod_id = ue_context_p->ue_context.handover_info->modid_t; - //X2AP_HANDOVER_REQ_ACK(msg).source_x2id = ue_context_p->ue_context.handover_info->source_x2id; + + X2AP_HANDOVER_REQ_ACK(msg).rnti = ue_context_p->ue_context.rnti; + X2AP_HANDOVER_REQ_ACK(msg).x2_id_target = ue_context_p->ue_context.handover_info->x2_id; + X2AP_HANDOVER_REQ_ACK(msg).source_assoc_id = ue_context_p->ue_context.handover_info->assoc_id; /* Call admission control not implemented yet */ X2AP_HANDOVER_REQ_ACK(msg).nb_e_rabs_tobesetup = ue_context_p->ue_context.setup_e_rabs; @@ -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 rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ctxt_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 , 0, 0 #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) 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 @@ -7709,9 +7586,11 @@ rrc_eNB_decode_dcch( if (EPC_MODE_ENABLED) { if (EPC_MODE_ENABLED == 1) { +#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP, ue_context_p, ul_dcch_msg); +#endif } } else { ue_context_p->ue_context.nb_of_e_rabs = 1; @@ -7759,9 +7638,11 @@ rrc_eNB_decode_dcch( sdu_sizeP); if (EPC_MODE_ENABLED == 1) { +#if defined(ENABLE_USE_MME) rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP, ue_context_p, ul_dcch_msg); +#endif } break; @@ -7898,100 +7779,350 @@ void rrc_enb_init(void) { } //----------------------------------------------------------------------------- -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; - // 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); - 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; +void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) +{ + int32_t current_timestamp_ms = 0; + int32_t ref_timestamp_ms = 0; + struct timeval ts; + struct rrc_eNB_ue_context_s *ue_context_p = NULL; + struct rrc_eNB_ue_context_s *ue_to_be_removed = NULL; +#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; - case MESSAGE_TEST: - LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p); - break; + 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); + } + } - /* 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 (ue_context_p->ue_context.ul_failure_timer > 0) { + ue_context_p->ue_context.ul_failure_timer++; - 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; + 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 } + } - 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; + if (ue_context_p->ue_context.ue_release_timer_s1 > 0) { + ue_context_p->ue_context.ue_release_timer_s1++; - /* 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 (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 (result != EXIT_SUCCESS) { - LOG_I(RRC, "Failed to free memory (%d)!\n",result); - break; - } + if (EPC_MODE_ENABLED) + rrc_eNB_generate_RRCConnectionRelease(ctxt_pP, ue_context_p); + else + ue_to_be_removed = ue_context_p; - break; + 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) - /* Messages from S1AP */ - case S1AP_DOWNLINK_NAS: - rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_eNB_mui); - break; + if (ue_context_p->ue_context.ue_release_timer_rrc > 0) { + ue_context_p->ue_context.ue_release_timer_rrc++; - case S1AP_INITIAL_CONTEXT_SETUP_REQ: - rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance); - break; + 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 + } + } - case S1AP_UE_CTXT_MODIFICATION_REQ: - rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(msg_p, msg_name_p, instance); - break; +#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 - case S1AP_PAGING_IND: - LOG_D(RRC, "[eNB %d] Received Paging message from S1AP: %s\n", instance, msg_name_p); - rrc_eNB_process_PAGING_IND(msg_p, msg_name_p, instance); + 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(>PV1U_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) { + LOG_I(RRC, "Failed to free memory (%d)!\n",result); + break; + } + + break; + + /* Messages from S1AP */ + case S1AP_DOWNLINK_NAS: + rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_eNB_mui); + break; + + case S1AP_INITIAL_CONTEXT_SETUP_REQ: + rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p, msg_name_p, instance); + break; + + case S1AP_UE_CTXT_MODIFICATION_REQ: + rrc_eNB_process_S1AP_UE_CTXT_MODIFICATION_REQ(msg_p, msg_name_p, instance); + break; + + case S1AP_PAGING_IND: + LOG_D(RRC, "[eNB %d] Received Paging message from S1AP: %s\n", instance, msg_name_p); + rrc_eNB_process_PAGING_IND(msg_p, msg_name_p, instance); break; case S1AP_E_RAB_SETUP_REQ: @@ -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); 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 */ - //LOG_I(RRC, "[eNB %d] Received message %s, not processed because procedure not synched\n", - //instance, msg_name_p); - if (rrc_eNB_get_ue_context(RC.rrc[instance], GTPV1U_ENB_DELETE_TUNNEL_RESP(msg_p).rnti) - && 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; + if (ue != NULL + && ue->ue_context.ue_release_timer_rrc > 0 + && (ue->ue_context.handover_info == NULL || ue->ue_context.handover_info->state != HO_RELEASE)) { + ue->ue_context.ue_release_timer_rrc = ue->ue_context.ue_release_timer_thres_rrc; } break; + } case S1AP_PATH_SWITCH_REQ_ACK: 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) { break; 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, - ctxt.frame, ctxt.subframe); + LOG_I(RRC, "[eNB %d] target eNB Receives X2 HO Req %s\n", instance, msg_name_p); rrc_eNB_process_handoverPreparationInformation(instance, &X2AP_HANDOVER_REQ(msg_p)); break; case X2AP_HANDOVER_REQ_ACK: { struct rrc_eNB_ue_context_s *ue_context_p = NULL; - ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], ctxt.rnti); - LOG_I(RRC, "[eNB %d] source eNB receives the X2 HO ACK %s at frame %d subframe %d \n", instance, msg_name_p, - ctxt.frame,ctxt.subframe); + ue_context_p = rrc_eNB_get_ue_context(RC.rrc[instance], X2AP_HANDOVER_REQ_ACK(msg_p).rnti); + if (ue_context_p == NULL) { + /* 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); if (ue_context_p->ue_context.handover_info->state != HO_REQUEST) abort(); @@ -8053,12 +8187,28 @@ void *rrc_enb_process_itti_msg(void *notUsed) { 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 */ case RRC_CONFIGURATION_REQ: 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)); break; + case RRC_SUBFRAME_PROCESS: + rrc_subframe_process(&RRC_SUBFRAME_PROCESS(msg_p).ctxt, RRC_SUBFRAME_PROCESS(msg_p).CC_id); + break; + default: LOG_E(RRC, "[eNB %d] Received unexpected message %s\n", instance, msg_name_p); break; @@ -8434,236 +8584,11 @@ rrc_rx_tx( ) //----------------------------------------------------------------------------- { - int32_t current_timestamp_ms = 0; - int32_t ref_timestamp_ms = 0; - struct timeval ts; - struct rrc_eNB_ue_context_s *ue_context_p = NULL; - struct rrc_eNB_ue_context_s *ue_to_be_removed = NULL; -#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(>PV1U_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); + MessageDef *message_p; + message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_SUBFRAME_PROCESS); + RRC_SUBFRAME_PROCESS(message_p).ctxt = *ctxt_pP; + RRC_SUBFRAME_PROCESS(message_p).CC_id = CC_id; + itti_send_msg_to_task(TASK_RRC_ENB, ctxt_pP->module_id, message_p); return RRC_OK; } diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index e07a4bd5d2c43cb85427975113ffad0e1659ff41..82818fcd1ed8c3ec226ba0d718d8fa02dfdc61e3 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -426,7 +426,7 @@ static e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_inte *\param security_capabilities The security capabilities received from S1AP. *\return TRUE if at least one algorithm has been changed else FALSE. */ -static int +int rrc_eNB_process_security( const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, @@ -477,7 +477,7 @@ rrc_eNB_process_security( *\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, rrc_eNB_ue_context_t *const ue_context_pP, uint8_t *security_key_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; 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, - 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].gtp_teid, 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, // NN: add conditions for e_rabs_failed 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", - 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_RRC_ENB, MSC_S1AP_ENB, @@ -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; /* 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; - i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg - i++) { - // assume that we are releasing all the DRBs - ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_TORELEASE; + i < ue_context_p->ue_context.setup_e_rabs; // go over total number of e_rabs received through x2_ho_req msg + i++) { + // assume that we are releasing all the DRBs + 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)); - //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 // the index for the rec - for (i = 0; - i < 1;//nb_e_rabs_tobeswitched; // go over total number of e_rabs received through x2_ho_req msg - 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 */ - ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_REESTABLISHED; - //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.sgw_addr= S1AP_PATH_SWITCH_REQ_ACK (msg_p).e_rabs_tobeswitched[i].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; - /* Tunnel must have been already created in X2_HO_REQ procedure */ + if (nb_e_rabs_tobeswitched>0) { + int e_rab_switch_index=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++) { + /* Harmonize with enb_gtp_teid, enb_gtp_addrs, and enb_gtp_rbi vars in the top level structure */ + 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[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[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[e_rab_switch_index].gtp_teid; + 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.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)); - - for (i = 0; - i < ue_context_p->ue_context.nb_release_of_e_rabs; - i++) { - 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; - 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.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; + i < ue_context_p->ue_context.setup_e_rabs; + 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); + ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_TORELEASE; + 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){ 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; /* this could also be done through ITTI message */ @@ -2069,9 +2087,59 @@ int rrc_eNB_process_S1AP_PATH_SWITCH_REQ_ACK (MessageDef *msg_p, const char *msg /* Security key */ ue_context_p->ue_context.next_hop_chain_count=S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_hop_chain_count; memcpy ( ue_context_p->ue_context.next_security_key, - S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key, - SECURITY_KEY_LENGTH); + S1AP_PATH_SWITCH_REQ_ACK (msg_p).next_security_key, + SECURITY_KEY_LENGTH); + + rrc_eNB_send_X2AP_UE_CONTEXT_RELEASE(&ctxt, ue_context_p); + 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; +} diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.h b/openair2/RRC/LTE/rrc_eNB_S1AP.h index 33a0caabc8923fd533d101e6f2645c815436abda..da63fc68a36ab17ec304bc6300015a1e852831b3 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.h +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.h @@ -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); 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_ */ diff --git a/openair2/X2AP/x2ap_eNB.c b/openair2/X2AP/x2ap_eNB.c index db29f32d7ba839fb8f5d98627b815feb902c9a8e..c05495a0c414c79bb5ee1bcf20da02065c9682f8 100644 --- a/openair2/X2AP/x2ap_eNB.c +++ b/openair2/X2AP/x2ap_eNB.c @@ -40,6 +40,7 @@ #include "x2ap_eNB_handler.h" #include "x2ap_eNB_generate_messages.h" #include "x2ap_common.h" +#include "x2ap_ids.h" #include "queue.h" #include "assertions.h" @@ -79,6 +80,11 @@ static void x2ap_eNB_handle_handover_req_ack(instance_t instance, 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 void x2ap_eNB_handle_sctp_data_ind(instance_t instance, sctp_data_ind_t *sctp_data_ind) { int result; @@ -130,7 +136,7 @@ void x2ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa sctp_new_association_resp->sctp_state, instance, 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); return; } @@ -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->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++) { new_instance->eutra_band[i] = x2ap_register_eNB->eutra_band[i]; new_instance->downlink_frequency[i] = x2ap_register_eNB->downlink_frequency[i]; @@ -371,30 +379,31 @@ static void x2ap_eNB_handle_handover_req(instance_t instance, x2ap_handover_req_t *x2ap_handover_req) { - /* TODO: remove this hack (the goal is to find the correct - * eNodeB structure for the target) - we need a proper way for RRC - * and X2AP to identify eNodeBs - * RRC knows about mod_id and X2AP knows about eNB_id (eNB_ID in - * the configuration file) - * as far as I understand.. CROUX - */ x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *target; + 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); - //instance_p = x2ap_eNB_get_instance(instance); - //DevAssert(instance_p != NULL); - - target = x2ap_is_eNB_id_in_list(instance_p->eNB_id); + target = x2ap_is_eNB_pci_in_list(target_pci); DevAssert(target != NULL); - /* store rnti at index 0 */ - //x2id_to_source_rnti[0] = x2ap_handover_req->source_rnti; - x2ap_eNB_generate_x2_handover_request(target, x2ap_handover_req); + /* allocate x2ap ID */ + id_manager = &instance_p->id_manager; + 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 @@ -410,17 +419,49 @@ void x2ap_eNB_handle_handover_req_ack(instance_t instance, */ x2ap_eNB_instance_t *instance_p; 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); 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); - x2ap_eNB_generate_x2_handover_request_ack(target, x2ap_handover_req_ack); - //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); + x2ap_eNB_generate_x2_ue_context_release(instance_p, target, x2ap_ue_context_release); + + /* 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) { @@ -454,6 +495,11 @@ void *x2ap_task(void *arg) { &X2AP_HANDOVER_REQ_ACK(received_msg)); 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: x2ap_eNB_handle_sctp_init_msg_multi_cnf(ITTI_MESSAGE_GET_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_init_msg_multi_cnf); diff --git a/openair2/X2AP/x2ap_eNB_decoder.c b/openair2/X2AP/x2ap_eNB_decoder.c index 553cf8e559c1d38b3969e33a2e21384c6401a326..a5b19fe2ccac109bd10256de1be489cb494ca75f 100644 --- a/openair2/X2AP/x2ap_eNB_decoder.c +++ b/openair2/X2AP/x2ap_eNB_decoder.c @@ -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); X2AP_INFO("x2ap_eNB_decode_initiating_message!\n"); 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: X2AP_ERROR("Unknown procedure ID (%d) for initiating message\n", diff --git a/openair2/X2AP/x2ap_eNB_defs.h b/openair2/X2AP/x2ap_eNB_defs.h index a5558c42a5307d7f55c64be8eca6cf788e37b3c8..3356a101b4e632927cc72d9397f850d1a75885ca 100644 --- a/openair2/X2AP/x2ap_eNB_defs.h +++ b/openair2/X2AP/x2ap_eNB_defs.h @@ -33,6 +33,8 @@ #include "sctp_eNB_defs.h" +#include "x2ap_ids.h" + #ifndef X2AP_ENB_DEFS_H_ #define X2AP_ENB_DEFS_H_ @@ -114,6 +116,10 @@ typedef struct x2ap_eNB_data_s { /* SCTP association id */ int32_t assoc_id; + /* Nid cells */ + uint32_t Nid_cell[MAX_NUM_CCs]; + int num_cc; + /* Only meaningfull in virtual mode */ struct x2ap_eNB_instance_s *x2ap_eNB_instance; } x2ap_eNB_data_t; @@ -163,7 +169,6 @@ typedef struct x2ap_eNB_instance_s { uint32_t downlink_frequency[MAX_NUM_CCs]; int32_t uplink_frequency_offset[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]; lte_frame_type_t frame_type[MAX_NUM_CCs]; uint32_t fdd_earfcn_DL[MAX_NUM_CCs]; @@ -177,6 +182,8 @@ typedef struct x2ap_eNB_instance_s { uint16_t sctp_out_streams; uint32_t enb_port_for_X2C; int multi_sd; + + x2ap_id_manager id_manager; } x2ap_eNB_instance_t; typedef struct { diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.c b/openair2/X2AP/x2ap_eNB_generate_messages.c index 76d6053b59a1fb3a242a8730e3dface21a4eecda..c13469d5d4bfc209c523c6b063620a4e6d5c8067 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.c +++ b/openair2/X2AP/x2ap_eNB_generate_messages.c @@ -35,6 +35,7 @@ #include "x2ap_eNB_generate_messages.h" #include "x2ap_eNB_encoder.h" #include "x2ap_eNB_decoder.h" +#include "x2ap_ids.h" #include "x2ap_eNB_itti_messaging.h" @@ -180,7 +181,7 @@ int x2ap_eNB_generate_x2_setup_request( 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_X2SetupResponse_t *out; @@ -189,18 +190,12 @@ int x2ap_eNB_generate_x2_setup_response(x2ap_eNB_data_t *x2ap_eNB_data_p) ServedCells__Member *servedCellMember; X2AP_GU_Group_ID_t *gu; - x2ap_eNB_instance_t *instance_p; - uint8_t *buffer; uint32_t len; 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(x2ap_eNB_data_p != NULL); /* Prepare the X2AP message to encode */ memset(&pdu, 0, sizeof(pdu)); @@ -414,8 +409,8 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, return 0; } -int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, - x2ap_handover_req_t *x2ap_handover_req) +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, int ue_id) { X2AP_X2AP_PDU_t pdu; @@ -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_LastVisitedCell_Item_t *lastVisitedCell_Item; - x2ap_eNB_instance_t *instance_p; - uint8_t *buffer; uint32_t len; 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(x2ap_eNB_data_p != NULL); /* Prepare the X2AP handover message to encode */ memset(&pdu, 0, sizeof(pdu)); @@ -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->criticality = X2AP_Criticality_reject; 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); /* mandatory */ @@ -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; MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, &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); /* mandatory */ @@ -576,7 +564,7 @@ int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, 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) { @@ -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_E_RABs_Admitted_ItemIEs_t *e_RABS_Admitted_ItemIEs; X2AP_E_RABs_Admitted_Item_t *e_RABs_Admitted_Item; - - x2ap_eNB_instance_t *instance_p; + int ue_id; + int id_source; + int id_target; uint8_t *buffer; uint32_t len; int ret = 0; + DevAssert(instance_p != NULL); DevAssert(x2ap_eNB_data_p != NULL); - /* get the eNB instance */ - instance_p = x2ap_eNB_data_p->x2ap_eNB_instance; - - DevAssert(instance_p != NULL); + 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; /* Prepare the X2AP handover message to encode */ 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, ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID; ie->criticality = X2AP_Criticality_ignore; 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); /* mandatory */ ie = (X2AP_HandoverRequestAcknowledge_IEs_t *)calloc(1, sizeof(X2AP_HandoverRequestAcknowledge_IEs_t)); ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID; ie->criticality = X2AP_Criticality_ignore; - ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID; - ie->value.choice.UE_X2AP_ID = 0; + ie->value.present = X2AP_HandoverRequestAcknowledge_IEs__value_PR_UE_X2AP_ID_1; + ie->value.choice.UE_X2AP_ID_1 = id_target; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* mandatory */ @@ -668,25 +657,30 @@ int x2ap_eNB_generate_x2_handover_request_ack (x2ap_eNB_data_t *x2ap_eNB_data_p, 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_UEContextRelease_t *out; X2AP_UEContextRelease_IEs_t *ie; - - x2ap_eNB_instance_t *instance_p; + int ue_id; + int id_source; + int id_target; uint8_t *buffer; uint32_t len; int ret = 0; + DevAssert(instance_p != NULL); DevAssert(x2ap_eNB_data_p != NULL); - /* get the eNB instance */ - instance_p = x2ap_eNB_data_p->x2ap_eNB_instance; - - DevAssert(instance_p != NULL); + 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); + } + 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 */ 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) ie->id = X2AP_ProtocolIE_ID_id_Old_eNB_UE_X2AP_ID; ie->criticality = X2AP_Criticality_reject; 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); /* mandatory */ ie = (X2AP_UEContextRelease_IEs_t *)calloc(1, sizeof(X2AP_UEContextRelease_IEs_t)); ie->id = X2AP_ProtocolIE_ID_id_New_eNB_UE_X2AP_ID; ie->criticality = X2AP_Criticality_reject; - ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID; - ie->value.choice.UE_X2AP_ID = 0; + ie->value.present = X2AP_UEContextRelease_IEs__value_PR_UE_X2AP_ID_1; + ie->value.choice.UE_X2AP_ID_1 = id_target; ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); if (x2ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { diff --git a/openair2/X2AP/x2ap_eNB_generate_messages.h b/openair2/X2AP/x2ap_eNB_generate_messages.h index 9028d8cd054e9d78388e7cf17967d6b00bdbee7f..059d213277599a465876f3ebfb4c6b5fba242ce2 100644 --- a/openair2/X2AP/x2ap_eNB_generate_messages.h +++ b/openair2/X2AP/x2ap_eNB_generate_messages.h @@ -35,7 +35,7 @@ int x2ap_eNB_generate_x2_setup_request(x2ap_eNB_instance_t *instance_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, uint32_t assoc_id, @@ -47,12 +47,13 @@ int x2ap_eNB_set_cause (X2AP_Cause_t * cause_p, X2AP_Cause_PR cause_type, long cause_value); -int x2ap_eNB_generate_x2_handover_request (x2ap_eNB_data_t *x2ap_eNB_data_p, - x2ap_handover_req_t *x2ap_handover_req); +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, 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); -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_ */ diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 52b14f1d236510804626c9ee889383f19f306e78..9da92787416a1a24f5453ad9b07541b2737c3670 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -36,6 +36,7 @@ #include "x2ap_eNB_defs.h" #include "x2ap_eNB_handler.h" #include "x2ap_eNB_decoder.h" +#include "x2ap_ids.h" #include "x2ap_eNB_management_procedures.h" #include "x2ap_eNB_generate_messages.h" @@ -71,6 +72,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance, uint32_t stream, 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 */ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { { x2ap_eNB_handle_handover_preparation, x2ap_eNB_handle_handover_response, 0 }, /* handoverPreparation */ @@ -78,7 +85,7 @@ x2ap_message_decoded_callback x2ap_messages_callback[][3] = { { 0, 0, 0 }, /* loadIndication */ { 0, 0, 0 }, /* errorIndication */ { 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 */ { 0, 0, 0 }, /* reset */ { 0, 0, 0 }, /* eNBConfigurationUpdate */ @@ -112,7 +119,7 @@ static char *x2ap_direction_String[] = { 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) { /* 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 if (enb_desc_p->state == X2AP_ENB_STATE_CONNECTED) { 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 */ - 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 (enb_desc_p->x2ap_eNB_instance->x2_target_enb_associated_nb == 0) { + if (instance_p->x2_target_enb_associated_nb == 0) { MessageDef *message_p; message_p = itti_alloc_new_message(TASK_X2AP, X2AP_DEREGISTERED_ENB_IND); 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 { /* Check that at least one setup message is pending */ - DevCheck(enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb > 0, - enb_desc_p->x2ap_eNB_instance->instance, - enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb, 0); + DevCheck(instance_p->x2_target_enb_pending_nb > 0, + instance_p->instance, + 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 */ - 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 (enb_desc_p->x2ap_eNB_instance->x2_target_enb_pending_nb == 0) { + if (instance_p->x2_target_enb_pending_nb == 0) { MessageDef *message_p; 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; - itti_send_msg_to_task(TASK_ENB_APP, enb_desc_p->x2ap_eNB_instance->instance, message_p); + X2AP_REGISTER_ENB_CNF(message_p).nb_x2 = instance_p->x2_target_enb_associated_nb; + 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, X2AP_X2SetupRequest_IEs_t *ie; ServedCells__Member *servedCellMember; + x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; uint32_t eNB_id = 0; @@ -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); - DevAssert(x2ap_eNB_data->x2ap_eNB_instance != NULL); - x2ap_eNB_generate_x2_setup_failure (x2ap_eNB_data->x2ap_eNB_instance->instance, + x2ap_eNB_generate_x2_setup_failure (instance, assoc_id, X2AP_Cause_PR_protocol, X2AP_CauseProtocol_unspecified, @@ -374,19 +381,22 @@ x2ap_eNB_handle_x2_setup_request(instance_t instance, /* Set proper pci */ X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupRequest_IEs_t, ie, x2SetupRequest, X2AP_ProtocolIE_ID_id_ServedCells, true); - if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); 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++) { 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 @@ -400,6 +410,7 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, X2AP_X2SetupResponse_IEs_t *ie; ServedCells__Member *servedCellMember; + x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; uint32_t eNB_id = 0; @@ -478,15 +489,16 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, /* Set proper pci */ X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, X2AP_ProtocolIE_ID_id_ServedCells, true); - if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); 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++) { 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, * Mark the association as connected. */ 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; } @@ -512,6 +528,7 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, X2AP_X2SetupFailure_t *x2SetupFailure; X2AP_X2SetupFailure_IEs_t *ie; + x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; DevAssert(pdu != NULL); @@ -552,7 +569,11 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, } 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; } @@ -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_Item_t *e_RABs_ToBeSetup_Item; + x2ap_eNB_instance_t *instance_p; x2ap_eNB_data_t *x2ap_eNB_data; MessageDef *msg; + int ue_id; DevAssert (pdu != NULL); x2HandoverRequest = &pdu->choice.initiatingMessage.value.choice.HandoverRequest; @@ -587,19 +610,30 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, 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_HANDOVER_REQ); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, 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 ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); 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. //measResultListEUTRA.list.array[ncell_index]->physCellId; X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, @@ -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).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 = BIT_STRING_to_uint16(&ie->value.choice.UE_ContextInformation.uESecurityCapabilities.encryptionAlgorithms); X2AP_HANDOVER_REQ(msg).security_capabilities.integrity_algorithms = @@ -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*/) { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); } - memcpy(X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer, c->buf, c->size); - X2AP_HANDOVER_REQ_ACK(msg).rrc_buffer_size = c->size; + memcpy(X2AP_HANDOVER_REQ(msg).rrc_buffer, c->buf, 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; } @@ -688,8 +726,13 @@ int x2ap_eNB_handle_handover_response (instance_t instance, X2AP_HandoverRequestAcknowledge_t *x2HandoverRequestAck; X2AP_HandoverRequestAcknowledge_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; + int rnti; DevAssert (pdu != NULL); x2HandoverRequestAck = &pdu->choice.successfulOutcome.value.choice.HandoverRequestAcknowledge; @@ -705,12 +748,44 @@ int x2ap_eNB_handle_handover_response (instance_t instance, 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_HANDOVER_REQ_ACK); - /* TODO: fill the message */ - //extern int x2id_to_source_rnti[1]; - //X2AP_HANDOVER_REQ_ACK(m).source_x2id = x2HandoverRequestAck->old_eNB_UE_X2AP_ID; - //X2AP_HANDOVER_REQ_ACK(m).source_rnti = x2id_to_source_rnti[x2HandoverRequestAck->old_eNB_UE_X2AP_ID]; + + X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, + 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_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_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true); @@ -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); 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; } diff --git a/openair2/X2AP/x2ap_eNB_handler.h b/openair2/X2AP/x2ap_eNB_handler.h index e4dac14e8e637078880ac10dd25b442a81cce51f..402212f62d78e453777d4bfa40d5fda7dbd0a741 100644 --- a/openair2/X2AP/x2ap_eNB_handler.h +++ b/openair2/X2AP/x2ap_eNB_handler.h @@ -31,7 +31,7 @@ #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, const uint8_t * const data, const uint32_t data_length); diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.c b/openair2/X2AP/x2ap_eNB_management_procedures.c index 670581406b9e2190ac0233bd9b5b797fc66ef521..137bad40add81872cb8641270131f0f0f97cb345 100644 --- a/openair2/X2AP/x2ap_eNB_management_procedures.c +++ b/openair2/X2AP/x2ap_eNB_management_procedures.c @@ -169,23 +169,6 @@ x2ap_eNB_instance_t *x2ap_eNB_get_instance(instance_t instance) 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 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--; } +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) { diff --git a/openair2/X2AP/x2ap_eNB_management_procedures.h b/openair2/X2AP/x2ap_eNB_management_procedures.h index 80234159515f401f439b47ed0695b9223963cc69..bcad728aaaf328fd7b15965c229c6392eabb83b5 100644 --- a/openair2/X2AP/x2ap_eNB_management_procedures.h +++ b/openair2/X2AP/x2ap_eNB_management_procedures.h @@ -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_pci_get_instance(uint32_t pci); - uint16_t x2ap_eNB_fetch_add_global_cnx_id(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); 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, int32_t assoc_id, uint16_t cnx_id); diff --git a/openair2/X2AP/x2ap_ids.c b/openair2/X2AP/x2ap_ids.c new file mode 100644 index 0000000000000000000000000000000000000000..b5607821fe5d97ef6c026000236c738740134963 --- /dev/null +++ b/openair2/X2AP/x2ap_ids.c @@ -0,0 +1,92 @@ +/* + * 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; +} diff --git a/openair2/X2AP/x2ap_ids.h b/openair2/X2AP/x2ap_ids.h new file mode 100644 index 0000000000000000000000000000000000000000..2232308f73dd944cd578e327467edcd017d67e6d --- /dev/null +++ b/openair2/X2AP/x2ap_ids.h @@ -0,0 +1,47 @@ +/* + * 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_ */ diff --git a/openair3/SCTP/sctp_eNB_itti_messaging.c b/openair3/SCTP/sctp_eNB_itti_messaging.c index d2064c74c08671b215bbca98525ca9b58be91d47..9c24da73706a2331d00280371d94d6437ae1fafb 100644 --- a/openair3/SCTP/sctp_eNB_itti_messaging.c +++ b/openair3/SCTP/sctp_eNB_itti_messaging.c @@ -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); } -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) { 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 sctp_data_ind_p->buffer_length = buffer_length; 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, diff --git a/openair3/SCTP/sctp_eNB_itti_messaging.h b/openair3/SCTP/sctp_eNB_itti_messaging.h index 49d2056a3cc254975c18fe469554d50d07bd8379..b4f1a0ee692ce858ca7ca464cc08a4c8429645f8 100644 --- a/openair3/SCTP/sctp_eNB_itti_messaging.h +++ b/openair3/SCTP/sctp_eNB_itti_messaging.h @@ -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_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); int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance, diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index b0c18c36923b1e9a65e3c548258d8de1de024cb7..68fa34f810d98aa2c1bf2dbf4b9a42432d106ff9 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -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)); @@ -1003,7 +1008,7 @@ sctp_eNB_read_from_socket( sinfo.sinfo_assoc_id, sctp_cnx->sd, n, ntohs(addr.sin_port), 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, buffer, n, sinfo.sinfo_stream); }