|
|
|
@@ -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"
|
|
|
|
@@ -109,6 +112,20 @@ 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);
|
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
@@ -260,6 +277,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 +291,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 +299,10 @@ 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 +310,56 @@ 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 +387,27 @@ 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.
|
|
|
|
|
*/
|
|
|
|
@@ -368,13 +459,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);
|
|
|
|
@@ -725,6 +810,9 @@ 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 = %ld\n", *ie->value.choice.CriticalityDiagnostics.procedureCode);
|
|
|
|
|
}
|
|
|
|
|
// TODO continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -807,9 +895,11 @@ 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
|
|
|
|
|
S1AP_ProtocolIE_ID_id_E_RABToBeSetupListCtxtSUReq, true);
|
|
|
|
|
|
|
|
|
@@ -852,6 +942,7 @@ 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -865,6 +956,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
|
|
|
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
|
|
|
|
|
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
|
|
|
|
|
} else {/* ie != NULL */
|
|
|
|
|
itti_free(ITTI_MSG_ORIGIN_ID(message_p), message_p);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -876,9 +968,10 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* id-NRUESecurityCapabilities */
|
|
|
|
|
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
|
|
|
|
|
S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false);
|
|
|
|
@@ -891,7 +984,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
|
|
|
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0;
|
|
|
|
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
@@ -918,6 +1011,13 @@ 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);
|
|
|
|
|
|
|
|
|
@@ -965,9 +1065,26 @@ 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)
|
|
|
|
|
{
|
|
|
|
|
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, 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);
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
@@ -975,12 +1092,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
|
|
|
|
@@ -999,7 +1114,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;
|
|
|
|
|
}
|
|
|
|
@@ -1026,7 +1141,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;
|
|
|
|
@@ -1099,6 +1214,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1119,13 +1235,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);
|
|
|
|
@@ -1153,6 +1262,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1180,6 +1290,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 {
|
|
|
|
@@ -1190,14 +1301,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1230,6 +1344,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1257,6 +1372,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1351,6 +1467,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1403,6 +1520,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1476,6 +1594,24 @@ int s1ap_eNB_handle_e_rab_release_command(uint32_t assoc_id,
|
|
|
|
|
message_p = itti_alloc_new_message(TASK_S1AP, 0, 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);
|
|
|
|
@@ -1491,24 +1627,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;
|
|
|
|
|
}
|
|
|
|
@@ -1533,7 +1651,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) {
|
|
|
|
@@ -1550,6 +1667,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1572,6 +1690,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1589,6 +1708,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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1602,14 +1722,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;
|
|
|
|
@@ -1688,9 +1804,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) {
|
|
|
|
@@ -1754,3 +1869,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;
|
|
|
|
|
}
|
|
|
|
|