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

This commit is contained in:
Raphael Defosseux
2019-03-07 16:54:34 +01:00
25 changed files with 1171 additions and 797 deletions
+1
View File
@@ -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)
+3
View File
@@ -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)
+8
View File
@@ -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_ */
+3
View File
@@ -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)
+22 -10
View File
@@ -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
View File
@@ -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);
}
}
}
}
}
+1 -1
View File
@@ -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)
{
+4 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+101 -33
View File
@@ -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;
}
+4
View File
@@ -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
View File
@@ -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);
+4
View File
@@ -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",
+8 -1
View File
@@ -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 {
+34 -40
View File
@@ -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) {
+6 -5
View File
@@ -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_ */
+191 -41
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+16 -17
View File
@@ -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);
+92
View File
@@ -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;
}
+47
View File
@@ -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_ */
+2 -2
View File
@@ -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,
+1 -1
View File
@@ -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,
+7 -2
View File
@@ -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);
}