From 63a5c693b436783bf35328aba30888bb2fe13f85 Mon Sep 17 00:00:00 2001 From: He Shanyun Date: Thu, 28 Nov 2019 10:25:13 +0900 Subject: [PATCH 01/15] modify decode error about supportedCodecList in NAS message --- openair3/NAS/COMMON/IES/SupportedCodecList.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair3/NAS/COMMON/IES/SupportedCodecList.c b/openair3/NAS/COMMON/IES/SupportedCodecList.c index 3a69eee366..15a2fecaa0 100644 --- a/openair3/NAS/COMMON/IES/SupportedCodecList.c +++ b/openair3/NAS/COMMON/IES/SupportedCodecList.c @@ -43,13 +43,17 @@ int decode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t CHECK_LENGTH_DECODER(len - decoded, ielen); supportedcodeclist->systemidentification = *(buffer + decoded); decoded++; + ielen--; supportedcodeclist->lengthofbitmap = *(buffer + decoded); decoded++; + ielen--; //IES_DECODE_U16(supportedcodeclist->codecbitmap, *(buffer + decoded)); IES_DECODE_U16(buffer, decoded, supportedcodeclist->codecbitmap); + ielen=ielen -2; #if defined (NAS_DEBUG) dump_supported_codec_list_xml(supportedcodeclist, iei); #endif + decoded = decoded + ielen; return decoded; } int encode_supported_codec_list(SupportedCodecList *supportedcodeclist, uint8_t iei, uint8_t *buffer, uint32_t len) From df17a8dd4f220aa9ba4c0ea0b5162939fdb1cbfb Mon Sep 17 00:00:00 2001 From: Wu Jing Date: Wed, 8 Jan 2020 16:50:16 +0900 Subject: [PATCH 02/15] merge NNSF feature based on v1.0.2 (cherry picked from commit b9e93a16379cf261502d9451b60bd787c07da64e) --- openair2/RRC/LTE/rrc_eNB_S1AP.c | 32 ++++++++--- openair3/S1AP/s1ap_eNB_defs.h | 2 + openair3/S1AP/s1ap_eNB_nas_procedures.c | 17 +++--- openair3/S1AP/s1ap_eNB_nnsf.c | 70 ++++++++++++++++++++++--- openair3/S1AP/s1ap_eNB_nnsf.h | 3 +- 5 files changed, 101 insertions(+), 23 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 4be9a50b32..b319491207 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -782,21 +782,37 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei; if (r_mme->plmn_Identity != NULL) { - if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count > 0)) { - /* Use first indicated PLMN MCC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[selected_plmn_identity]; + if ((r_mme->plmn_Identity->mcc != NULL) && (r_mme->plmn_Identity->mcc->list.count == 3)) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = (*r_mme->plmn_Identity->mcc->list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mcc->list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mcc->list.array[2] & 0xf); LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc, ue_context_pP->ue_context.rnti); } - - if (r_mme->plmn_Identity->mnc.list.count > 0) { - /* Use first indicated PLMN MNC if it is defined */ - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = *r_mme->plmn_Identity->mnc.list.array[selected_plmn_identity]; - LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u ue %x\n", + if(r_mme->plmn_Identity->mnc.list.count == 3) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 100 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[2] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 3; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", ctxt_pP->module_id, S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, + ue_context_pP->ue_context.rnti); + } + else if(r_mme->plmn_Identity->mnc.list.count == 2) + { + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = (*r_mme->plmn_Identity->mnc.list.array[0] & 0xf) * 10 + + (*r_mme->plmn_Identity->mnc.list.array[1] & 0xf); + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = 2; + LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MNC %u %udigit ue %x\n", + ctxt_pP->module_id, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len, ue_context_pP->ue_context.rnti); } } else { // end if plmn_Identity != NULL diff --git a/openair3/S1AP/s1ap_eNB_defs.h b/openair3/S1AP/s1ap_eNB_defs.h index d4bc6cfc0f..c6f44cdb18 100644 --- a/openair3/S1AP/s1ap_eNB_defs.h +++ b/openair3/S1AP/s1ap_eNB_defs.h @@ -164,6 +164,8 @@ typedef struct s1ap_eNB_mme_data_s { /* Only meaningfull in virtual mode */ struct s1ap_eNB_instance_s *s1ap_eNB_instance; + + uint32_t nb_calls; } s1ap_eNB_mme_data_t; typedef struct s1ap_eNB_instance_s { diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index d931e76bb6..4744ff4e43 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -138,8 +138,9 @@ int s1ap_eNB_handle_nas_first_req( * identity, selects the MME with the highest capacity. */ mme_desc_p = s1ap_eNB_nnsf_select_mme( - instance_p, - s1ap_nas_first_req_p->establishment_cause); + instance_p, + s1ap_nas_first_req_p->establishment_cause, + s1ap_nas_first_req_p->selected_plmn_identity); if (mme_desc_p) { S1AP_INFO("[eNB %d] Chose MME '%s' (assoc_id %d) through highest relative capacity\n", @@ -232,9 +233,9 @@ int s1ap_eNB_handle_nas_first_req( MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, // Cell ID &ie->value.choice.EUTRAN_CGI.cell_ID); - MCC_MNC_TO_TBCD(instance_p->mcc[ue_desc_p->selected_plmn_identity], - instance_p->mnc[ue_desc_p->selected_plmn_identity], - instance_p->mnc_digit_length[ue_desc_p->selected_plmn_identity], + MCC_MNC_TO_TBCD(instance_p->mcc[mme_desc_p->broadcast_plmn_index[0]], + instance_p->mnc[mme_desc_p->broadcast_plmn_index[0]], + instance_p->mnc_digit_length[mme_desc_p->broadcast_plmn_index[0]], &ie->value.choice.EUTRAN_CGI.pLMNidentity); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* Set the establishment cause according to those provided by RRC */ @@ -494,9 +495,9 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_ ie->criticality = S1AP_Criticality_ignore; ie->value.present = S1AP_UplinkNASTransport_IEs__value_PR_EUTRAN_CGI; MCC_MNC_TO_PLMNID( - s1ap_eNB_instance_p->mcc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc[ue_context_p->selected_plmn_identity], - s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->selected_plmn_identity], + s1ap_eNB_instance_p->mcc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc[ue_context_p->mme_ref->broadcast_plmn_index[0]], + s1ap_eNB_instance_p->mnc_digit_length[ue_context_p->mme_ref->broadcast_plmn_index[0]], &ie->value.choice.EUTRAN_CGI.pLMNidentity); //#warning "TODO get cell id from RRC" MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id, diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c index 6319f6e054..6577b8f10b 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.c +++ b/openair3/S1AP/s1ap_eNB_nnsf.c @@ -38,13 +38,27 @@ struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, - rrc_establishment_cause_t cause) + rrc_establishment_cause_t cause, + uint32_t plmn_id) { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; + typedef struct MME_nnsf_inf { + struct s1ap_eNB_mme_data_s *mme_p; + uint64_t weight; + } MME_nnsf_inf_t; + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + struct served_gummei_s *gummei_p = NULL; + capacity_sum = capacity_sum + mme_data_p->relative_mme_capacity; if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { /* The association between MME and eNB is not ready for the moment, * go to the next known MME. @@ -79,12 +93,56 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, } } - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; + gummei_p = mme_data_p->served_gummei.stqh_first; + if( gummei_p != NULL ) + { + struct plmn_identity_s *served_plmns_p = NULL; + + served_plmns_p = gummei_p->served_plmns.stqh_first; + if( served_plmns_p != 0 ) + for( cnt = 0 ; cnt < 8 ; cnt++) + { + if ( (served_plmns_p->mcc == instance_p->mcc[plmn_id]) && + (served_plmns_p->mnc == instance_p->mnc[plmn_id]) ) + { + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; + break; + } + if( served_plmns_p->next.stqe_next == 0 ) + { + break; + } + served_plmns_p = served_plmns_p->next.stqe_next; + } } } + if( nb_mme != 0 ) + { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) + { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) + { + if( weight > mme_inf[cnt].weight ) + { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } + else + { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) + { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } diff --git a/openair3/S1AP/s1ap_eNB_nnsf.h b/openair3/S1AP/s1ap_eNB_nnsf.h index d5f080649b..de039b7d30 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.h +++ b/openair3/S1AP/s1ap_eNB_nnsf.h @@ -24,7 +24,8 @@ struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, - rrc_establishment_cause_t cause); + rrc_establishment_cause_t cause, + uint32_t plmn_id); struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, From f006866c74a74554ac694a216f21a30e767bc07d Mon Sep 17 00:00:00 2001 From: Haruki NAOI Date: Thu, 12 Mar 2020 14:55:26 +0900 Subject: [PATCH 03/15] Fix: Drop paging message on sctp stream zero. (cherry picked from commit 2d45f940be267e013781d6baba5b2ab665e64c88) --- openair3/S1AP/s1ap_eNB_handlers.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 79501a1a09..7a3715f61b 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -1105,13 +1105,6 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, // received Paging Message from MME S1AP_DEBUG("[SCTP %d] Received Paging Message From MME\n",assoc_id); - /* Paging procedure -> stream != 0 */ - if (stream == 0) { - LOG_W(S1AP,"[SCTP %d] Received Paging procedure on stream (%d)\n", - assoc_id, stream); - return -1; - } - if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received Paging for non " "existing MME context\n", assoc_id); From cead17f2d8efa326392d31cbbf9b79a6ccdcb793 Mon Sep 17 00:00:00 2001 From: Wu Jing Date: Thu, 2 Apr 2020 10:09:02 +0900 Subject: [PATCH 04/15] Fix openair3/NAS/UE cppcheck error --- openair3/NAS/UE/EMM/SAP/emm_as.c | 4 ++-- openair3/NAS/UE/EMM/SecurityModeControl.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index 99a3763dea..10b118eac0 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -443,14 +443,14 @@ static int _emm_as_data_ind(nas_user_t *user, const emm_as_data_t *msg, int *emm EPS_MOBILITY_MANAGEMENT_MESSAGE) { /* Process EMM data */ rc = _emm_as_recv(user, plain_msg, bytes, emm_cause); + free(plain_msg); } else if (header.protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) { const OctetString data = {bytes, (uint8_t *)plain_msg}; /* Foward ESM data to EPS session management */ rc = lowerlayer_data_ind(user, &data); + free(plain_msg); } - - free(plain_msg); } } else { /* Process successfull lower layer transfer indication */ diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index 67bfaf784e..b27270fadc 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -296,16 +296,16 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, else { /* Setup EMM cause code */ emm_cause = EMM_CAUSE_SECURITY_MODE_REJECTED; - - /* Release security mode control internal data */ - if (security_data->kenb.value) { - free(security_data->kenb.value); - security_data->kenb.value = NULL; - security_data->kenb.length = 0; - } } } + /* Release security mode control internal data */ + if (security_data->kenb.value) { + free(security_data->kenb.value); + security_data->kenb.value = NULL; + security_data->kenb.length = 0; + } + /* Setup EMM procedure handler to be executed upon receiving * lower layer notification */ rc = emm_proc_lowerlayer_initialize(user->lowerlayer_data, NULL, NULL, NULL, NULL); From 7631a1dc1df843f328fcb299fd6d39533be84162 Mon Sep 17 00:00:00 2001 From: Ding Yumei Date: Sun, 20 Dec 2020 18:32:40 +0100 Subject: [PATCH 05/15] fix s1ap StreamID issue --- openair3/S1AP/s1ap_eNB_handlers.c | 4 +--- openair3/S1AP/s1ap_eNB_overload.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 7a3715f61b..0895494837 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -1512,7 +1512,6 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (stream == 0) { S1AP_ERROR("[SCTP %d] Received s1 path switch request ack on stream (%d)\n", assoc_id, stream); - //return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { @@ -1667,9 +1666,8 @@ int s1ap_eNB_handle_s1_path_switch_request_failure(uint32_t assoc_ pathSwitchRequestFailure = &pdu->choice.unsuccessfulOutcome.value.choice.PathSwitchRequestFailure; if (stream != 0) { - S1AP_ERROR("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", + S1AP_WARN("[SCTP %d] Received s1 path switch request failure on stream != 0 (%d)\n", assoc_id, stream); - return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { diff --git a/openair3/S1AP/s1ap_eNB_overload.c b/openair3/S1AP/s1ap_eNB_overload.c index 9358ae62bd..e331d03b4a 100644 --- a/openair3/S1AP/s1ap_eNB_overload.c +++ b/openair3/S1AP/s1ap_eNB_overload.c @@ -63,7 +63,11 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id, S1AP_OverloadResponse_PR_overloadAction, 0, 0); } /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload start on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ @@ -93,7 +97,11 @@ int s1ap_eNB_handle_overload_stop(uint32_t assoc_id, s1ap_eNB_mme_data_t *mme_desc_p; /* Non UE-associated signalling -> stream 0 */ - DevCheck(stream == 0, stream, 0, 0); + if (stream != 0) { + S1AP_ERROR("[SCTP %d] Received s1 overload stop on stream != 0 (%d)\n", + assoc_id, stream); + return -1; + } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { /* No MME context associated */ From 46407ca42b51404e0251a2d27bd42ed63ae88b8e Mon Sep 17 00:00:00 2001 From: Haruki NAOI Date: Wed, 8 Apr 2020 11:50:58 +0900 Subject: [PATCH 06/15] Add S1down auto recovery. (cherry picked from commit 2339972ceaeb75fe18c0b2ae9ea69216dd919668) --- cmake_targets/CMakeLists.txt | 1 + openair2/COMMON/s1ap_messages_types.h | 5 + openair2/COMMON/tasks_def.h | 3 +- openair2/ENB_APP/enb_config.c | 59 +++ openair2/ENB_APP/enb_paramdef.h | 15 + openair2/X2AP/x2ap_common.h | 2 +- openair2/X2AP/x2ap_eNB_handler.c | 35 +- openair3/S1AP/s1ap_common.h | 7 +- openair3/S1AP/s1ap_eNB.c | 398 +++++++++++++++-- openair3/S1AP/s1ap_eNB_defs.h | 12 + openair3/S1AP/s1ap_eNB_handlers.c | 409 +++++++++++++++--- .../S1AP/s1ap_eNB_management_procedures.c | 47 +- openair3/S1AP/s1ap_eNB_nas_procedures.c | 12 + openair3/S1AP/s1ap_eNB_overload.c | 4 + openair3/S1AP/s1ap_eNB_timer.c | 300 +++++++++++++ openair3/S1AP/s1ap_eNB_timer.h | 86 ++++ openair3/S1AP/s1ap_eNB_trace.c | 4 + openair3/SCTP/sctp_default_values.h | 4 +- openair3/SCTP/sctp_eNB_task.c | 4 +- 19 files changed, 1289 insertions(+), 118 deletions(-) create mode 100644 openair3/S1AP/s1ap_eNB_timer.c create mode 100644 openair3/S1AP/s1ap_eNB_timer.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 0b9d925017..a85dc7e5ea 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -540,6 +540,7 @@ add_library(S1AP_ENB ${S1AP_DIR}/s1ap_eNB_overload.c ${S1AP_DIR}/s1ap_eNB_trace.c ${S1AP_DIR}/s1ap_eNB_ue_context.c + ${S1AP_DIR}/s1ap_eNB_timer.c ) add_dependencies(S1AP_ENB rrc_flag s1ap_flag) diff --git a/openair2/COMMON/s1ap_messages_types.h b/openair2/COMMON/s1ap_messages_types.h index f6b4f3c4e2..38214fc71f 100644 --- a/openair2/COMMON/s1ap_messages_types.h +++ b/openair2/COMMON/s1ap_messages_types.h @@ -393,6 +393,11 @@ typedef struct s1ap_register_enb_req_s { /* Number of SCTP streams used for a mme association */ uint16_t sctp_in_streams; uint16_t sctp_out_streams; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; } s1ap_register_enb_req_t; //-------------------------------------------------------------------------------------------// diff --git a/openair2/COMMON/tasks_def.h b/openair2/COMMON/tasks_def.h index 33b6d5f9d4..f84195d5d7 100644 --- a/openair2/COMMON/tasks_def.h +++ b/openair2/COMMON/tasks_def.h @@ -47,7 +47,8 @@ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200) TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000) // GTP_V1U task TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000) -TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200) +//TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200) +TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 2000) TASK_DEF(TASK_CU_F1, TASK_PRIORITY_MED, 200) TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200) /// M3ap task, acts as both source and target diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index de77d783c7..31d0efb0aa 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2426,6 +2426,65 @@ int RCconfig_S1( "to\n" " tracking_area_code = 1; // no string!!\n" " plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n"); + if(*ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_rsp_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_RSP_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setuprsp_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_wait_timer = 5; + } + + if(*ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "s1setup_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_S1SETUP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).s1_setupreq_count = 0xffff; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_timer value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_TIMER_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_timer = 180; + } + + if(*ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr <= 0xffff) + { + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr; + } + else + { + LOG_E(S1AP, + "sctp_req_count value in conf file is invalid (%d). Default value is set.\n", + *ENBParamList.paramarray[k][ENB_SCTP_REQ_COUNT_IDX].uptr); + S1AP_REGISTER_ENB_REQ(msg_p).sctp_req_count = 0xffff; + } config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix); if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6) { diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index de7e0bbdad..f26863414c 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -214,6 +214,11 @@ typedef enum { #define ENB_CONFIG_STRING_X2 "enable_x2" #define ENB_CONFIG_STRING_ENB_M2 "enable_enb_m2" #define ENB_CONFIG_STRING_MCE_M2 "enable_mce_m2" +#define ENB_CONFIG_STRING_S1SETUP_RSP_TIMER "s1setup_rsp_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_TIMER "s1setup_req_timer" +#define ENB_CONFIG_STRING_S1SETUP_REQ_COUNT "s1setup_req_count" +#define ENB_CONFIG_STRING_SCTP_REQ_TIMER "sctp_req_timer" +#define ENB_CONFIG_STRING_SCTP_REQ_COUNT "sctp_req_count" /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* cell configuration parameters */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ @@ -239,6 +244,11 @@ typedef enum { {ENB_CONFIG_STRING_X2, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_ENB_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ {ENB_CONFIG_STRING_MCE_M2, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_RSP_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:5, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_S1SETUP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_TIMER, NULL, 0, uptr:NULL, defuintval:180, TYPE_UINT, 0}, \ + {ENB_CONFIG_STRING_SCTP_REQ_COUNT, NULL, 0, uptr:NULL, defuintval:65535, TYPE_UINT, 0}, \ } #define ENB_ENB_ID_IDX 0 @@ -261,6 +271,11 @@ typedef enum { #define ENB_ENABLE_X2 17 #define ENB_ENABLE_ENB_M2 18 #define ENB_ENABLE_MCE_M2 19 +#define ENB_S1SETUP_RSP_TIMER_IDX 20 +#define ENB_S1SETUP_REQ_TIMER_IDX 21 +#define ENB_S1SETUP_REQ_COUNT_IDX 22 +#define ENB_SCTP_REQ_TIMER_IDX 23 +#define ENB_SCTP_REQ_COUNT_IDX 24 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD} #define ENBPARAMS_CHECK { \ diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index a2f903a737..470a023c31 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -84,7 +84,7 @@ extern int asn1_xer_print; break; \ } \ } \ - if (mandatory) DevAssert(ie != NULL); \ +/* if (mandatory) DevAssert(ie != NULL); \*/ \ } while(0) /** \brief Function callback prototype. diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index bbdeaf0ac8..db03507539 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -536,6 +536,14 @@ int x2ap_eNB_handle_x2_setup_response(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Response Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup response\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupResponse_IEs_t, ie, x2SetupResponse, @@ -662,6 +670,14 @@ int x2ap_eNB_handle_x2_setup_failure(instance_t instance, return -1; } + if((x2ap_eNB_data->state == X2AP_ENB_STATE_CONNECTED) || + (x2ap_eNB_data->state == X2AP_ENB_STATE_READY)) + + { + X2AP_ERROR("Received Unexpexted X2 Setup Failure Message\n"); + return -1; + } + X2AP_DEBUG("Received a new X2 setup failure\n"); X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_X2SetupFailure_IEs_t, ie, x2SetupFailure, @@ -730,6 +746,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, 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__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -750,7 +767,11 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, //measResultListEUTRA.list.array[ncell_index]->physCellId; X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequest_IEs_t, ie, x2HandoverRequest, X2AP_ProtocolIE_ID_id_GUMMEI_ID, true); - + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } TBCD_TO_MCC_MNC(&ie->value.choice.ECGI.pLMN_Identity, X2AP_HANDOVER_REQ(msg).ue_gummei.mcc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc, X2AP_HANDOVER_REQ(msg).ue_gummei.mnc_len); OCTET_STRING_TO_INT8(&ie->value.choice.GUMMEI.mME_Code, X2AP_HANDOVER_REQ(msg).ue_gummei.mme_code); @@ -761,6 +782,7 @@ int x2ap_eNB_handle_handover_preparation (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -872,6 +894,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -882,6 +905,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -912,6 +936,7 @@ int x2ap_eNB_handle_handover_response (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n", __FILE__, __LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; }else{ if (ie->value.choice.E_RABs_Admitted_List.list.count > 0) { @@ -959,6 +984,12 @@ int x2ap_eNB_handle_handover_response (instance_t instance, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_HandoverRequestAcknowledge_IEs_t, ie, x2HandoverRequestAck, X2AP_ProtocolIE_ID_id_TargeteNBtoSource_eNBTransparentContainer, true); + if (ie == NULL ) { + X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); + return -1; + } + X2AP_TargeteNBtoSource_eNBTransparentContainer_t *c = &ie->value.choice.TargeteNBtoSource_eNBTransparentContainer; if (c->size > 1024 /* TODO: this is the size of rrc_buffer in struct x2ap_handover_req_ack_s */) @@ -1012,6 +1043,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } @@ -1022,6 +1054,7 @@ int x2ap_eNB_handle_ue_context_release (instance_t instance, if (ie == NULL ) { X2AP_ERROR("%s %d: ie is a NULL pointer \n",__FILE__,__LINE__); + itti_free(ITTI_MSG_ORIGIN_ID(msg), msg); return -1; } diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index 77d03f4ae4..efac0201a3 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -106,7 +106,12 @@ extern int asn1_xer_print; if (ie == NULL ) { \ S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ } \ - if (mandatory) DevAssert(ie != NULL); \ + if (mandatory) { \ + if (ie == NULL) { \ + S1AP_ERROR("S1AP_FIND_PROTOCOLIE_BY_ID: %s %d: ie is NULL\n",__FILE__,__LINE__);\ + return -1; \ + } \ + } \ } while(0) /** \brief Function callback prototype. **/ diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 2a153acaa2..8452d9e563 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -58,6 +58,8 @@ #include "s1ap_eNB_ue_context.h" // test, to be removed #include "msc.h" +#include "s1ap_eNB_timer.h" + #include "assertions.h" #include "conversions.h" #if defined(TEST_S1C_MME) @@ -73,6 +75,11 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp); +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); +void s1ap_eNB_timer_expired(instance_t instance, + s1ap_timer_has_expired_t *msg_p); + uint32_t s1ap_generate_eNB_id(void) { char *out; char hostname[50]; @@ -114,9 +121,9 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, local_ip_addr, sizeof(*local_ip_addr)); S1AP_INFO("[eNB %d] check the mme registration state\n",instance_p->instance); - mme = NULL; - - if ( mme == NULL ) { +// mme = NULL; +// +// if ( mme == NULL ) { /* Create new MME descriptor */ s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); DevAssert(s1ap_mme_data_p != NULL); @@ -136,28 +143,33 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, * but not yet associated. */ RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); - s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; - instance_p->s1ap_mme_nb ++; +// s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) ); + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->sctp_req_cnt++; + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; +// instance_p->s1ap_mme_nb ++; instance_p->s1ap_mme_pending_nb ++; - } else if (mme->state == S1AP_ENB_STATE_WAITING) { - instance_p->s1ap_mme_pending_nb ++; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - /*s1ap_mme_data_p->cnx_id = mme->cnx_id; - sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; - - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - */ - } else { - S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", - instance_p->instance, - mme->state, mme->cnx_id, - instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); - } +// } else if (mme->state == S1AP_ENB_STATE_WAITING) { +// instance_p->s1ap_mme_pending_nb ++; +// sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; +// S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", +// instance_p->instance, +// mme->state, mme->cnx_id, +// instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); +// /*s1ap_mme_data_p->cnx_id = mme->cnx_id; +// sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; +// +// s1ap_mme_data_p->assoc_id = -1; +// s1ap_mme_data_p->s1ap_eNB_instance = instance_p; +// */ +// } else { +// S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", +// instance_p->instance, +// mme->state, mme->cnx_id, +// instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); +// } itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); } @@ -168,6 +180,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * uint8_t index; DevAssert(s1ap_register_eNB != NULL); /* Look if the provided instance already exists */ + s1ap_timer_init(); new_instance = s1ap_eNB_get_instance(instance); if (new_instance != NULL) { @@ -195,7 +208,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->eNB_id = s1ap_register_eNB->eNB_id; new_instance->cell_type = s1ap_register_eNB->cell_type; new_instance->tac = s1ap_register_eNB->tac; - + memcpy(&new_instance->eNB_s1_ip, &s1ap_register_eNB->enb_ip_address, sizeof(s1ap_register_eNB->enb_ip_address)); @@ -206,6 +219,15 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->mnc_digit_length[i] = s1ap_register_eNB->mnc_digit_length[i]; } + memcpy( &(new_instance->enb_ip_address), &(s1ap_register_eNB->enb_ip_address), sizeof(net_ip_address_t) ); + new_instance->s1_setuprsp_wait_timer = s1ap_register_eNB->s1_setuprsp_wait_timer; + new_instance->s1_setupreq_wait_timer = s1ap_register_eNB->s1_setupreq_wait_timer; + new_instance->s1_setupreq_count = s1ap_register_eNB->s1_setupreq_count; + new_instance->sctp_req_timer = s1ap_register_eNB->sctp_req_timer; + new_instance->sctp_req_count = s1ap_register_eNB->sctp_req_count; + new_instance->sctp_in_streams = s1ap_register_eNB->sctp_in_streams; + new_instance->sctp_out_streams = s1ap_register_eNB->sctp_out_streams; + new_instance->num_plmn = s1ap_register_eNB->num_plmn; new_instance->default_drx = s1ap_register_eNB->default_drx; /* Add the new instance to the list of eNB (meaningfull in virtual mode) */ @@ -216,8 +238,14 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * s1ap_register_eNB->eNB_id); } - DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, - S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); +// DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, +// S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); + if( s1ap_register_eNB->nb_mme > S1AP_MAX_NB_MME_IP_ADDRESS ) + { + S1AP_ERROR("Invalid MME number = %d\n ", s1ap_register_eNB->nb_mme); + s1ap_register_eNB->nb_mme = S1AP_MAX_NB_MME_IP_ADDRESS; + } + new_instance->s1ap_mme_nb = s1ap_register_eNB->nb_mme; /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { @@ -249,28 +277,153 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) { s1ap_eNB_instance_t *instance_p; s1ap_eNB_mme_data_t *s1ap_mme_data_p; + s1ap_eNB_ue_context_t *ue_p = NULL; + MessageDef *message_p = NULL; + uint32_t timer_kind = 0; + struct plmn_identity_s* plmnInfo; + struct served_group_id_s* groupInfo; + struct served_gummei_s* gummeiInfo; + struct mme_code_s* mmeCode; + int8_t cnt = 0; + unsigned enb_s1ap_id[20]; DevAssert(sctp_new_association_resp != NULL); instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1, sctp_new_association_resp->ulp_cnx_id); DevAssert(s1ap_mme_data_p != NULL); - - if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { - S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", - sctp_new_association_resp->sctp_state, - instance, - sctp_new_association_resp->ulp_cnx_id); - s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); - return; + memset(enb_s1ap_id, 0, sizeof(enb_s1ap_id) ); + if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) + { + s1ap_timer_remove( s1ap_mme_data_p->timer_id ); + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; } + + if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) + { + RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) + { + if( ue_p->mme_ref == s1ap_mme_data_p ) + { + enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; + cnt++; + + message_p = NULL; + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); + + if( message_p != NULL ) + { + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; + + if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) + { + S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%d\n", ue_p->eNB_ue_s1ap_id); + } + } + else + { + S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%d\n", ue_p->eNB_ue_s1ap_id); + } + } + } + for( ; cnt > 0 ; ) + { + cnt--; + s1ap_ue_context_release( instance, (uint32_t)enb_s1ap_id[cnt] ); + } + s1ap_mme_data_p->mme_name = 0; + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->nextstream = 0; + s1ap_mme_data_p->in_streams = 0; + s1ap_mme_data_p->out_streams = 0; + s1ap_mme_data_p->assoc_id = -1; + + while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) + { + gummeiInfo = STAILQ_FIRST(&s1ap_mme_data_p->served_gummei); + STAILQ_REMOVE_HEAD(&s1ap_mme_data_p->served_gummei, next); + while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) + { + plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next); + free(plmnInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) + { + groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids); + STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next); + free(groupInfo); + } + while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) + { + mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes); + STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next); + free(mmeCode); + } + free(gummeiInfo); + } + + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + + if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) + { + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) + { + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | SCTP_REQ_WAIT; + + if( s1ap_timer_setup( instance_p->sctp_req_timer, 0, TASK_S1AP, instance_p->instance, + timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(SCTP retransmission wait timer) : MME=%d\n",s1ap_mme_data_p->cnx_id); + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } + } + else + { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + } + else + { + S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id); + + if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || + (instance_p->sctp_req_count == 0xffff) ) + { + s1ap_sctp_req( instance_p, s1ap_mme_data_p ); + } + else + { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + } + } +// if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { +// S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", +// sctp_new_association_resp->sctp_state, +// instance, +// sctp_new_association_resp->ulp_cnx_id); +// s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); +// return; +// } + else + { /* Update parameters */ s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; /* Prepare new S1 Setup Request */ - s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p); + s1ap_mme_data_p->s1_setupreq_cnt = 0; + s1ap_mme_data_p->sctp_req_cnt = 0; + if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) { + S1AP_ERROR("s1ap eNB generate s1 setup request failed\n"); + return; + } } static @@ -288,9 +441,102 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } +void s1ap_eNB_timer_expired( + instance_t instance, + s1ap_timer_has_expired_t *msg_p) +{ + uint32_t timer_kind = 0; + int16_t line_ind = 0; + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + uint32_t timer_ind = 0; + s1ap_eNB_instance_t *instance_p = NULL; + long timer_id = S1AP_TIMERID_INIT; + + instance_p = s1ap_eNB_get_instance(instance); + timer_kind = msg_p->timer_kind; + line_ind = (int16_t)(timer_kind & S1AP_LINEIND); + timer_id = msg_p->timer_id; + + if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) + { + mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind); + if(mme_desc_p != NULL) + { + if( timer_id == mme_desc_p->timer_id ) + { + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + timer_ind = timer_kind & S1AP_TIMERIND; + + switch(timer_ind) + { + case S1_SETRSP_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) + { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } + else + { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case S1_SETREQ_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) + { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } + else + { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); + } + break; + } + case SCTP_REQ_WAIT: + { + if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) || + (instance_p->sctp_req_count == 0xffff) ) + { + s1ap_sctp_req( instance_p, mme_desc_p ); + } + else + { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind); + } + break; + } + default: + { + S1AP_WARN("Invalid Timer indication\n"); + break; + } + } + } + else + { + S1AP_DEBUG("Unmatch timer id\n"); + return; + } + } + else + { + S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind); + return; + } + } + else + { + } + return; +} + void s1ap_eNB_init(void) { S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); + s1ap_timer_init(); itti_mark_task_ready(TASK_S1AP); MSC_START_USE(); } @@ -411,6 +657,13 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { } break; + case TIMER_HAS_EXPIRED: + { + s1ap_eNB_timer_expired(ITTI_MESSAGE_GET_INSTANCE(received_msg), + &TIMER_HAS_EXPIRED(received_msg)); + } + break; + default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); @@ -451,6 +704,7 @@ static int s1ap_eNB_generate_s1_setup_request( uint8_t *buffer = NULL; uint32_t len = 0; int ret = 0; + uint32_t timer_kind = 0; DevAssert(instance_p != NULL); DevAssert(s1ap_mme_data_p != NULL); s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; @@ -525,6 +779,17 @@ static int s1ap_eNB_generate_s1_setup_request( return -1; } + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + /* Non UE-Associated signalling -> stream = 0 */ s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); return ret; @@ -533,3 +798,64 @@ static int s1ap_eNB_generate_s1_setup_request( +static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +{ + MessageDef *message_p = NULL; + sctp_new_association_req_t *sctp_new_association_req_p = NULL; + + if( instance_p == NULL ) + { + S1AP_ERROR("Invalid instance_p\n"); + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_association_req_p->port = S1AP_PORT_NUMBER; + sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; + sctp_new_association_req_p->in_streams = instance_p->sctp_in_streams; + sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams; + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + + if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) + { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv4 != 0 ) + { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } + else + { + S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n"); + return -1; + } + } + else + { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv6 != 0 ) + { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } + else + { + S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n"); + return -1; + } + } + + itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); + + s1ap_mme_data_p->sctp_req_cnt++; + + return 0; +} diff --git a/openair3/S1AP/s1ap_eNB_defs.h b/openair3/S1AP/s1ap_eNB_defs.h index c6f44cdb18..78a8866e01 100644 --- a/openair3/S1AP/s1ap_eNB_defs.h +++ b/openair3/S1AP/s1ap_eNB_defs.h @@ -166,6 +166,10 @@ typedef struct s1ap_eNB_mme_data_s { struct s1ap_eNB_instance_s *s1ap_eNB_instance; uint32_t nb_calls; + net_ip_address_t mme_ip_address; + long timer_id; + uint16_t s1_setupreq_cnt; + uint16_t sctp_req_cnt; } s1ap_eNB_mme_data_t; typedef struct s1ap_eNB_instance_s { @@ -218,6 +222,14 @@ typedef struct s1ap_eNB_instance_s { /* Default Paging DRX of the eNB as defined in TS 36.304 */ paging_drx_t default_drx; + net_ip_address_t enb_ip_address; + uint16_t s1_setuprsp_wait_timer; + uint16_t s1_setupreq_wait_timer; + uint16_t s1_setupreq_count; + uint16_t sctp_req_timer; + uint16_t sctp_req_count; + uint16_t sctp_in_streams; + uint16_t sctp_out_streams; } s1ap_eNB_instance_t; typedef struct { diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 0895494837..5d43c5b3fa 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -49,6 +49,7 @@ #include "assertions.h" #include "conversions.h" #include "msc.h" +#include "s1ap_eNB_timer.h" static int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, @@ -109,6 +110,10 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as uint32_t stream, S1AP_S1AP_PDU_t *pdu); +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p); + /* Handlers matrix. Only eNB related procedure present here */ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* HandoverPreparation */ @@ -260,6 +265,10 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_S1SetupFailure_t *container; S1AP_S1SetupFailureIEs_t *ie; s1ap_eNB_mme_data_t *mme_desc_p; + uint32_t interval_sec = 0; + uint32_t timer_kind = 0; + s1ap_eNB_instance_t *instance_p; + DevAssert(pdu != NULL); container = &pdu->choice.unsuccessfulOutcome.value.choice.S1SetupFailure; @@ -270,7 +279,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing " + S1AP_ERROR("[SCTP %d] Received S1 setup failure for non existing " "MME context\n", assoc_id); return -1; } @@ -278,6 +287,11 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, S1AP_ProtocolIE_ID_id_Cause,true); + if(ie == NULL) + { + return -1; + } + if ((ie->value.choice.Cause.present == S1AP_Cause_PR_misc) && (ie->value.choice.Cause.choice.misc == S1AP_CauseMisc_unspecified)) { S1AP_WARN("Received s1 setup failure for MME... MME is not ready\n"); @@ -285,8 +299,65 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n"); } - mme_desc_p->state = S1AP_ENB_STATE_WAITING; - s1ap_handle_s1_setup_message(mme_desc_p, 0); + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) + { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + instance_p = mme_desc_p->s1ap_eNB_instance; + if( ( instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + ( instance_p->s1_setupreq_count == 0xffff) ) + { + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_TimeToWait, false); + if( ie != NULL ) + { + switch(ie->value.choice.TimeToWait) + { + case S1AP_TimeToWait_v1s: + interval_sec = 1; + break; + case S1AP_TimeToWait_v2s: + interval_sec = 2; + break; + case S1AP_TimeToWait_v5s: + interval_sec = 5; + break; + case S1AP_TimeToWait_v10s: + interval_sec = 10; + break; + case S1AP_TimeToWait_v20s: + interval_sec = 20; + break; + case S1AP_TimeToWait_v60s: + interval_sec = 60; + break; + default: + interval_sec = instance_p->s1_setupreq_wait_timer; + break; + } + } + else + { + interval_sec = instance_p->s1_setupreq_wait_timer; + } + + timer_kind = mme_desc_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETREQ_WAIT; + + if( s1ap_timer_setup(interval_sec, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &mme_desc_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Request) : MME=%d\n",mme_desc_p->cnx_id); + + s1ap_eNB_snd_s1_setup_request( instance_p, mme_desc_p ); + } + } + else + { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id); + } return 0; } @@ -314,9 +385,29 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, return -1; } + /* Set the capacity of this MME */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); + if(ie == NULL) + { + return -1; + } + mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true); + if(ie == NULL) + { + return -1; + } + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) + { + s1ap_timer_remove( mme_desc_p->timer_id ); + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + } + mme_desc_p->s1_setupreq_cnt = 0; + mme_desc_p->sctp_req_cnt = 0; /* The list of served gummei can contain at most 8 elements. * LTE related gummei is the first element in the list, i.e with an id of 0. */ @@ -370,11 +461,11 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, } /* Set the capacity of this MME */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); - - mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; - +// S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, +// S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); +// +// mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; +// /* Optionaly set the mme name */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_MMEname, false); @@ -392,7 +483,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; - s1ap_handle_s1_setup_message(mme_desc_p, 0); +// s1ap_handle_s1_setup_message(mme_desc_p, 0); return 0; } @@ -725,6 +816,10 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); if (ie) { + if( ie->value.choice.CriticalityDiagnostics.procedureCode ) + { + S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %d\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); + } // TODO continue } @@ -807,6 +902,33 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, &(S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_ambr.br_dl)); /* id-E-RABToBeSetupListCtxtSUReq */ } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); + return -1; + } + + /* id-UESecurityCapabilities */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_UESecurityCapabilities, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.encryption_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms); + S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = + BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); + /* id-SecurityKey : Copy the security key */ + } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); + return -1; + } + + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_SecurityKey, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, + ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); + } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -852,34 +974,11 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, item_p->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability; } /* for i... */ } else {/* ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } - /* id-UESecurityCapabilities */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_UESecurityCapabilities, true); - - if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.encryption_algorithms = - BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms); - S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms = - BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms); - /* id-SecurityKey : Copy the security key */ - } else {/* ie != NULL */ - return -1; - } - - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_SecurityKey, true); - - if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key, - ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size); itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); - } else {/* ie != NULL */ - return -1; - } - return 0; } @@ -904,6 +1003,14 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, + S1AP_ProtocolIE_ID_id_Cause, true); + if( ie == NULL ) + { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(Cause)\n" ); + return -1; + } + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_UE_S1AP_IDs, true); @@ -951,9 +1058,29 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, //#warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?" case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID: - mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; - S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); - (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */ +// mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; +// S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); +// (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */ + mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.mME_UE_S1AP_ID; + + RB_FOREACH(ue_desc_p, s1ap_ue_map, &mme_desc_p->s1ap_eNB_instance->s1ap_ue_head) + { + if( ue_desc_p->mme_ue_s1ap_id == mme_ue_s1ap_id ) + { + enb_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; + + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; + itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); + + return 0; + } + } + S1AP_ERROR("[SCTP %d] Received UE context release command(mME_UE_S1AP_ID) for non " + "existing UE context 0x%06lx\n", + assoc_id, + mme_ue_s1ap_id); + return -1; case S1AP_UE_S1AP_IDs_PR_NOTHING: default: @@ -961,12 +1088,10 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, return -1; } } else { + S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(UE_S1AP_IDs)\n" ); return -1; } - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, - S1AP_ProtocolIE_ID_id_Cause, true); - /* TBD */ } static @@ -985,7 +1110,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.E_RABSetupRequest; if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing MME context\n", assoc_id); return -1; } @@ -1012,7 +1137,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, enb_ue_s1ap_id)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received E-RAB setup request for non " "existing UE context 0x%06lx\n", assoc_id, enb_ue_s1ap_id); return -1; @@ -1085,6 +1210,7 @@ int s1ap_eNB_handle_e_rab_setup_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1132,6 +1258,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.mme_code = 0; S1AP_PAGING_IND(message_p).ue_paging_identity.choice.s_tmsi.m_tmsi = 0; } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1159,6 +1286,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if(i != ie->value.choice.UEPagingID.choice.iMSI.size - 1) { /* invalid paging_p->uePagingID.choise.iMSI.buffer */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI error(i %d 0x0F)\n", assoc_id,i); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { @@ -1169,14 +1297,17 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, if (S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length >= S1AP_IMSI_LENGTH) { /* invalid paging_p->uePagingID.choise.iMSI.size */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.choise.iMSI.size(%d) is over IMSI length(%d)\n", assoc_id, S1AP_PAGING_IND(message_p).ue_paging_identity.choice.imsi.length, S1AP_IMSI_LENGTH); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of if (ie->value.choice.UEPagingID.present == S1AP_UEPagingID_PR_iMSI) */ /* invalid paging_p->uePagingID.present */ S1AP_ERROR("[SCTP %d] Received Paging : uePagingID.present(%d) is unknown\n", assoc_id, ie->value.choice.UEPagingID.present); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } } else { /* of ie != NULL */ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1209,6 +1340,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, return -1; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1236,6 +1368,7 @@ int s1ap_eNB_handle_paging(uint32_t assoc_id, S1AP_PAGING_IND(message_p).tac[i]); } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1330,6 +1463,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, S1AP_E_RAB_MODIFY_RESP(message_p).e_rabs_failed[nb_of_e_rabs_failed].cause_value = S1AP_CauseRadioNetwork_unknown_mme_ue_s1ap_id; } } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1382,6 +1516,7 @@ int s1ap_eNB_handle_e_rab_modify_request(uint32_t assoc_id, itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); } else { /* of if (ie != NULL)*/ + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1455,6 +1590,24 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, message_p = itti_alloc_new_message(TASK_S1AP, S1AP_E_RAB_RELEASE_COMMAND); S1AP_E_RAB_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; S1AP_E_RAB_RELEASE_COMMAND(message_p).mme_ue_s1ap_id = mme_ue_s1ap_id; + /* id-E-RABToBeReleasedList */ + S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, + S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); + + if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ + S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; + + for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { + S1AP_E_RABItem_t *item_p; + item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); + S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; + S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); + } + } else { + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); + return -1; + } + /* id-NAS-PDU */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, false); @@ -1470,24 +1623,6 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id, S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.length = 0; S1AP_E_RAB_RELEASE_COMMAND(message_p).nas_pdu.buffer = NULL; } - - /* id-E-RABToBeReleasedList */ - S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_E_RABReleaseCommandIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_E_RABToBeReleasedList, true); - - if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */ - S1AP_E_RAB_RELEASE_COMMAND(message_p).nb_e_rabs_torelease = ie->value.choice.E_RABList.list.count; - - for (i = 0; i < ie->value.choice.E_RABList.list.count; i++) { - S1AP_E_RABItem_t *item_p; - item_p = &(((S1AP_E_RABItemIEs_t *)ie->value.choice.E_RABList.list.array[i])->value.choice.E_RABItem); - S1AP_E_RAB_RELEASE_COMMAND(message_p).e_rab_release_params[i].e_rab_id = item_p->e_RAB_ID; - S1AP_DEBUG("[SCTP] Received E-RAB release command for e-rab id %ld\n", item_p->e_RAB_ID); - } - } else { - return -1; - } - itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); return 0; } @@ -1528,6 +1663,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1550,6 +1686,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1567,6 +1704,7 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, if (ie == NULL) { S1AP_ERROR("[SCTP %d] Received path switch request ack for non " "ie context is NULL\n", assoc_id); + itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p); return -1; } @@ -1580,14 +1718,10 @@ int s1ap_eNB_handle_s1_path_switch_request_ack(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_uEaggregateMaximumBitrate, false); if (ie) { - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul - ); - OCTET_STRING_TO_INT32 ( - &ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, - S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl - ); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateUL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul); + asn_INTEGER2ulong(&ie->value.choice.UEAggregateMaximumBitrate.uEaggregateMaximumBitRateDL, + &S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_dl); } else { S1AP_WARN("UEAggregateMaximumBitrate not supported\n"); S1AP_PATH_SWITCH_REQ_ACK(message_p).ue_ambr.br_ul = 0; @@ -1731,3 +1865,144 @@ int s1ap_eNB_handle_s1_ENDC_e_rab_modification_confirm(uint32_t as return 0; } +//----------------------------------------------------------------------------- +/* +* eNB generate a S1 setup request towards MME +*/ +static int s1ap_eNB_snd_s1_setup_request( + s1ap_eNB_instance_t *instance_p, + s1ap_eNB_mme_data_t *s1ap_mme_data_p) +//----------------------------------------------------------------------------- +{ + S1AP_S1AP_PDU_t pdu; + S1AP_S1SetupRequest_t *out = NULL; + S1AP_S1SetupRequestIEs_t *ie = NULL; + S1AP_SupportedTAs_Item_t *ta = NULL; + S1AP_PLMNidentity_t *plmn = NULL; + uint8_t *buffer = NULL; + uint32_t len = 0; + int ret = 0; + uint32_t timer_kind = 0; + + DevAssert(instance_p != NULL); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; + /* Prepare the S1AP message to encode */ + memset(&pdu, 0, sizeof(pdu)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_S1Setup; + pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject; + pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_S1SetupRequest; + out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest; + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_Global_ENB_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID; + MCC_MNC_TO_PLMNID(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[0]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[0]], + &ie->value.choice.Global_ENB_ID.pLMNidentity); + ie->value.choice.Global_ENB_ID.eNB_ID.present = S1AP_ENB_ID_PR_macroENB_ID; + MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id, + &ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID); + S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], + ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (instance_p->eNB_name) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_eNBname; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_ENBname; + OCTET_STRING_fromBuf(&ie->value.choice.ENBname, instance_p->eNB_name, + strlen(instance_p->eNB_name)); + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_SupportedTAs; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_SupportedTAs; + { + ta = (S1AP_SupportedTAs_Item_t *)calloc(1, sizeof(S1AP_SupportedTAs_Item_t)); + INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC); + { + for (int i = 0; i < s1ap_mme_data_p->broadcast_plmn_num; ++i) { + plmn = (S1AP_PLMNidentity_t *)calloc(1, sizeof(S1AP_PLMNidentity_t)); + MCC_MNC_TO_TBCD(instance_p->mcc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc[s1ap_mme_data_p->broadcast_plmn_index[i]], + instance_p->mnc_digit_length[s1ap_mme_data_p->broadcast_plmn_index[i]], + plmn); + ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn); + } + } + ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta); + } + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + /* mandatory */ + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_PagingDRX; + ie->value.choice.PagingDRX = instance_p->default_drx; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_CSG_IdList; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_CSG_IdList; + // ie->value.choice.CSG_IdList = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ +#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0)) + + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_UE_RetentionInformation; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation; + // ie->value.choice.UE_RetentionInformation = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + + /* optional */ + if (0) { + ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t)); + ie->id = S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX; + // ie->value.choice.NB_IoT_DefaultPagingDRX = ; + ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); + } + +#endif /* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */ + + if (s1ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) { + S1AP_ERROR("Failed to encode S1 setup request\n"); + return -1; + } + + timer_kind = s1ap_mme_data_p->cnx_id; + timer_kind = timer_kind | S1AP_MMEIND; + timer_kind = timer_kind | S1_SETRSP_WAIT; + + if( s1ap_timer_setup(instance_p->s1_setuprsp_wait_timer, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, + NULL, &s1ap_mme_data_p->timer_id) < 0 ) + { + S1AP_ERROR("Timer Start NG(S1 Setup Response) : MME=%d\n",s1ap_mme_data_p->cnx_id); + } + s1ap_mme_data_p->s1_setupreq_cnt++; + + /* Non UE-Associated signalling -> stream = 0 */ + s1ap_eNB_itti_send_sctp_data_req(instance_p->instance, s1ap_mme_data_p->assoc_id, buffer, len, 0); + return ret; +} diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c index fc7ae70e49..1fdc09664b 100644 --- a/openair3/S1AP/s1ap_eNB_management_procedures.c +++ b/openair3/S1AP/s1ap_eNB_management_procedures.c @@ -95,23 +95,54 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME( { struct s1ap_eNB_mme_data_s temp; struct s1ap_eNB_mme_data_s *found; + struct s1ap_eNB_mme_data_s *mme_p; memset(&temp, 0, sizeof(struct s1ap_eNB_mme_data_s)); temp.assoc_id = assoc_id; temp.cnx_id = cnx_id; - if (instance_p == NULL) { - STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, - s1ap_eNB_entries) { - found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + if( cnx_id != 0 ) + { + if (instance_p == NULL) { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) { + found = RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); - if (found != NULL) { - return found; + if (found != NULL) { + return found; + } + } + } else { + return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); + } + } + else + { + if (instance_p == NULL) + { + STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, + s1ap_eNB_entries) + { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) + { + if( mme_p->assoc_id == assoc_id ) + { + return mme_p; + } + } + } + } + else + { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) + { + if( mme_p->assoc_id == assoc_id ) + { + return mme_p; + } } } - } else { - return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); } return NULL; diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index 4744ff4e43..c617dc399d 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -359,10 +359,18 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.DownlinkNASTransport; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } mme_ue_s1ap_id = ie->value.choice.MME_UE_S1AP_ID; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true); + if(ie == NULL) + { + return -1; + } enb_ue_s1ap_id = ie->value.choice.ENB_UE_S1AP_ID; if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance, @@ -417,6 +425,10 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_DownlinkNASTransport_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_NAS_PDU, true); + if(ie == NULL) + { + return -1; + } /* Forward the NAS PDU to RRC */ s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance, ue_desc_p->ue_initial_id, diff --git a/openair3/S1AP/s1ap_eNB_overload.c b/openair3/S1AP/s1ap_eNB_overload.c index e331d03b4a..64d3fcdf65 100644 --- a/openair3/S1AP/s1ap_eNB_overload.c +++ b/openair3/S1AP/s1ap_eNB_overload.c @@ -62,6 +62,10 @@ int s1ap_eNB_handle_overload_start(uint32_t assoc_id, S1AP_OverloadResponse_PR_overloadAction, S1AP_OverloadResponse_PR_overloadAction, 0, 0); } + else + { + return -1; + } /* Non UE-associated signalling -> stream 0 */ if (stream != 0) { S1AP_ERROR("[SCTP %d] Received s1 overload start on stream != 0 (%d)\n", diff --git a/openair3/S1AP/s1ap_eNB_timer.c b/openair3/S1AP/s1ap_eNB_timer.c new file mode 100644 index 0000000000..d4b5bdbd14 --- /dev/null +++ b/openair3/S1AP/s1ap_eNB_timer.c @@ -0,0 +1,300 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#include "assertions.h" +#include "intertask_interface.h" +#include "s1ap_eNB_timer.h" +#include "common/utils/LOG/log.h" +#include "queue.h" +#include "s1ap_common.h" + +struct s1ap_timer_elm_s { + task_id_t task_id; ///< Task ID which has requested the timer + int32_t instance; ///< Instance of the task which has requested the timer + uint32_t timer_kind; ///< Instance of the task which has requested the timer + timer_t timer; ///< Unique timer id + timer_type_t type; ///< Timer type + void *timer_arg; ///< Optional argument that will be passed when timer expires + STAILQ_ENTRY(s1ap_timer_elm_s) entries; ///< Pointer to next element +}; + +typedef struct timer_desc_s { + STAILQ_HEAD(timer_list_head, s1ap_timer_elm_s) timer_queue; + pthread_mutex_t timer_list_mutex; + struct timespec timeout; +} timer_desc_t; + +static timer_desc_t timer_desc; + +#define TIMER_SEARCH(vAR, tIMERfIELD, tIMERvALUE, tIMERqUEUE) \ +do { \ + STAILQ_FOREACH(vAR, tIMERqUEUE, entries) { \ + if (((vAR)->tIMERfIELD == tIMERvALUE)) \ + break; \ + } \ +} while(0) + +int s1ap_timer_timeout(sigval_t info) +{ + struct s1ap_timer_elm_s *timer_p; + MessageDef *message_p; + s1ap_timer_has_expired_t *timer_expired_p; + task_id_t task_id; + int32_t instance; + uint32_t timer_kind; + + timer_kind = info.sival_int; + if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex lock timeout=%x\n", timer_kind); + + return -1; + } + TIMER_SEARCH(timer_p, timer_kind, timer_kind, &timer_desc.timer_queue); + + if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex unlock timeout=%x\n", timer_kind); + } + if (timer_p == NULL) + { + S1AP_ERROR("Didn't find timer 0x%lx in list\n", timer_kind); + + return -1; + } + S1AP_DEBUG("Timer kind 0x%x has expired\n", timer_kind); + + task_id = timer_p->task_id; + instance = timer_p->instance; + message_p = itti_alloc_new_message(TASK_UNKNOWN, TIMER_HAS_EXPIRED); + + timer_expired_p = &message_p->ittiMsg.timer_has_expired; + + timer_expired_p->timer_id = (long)timer_p->timer; + timer_expired_p->timer_kind = timer_p->timer_kind; + timer_expired_p->arg = timer_p->timer_arg; + + /* Timer is a one shot timer, remove it */ + if( timer_p->type == S1AP_TIMER_ONE_SHOT ) + { + if( s1ap_timer_remove((long)timer_p->timer) != 0 ) + { + S1AP_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer); + } + } + + /* Notify task of timer expiry */ + if( itti_send_msg_to_task(task_id, instance, message_p) < 0 ) + { + S1AP_ERROR("Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id); + free(message_p); + return -1; + } + + return 0; +} + +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id) +{ + struct sigevent evp; + struct itimerspec its; + struct s1ap_timer_elm_s *timer_p; + timer_t timer; + + if( timer_id == NULL ) + { + S1AP_ERROR("Invalid timer_id\n"); + return -1; + } + + if( type >= S1AP_TIMER_TYPE_MAX ) + { + S1AP_ERROR("Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX); + return -1; + } + + if( *timer_id != S1AP_TIMERID_INIT ) + { + if( s1ap_timer_remove(*timer_id) != 0 ) + { + S1AP_ERROR("Failed to delete timer when the timer start 0x%lx\n", *timer_id); + } + } + + /* Allocate new timer list element */ + timer_p = malloc(sizeof(struct s1ap_timer_elm_s)); + + if( timer_p == NULL ) + { + S1AP_ERROR("Failed to create new timer element\n"); + return -1; + } + + memset(&timer, 0, sizeof(timer_t)); + memset(&evp, 0, sizeof(evp)); + + timer_p->task_id = task_id; + timer_p->instance = instance; + timer_p->timer_kind = timer_kind; + timer_p->type = type; + timer_p->timer_arg = timer_arg; + + evp.sigev_notify = (int)SIGEV_THREAD; + evp.sigev_notify_function = (void *)s1ap_timer_timeout; + evp.sigev_signo = SIGRTMIN; + evp.sigev_notify_attributes = NULL; + evp.sigev_value.sival_int = timer_kind; + + /* At the timer creation, the timer structure will be filled in with timer_id, + * which is unique for this process. This id is allocated by kernel and the + * value might be used to distinguish timers. + */ + if( timer_create(CLOCK_REALTIME, &evp, &timer) < 0 ) + { + S1AP_ERROR("Failed to create timer: (%s:%d)\n", strerror(errno), errno); + free(timer_p); + return -1; + } + + /* Fill in the first expiration value. */ + its.it_value.tv_sec = interval_sec; + its.it_value.tv_nsec = interval_us * 1000; + + if( type == S1AP_TIMER_PERIODIC ) + { + /* Asked for periodic timer. We set the interval time */ + its.it_interval.tv_sec = interval_sec; + its.it_interval.tv_nsec = interval_us * 1000; + } + else + { + /* Asked for one-shot timer. Do not set the interval field */ + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + } + + if( timer_settime(timer, 0, &its, NULL) ) + { + S1AP_ERROR("Failed to Settimer: (%s:%d)\n", strerror(errno), errno); + free(timer_p); + return -1; + } + + /* Simply set the timer_id argument. so it can be used by caller */ + *timer_id = (long)timer; + + timer_p->timer = timer; + + /* Lock the queue and insert the timer at the tail */ + if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex lock\n"); + if( timer_delete(timer_p->timer) < 0 ) + { + S1AP_ERROR("Failed to delete timer 0x%lx\n", (long)timer_p->timer); + } + free(timer_p); + timer_p = NULL; + + return -1; + } + + STAILQ_INSERT_TAIL(&timer_desc.timer_queue, timer_p, entries); + if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex unlock\n"); + } + + return 0; +} + +int s1ap_timer_remove(long timer_id) +{ + int rc = 0; + struct s1ap_timer_elm_s *timer_p; + + + if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex lock\n"); + if( timer_delete(timer_id) < 0 ) + { + S1AP_ERROR("Failed to delete timer 0x%lx\n", (long)timer_id); + } + + return -1; + } + + TIMER_SEARCH(timer_p, timer, ((timer_t)timer_id), &timer_desc.timer_queue); + + /* We didn't find the timer in list */ + if (timer_p == NULL) + { + S1AP_ERROR("Didn't find timer 0x%lx in list\n", timer_id); + if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex unlock\n"); + } + + return -1; + } + + timer_delete(timer_p->timer); + + STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, s1ap_timer_elm_s, entries); + + if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) + { + S1AP_ERROR("Failed to mutex unlock\n"); + } + + free(timer_p); + timer_p = NULL; + return rc; +} + +int s1ap_timer_init(void) +{ + memset(&timer_desc, 0, sizeof(timer_desc_t)); + + STAILQ_INIT(&timer_desc.timer_queue); + pthread_mutex_init(&timer_desc.timer_list_mutex, NULL); + + return 0; +} diff --git a/openair3/S1AP/s1ap_eNB_timer.h b/openair3/S1AP/s1ap_eNB_timer.h new file mode 100644 index 0000000000..7af80eb806 --- /dev/null +++ b/openair3/S1AP/s1ap_eNB_timer.h @@ -0,0 +1,86 @@ +/* + * 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 TIMER_H_ +#define TIMER_H_ + +#include + +#define SIGTIMER SIGRTMIN + +typedef enum s1ap_timer_type_s { + S1AP_TIMER_PERIODIC, + S1AP_TIMER_ONE_SHOT, + S1AP_TIMER_TYPE_MAX, +} s1ap_timer_type_t; + +typedef struct { + void *arg; + long timer_id; + int32_t timer_kind; +} s1ap_timer_has_expired_t; + + +int s1ap_timer_timeout(sigval_t info); + +/** \brief Request a new timer + * \param interval_sec timer interval in seconds + * \param interval_us timer interval in micro seconds + * \param task_id task id of the task requesting the timer + * \param instance instance of the task requesting the timer + * \param type timer type + * \param timer_id unique timer identifier + * @returns -1 on failure, 0 otherwise + **/ +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id); + +/** \brief Remove the timer from list + * \param timer_id unique timer id + * @returns -1 on failure, 0 otherwise + **/ + +int s1ap_timer_remove(long timer_id); + +/** \brief Initialize timer task and its API + * \param mme_config MME common configuration + * @returns -1 on failure, 0 otherwise + **/ +int s1ap_timer_init(void); + +#define S1AP_MMEIND 0x80000000 +#define S1AP_UEIND 0x00000000 +#define S1_SETRSP_WAIT 0x00010000 +#define S1_SETREQ_WAIT 0x00020000 +#define SCTP_REQ_WAIT 0x00030000 +#define S1AP_LINEIND 0x0000ffff +#define S1AP_TIMERIND 0x00ff0000 + +#define S1AP_TIMERID_INIT 0xffffffffffffffff + +#endif diff --git a/openair3/S1AP/s1ap_eNB_trace.c b/openair3/S1AP/s1ap_eNB_trace.c index 19f5059238..695eeb4ef8 100644 --- a/openair3/S1AP/s1ap_eNB_trace.c +++ b/openair3/S1AP/s1ap_eNB_trace.c @@ -121,6 +121,10 @@ int s1ap_eNB_handle_trace_start(uint32_t assoc_id, if (ie != NULL) { ue_desc_p = s1ap_eNB_get_ue_context(mme_ref_p->s1ap_eNB_instance, ie->value.choice.ENB_UE_S1AP_ID); + } + else + { + return -1; } if (ue_desc_p == NULL) { /* Could not find context associated with this eNB_ue_s1ap_id -> generate diff --git a/openair3/SCTP/sctp_default_values.h b/openair3/SCTP/sctp_default_values.h index 528ffb5a05..0f8f94dca9 100644 --- a/openair3/SCTP/sctp_default_values.h +++ b/openair3/SCTP/sctp_default_values.h @@ -24,8 +24,8 @@ #define SCTP_OUT_STREAMS (16) #define SCTP_IN_STREAMS (16) -#define SCTP_MAX_ATTEMPTS (2) -#define SCTP_TIMEOUT (5) +#define SCTP_MAX_ATTEMPTS (8) +#define SCTP_TIMEOUT (60000) #define SCTP_RECV_BUFFER_SIZE (8192) #endif /* SCTP_DEFAULT_VALUES_H_ */ diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index ee006338c5..ec9e62bb3f 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -943,10 +943,12 @@ sctp_eNB_read_from_socket( &sinfo, &flags); if (n < 0) { - if (errno == ENOTCONN) { + if( (errno == ENOTCONN) || (errno == ECONNRESET) || (errno == ETIMEDOUT) || (errno == ECONNREFUSED) ) + { itti_unsubscribe_event_fd(TASK_SCTP, sctp_cnx->sd); SCTP_DEBUG("Received not connected for sd %d\n", sctp_cnx->sd); + SCTP_ERROR("sctp_recvmsg (fd %d, len %d ): %s:%d\n", sctp_cnx->sd, n, strerror(errno), errno); sctp_itti_send_association_resp( sctp_cnx->task_id, sctp_cnx->instance, -1, From 8c607fe85bcae0baea227a783674403459ff85f5 Mon Sep 17 00:00:00 2001 From: "Wu.Jing" Date: Thu, 9 Apr 2020 11:39:57 +0800 Subject: [PATCH 07/15] Fix build error in --UE because of s1ap_eNB.c (cherry picked from commit 519e6628d572c9b6cf8031632d4e22e2f8dc5b93) --- openair3/S1AP/s1ap_eNB.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 8452d9e563..b3ceb7ff2c 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -329,7 +329,13 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa for( ; cnt > 0 ; ) { cnt--; - s1ap_ue_context_release( instance, (uint32_t)enb_s1ap_id[cnt] ); + struct s1ap_eNB_ue_context_s *ue_context_p = NULL; + struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL; + ue_context_p = s1ap_eNB_get_ue_context(instance_p, (uint32_t)enb_s1ap_id[cnt]); + if (ue_context_p != NULL) { + s1ap_ue_context_p = RB_REMOVE(s1ap_ue_map, &instance_p->s1ap_ue_head, ue_context_p); + s1ap_eNB_free_ue_context(s1ap_ue_context_p); + } } s1ap_mme_data_p->mme_name = 0; s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; From 4c75866a549bd70ae39b33c853f3ad9643387ecf Mon Sep 17 00:00:00 2001 From: "Wu.Jing" Date: Thu, 9 Apr 2020 12:34:02 +0800 Subject: [PATCH 08/15] Fix cppcheck warning (cherry picked from commit aaa4d390fdefc4e8071b80edc90a580907c9dec3) --- openair3/S1AP/s1ap_eNB.c | 4 ++-- openair3/S1AP/s1ap_eNB_timer.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index b3ceb7ff2c..9eebb68fe7 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -317,12 +317,12 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) { - S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%d\n", ue_p->eNB_ue_s1ap_id); + S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); } } else { - S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%d\n", ue_p->eNB_ue_s1ap_id); + S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); } } } diff --git a/openair3/S1AP/s1ap_eNB_timer.c b/openair3/S1AP/s1ap_eNB_timer.c index d4b5bdbd14..4e9fb166d3 100644 --- a/openair3/S1AP/s1ap_eNB_timer.c +++ b/openair3/S1AP/s1ap_eNB_timer.c @@ -82,11 +82,11 @@ int s1ap_timer_timeout(sigval_t info) if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) { - S1AP_ERROR("Failed to mutex unlock timeout=%x\n", timer_kind); + S1AP_ERROR("Failed to mutex unlock timeout=0x%x\n", timer_kind); } if (timer_p == NULL) { - S1AP_ERROR("Didn't find timer 0x%lx in list\n", timer_kind); + S1AP_ERROR("Didn't find timer 0x%x in list\n", timer_kind); return -1; } From 52acfc75de38e86f3c3396dec30e428b9600c20e Mon Sep 17 00:00:00 2001 From: Cai Yang Date: Thu, 9 Apr 2020 15:28:55 +0900 Subject: [PATCH 09/15] Fix s1ap_eNB_timer.c warnings (cherry picked from commit 39850dcfadb37e24ccfe41e0a85a9f2136eeff4a) --- openair3/S1AP/s1ap_eNB_timer.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB_timer.c b/openair3/S1AP/s1ap_eNB_timer.c index 4e9fb166d3..ccb294cb54 100644 --- a/openair3/S1AP/s1ap_eNB_timer.c +++ b/openair3/S1AP/s1ap_eNB_timer.c @@ -96,14 +96,14 @@ int s1ap_timer_timeout(sigval_t info) instance = timer_p->instance; message_p = itti_alloc_new_message(TASK_UNKNOWN, TIMER_HAS_EXPIRED); - timer_expired_p = &message_p->ittiMsg.timer_has_expired; + timer_expired_p = (s1ap_timer_has_expired_t *)(&message_p->ittiMsg.timer_has_expired); timer_expired_p->timer_id = (long)timer_p->timer; timer_expired_p->timer_kind = timer_p->timer_kind; timer_expired_p->arg = timer_p->timer_arg; /* Timer is a one shot timer, remove it */ - if( timer_p->type == S1AP_TIMER_ONE_SHOT ) + if( (int)timer_p->type == (int)S1AP_TIMER_ONE_SHOT ) { if( s1ap_timer_remove((long)timer_p->timer) != 0 ) { @@ -143,7 +143,7 @@ int s1ap_timer_setup( return -1; } - if( type >= S1AP_TIMER_TYPE_MAX ) + if( (int)type >= (int)S1AP_TIMER_TYPE_MAX ) { S1AP_ERROR("Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX); return -1; @@ -196,7 +196,7 @@ int s1ap_timer_setup( its.it_value.tv_sec = interval_sec; its.it_value.tv_nsec = interval_us * 1000; - if( type == S1AP_TIMER_PERIODIC ) + if( (int)type == (int)S1AP_TIMER_PERIODIC ) { /* Asked for periodic timer. We set the interval time */ its.it_interval.tv_sec = interval_sec; @@ -253,7 +253,7 @@ int s1ap_timer_remove(long timer_id) if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) { S1AP_ERROR("Failed to mutex lock\n"); - if( timer_delete(timer_id) < 0 ) + if( timer_delete((timer_t)timer_id) < 0 ) { S1AP_ERROR("Failed to delete timer 0x%lx\n", (long)timer_id); } From 4a14c4c706400311326adab8e2a8dad73bdf79a4 Mon Sep 17 00:00:00 2001 From: Wu Jing Date: Mon, 13 Apr 2020 14:37:50 +0900 Subject: [PATCH 10/15] fix build waning (cherry picked from commit 624fe21f52117959940066a6cfc5f8beac70e462) # Conflicts: # openair2/LAYER2/MAC/eNB_scheduler_RA.c # openair2/LAYER2/MAC/eNB_scheduler_dlsch.c # openair2/LAYER2/MAC/eNB_scheduler_fairRR.c # openair3/S1AP/s1ap_eNB.c # Conflicts: # openair3/S1AP/s1ap_eNB.c --- openair3/S1AP/s1ap_eNB.c | 4 ++-- openair3/S1AP/s1ap_eNB_handlers.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 9eebb68fe7..742766909b 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -105,7 +105,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, MessageDef *message_p = NULL; sctp_new_association_req_t *sctp_new_association_req_p = NULL; s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL; - struct s1ap_eNB_mme_data_s *mme = NULL; +// struct s1ap_eNB_mme_data_s *mme = NULL; DevAssert(instance_p != NULL); DevAssert(mme_ip_address != NULL); message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ); @@ -666,7 +666,7 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { case TIMER_HAS_EXPIRED: { s1ap_eNB_timer_expired(ITTI_MESSAGE_GET_INSTANCE(received_msg), - &TIMER_HAS_EXPIRED(received_msg)); + (s1ap_timer_has_expired_t *) &TIMER_HAS_EXPIRED(received_msg)); } break; diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 5d43c5b3fa..89f82fa485 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -38,6 +38,9 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_handlers.h" #include "s1ap_eNB_decoder.h" +#include "s1ap_eNB_encoder.h" + +#include "s1ap_eNB_itti_messaging.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_trace.h" @@ -818,7 +821,7 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, if (ie) { if( ie->value.choice.CriticalityDiagnostics.procedureCode ) { - S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %d\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); + S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); } // TODO continue } From cf41c788d682c301e6cb0f981add5681e3dff626 Mon Sep 17 00:00:00 2001 From: Haruki NAOI Date: Mon, 27 Jul 2020 12:34:14 +0900 Subject: [PATCH 11/15] fix s1ap stack overflow. (cherry picked from commit f6b51079021347c19d528200f04d7cdba1dde0e5) # Conflicts: # openair3/S1AP/s1ap_eNB.c --- openair3/S1AP/s1ap_eNB.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 742766909b..2501fe334c 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -285,7 +285,7 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa struct served_gummei_s* gummeiInfo; struct mme_code_s* mmeCode; int8_t cnt = 0; - unsigned enb_s1ap_id[20]; + unsigned enb_s1ap_id[NUMBER_OF_UE_MAX]; DevAssert(sctp_new_association_resp != NULL); instance_p = s1ap_eNB_get_instance(instance); DevAssert(instance_p != NULL); @@ -305,6 +305,7 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa { if( ue_p->mme_ref == s1ap_mme_data_p ) { + if(cnt < NUMBER_OF_UE_MAX){ enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; cnt++; @@ -324,6 +325,9 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa { S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); } + }else{ + S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); + } } } for( ; cnt > 0 ; ) @@ -419,18 +423,18 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa // } else { - /* Update parameters */ - s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; - s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; - s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; - /* Prepare new S1 Setup Request */ - s1ap_mme_data_p->s1_setupreq_cnt = 0; - s1ap_mme_data_p->sctp_req_cnt = 0; - if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) { - S1AP_ERROR("s1ap eNB generate s1 setup request failed\n"); - return; + /* Update parameters */ + s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; + s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; + s1ap_mme_data_p->out_streams = sctp_new_association_resp->out_streams; + /* Prepare new S1 Setup Request */ + s1ap_mme_data_p->s1_setupreq_cnt = 0; + s1ap_mme_data_p->sctp_req_cnt = 0; + if (s1ap_eNB_generate_s1_setup_request(instance_p, s1ap_mme_data_p) == -1) { + S1AP_ERROR("s1ap eNB generate s1 setup request failed\n"); + return; + } } -} static void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { From 27413fc4fc58347f18abe8aaab4de4d39119a768 Mon Sep 17 00:00:00 2001 From: "masayuki.harada" Date: Fri, 20 Nov 2020 22:13:27 +0900 Subject: [PATCH 12/15] Fix merge miss. --- openair2/COMMON/tasks_def.h | 3 +- openair2/X2AP/x2ap_common.h | 2 +- openair3/S1AP/s1ap_eNB.c | 123 +++++++++++++----------------------- 3 files changed, 47 insertions(+), 81 deletions(-) diff --git a/openair2/COMMON/tasks_def.h b/openair2/COMMON/tasks_def.h index f84195d5d7..33b6d5f9d4 100644 --- a/openair2/COMMON/tasks_def.h +++ b/openair2/COMMON/tasks_def.h @@ -47,8 +47,7 @@ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200) TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000) // GTP_V1U task TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000) -//TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200) -TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 2000) +TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200) TASK_DEF(TASK_CU_F1, TASK_PRIORITY_MED, 200) TASK_DEF(TASK_DU_F1, TASK_PRIORITY_MED, 200) /// M3ap task, acts as both source and target diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index 470a023c31..a2f903a737 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -84,7 +84,7 @@ extern int asn1_xer_print; break; \ } \ } \ -/* if (mandatory) DevAssert(ie != NULL); \*/ \ + if (mandatory) DevAssert(ie != NULL); \ } while(0) /** \brief Function callback prototype. diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 2501fe334c..c011653f76 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -121,55 +121,31 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p, local_ip_addr, sizeof(*local_ip_addr)); S1AP_INFO("[eNB %d] check the mme registration state\n",instance_p->instance); -// mme = NULL; -// -// if ( mme == NULL ) { - /* Create new MME descriptor */ - s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); - DevAssert(s1ap_mme_data_p != NULL); - s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); - sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; - s1ap_mme_data_p->assoc_id = -1; - s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; - memcpy(&s1ap_mme_data_p->mme_s1_ip, - mme_ip_address, - sizeof(*mme_ip_address)); - for (int i = 0; i < broadcast_plmn_num; ++i) - s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; + /* Create new MME descriptor */ + s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p)); + DevAssert(s1ap_mme_data_p != NULL); + s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id(); + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + s1ap_mme_data_p->assoc_id = -1; + s1ap_mme_data_p->broadcast_plmn_num = broadcast_plmn_num; + memcpy(&s1ap_mme_data_p->mme_s1_ip, + mme_ip_address, + sizeof(*mme_ip_address)); + for (int i = 0; i < broadcast_plmn_num; ++i) + s1ap_mme_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i]; - s1ap_mme_data_p->s1ap_eNB_instance = instance_p; - STAILQ_INIT(&s1ap_mme_data_p->served_gummei); - /* Insert the new descriptor in list of known MME - * but not yet associated. - */ - RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); -// s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING; - s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; - memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) ); - s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; - s1ap_mme_data_p->sctp_req_cnt++; - s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; -// instance_p->s1ap_mme_nb ++; - instance_p->s1ap_mme_pending_nb ++; -// } else if (mme->state == S1AP_ENB_STATE_WAITING) { -// instance_p->s1ap_mme_pending_nb ++; -// sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; -// S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", -// instance_p->instance, -// mme->state, mme->cnx_id, -// instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); -// /*s1ap_mme_data_p->cnx_id = mme->cnx_id; -// sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id; -// -// s1ap_mme_data_p->assoc_id = -1; -// s1ap_mme_data_p->s1ap_eNB_instance = instance_p; -// */ -// } else { -// S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n", -// instance_p->instance, -// mme->state, mme->cnx_id, -// instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb); -// } + s1ap_mme_data_p->s1ap_eNB_instance = instance_p; + STAILQ_INIT(&s1ap_mme_data_p->served_gummei); + /* Insert the new descriptor in list of known MME + * but not yet associated. + */ + RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p); + s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; + memcpy( &(s1ap_mme_data_p->mme_ip_address), mme_ip_address, sizeof(net_ip_address_t) ); + s1ap_mme_data_p->overload_state = S1AP_NO_OVERLOAD; + s1ap_mme_data_p->sctp_req_cnt++; + s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; + instance_p->s1ap_mme_pending_nb ++; itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); } @@ -210,8 +186,8 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * new_instance->tac = s1ap_register_eNB->tac; memcpy(&new_instance->eNB_s1_ip, - &s1ap_register_eNB->enb_ip_address, - sizeof(s1ap_register_eNB->enb_ip_address)); + &s1ap_register_eNB->enb_ip_address, + sizeof(s1ap_register_eNB->enb_ip_address)); for (int i = 0; i < s1ap_register_eNB->num_plmn; i++) { new_instance->mcc[i] = s1ap_register_eNB->mcc[i]; @@ -238,8 +214,6 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * s1ap_register_eNB->eNB_id); } -// DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS, -// S1AP_MAX_NB_MME_IP_ADDRESS, s1ap_register_eNB->nb_mme, 0); if( s1ap_register_eNB->nb_mme > S1AP_MAX_NB_MME_IP_ADDRESS ) { S1AP_ERROR("Invalid MME number = %d\n ", s1ap_register_eNB->nb_mme); @@ -306,27 +280,27 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa if( ue_p->mme_ref == s1ap_mme_data_p ) { if(cnt < NUMBER_OF_UE_MAX){ - enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; - cnt++; - - message_p = NULL; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); - - if( message_p != NULL ) - { - S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; + enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; + cnt++; - if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) + message_p = NULL; + message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); + + if( message_p != NULL ) { - S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; + + if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) + { + S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); + } + } + else + { + S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); } - } - else - { - S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); - } }else{ - S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); + S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); } } } @@ -396,7 +370,7 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa { S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); } - } + } else { S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id); @@ -413,14 +387,6 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; } } -// if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) { -// S1AP_WARN("Received unsuccessful result for SCTP association (%u), instance %d, cnx_id %u\n", -// sctp_new_association_resp->sctp_state, -// instance, -// sctp_new_association_resp->ulp_cnx_id); -// s1ap_handle_s1_setup_message(s1ap_mme_data_p, sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN); -// return; -// } else { /* Update parameters */ @@ -435,6 +401,7 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa return; } } +} static void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { From 674339237fd94c7c79dc8c1af49f90b9a31da1f7 Mon Sep 17 00:00:00 2001 From: "masayuki.harada" Date: Tue, 24 Nov 2020 11:11:54 +0900 Subject: [PATCH 13/15] Add handling of error case. --- openair3/GTPV1-U/gtpv1u_eNB.c | 2 +- openair3/NAS/COMMON/EMM/MSG/AttachAccept.c | 1 - openair3/S1AP/s1ap_eNB.c | 6 ++++-- openair3/S1AP/s1ap_eNB_decoder.c | 2 -- openair3/SCTP/sctp_eNB_task.c | 8 ++++---- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/openair3/GTPV1-U/gtpv1u_eNB.c b/openair3/GTPV1-U/gtpv1u_eNB.c index 1e2954ba95..25f506f9a1 100644 --- a/openair3/GTPV1-U/gtpv1u_eNB.c +++ b/openair3/GTPV1-U/gtpv1u_eNB.c @@ -1211,7 +1211,7 @@ int gtpv1u_eNB_init(void) { //gtpv1u_data_g.udp_data; RC.gtpv1u_data_g->seq_num = 0; RC.gtpv1u_data_g->restart_counter = 0; - + RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up = 0; /* Initializing GTPv1-U stack */ if ((rc = nwGtpv1uInitialize(&RC.gtpv1u_data_g->gtpv1u_stack, GTPU_STACK_ENB)) != NW_GTPV1U_OK) { LOG_E(GTPU, "Failed to setup nwGtpv1u stack %x\n", rc); diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c index 8ac43cf7b1..637d930226 100644 --- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c +++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c @@ -190,7 +190,6 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint default: errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI; LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded); - AssertFatal(0, " "); return TLV_DECODE_UNEXPECTED_IEI; } } diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c011653f76..9435296371 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -411,8 +411,10 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { mme_test_s1_notify_sctp_data_ind(sctp_data_ind->assoc_id, sctp_data_ind->stream, sctp_data_ind->buffer, sctp_data_ind->buffer_length); #else - s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, - sctp_data_ind->buffer, sctp_data_ind->buffer_length); + if (s1ap_eNB_handle_message(sctp_data_ind->assoc_id, sctp_data_ind->stream, + sctp_data_ind->buffer, sctp_data_ind->buffer_length) == -1) { + S1AP_ERROR("Failed to handle s1ap eNB message\n"); + } #endif result = itti_free(TASK_UNKNOWN, sctp_data_ind->buffer); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); diff --git a/openair3/S1AP/s1ap_eNB_decoder.c b/openair3/S1AP/s1ap_eNB_decoder.c index 4635946a05..14e4b49238 100644 --- a/openair3/S1AP/s1ap_eNB_decoder.c +++ b/openair3/S1AP/s1ap_eNB_decoder.c @@ -89,8 +89,6 @@ static int s1ap_eNB_decode_initiating_message(S1AP_S1AP_PDU_t *pdu) { default: S1AP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage.procedureCode); - AssertFatal( 0, "Unknown procedure ID (%d) for initiating message\n", - (int)pdu->choice.initiatingMessage.procedureCode); return -1; } diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index ec9e62bb3f..abaae7090f 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -270,7 +270,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv6_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv6 address %*s to network type\n", @@ -290,7 +290,7 @@ sctp_handle_new_association_req_multi( sctp_new_association_req_p->remote_address.ipv4_address); //close(sd); //return; - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: inet_pton error"); } SCTP_DEBUG("Converted ipv4 address %*s to network type\n", @@ -329,7 +329,7 @@ sctp_handle_new_association_req_multi( if (ns == -1) { perror("sctp_peeloff"); printf("sctp_peeloff: sd=%d assoc_id=%d\n", sd, assoc_id); - exit(1); + exit_fun("sctp_handle_new_association_req_multi fatal: sctp_peeloff error"); } sctp_cnx = calloc(1, sizeof(*sctp_cnx)); @@ -971,7 +971,7 @@ sctp_eNB_read_from_socket( if (!(flags & MSG_EOR)) { SCTP_ERROR("fatal: partial SCTP messages are not handled\n"); - exit(1); + exit_fun("fatal: partial SCTP messages are not handled" ); } if (flags & MSG_NOTIFICATION) { From 969425f6a8a5cec22d8b70e26683cc2a3954c4f0 Mon Sep 17 00:00:00 2001 From: "masayuki.harada" Date: Tue, 9 Mar 2021 03:25:00 +0900 Subject: [PATCH 14/15] Replace to itti timer. Fix nnsf selection. Fix indentation and opening brace. --- openair3/S1AP/s1ap_eNB.c | 327 ++++++++---------- openair3/S1AP/s1ap_eNB_handlers.c | 52 +-- .../S1AP/s1ap_eNB_management_procedures.c | 29 +- openair3/S1AP/s1ap_eNB_nas_procedures.c | 9 +- openair3/S1AP/s1ap_eNB_nnsf.c | 102 +++--- openair3/S1AP/s1ap_eNB_nnsf.h | 3 +- openair3/S1AP/s1ap_eNB_timer.c | 260 +------------- 7 files changed, 226 insertions(+), 556 deletions(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c40cc7cea9..6cb82de8d3 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -78,7 +78,7 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p); void s1ap_eNB_timer_expired(instance_t instance, - s1ap_timer_has_expired_t *msg_p); + timer_has_expired_t *msg_p); uint32_t s1ap_generate_eNB_id(void) { char *out; @@ -157,7 +157,6 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * uint8_t index; DevAssert(s1ap_register_eNB != NULL); /* Look if the provided instance already exists */ - s1ap_timer_init(); new_instance = s1ap_eNB_get_instance(instance); if (new_instance != NULL) { @@ -268,45 +267,36 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa sctp_new_association_resp->ulp_cnx_id); DevAssert(s1ap_mme_data_p != NULL); memset(enb_s1ap_id, 0, sizeof(enb_s1ap_id) ); - if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) - { + if( s1ap_mme_data_p->timer_id != S1AP_TIMERID_INIT ) { s1ap_timer_remove( s1ap_mme_data_p->timer_id ); s1ap_mme_data_p->timer_id = S1AP_TIMERID_INIT; } - if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) - { - RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) - { - if( ue_p->mme_ref == s1ap_mme_data_p ) - { - if(cnt < NUMBER_OF_UE_MAX){ + if( sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED ) { + RB_FOREACH(ue_p, s1ap_ue_map, &instance_p->s1ap_ue_head) { + if( ue_p->mme_ref == s1ap_mme_data_p ) { + if(cnt < NUMBER_OF_UE_MAX) { enb_s1ap_id[cnt] = ue_p->eNB_ue_s1ap_id; cnt++; message_p = NULL; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); - if( message_p != NULL ) - { + if( message_p != NULL ) { S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = ue_p->eNB_ue_s1ap_id; - if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) - { + if( itti_send_msg_to_task(TASK_RRC_ENB, ue_p->eNB_instance->instance, message_p) < 0 ) { S1AP_ERROR("UE Context Release Command Transmission Failure: eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); } - } - else - { + } else { S1AP_ERROR("Invalid message_p : eNB_ue_s1ap_id=%u\n", ue_p->eNB_ue_s1ap_id); } }else{ - S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); + S1AP_ERROR("s1ap_eNB_handle_sctp_association_resp: cnt %d > max\n", cnt); } } } - for( ; cnt > 0 ; ) - { + for( ; cnt > 0 ; ) { cnt--; struct s1ap_eNB_ue_context_s *ue_context_p = NULL; struct s1ap_eNB_ue_context_s *s1ap_ue_context_p = NULL; @@ -323,25 +313,21 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa s1ap_mme_data_p->out_streams = 0; s1ap_mme_data_p->assoc_id = -1; - while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) - { + while (!STAILQ_EMPTY(&s1ap_mme_data_p->served_gummei)) { gummeiInfo = STAILQ_FIRST(&s1ap_mme_data_p->served_gummei); STAILQ_REMOVE_HEAD(&s1ap_mme_data_p->served_gummei, next); - while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) - { + while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) { plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns); STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next); free(plmnInfo); } - while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) - { + while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) { groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids); STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next); free(groupInfo); } - while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) - { + while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) { mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes); STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next); free(mmeCode); @@ -351,45 +337,33 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa STAILQ_INIT(&s1ap_mme_data_p->served_gummei); - if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) - { + if( s1ap_mme_data_p->state == S1AP_ENB_STATE_DISCONNECTED ) { if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || - (instance_p->sctp_req_count == 0xffff) ) - { + (instance_p->sctp_req_count == 0xffff) ) { timer_kind = s1ap_mme_data_p->cnx_id; timer_kind = timer_kind | S1AP_MMEIND; timer_kind = timer_kind | SCTP_REQ_WAIT; if( s1ap_timer_setup( instance_p->sctp_req_timer, 0, TASK_S1AP, instance_p->instance, - timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) - { + timer_kind, S1AP_TIMER_ONE_SHOT, NULL, &s1ap_mme_data_p->timer_id) < 0 ) { S1AP_ERROR("Timer Start NG(SCTP retransmission wait timer) : MME=%d\n",s1ap_mme_data_p->cnx_id); s1ap_sctp_req( instance_p, s1ap_mme_data_p ); } - } - else - { + } else { S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); } - } - else - { + } else { S1AP_ERROR("SCTP disconnection reception : MME = %d\n",s1ap_mme_data_p->cnx_id); if( (s1ap_mme_data_p->sctp_req_cnt <= instance_p->sctp_req_count) || - (instance_p->sctp_req_count == 0xffff) ) - { + (instance_p->sctp_req_count == 0xffff) ) { s1ap_sctp_req( instance_p, s1ap_mme_data_p ); - } - else - { + } else { S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",s1ap_mme_data_p->cnx_id); } s1ap_mme_data_p->state = S1AP_ENB_STATE_DISCONNECTED; } - } - else - { + } else { /* Update parameters */ s1ap_mme_data_p->assoc_id = sctp_new_association_resp->assoc_id; s1ap_mme_data_p->in_streams = sctp_new_association_resp->in_streams; @@ -422,101 +396,81 @@ void s1ap_eNB_handle_sctp_data_ind(sctp_data_ind_t *sctp_data_ind) { } void s1ap_eNB_timer_expired( - instance_t instance, - s1ap_timer_has_expired_t *msg_p) + instance_t instance, + timer_has_expired_t *msg_p) { - uint32_t timer_kind = 0; - int16_t line_ind = 0; - s1ap_eNB_mme_data_t *mme_desc_p = NULL; - uint32_t timer_ind = 0; - s1ap_eNB_instance_t *instance_p = NULL; - long timer_id = S1AP_TIMERID_INIT; - - instance_p = s1ap_eNB_get_instance(instance); - timer_kind = msg_p->timer_kind; - line_ind = (int16_t)(timer_kind & S1AP_LINEIND); - timer_id = msg_p->timer_id; - - if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) - { - mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind); - if(mme_desc_p != NULL) + uint32_t timer_kind = 0; + int16_t line_ind = 0; + s1ap_eNB_mme_data_t *mme_desc_p = NULL; + uint32_t timer_ind = 0; + s1ap_eNB_instance_t *instance_p = NULL; + long timer_id = S1AP_TIMERID_INIT; + + instance_p = s1ap_eNB_get_instance(instance); + timer_kind = *((uint32_t*)msg_p->arg); + line_ind = (int16_t)(timer_kind & S1AP_LINEIND); + timer_id = msg_p->timer_id; + + if( (timer_kind & S1AP_MMEIND) == S1AP_MMEIND ) { + mme_desc_p = s1ap_eNB_get_MME(instance_p, -1, line_ind); + if(mme_desc_p != NULL) { + if( timer_id == mme_desc_p->timer_id ) { + mme_desc_p->timer_id = S1AP_TIMERID_INIT; + timer_ind = timer_kind & S1AP_TIMERIND; + + switch(timer_ind) { - if( timer_id == mme_desc_p->timer_id ) - { - mme_desc_p->timer_id = S1AP_TIMERID_INIT; - timer_ind = timer_kind & S1AP_TIMERIND; - - switch(timer_ind) - { - case S1_SETRSP_WAIT: - { - if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || - (instance_p->s1_setupreq_count == 0xffff) ) - { - s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); - } - else - { - S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); - } - break; - } - case S1_SETREQ_WAIT: - { - if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || - (instance_p->s1_setupreq_count == 0xffff) ) - { - s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); - } - else - { - S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); - } - break; - } - case SCTP_REQ_WAIT: - { - if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) || - (instance_p->sctp_req_count == 0xffff) ) - { - s1ap_sctp_req( instance_p, mme_desc_p ); - } - else - { - S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind); - } - break; - } - default: - { - S1AP_WARN("Invalid Timer indication\n"); - break; - } - } + case S1_SETRSP_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); } - else - { - S1AP_DEBUG("Unmatch timer id\n"); - return; + break; + } + case S1_SETREQ_WAIT: + { + if( (instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || + (instance_p->s1_setupreq_count == 0xffff) ) { + s1ap_eNB_generate_s1_setup_request( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",line_ind); } + break; + } + case SCTP_REQ_WAIT: + { + if( (instance_p->sctp_req_count >= mme_desc_p->sctp_req_cnt) || + (instance_p->sctp_req_count == 0xffff) ) { + s1ap_sctp_req( instance_p, mme_desc_p ); + } else { + S1AP_ERROR("Retransmission count exceeded of SCTP : MME=%d\n",line_ind); + } + break; + } + default: + { + S1AP_WARN("Invalid Timer indication\n"); + break; + } } - else - { - S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind); - return; - } + } else { + S1AP_DEBUG("Unmatch timer id\n"); + return; + } + } else { + S1AP_WARN("Not applicable MME detected : connection id = %d\n", line_ind); + return; } - else - { - } - return; + } + return; } void s1ap_eNB_init(void) { S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); - s1ap_timer_init(); itti_mark_task_ready(TASK_S1AP); MSC_START_USE(); } @@ -639,8 +593,8 @@ void *s1ap_eNB_process_itti_msg(void *notUsed) { case TIMER_HAS_EXPIRED: { - s1ap_eNB_timer_expired(ITTI_MESSAGE_GET_INSTANCE(received_msg), - (s1ap_timer_has_expired_t *) &TIMER_HAS_EXPIRED(received_msg)); + s1ap_eNB_timer_expired(ITTI_MSG_DESTINATION_INSTANCE(received_msg), + &received_msg->ittiMsg.timer_has_expired); } break; @@ -781,61 +735,52 @@ static int s1ap_eNB_generate_s1_setup_request( static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p) { - MessageDef *message_p = NULL; - sctp_new_association_req_t *sctp_new_association_req_p = NULL; - - if( instance_p == NULL ) - { - S1AP_ERROR("Invalid instance_p\n"); - return -1; + MessageDef *message_p = NULL; + sctp_new_association_req_t *sctp_new_association_req_p = NULL; + + if( instance_p == NULL ) + { + S1AP_ERROR("Invalid instance_p\n"); + return -1; + } + + message_p = itti_alloc_new_message(TASK_S1AP, 0, SCTP_NEW_ASSOCIATION_REQ); + sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; + sctp_new_association_req_p->port = S1AP_PORT_NUMBER; + sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; + sctp_new_association_req_p->in_streams = instance_p->sctp_in_streams; + sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams; + sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; + + if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv4 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n"); + return -1; } - - message_p = itti_alloc_new_message(TASK_S1AP, SCTP_NEW_ASSOCIATION_REQ); - sctp_new_association_req_p = &message_p->ittiMsg.sctp_new_association_req; - sctp_new_association_req_p->port = S1AP_PORT_NUMBER; - sctp_new_association_req_p->ppid = S1AP_SCTP_PPID; - sctp_new_association_req_p->in_streams = instance_p->sctp_in_streams; - sctp_new_association_req_p->out_streams = instance_p->sctp_out_streams; - sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id; - - if( s1ap_mme_data_p->mme_ip_address.ipv4 != 0 ) - { - memcpy(&sctp_new_association_req_p->remote_address, - &s1ap_mme_data_p->mme_ip_address, - sizeof(net_ip_address_t)); - if( instance_p->enb_ip_address.ipv4 != 0 ) - { - memcpy(&sctp_new_association_req_p->local_address, - &instance_p->enb_ip_address, - sizeof(net_ip_address_t)); - } - else - { - S1AP_ERROR("Invalid IP Address Format V4(MME):V6\n"); - return -1; - } + } else { + memcpy(&sctp_new_association_req_p->remote_address, + &s1ap_mme_data_p->mme_ip_address, + sizeof(net_ip_address_t)); + if( instance_p->enb_ip_address.ipv6 != 0 ) { + memcpy(&sctp_new_association_req_p->local_address, + &instance_p->enb_ip_address, + sizeof(net_ip_address_t)); + } else { + S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n"); + return -1; } - else - { - memcpy(&sctp_new_association_req_p->remote_address, - &s1ap_mme_data_p->mme_ip_address, - sizeof(net_ip_address_t)); - if( instance_p->enb_ip_address.ipv6 != 0 ) - { - memcpy(&sctp_new_association_req_p->local_address, - &instance_p->enb_ip_address, - sizeof(net_ip_address_t)); - } - else - { - S1AP_ERROR("Invalid IP Address Format V6(MME):V4\n"); - return -1; - } - } - - itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); - - s1ap_mme_data_p->sctp_req_cnt++; - - return 0; + } + + itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p); + + s1ap_mme_data_p->sctp_req_cnt++; + + return 0; } diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index ce9e2ce302..7c611b0fbf 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -290,8 +290,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, S1AP_ProtocolIE_ID_id_Cause,true); - if(ie == NULL) - { + if(ie == NULL) { return -1; } @@ -302,19 +301,16 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, S1AP_ERROR("Received s1 setup failure for MME... please check your parameters\n"); } - if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) - { + if( mme_desc_p->timer_id != S1AP_TIMERID_INIT ) { s1ap_timer_remove( mme_desc_p->timer_id ); mme_desc_p->timer_id = S1AP_TIMERID_INIT; } instance_p = mme_desc_p->s1ap_eNB_instance; if( ( instance_p->s1_setupreq_count >= mme_desc_p->s1_setupreq_cnt) || - ( instance_p->s1_setupreq_count == 0xffff) ) - { + ( instance_p->s1_setupreq_count == 0xffff) ) { S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupFailureIEs_t, ie, container, S1AP_ProtocolIE_ID_id_TimeToWait, false); - if( ie != NULL ) - { + if( ie != NULL ) { switch(ie->value.choice.TimeToWait) { case S1AP_TimeToWait_v1s: @@ -339,9 +335,7 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, interval_sec = instance_p->s1_setupreq_wait_timer; break; } - } - else - { + } else { interval_sec = instance_p->s1_setupreq_wait_timer; } @@ -350,16 +344,12 @@ int s1ap_eNB_handle_s1_setup_failure(uint32_t assoc_id, timer_kind = timer_kind | S1_SETREQ_WAIT; if( s1ap_timer_setup(interval_sec, 0, TASK_S1AP, instance_p->instance, timer_kind, S1AP_TIMER_ONE_SHOT, - NULL, &mme_desc_p->timer_id) < 0 ) - { + NULL, &mme_desc_p->timer_id) < 0 ) { S1AP_ERROR("Timer Start NG(S1 Setup Request) : MME=%d\n",mme_desc_p->cnx_id); - s1ap_eNB_snd_s1_setup_request( instance_p, mme_desc_p ); } - } - else - { - S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id); + } else { + S1AP_ERROR("Retransmission count exceeded of S1 SETUP REQUEST : MME=%d\n",mme_desc_p->cnx_id); } return 0; } @@ -391,16 +381,14 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, /* Set the capacity of this MME */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); - if(ie == NULL) - { + if(ie == NULL) { return -1; } mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_ServedGUMMEIs, true); - if(ie == NULL) - { + if(ie == NULL) { return -1; } @@ -462,13 +450,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next); } - - /* Set the capacity of this MME */ -// S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, -// S1AP_ProtocolIE_ID_id_RelativeMMECapacity, true); -// -// mme_desc_p->relative_mme_capacity = ie->value.choice.RelativeMMECapacity; -// + /* Optionaly set the mme name */ S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_S1SetupResponseIEs_t, ie, container, S1AP_ProtocolIE_ID_id_MMEname, false); @@ -486,7 +468,6 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; -// s1ap_handle_s1_setup_message(mme_desc_p, 0); return 0; } @@ -819,8 +800,7 @@ int s1ap_eNB_handle_error_indication(uint32_t assoc_id, S1AP_ProtocolIE_ID_id_CriticalityDiagnostics, false); if (ie) { - if( ie->value.choice.CriticalityDiagnostics.procedureCode ) - { + if( ie->value.choice.CriticalityDiagnostics.procedureCode ) { S1AP_WARN("Received S1 Error indication CriticalityDiagnostics procedureCode = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode); } // TODO continue @@ -1023,8 +1003,7 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_UEContextReleaseCommand_IEs_t, ie, container, S1AP_ProtocolIE_ID_id_Cause, true); - if( ie == NULL ) - { + if( ie == NULL ) { S1AP_ERROR( "Mandatory Element Nothing : UEContextReleaseCommand(Cause)\n" ); return -1; } @@ -1076,9 +1055,6 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, //#warning "TODO mapping mme_ue_s1ap_id enb_ue_s1ap_id?" case S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID: -// mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.uE_S1AP_ID_pair.mME_UE_S1AP_ID; -// S1AP_ERROR("TO DO mapping mme_ue_s1ap_id enb_ue_s1ap_id"); -// (void)mme_ue_s1ap_id; /* TODO: remove - it's to remove gcc warning about unused var */ mme_ue_s1ap_id = ie->value.choice.UE_S1AP_IDs.choice.mME_UE_S1AP_ID; RB_FOREACH(ue_desc_p, s1ap_ue_map, &mme_desc_p->s1ap_eNB_instance->s1ap_ue_head) @@ -1087,7 +1063,7 @@ int s1ap_eNB_handle_ue_context_release_command(uint32_t assoc_id, { enb_ue_s1ap_id = ue_desc_p->eNB_ue_s1ap_id; - message_p = itti_alloc_new_message(TASK_S1AP, S1AP_UE_CONTEXT_RELEASE_COMMAND); + message_p = itti_alloc_new_message(TASK_S1AP, 0, S1AP_UE_CONTEXT_RELEASE_COMMAND); S1AP_UE_CONTEXT_RELEASE_COMMAND(message_p).eNB_ue_s1ap_id = enb_ue_s1ap_id; itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p); diff --git a/openair3/S1AP/s1ap_eNB_management_procedures.c b/openair3/S1AP/s1ap_eNB_management_procedures.c index 1fdc09664b..a870e975a2 100644 --- a/openair3/S1AP/s1ap_eNB_management_procedures.c +++ b/openair3/S1AP/s1ap_eNB_management_procedures.c @@ -102,8 +102,7 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME( temp.assoc_id = assoc_id; temp.cnx_id = cnx_id; - if( cnx_id != 0 ) - { + if( cnx_id != 0 ) { if (instance_p == NULL) { STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, s1ap_eNB_entries) { @@ -116,29 +115,19 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME( } else { return RB_FIND(s1ap_mme_map, &instance_p->s1ap_mme_head, &temp); } - } - else - { - if (instance_p == NULL) - { + } else { + if (instance_p == NULL) { STAILQ_FOREACH(instance_p, &s1ap_eNB_internal_data.s1ap_eNB_instances_head, - s1ap_eNB_entries) - { - RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) - { - if( mme_p->assoc_id == assoc_id ) - { + s1ap_eNB_entries) { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { return mme_p; } } } - } - else - { - RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) - { - if( mme_p->assoc_id == assoc_id ) - { + } else { + RB_FOREACH(mme_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { + if( mme_p->assoc_id == assoc_id ) { return mme_p; } } diff --git a/openair3/S1AP/s1ap_eNB_nas_procedures.c b/openair3/S1AP/s1ap_eNB_nas_procedures.c index 206201089d..b55bc06e11 100644 --- a/openair3/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair3/S1AP/s1ap_eNB_nas_procedures.c @@ -139,8 +139,7 @@ int s1ap_eNB_handle_nas_first_req( */ mme_desc_p = s1ap_eNB_nnsf_select_mme( instance_p, - s1ap_nas_first_req_p->establishment_cause, - s1ap_nas_first_req_p->selected_plmn_identity); + s1ap_nas_first_req_p->establishment_cause); if (mme_desc_p) { S1AP_INFO("[eNB %ld] Chose MME '%s' (assoc_id %d) through highest relative capacity\n", @@ -233,9 +232,9 @@ int s1ap_eNB_handle_nas_first_req( MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id, 0, // Cell ID &ie->value.choice.EUTRAN_CGI.cell_ID); - MCC_MNC_TO_TBCD(instance_p->mcc[mme_desc_p->broadcast_plmn_index[0]], - instance_p->mnc[mme_desc_p->broadcast_plmn_index[0]], - instance_p->mnc_digit_length[mme_desc_p->broadcast_plmn_index[0]], + MCC_MNC_TO_TBCD(instance_p->mcc[ue_desc_p->selected_plmn_identity], + instance_p->mnc[ue_desc_p->selected_plmn_identity], + instance_p->mnc_digit_length[ue_desc_p->selected_plmn_identity], &ie->value.choice.EUTRAN_CGI.pLMNidentity); ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie); /* Set the establishment cause according to those provided by RRC */ diff --git a/openair3/S1AP/s1ap_eNB_nnsf.c b/openair3/S1AP/s1ap_eNB_nnsf.c index 6577b8f10b..a5a4e74734 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.c +++ b/openair3/S1AP/s1ap_eNB_nnsf.c @@ -36,17 +36,18 @@ #include "s1ap_eNB_defs.h" #include "s1ap_eNB_nnsf.h" + +typedef struct MME_nnsf_inf { + struct s1ap_eNB_mme_data_s *mme_p; + uint64_t weight; +} MME_nnsf_inf_t; + struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, - rrc_establishment_cause_t cause, - uint32_t plmn_id) + rrc_establishment_cause_t cause) { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - typedef struct MME_nnsf_inf { - struct s1ap_eNB_mme_data_s *mme_p; - uint64_t weight; - } MME_nnsf_inf_t; uint16_t capacity_sum = 0; MME_nnsf_inf_t mme_inf[10]; @@ -55,9 +56,8 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, uint64_t weight = 0; memset(mme_inf, 0, sizeof(mme_inf)); - + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { - struct served_gummei_s *gummei_p = NULL; capacity_sum = capacity_sum + mme_data_p->relative_mme_capacity; if (mme_data_p->state != S1AP_ENB_STATE_CONNECTED) { /* The association between MME and eNB is not ready for the moment, @@ -83,7 +83,8 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, || (cause == RRC_CAUSE_HIGH_PRIO_ACCESS))) { continue; } - + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; /* At this point, the RRC establishment can be handled by the MME * even if it is in overload state. */ @@ -92,58 +93,27 @@ s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, continue; } } - - gummei_p = mme_data_p->served_gummei.stqh_first; - if( gummei_p != NULL ) - { - struct plmn_identity_s *served_plmns_p = NULL; - - served_plmns_p = gummei_p->served_plmns.stqh_first; - if( served_plmns_p != 0 ) - for( cnt = 0 ; cnt < 8 ; cnt++) - { - if ( (served_plmns_p->mcc == instance_p->mcc[plmn_id]) && - (served_plmns_p->mnc == instance_p->mnc[plmn_id]) ) - { - mme_inf[nb_mme].mme_p = mme_data_p; - nb_mme++; - break; - } - if( served_plmns_p->next.stqe_next == 0 ) - { - break; - } - served_plmns_p = served_plmns_p->next.stqe_next; - } - } } - if( nb_mme != 0 ) - { - for( cnt = 0 ; cnt < nb_mme ; cnt++ ) - { + + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); } mme_highest_capacity_p = mme_inf[0].mme_p; weight = mme_inf[0].weight; - for( cnt = 1 ; cnt < nb_mme ; cnt++ ) - { - if( weight > mme_inf[cnt].weight ) - { + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { mme_highest_capacity_p = mme_inf[cnt].mme_p; weight = mme_inf[cnt].weight; } } - } - else - { + } else { mme_highest_capacity_p = NULL; } - if( mme_highest_capacity_p != NULL ) - { + if( mme_highest_capacity_p != NULL ) { mme_highest_capacity_p->nb_calls++; } - return mme_highest_capacity_p; } @@ -154,8 +124,15 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, { struct s1ap_eNB_mme_data_s *mme_data_p = NULL; struct s1ap_eNB_mme_data_s *mme_highest_capacity_p = NULL; - uint8_t current_capacity = 0; - + + uint16_t capacity_sum = 0; + MME_nnsf_inf_t mme_inf[10]; + int cnt; + int nb_mme = 0; + uint64_t weight = 0; + + memset(mme_inf, 0, sizeof(mme_inf)); + RB_FOREACH(mme_data_p, s1ap_mme_map, &instance_p->s1ap_mme_head) { struct served_gummei_s *gummei_p = NULL; struct plmn_identity_s *served_plmn_p = NULL; @@ -198,6 +175,8 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, STAILQ_FOREACH(served_plmn_p, &gummei_p->served_plmns, next) { if ((served_plmn_p->mcc == instance_p->mcc[selected_plmn_identity]) && (served_plmn_p->mnc == instance_p->mnc[selected_plmn_identity])) { + mme_inf[nb_mme].mme_p = mme_data_p; + nb_mme++; break; } } @@ -206,14 +185,27 @@ s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, } /* if we didn't find such a served PLMN, go on with the next MME */ if (!served_plmn_p) continue; - - if (current_capacity < mme_data_p->relative_mme_capacity) { - /* We find a better MME, keep a reference to it */ - current_capacity = mme_data_p->relative_mme_capacity; - mme_highest_capacity_p = mme_data_p; - } } + if( nb_mme != 0 ) { + for( cnt = 0 ; cnt < nb_mme ; cnt++ ) { + mme_inf[cnt].weight = (capacity_sum*10)/mme_inf[cnt].mme_p->relative_mme_capacity; + mme_inf[cnt].weight = (mme_inf[cnt].weight)*(mme_inf[cnt].mme_p->nb_calls + 1); + } + mme_highest_capacity_p = mme_inf[0].mme_p; + weight = mme_inf[0].weight; + for( cnt = 1 ; cnt < nb_mme ; cnt++ ) { + if( weight > mme_inf[cnt].weight ) { + mme_highest_capacity_p = mme_inf[cnt].mme_p; + weight = mme_inf[cnt].weight; + } + } + } else { + mme_highest_capacity_p = NULL; + } + if( mme_highest_capacity_p != NULL ) { + mme_highest_capacity_p->nb_calls++; + } return mme_highest_capacity_p; } diff --git a/openair3/S1AP/s1ap_eNB_nnsf.h b/openair3/S1AP/s1ap_eNB_nnsf.h index de039b7d30..d5f080649b 100644 --- a/openair3/S1AP/s1ap_eNB_nnsf.h +++ b/openair3/S1AP/s1ap_eNB_nnsf.h @@ -24,8 +24,7 @@ struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme(s1ap_eNB_instance_t *instance_p, - rrc_establishment_cause_t cause, - uint32_t plmn_id); + rrc_establishment_cause_t cause); struct s1ap_eNB_mme_data_s * s1ap_eNB_nnsf_select_mme_by_plmn_id(s1ap_eNB_instance_t *instance_p, diff --git a/openair3/S1AP/s1ap_eNB_timer.c b/openair3/S1AP/s1ap_eNB_timer.c index ccb294cb54..3014f961a9 100644 --- a/openair3/S1AP/s1ap_eNB_timer.c +++ b/openair3/S1AP/s1ap_eNB_timer.c @@ -36,91 +36,6 @@ #include "queue.h" #include "s1ap_common.h" -struct s1ap_timer_elm_s { - task_id_t task_id; ///< Task ID which has requested the timer - int32_t instance; ///< Instance of the task which has requested the timer - uint32_t timer_kind; ///< Instance of the task which has requested the timer - timer_t timer; ///< Unique timer id - timer_type_t type; ///< Timer type - void *timer_arg; ///< Optional argument that will be passed when timer expires - STAILQ_ENTRY(s1ap_timer_elm_s) entries; ///< Pointer to next element -}; - -typedef struct timer_desc_s { - STAILQ_HEAD(timer_list_head, s1ap_timer_elm_s) timer_queue; - pthread_mutex_t timer_list_mutex; - struct timespec timeout; -} timer_desc_t; - -static timer_desc_t timer_desc; - -#define TIMER_SEARCH(vAR, tIMERfIELD, tIMERvALUE, tIMERqUEUE) \ -do { \ - STAILQ_FOREACH(vAR, tIMERqUEUE, entries) { \ - if (((vAR)->tIMERfIELD == tIMERvALUE)) \ - break; \ - } \ -} while(0) - -int s1ap_timer_timeout(sigval_t info) -{ - struct s1ap_timer_elm_s *timer_p; - MessageDef *message_p; - s1ap_timer_has_expired_t *timer_expired_p; - task_id_t task_id; - int32_t instance; - uint32_t timer_kind; - - timer_kind = info.sival_int; - if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex lock timeout=%x\n", timer_kind); - - return -1; - } - TIMER_SEARCH(timer_p, timer_kind, timer_kind, &timer_desc.timer_queue); - - if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex unlock timeout=0x%x\n", timer_kind); - } - if (timer_p == NULL) - { - S1AP_ERROR("Didn't find timer 0x%x in list\n", timer_kind); - - return -1; - } - S1AP_DEBUG("Timer kind 0x%x has expired\n", timer_kind); - - task_id = timer_p->task_id; - instance = timer_p->instance; - message_p = itti_alloc_new_message(TASK_UNKNOWN, TIMER_HAS_EXPIRED); - - timer_expired_p = (s1ap_timer_has_expired_t *)(&message_p->ittiMsg.timer_has_expired); - - timer_expired_p->timer_id = (long)timer_p->timer; - timer_expired_p->timer_kind = timer_p->timer_kind; - timer_expired_p->arg = timer_p->timer_arg; - - /* Timer is a one shot timer, remove it */ - if( (int)timer_p->type == (int)S1AP_TIMER_ONE_SHOT ) - { - if( s1ap_timer_remove((long)timer_p->timer) != 0 ) - { - S1AP_DEBUG("Failed to delete timer 0x%lx\n", (long)timer_p->timer); - } - } - - /* Notify task of timer expiry */ - if( itti_send_msg_to_task(task_id, instance, message_p) < 0 ) - { - S1AP_ERROR("Failed to send msg TIMER_HAS_EXPIRED to task %u\n", task_id); - free(message_p); - return -1; - } - - return 0; -} int s1ap_timer_setup( uint32_t interval_sec, @@ -132,169 +47,24 @@ int s1ap_timer_setup( void *timer_arg, long *timer_id) { - struct sigevent evp; - struct itimerspec its; - struct s1ap_timer_elm_s *timer_p; - timer_t timer; - - if( timer_id == NULL ) - { - S1AP_ERROR("Invalid timer_id\n"); - return -1; - } - - if( (int)type >= (int)S1AP_TIMER_TYPE_MAX ) - { - S1AP_ERROR("Invalid timer type (%d/%d)!\n", type, TIMER_TYPE_MAX); - return -1; - } - - if( *timer_id != S1AP_TIMERID_INIT ) - { - if( s1ap_timer_remove(*timer_id) != 0 ) - { - S1AP_ERROR("Failed to delete timer when the timer start 0x%lx\n", *timer_id); - } - } - - /* Allocate new timer list element */ - timer_p = malloc(sizeof(struct s1ap_timer_elm_s)); - - if( timer_p == NULL ) - { - S1AP_ERROR("Failed to create new timer element\n"); - return -1; - } - - memset(&timer, 0, sizeof(timer_t)); - memset(&evp, 0, sizeof(evp)); - - timer_p->task_id = task_id; - timer_p->instance = instance; - timer_p->timer_kind = timer_kind; - timer_p->type = type; - timer_p->timer_arg = timer_arg; - - evp.sigev_notify = (int)SIGEV_THREAD; - evp.sigev_notify_function = (void *)s1ap_timer_timeout; - evp.sigev_signo = SIGRTMIN; - evp.sigev_notify_attributes = NULL; - evp.sigev_value.sival_int = timer_kind; - - /* At the timer creation, the timer structure will be filled in with timer_id, - * which is unique for this process. This id is allocated by kernel and the - * value might be used to distinguish timers. - */ - if( timer_create(CLOCK_REALTIME, &evp, &timer) < 0 ) - { - S1AP_ERROR("Failed to create timer: (%s:%d)\n", strerror(errno), errno); - free(timer_p); - return -1; - } - - /* Fill in the first expiration value. */ - its.it_value.tv_sec = interval_sec; - its.it_value.tv_nsec = interval_us * 1000; - - if( (int)type == (int)S1AP_TIMER_PERIODIC ) - { - /* Asked for periodic timer. We set the interval time */ - its.it_interval.tv_sec = interval_sec; - its.it_interval.tv_nsec = interval_us * 1000; - } - else - { - /* Asked for one-shot timer. Do not set the interval field */ - its.it_interval.tv_sec = 0; - its.it_interval.tv_nsec = 0; - } - - if( timer_settime(timer, 0, &its, NULL) ) - { - S1AP_ERROR("Failed to Settimer: (%s:%d)\n", strerror(errno), errno); - free(timer_p); - return -1; - } - - /* Simply set the timer_id argument. so it can be used by caller */ - *timer_id = (long)timer; - - timer_p->timer = timer; - - /* Lock the queue and insert the timer at the tail */ - if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex lock\n"); - if( timer_delete(timer_p->timer) < 0 ) - { - S1AP_ERROR("Failed to delete timer 0x%lx\n", (long)timer_p->timer); - } - free(timer_p); - timer_p = NULL; - - return -1; - } - - STAILQ_INSERT_TAIL(&timer_desc.timer_queue, timer_p, entries); - if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex unlock\n"); - } - - return 0; + uint32_t *timeoutArg=NULL; + int ret=0; + timeoutArg=malloc(sizeof(uint32_t)); + *timeoutArg=timer_kind; + ret=timer_setup(interval_sec, + interval_us, + task_id, + instance, + type, + (void*)timeoutArg, + timer_id); + return ret; } int s1ap_timer_remove(long timer_id) { - int rc = 0; - struct s1ap_timer_elm_s *timer_p; - - - if( pthread_mutex_lock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex lock\n"); - if( timer_delete((timer_t)timer_id) < 0 ) - { - S1AP_ERROR("Failed to delete timer 0x%lx\n", (long)timer_id); - } - - return -1; - } - - TIMER_SEARCH(timer_p, timer, ((timer_t)timer_id), &timer_desc.timer_queue); - - /* We didn't find the timer in list */ - if (timer_p == NULL) - { - S1AP_ERROR("Didn't find timer 0x%lx in list\n", timer_id); - if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex unlock\n"); - } - - return -1; - } - - timer_delete(timer_p->timer); - - STAILQ_REMOVE(&timer_desc.timer_queue, timer_p, s1ap_timer_elm_s, entries); - - if( pthread_mutex_unlock(&timer_desc.timer_list_mutex) != 0 ) - { - S1AP_ERROR("Failed to mutex unlock\n"); - } - - free(timer_p); - timer_p = NULL; - return rc; + int ret; + ret=timer_remove(timer_id); + return ret; } -int s1ap_timer_init(void) -{ - memset(&timer_desc, 0, sizeof(timer_desc_t)); - - STAILQ_INIT(&timer_desc.timer_queue); - pthread_mutex_init(&timer_desc.timer_list_mutex, NULL); - - return 0; -} From 535efa0fd265671afbe021f6f41ee7844349be46 Mon Sep 17 00:00:00 2001 From: "masayuki.harada" Date: Wed, 10 Mar 2021 23:16:12 +0900 Subject: [PATCH 15/15] Remove s1ap_eNB_timer.c and s1ap_eNB_timer.h --- cmake_targets/CMakeLists.txt | 1 - openair3/S1AP/s1ap_eNB.c | 41 +++++++++++++-- openair3/S1AP/s1ap_eNB.h | 17 ++++++ openair3/S1AP/s1ap_eNB_handlers.c | 11 +++- openair3/S1AP/s1ap_eNB_timer.c | 70 ------------------------- openair3/S1AP/s1ap_eNB_timer.h | 86 ------------------------------- 6 files changed, 65 insertions(+), 161 deletions(-) delete mode 100644 openair3/S1AP/s1ap_eNB_timer.c delete mode 100644 openair3/S1AP/s1ap_eNB_timer.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index fecb69939f..e11c850b8e 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -539,7 +539,6 @@ add_library(S1AP_ENB ${S1AP_DIR}/s1ap_eNB_overload.c ${S1AP_DIR}/s1ap_eNB_trace.c ${S1AP_DIR}/s1ap_eNB_ue_context.c - ${S1AP_DIR}/s1ap_eNB_timer.c ) add_dependencies(S1AP_ENB rrc_flag s1ap_flag) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index 6cb82de8d3..e528c9e53e 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -58,8 +58,6 @@ #include "s1ap_eNB_ue_context.h" // test, to be removed #include "msc.h" -#include "s1ap_eNB_timer.h" - #include "assertions.h" #include "conversions.h" #if defined(TEST_S1C_MME) @@ -80,6 +78,37 @@ static int s1ap_sctp_req(s1ap_eNB_instance_t *instance_p, void s1ap_eNB_timer_expired(instance_t instance, timer_has_expired_t *msg_p); +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id) +{ + uint32_t *timeoutArg=NULL; + int ret=0; + timeoutArg=malloc(sizeof(uint32_t)); + *timeoutArg=timer_kind; + ret=timer_setup(interval_sec, + interval_us, + task_id, + instance, + type, + (void*)timeoutArg, + timer_id); + return ret; +} + +int s1ap_timer_remove(long timer_id) +{ + int ret; + ret=timer_remove(timer_id); + return ret; +} + uint32_t s1ap_generate_eNB_id(void) { char *out; char hostname[50]; @@ -407,7 +436,13 @@ void s1ap_eNB_timer_expired( long timer_id = S1AP_TIMERID_INIT; instance_p = s1ap_eNB_get_instance(instance); - timer_kind = *((uint32_t*)msg_p->arg); + if(msg_p->arg!=NULL){ + timer_kind = *((uint32_t*)msg_p->arg); + free(msg_p->arg); + }else{ + S1AP_ERROR("s1 timer timer_kind is NULL\n"); + return; + } line_ind = (int16_t)(timer_kind & S1AP_LINEIND); timer_id = msg_p->timer_id; diff --git a/openair3/S1AP/s1ap_eNB.h b/openair3/S1AP/s1ap_eNB.h index 2abbc53ec9..2183587214 100644 --- a/openair3/S1AP/s1ap_eNB.h +++ b/openair3/S1AP/s1ap_eNB.h @@ -30,6 +30,22 @@ #ifndef S1AP_ENB_H_ #define S1AP_ENB_H_ +#define S1AP_MMEIND 0x80000000 +#define S1AP_UEIND 0x00000000 +#define S1_SETRSP_WAIT 0x00010000 +#define S1_SETREQ_WAIT 0x00020000 +#define SCTP_REQ_WAIT 0x00030000 +#define S1AP_LINEIND 0x0000ffff +#define S1AP_TIMERIND 0x00ff0000 + +#define S1AP_TIMERID_INIT 0xffffffffffffffff + +typedef enum s1ap_timer_type_s { + S1AP_TIMER_PERIODIC, + S1AP_TIMER_ONE_SHOT, + S1AP_TIMER_TYPE_MAX, +} s1ap_timer_type_t; + typedef struct s1ap_eNB_config_s { // MME related params unsigned char mme_enabled; ///< MME enabled ? @@ -43,6 +59,7 @@ void *s1ap_eNB_process_itti_msg(void*); void s1ap_eNB_init(void); void *s1ap_eNB_task(void *arg); +int s1ap_timer_remove(long timer_id); uint32_t s1ap_generate_eNB_id(void); #endif /* S1AP_ENB_H_ */ diff --git a/openair3/S1AP/s1ap_eNB_handlers.c b/openair3/S1AP/s1ap_eNB_handlers.c index 7c611b0fbf..9ee3287b94 100644 --- a/openair3/S1AP/s1ap_eNB_handlers.c +++ b/openair3/S1AP/s1ap_eNB_handlers.c @@ -52,7 +52,6 @@ #include "assertions.h" #include "conversions.h" #include "msc.h" -#include "s1ap_eNB_timer.h" static int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, @@ -117,6 +116,16 @@ static int s1ap_eNB_snd_s1_setup_request( s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p); +int s1ap_timer_setup( + uint32_t interval_sec, + uint32_t interval_us, + task_id_t task_id, + int32_t instance, + uint32_t timer_kind, + timer_type_t type, + void *timer_arg, + long *timer_id); + /* Handlers matrix. Only eNB related procedure present here */ s1ap_message_decoded_callback messages_callback[][3] = { { 0, 0, 0 }, /* HandoverPreparation */ diff --git a/openair3/S1AP/s1ap_eNB_timer.c b/openair3/S1AP/s1ap_eNB_timer.c deleted file mode 100644 index 3014f961a9..0000000000 --- a/openair3/S1AP/s1ap_eNB_timer.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 -#include -#include -#include -#include - -#include -#include -#include - -#include "assertions.h" -#include "intertask_interface.h" -#include "s1ap_eNB_timer.h" -#include "common/utils/LOG/log.h" -#include "queue.h" -#include "s1ap_common.h" - - -int s1ap_timer_setup( - uint32_t interval_sec, - uint32_t interval_us, - task_id_t task_id, - int32_t instance, - uint32_t timer_kind, - timer_type_t type, - void *timer_arg, - long *timer_id) -{ - uint32_t *timeoutArg=NULL; - int ret=0; - timeoutArg=malloc(sizeof(uint32_t)); - *timeoutArg=timer_kind; - ret=timer_setup(interval_sec, - interval_us, - task_id, - instance, - type, - (void*)timeoutArg, - timer_id); - return ret; -} - -int s1ap_timer_remove(long timer_id) -{ - int ret; - ret=timer_remove(timer_id); - return ret; -} - diff --git a/openair3/S1AP/s1ap_eNB_timer.h b/openair3/S1AP/s1ap_eNB_timer.h deleted file mode 100644 index 7af80eb806..0000000000 --- a/openair3/S1AP/s1ap_eNB_timer.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 TIMER_H_ -#define TIMER_H_ - -#include - -#define SIGTIMER SIGRTMIN - -typedef enum s1ap_timer_type_s { - S1AP_TIMER_PERIODIC, - S1AP_TIMER_ONE_SHOT, - S1AP_TIMER_TYPE_MAX, -} s1ap_timer_type_t; - -typedef struct { - void *arg; - long timer_id; - int32_t timer_kind; -} s1ap_timer_has_expired_t; - - -int s1ap_timer_timeout(sigval_t info); - -/** \brief Request a new timer - * \param interval_sec timer interval in seconds - * \param interval_us timer interval in micro seconds - * \param task_id task id of the task requesting the timer - * \param instance instance of the task requesting the timer - * \param type timer type - * \param timer_id unique timer identifier - * @returns -1 on failure, 0 otherwise - **/ -int s1ap_timer_setup( - uint32_t interval_sec, - uint32_t interval_us, - task_id_t task_id, - int32_t instance, - uint32_t timer_kind, - timer_type_t type, - void *timer_arg, - long *timer_id); - -/** \brief Remove the timer from list - * \param timer_id unique timer id - * @returns -1 on failure, 0 otherwise - **/ - -int s1ap_timer_remove(long timer_id); - -/** \brief Initialize timer task and its API - * \param mme_config MME common configuration - * @returns -1 on failure, 0 otherwise - **/ -int s1ap_timer_init(void); - -#define S1AP_MMEIND 0x80000000 -#define S1AP_UEIND 0x00000000 -#define S1_SETRSP_WAIT 0x00010000 -#define S1_SETREQ_WAIT 0x00020000 -#define SCTP_REQ_WAIT 0x00030000 -#define S1AP_LINEIND 0x0000ffff -#define S1AP_TIMERIND 0x00ff0000 - -#define S1AP_TIMERID_INIT 0xffffffffffffffff - -#endif