Merge remote-tracking branch 'origin/x2' into develop_integration_2019_w10
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+151
-149
@@ -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_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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
+394
-469
File diff suppressed because it is too large
Load Diff
+101
-33
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
+68
-22
@@ -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_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);
|
||||
/* 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_get_eNB(NULL, source_assoc_id, 0);
|
||||
DevAssert(target != NULL);
|
||||
|
||||
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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user