diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index f393cc6d3..fd44ab69e 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -347,6 +347,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) } if (procedureCode == S1AP_ProcedureCode_id_initialUEMessage) { + ogs_debug(" Initial UE Message"); if (mme_ue->nas_eps.service.service_type == NAS_SERVICE_TYPE_CS_FALLBACK_FROM_UE || mme_ue->nas_eps.service.service_type == @@ -368,12 +369,34 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) OGS_FSM_TRAN(s, &emm_state_exception); return; } - ogs_debug(" Iniital UE Message"); rv = s1ap_send_initial_context_setup_request(mme_ue); ogs_assert(rv == OGS_OK); } else if (procedureCode == S1AP_ProcedureCode_id_uplinkNASTransport) { - ogs_error(" Uplink NAS Transport : Not Implemented"); - ogs_assert_if_reached(); + ogs_debug(" Uplink NAS Transport"); + if (mme_ue->nas_eps.service.service_type == + NAS_SERVICE_TYPE_CS_FALLBACK_FROM_UE || + mme_ue->nas_eps.service.service_type == + NAS_SERVICE_TYPE_CS_FALLBACK_EMERGENCY_CALL_FROM_UE) { + ogs_debug(" MO-CSFB-INDICATION[%d]", + mme_ue->nas_eps.service.service_type); + sgsap_send_mo_csfb_indication(mme_ue); + } else if (mme_ue->nas_eps.service.service_type == + NAS_SERVICE_TYPE_CS_FALLBACK_TO_UE) { + ogs_debug(" SERVICE_REQUEST[%d]", + mme_ue->nas_eps.service.service_type); + sgsap_send_service_request(mme_ue, SGSAP_EMM_CONNECTED_MODE); + } else { + ogs_warn(" Unknown CSFB Service Type[%d]", + mme_ue->nas_eps.service.service_type); + rv = nas_send_service_reject(mme_ue, + EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK); + ogs_assert(rv == OGS_OK); + OGS_FSM_TRAN(s, &emm_state_exception); + return; + } + + rv = s1ap_send_ue_context_modification_request(mme_ue); + ogs_assert(rv == OGS_OK); } else { ogs_fatal("Invalid Procedure Code[%d]", (int)procedureCode); ogs_assert_if_reached(); diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index cb6cd7496..dae58338b 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -559,6 +559,236 @@ int s1ap_build_initial_context_setup_request( return OGS_OK; } +int s1ap_build_ue_context_modification_request( + ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue) +{ + int rv; + + S1AP_S1AP_PDU_t pdu; + S1AP_InitiatingMessage_t *initiatingMessage = NULL; + S1AP_UEContextModificationRequest_t *UEContextModificationRequest = NULL; + + S1AP_UEContextModificationRequestIEs_t *ie = NULL; + + S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + S1AP_UESecurityCapabilities_t *UESecurityCapabilities = NULL; + S1AP_SecurityKey_t *SecurityKey = NULL; + S1AP_CSFallbackIndicator_t *CSFallbackIndicator = NULL; + S1AP_LAI_t *LAI = NULL; + + enb_ue_t *enb_ue = NULL; + + ogs_assert(mme_ue); + enb_ue = mme_ue->enb_ue; + ogs_assert(enb_ue); + + ogs_debug("[MME] UE context modification request"); + + memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = + ogs_calloc(1, sizeof(S1AP_InitiatingMessage_t)); + + initiatingMessage = pdu.choice.initiatingMessage; + initiatingMessage->procedureCode = + S1AP_ProcedureCode_id_UEContextModification; + initiatingMessage->criticality = S1AP_Criticality_reject; + initiatingMessage->value.present = + S1AP_InitiatingMessage__value_PR_UEContextModificationRequest; + + UEContextModificationRequest = + &initiatingMessage->value.choice.UEContextModificationRequest; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationRequestIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationRequest->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_UEContextModificationRequestIEs__value_PR_MME_UE_S1AP_ID, + + MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationRequestIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationRequest->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_UEContextModificationRequestIEs__value_PR_ENB_UE_S1AP_ID, + + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationRequestIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationRequest->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_UESecurityCapabilities; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_UEContextModificationRequestIEs__value_PR_UESecurityCapabilities, + + UESecurityCapabilities = &ie->value.choice.UESecurityCapabilities; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationRequestIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationRequest->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_SecurityKey; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_UEContextModificationRequestIEs__value_PR_SecurityKey, + + SecurityKey = &ie->value.choice.SecurityKey; + + ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); + + *MME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id; + *ENB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id; + + UESecurityCapabilities->encryptionAlgorithms.size = 2; + UESecurityCapabilities->encryptionAlgorithms.buf = + ogs_calloc(UESecurityCapabilities->encryptionAlgorithms.size, + sizeof(uint8_t)); + UESecurityCapabilities->encryptionAlgorithms.bits_unused = 0; + UESecurityCapabilities->encryptionAlgorithms.buf[0] = + (mme_ue->ue_network_capability.eea << 1); + + UESecurityCapabilities->integrityProtectionAlgorithms.size = 2; + UESecurityCapabilities->integrityProtectionAlgorithms.buf = + ogs_calloc(UESecurityCapabilities-> + integrityProtectionAlgorithms.size, sizeof(uint8_t)); + UESecurityCapabilities->integrityProtectionAlgorithms.bits_unused = 0; + UESecurityCapabilities->integrityProtectionAlgorithms.buf[0] = + (mme_ue->ue_network_capability.eia << 1); + + SecurityKey->size = OGS_SHA256_DIGEST_SIZE; + SecurityKey->buf = + ogs_calloc(SecurityKey->size, sizeof(uint8_t)); + SecurityKey->bits_unused = 0; + memcpy(SecurityKey->buf, mme_ue->kenb, SecurityKey->size); + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationRequestIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationRequest->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_CSFallbackIndicator; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = + S1AP_UEContextModificationRequestIEs__value_PR_CSFallbackIndicator; + + CSFallbackIndicator = &ie->value.choice.CSFallbackIndicator; + ogs_assert(CSFallbackIndicator); + + *CSFallbackIndicator = S1AP_CSFallbackIndicator_cs_fallback_required; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationRequestIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationRequest->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_RegisteredLAI; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = + S1AP_UEContextModificationRequestIEs__value_PR_LAI; + + LAI = &ie->value.choice.LAI; + ogs_assert(LAI); + + s1ap_buffer_to_OCTET_STRING(&mme_ue->tai.plmn_id, sizeof(plmn_id_t), + &LAI->pLMNidentity); + ogs_assert(mme_ue->vlr); + ogs_assert(mme_ue->p_tmsi); + s1ap_uint16_to_OCTET_STRING(mme_ue->vlr->lai.lac, &LAI->lAC); + + rv = s1ap_encode_pdu(s1apbuf, &pdu); + s1ap_free_pdu(&pdu); + + if (rv != OGS_OK) { + ogs_error("s1ap_encode_pdu() failed"); + return OGS_ERROR; + } + + return OGS_OK; +} + +int s1ap_build_ue_context_release_command( + ogs_pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause) +{ + int rv; + + S1AP_S1AP_PDU_t pdu; + S1AP_InitiatingMessage_t *initiatingMessage = NULL; + S1AP_UEContextReleaseCommand_t *UEContextReleaseCommand = NULL; + + S1AP_UEContextReleaseCommand_IEs_t *ie = NULL; + S1AP_UE_S1AP_IDs_t *UE_S1AP_IDs = NULL; + S1AP_Cause_t *Cause = NULL; + + ogs_assert(enb_ue); + + if (enb_ue->mme_ue_s1ap_id == 0) { + ogs_error("invalid mme ue s1ap id"); + return OGS_ERROR; + } + + memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); + pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; + pdu.choice.initiatingMessage = + ogs_calloc(1, sizeof(S1AP_InitiatingMessage_t)); + + initiatingMessage = pdu.choice.initiatingMessage; + initiatingMessage->procedureCode = S1AP_ProcedureCode_id_UEContextRelease; + initiatingMessage->criticality = S1AP_Criticality_reject; + initiatingMessage->value.present = + S1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; + + UEContextReleaseCommand = + &initiatingMessage->value.choice.UEContextReleaseCommand; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextReleaseCommand_IEs_t)); + ASN_SEQUENCE_ADD(&UEContextReleaseCommand->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_UE_S1AP_IDs; + ie->criticality = S1AP_Criticality_reject; + ie->value.present = S1AP_UEContextReleaseCommand_IEs__value_PR_UE_S1AP_IDs; + + UE_S1AP_IDs = &ie->value.choice.UE_S1AP_IDs; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextReleaseCommand_IEs_t)); + ASN_SEQUENCE_ADD(&UEContextReleaseCommand->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_Cause; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = S1AP_UEContextReleaseCommand_IEs__value_PR_Cause; + + Cause = &ie->value.choice.Cause; + + if (enb_ue->enb_ue_s1ap_id == INVALID_UE_S1AP_ID) { + UE_S1AP_IDs->present = S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID; + UE_S1AP_IDs->choice.mME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id; + } else { + UE_S1AP_IDs->present = S1AP_UE_S1AP_IDs_PR_uE_S1AP_ID_pair; + UE_S1AP_IDs->choice.uE_S1AP_ID_pair = + ogs_calloc(1, sizeof(S1AP_UE_S1AP_ID_pair_t)); + UE_S1AP_IDs->choice.uE_S1AP_ID_pair->mME_UE_S1AP_ID = + enb_ue->mme_ue_s1ap_id; + UE_S1AP_IDs->choice.uE_S1AP_ID_pair->eNB_UE_S1AP_ID = + enb_ue->enb_ue_s1ap_id; + } + + Cause->present = group; + Cause->choice.radioNetwork = cause; + + rv = s1ap_encode_pdu(s1apbuf, &pdu); + s1ap_free_pdu(&pdu); + + if (rv != OGS_OK) { + ogs_error("s1ap_encode_pdu() failed"); + return OGS_ERROR; + } + + return OGS_OK; +} + + int s1ap_build_e_rab_setup_request( ogs_pkbuf_t **s1apbuf, mme_bearer_t *bearer, ogs_pkbuf_t *esmbuf) { @@ -986,85 +1216,6 @@ int s1ap_build_e_rab_release_command(ogs_pkbuf_t **s1apbuf, return OGS_OK; } -int s1ap_build_ue_context_release_command( - ogs_pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause) -{ - int rv; - - S1AP_S1AP_PDU_t pdu; - S1AP_InitiatingMessage_t *initiatingMessage = NULL; - S1AP_UEContextReleaseCommand_t *UEContextReleaseCommand = NULL; - - S1AP_UEContextReleaseCommand_IEs_t *ie = NULL; - S1AP_UE_S1AP_IDs_t *UE_S1AP_IDs = NULL; - S1AP_Cause_t *Cause = NULL; - - ogs_assert(enb_ue); - - if (enb_ue->mme_ue_s1ap_id == 0) { - ogs_error("invalid mme ue s1ap id"); - return OGS_ERROR; - } - - memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); - pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage; - pdu.choice.initiatingMessage = - ogs_calloc(1, sizeof(S1AP_InitiatingMessage_t)); - - initiatingMessage = pdu.choice.initiatingMessage; - initiatingMessage->procedureCode = S1AP_ProcedureCode_id_UEContextRelease; - initiatingMessage->criticality = S1AP_Criticality_reject; - initiatingMessage->value.present = - S1AP_InitiatingMessage__value_PR_UEContextReleaseCommand; - - UEContextReleaseCommand = - &initiatingMessage->value.choice.UEContextReleaseCommand; - - ie = ogs_calloc(1, sizeof(S1AP_UEContextReleaseCommand_IEs_t)); - ASN_SEQUENCE_ADD(&UEContextReleaseCommand->protocolIEs, ie); - - ie->id = S1AP_ProtocolIE_ID_id_UE_S1AP_IDs; - ie->criticality = S1AP_Criticality_reject; - ie->value.present = S1AP_UEContextReleaseCommand_IEs__value_PR_UE_S1AP_IDs; - - UE_S1AP_IDs = &ie->value.choice.UE_S1AP_IDs; - - ie = ogs_calloc(1, sizeof(S1AP_UEContextReleaseCommand_IEs_t)); - ASN_SEQUENCE_ADD(&UEContextReleaseCommand->protocolIEs, ie); - - ie->id = S1AP_ProtocolIE_ID_id_Cause; - ie->criticality = S1AP_Criticality_ignore; - ie->value.present = S1AP_UEContextReleaseCommand_IEs__value_PR_Cause; - - Cause = &ie->value.choice.Cause; - - if (enb_ue->enb_ue_s1ap_id == INVALID_UE_S1AP_ID) { - UE_S1AP_IDs->present = S1AP_UE_S1AP_IDs_PR_mME_UE_S1AP_ID; - UE_S1AP_IDs->choice.mME_UE_S1AP_ID = enb_ue->mme_ue_s1ap_id; - } else { - UE_S1AP_IDs->present = S1AP_UE_S1AP_IDs_PR_uE_S1AP_ID_pair; - UE_S1AP_IDs->choice.uE_S1AP_ID_pair = - ogs_calloc(1, sizeof(S1AP_UE_S1AP_ID_pair_t)); - UE_S1AP_IDs->choice.uE_S1AP_ID_pair->mME_UE_S1AP_ID = - enb_ue->mme_ue_s1ap_id; - UE_S1AP_IDs->choice.uE_S1AP_ID_pair->eNB_UE_S1AP_ID = - enb_ue->enb_ue_s1ap_id; - } - - Cause->present = group; - Cause->choice.radioNetwork = cause; - - rv = s1ap_encode_pdu(s1apbuf, &pdu); - s1ap_free_pdu(&pdu); - - if (rv != OGS_OK) { - ogs_error("s1ap_encode_pdu() failed"); - return OGS_ERROR; - } - - return OGS_OK; -} - int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) { diff --git a/src/mme/s1ap-build.h b/src/mme/s1ap-build.h index cfb6804c4..b82a4e907 100644 --- a/src/mme/s1ap-build.h +++ b/src/mme/s1ap-build.h @@ -32,18 +32,24 @@ extern "C" { int s1ap_build_setup_rsp(ogs_pkbuf_t **pkbuf); int s1ap_build_setup_failure( ogs_pkbuf_t **pkbuf, S1AP_Cause_PR group, long cause, long time_to_wait); + int s1ap_build_downlink_nas_transport( ogs_pkbuf_t **s1apbuf, enb_ue_t *enb_ue, ogs_pkbuf_t *emmbuf); + int s1ap_build_initial_context_setup_request( ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue, ogs_pkbuf_t *emmbuf); +int s1ap_build_ue_context_modification_request( + ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue); +int s1ap_build_ue_context_release_command( + ogs_pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause); + int s1ap_build_e_rab_setup_request( ogs_pkbuf_t **s1apbuf, mme_bearer_t *bearer, ogs_pkbuf_t *esmbuf); int s1ap_build_e_rab_modify_request( ogs_pkbuf_t **s1apbuf, mme_bearer_t *bearer, ogs_pkbuf_t *esmbuf); int s1ap_build_e_rab_release_command(ogs_pkbuf_t **s1apbuf, mme_bearer_t *bearer, ogs_pkbuf_t *esmbuf, S1AP_Cause_PR group, long cause); -int s1ap_build_ue_context_release_command( - ogs_pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause); + int s1ap_build_paging(ogs_pkbuf_t **s1apbuf, mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain); diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 10e89d988..dd2d74a43 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -567,8 +567,8 @@ void s1ap_handle_initial_context_setup_failure( enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, *ENB_UE_S1AP_ID); if (enb_ue == NULL) { - ogs_warn("Initial context setup failure : cannot find eNB-UE-S1AP-ID[%d]", - (int)*ENB_UE_S1AP_ID); + ogs_warn("Initial context setup failure : " + "cannot find eNB-UE-S1AP-ID[%d]", (int)*ENB_UE_S1AP_ID); return; } mme_ue = enb_ue->mme_ue; @@ -600,6 +600,119 @@ void s1ap_handle_initial_context_setup_failure( } } +void s1ap_handle_ue_context_modification_response( + mme_enb_t *enb, s1ap_message_t *message) +{ + char buf[OGS_ADDRSTRLEN]; + int i; + + S1AP_SuccessfulOutcome_t *successfulOutcome = NULL; + S1AP_UEContextModificationResponse_t *UEContextModificationResponse = NULL; + + S1AP_UEContextModificationResponseIEs_t *ie = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + + mme_ue_t *mme_ue = NULL; + enb_ue_t *enb_ue = NULL; + + ogs_assert(enb); + ogs_assert(enb->sock); + + ogs_assert(message); + successfulOutcome = message->choice.successfulOutcome; + ogs_assert(successfulOutcome); + UEContextModificationResponse = + &successfulOutcome->value.choice.UEContextModificationResponse; + ogs_assert(UEContextModificationResponse); + + ogs_debug("[MME] UE context modification response"); + + for (i = 0; i < UEContextModificationResponse->protocolIEs.list.count; i++) { + ie = UEContextModificationResponse->protocolIEs.list.array[i]; + switch (ie->id) { + case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID: + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + break; + default: + break; + } + } + + ogs_debug(" IP[%s] ENB_ID[%d]", + OGS_ADDR(enb->addr, buf), enb->enb_id); + + ogs_assert(ENB_UE_S1AP_ID); + enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, *ENB_UE_S1AP_ID); + ogs_assert(enb_ue); + mme_ue = enb_ue->mme_ue; + ogs_assert(mme_ue); + + ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); + +} + +void s1ap_handle_ue_context_modification_failure( + mme_enb_t *enb, s1ap_message_t *message) +{ + char buf[OGS_ADDRSTRLEN]; + int i; + + S1AP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL; + S1AP_UEContextModificationFailure_t *UEContextModificationFailure = NULL; + + S1AP_UEContextModificationFailureIEs_t *ie = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + S1AP_Cause_t *Cause = NULL; + + enb_ue_t *enb_ue = NULL; + + ogs_assert(enb); + ogs_assert(enb->sock); + + ogs_assert(message); + unsuccessfulOutcome = message->choice.unsuccessfulOutcome; + ogs_assert(unsuccessfulOutcome); + UEContextModificationFailure = + &unsuccessfulOutcome->value.choice.UEContextModificationFailure; + ogs_assert(UEContextModificationFailure); + + ogs_warn("[MME] UE context modification failure"); + + for (i = 0; i < UEContextModificationFailure->protocolIEs.list.count; i++) { + ie = UEContextModificationFailure->protocolIEs.list.array[i]; + switch (ie->id) { + case S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID: + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + break; + case S1AP_ProtocolIE_ID_id_Cause: + Cause = &ie->value.choice.Cause; + break; + default: + break; + } + } + + ogs_debug(" IP[%s] ENB_ID[%d]", + OGS_ADDR(enb->addr, buf), enb->enb_id); + + ogs_assert(ENB_UE_S1AP_ID); + ogs_assert(Cause); + + enb_ue = enb_ue_find_by_enb_ue_s1ap_id(enb, *ENB_UE_S1AP_ID); + if (enb_ue == NULL) { + ogs_warn("Initial context setup failure : " + "cannot find eNB-UE-S1AP-ID[%d]", (int)*ENB_UE_S1AP_ID); + return; + } + + ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", + enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); + ogs_debug(" Cause[Group:%d Cause:%d]", + Cause->present, (int)Cause->choice.radioNetwork); +} + + void s1ap_handle_e_rab_setup_response( mme_enb_t *enb, s1ap_message_t *message) { diff --git a/src/mme/s1ap-handler.h b/src/mme/s1ap-handler.h index fd8af2f73..8295e7fdd 100644 --- a/src/mme/s1ap-handler.h +++ b/src/mme/s1ap-handler.h @@ -40,7 +40,10 @@ void s1ap_handle_initial_context_setup_response( mme_enb_t *enb, s1ap_message_t *message); void s1ap_handle_initial_context_setup_failure( mme_enb_t *enb, s1ap_message_t *message); -void s1ap_handle_e_rab_setup_response( + +void s1ap_handle_ue_context_modification_response( + mme_enb_t *enb, s1ap_message_t *message); +void s1ap_handle_ue_context_modification_failure( mme_enb_t *enb, s1ap_message_t *message); void s1ap_handle_ue_context_release_request( @@ -48,6 +51,9 @@ void s1ap_handle_ue_context_release_request( void s1ap_handle_ue_context_release_complete( mme_enb_t *enb, s1ap_message_t *message); +void s1ap_handle_e_rab_setup_response( + mme_enb_t *enb, s1ap_message_t *message); + void s1ap_handle_path_switch_request( mme_enb_t *enb, s1ap_message_t *message); diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index f4b1b6da6..267248dc6 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -257,6 +257,22 @@ int s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue) return OGS_OK; } +int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue) +{ + int rv; + ogs_pkbuf_t *s1apbuf = NULL; + + ogs_assert(mme_ue); + + rv = s1ap_build_ue_context_modification_request(&s1apbuf, mme_ue); + ogs_assert(rv == OGS_OK && s1apbuf); + + rv = nas_send_to_enb(mme_ue, s1apbuf); + ogs_assert(rv == OGS_OK); + + return OGS_OK; +} + int s1ap_send_ue_context_release_command( enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause, uint8_t action, uint32_t delay) diff --git a/src/mme/s1ap-path.h b/src/mme/s1ap-path.h index b815d7bca..7b202ebcf 100644 --- a/src/mme/s1ap-path.h +++ b/src/mme/s1ap-path.h @@ -50,8 +50,8 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue, S1AP_ProcedureCode_t procedureCode, S1AP_NAS_PDU_t *nasPdu); int s1ap_send_to_esm(mme_ue_t *mme_ue, ogs_pkbuf_t *esmbuf); -int s1ap_send_initial_context_setup_request( - mme_ue_t *mme_ue); +int s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue); +int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue); int s1ap_send_ue_context_release_command( enb_ue_t *enb_ue, S1AP_Cause_PR group, long cause, uint8_t action, uint32_t delay); diff --git a/src/mme/s1ap-sm.c b/src/mme/s1ap-sm.c index 0a09afe23..1bc6f12f5 100644 --- a/src/mme/s1ap-sm.c +++ b/src/mme/s1ap-sm.c @@ -125,20 +125,23 @@ void s1ap_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_assert(successfulOutcome); switch (successfulOutcome->procedureCode) { - case S1AP_ProcedureCode_id_InitialContextSetup : + case S1AP_ProcedureCode_id_InitialContextSetup: s1ap_handle_initial_context_setup_response(enb, pdu); break; - case S1AP_ProcedureCode_id_E_RABSetup : - s1ap_handle_e_rab_setup_response(enb, pdu); + case S1AP_ProcedureCode_id_UEContextModification: + s1ap_handle_ue_context_modification_response(enb, pdu); break; - case S1AP_ProcedureCode_id_E_RABModify : - break; - case S1AP_ProcedureCode_id_E_RABRelease : - break; - case S1AP_ProcedureCode_id_UEContextRelease : + case S1AP_ProcedureCode_id_UEContextRelease: s1ap_handle_ue_context_release_complete( enb, pdu); break; + case S1AP_ProcedureCode_id_E_RABSetup: + s1ap_handle_e_rab_setup_response(enb, pdu); + break; + case S1AP_ProcedureCode_id_E_RABModify: + break; + case S1AP_ProcedureCode_id_E_RABRelease: + break; case S1AP_ProcedureCode_id_HandoverResourceAllocation: s1ap_handle_handover_request_ack(enb, pdu); break; @@ -162,6 +165,9 @@ void s1ap_state_operational(ogs_fsm_t *s, mme_event_t *e) case S1AP_ProcedureCode_id_InitialContextSetup : s1ap_handle_initial_context_setup_failure(enb, pdu); break; + case S1AP_ProcedureCode_id_UEContextModification: + s1ap_handle_ue_context_modification_failure(enb, pdu); + break; case S1AP_ProcedureCode_id_HandoverResourceAllocation : s1ap_handle_handover_failure(enb, pdu); break; diff --git a/tests/Makefile.am b/tests/Makefile.am index b5ed9942c..4866d4ed4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -44,6 +44,7 @@ testcsfb_SOURCES = \ common/test-app.h \ csfb/abts-main.c csfb/test-app.c \ csfb/mo-idle-test.c csfb/mt-idle-test.c \ + csfb/mo-active-test.c \ $(NULL) testcsfb_LDADD = $(top_srcdir)/src/libepc.la diff --git a/tests/common/test-packet.c b/tests/common/test-packet.c index 313266508..aec40f2b3 100644 --- a/tests/common/test-packet.c +++ b/tests/common/test-packet.c @@ -1145,6 +1145,70 @@ int tests1ap_build_initial_context_setup_response( return OGS_OK; } +int tests1ap_build_ue_context_modification_response( + ogs_pkbuf_t **pkbuf, + uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id) +{ + int rv; + + S1AP_S1AP_PDU_t pdu; + S1AP_SuccessfulOutcome_t *successfulOutcome = NULL; + S1AP_UEContextModificationResponse_t *UEContextModificationResponse = NULL; + ogs_sockaddr_t *addr = NULL; + + S1AP_UEContextModificationResponseIEs_t *ie = NULL; + S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; + S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + + memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t)); + pdu.present = S1AP_S1AP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = + ogs_calloc(1, sizeof(S1AP_SuccessfulOutcome_t)); + + successfulOutcome = pdu.choice.successfulOutcome; + successfulOutcome->procedureCode = + S1AP_ProcedureCode_id_UEContextModification; + successfulOutcome->criticality = S1AP_Criticality_reject; + successfulOutcome->value.present = + S1AP_SuccessfulOutcome__value_PR_UEContextModificationResponse; + + UEContextModificationResponse = + &successfulOutcome->value.choice.UEContextModificationResponse; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationResponseIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationResponse->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = + S1AP_UEContextModificationResponseIEs__value_PR_MME_UE_S1AP_ID; + + MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID; + + ie = ogs_calloc(1, sizeof(S1AP_UEContextModificationResponseIEs_t)); + ASN_SEQUENCE_ADD(&UEContextModificationResponse->protocolIEs, ie); + + ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID; + ie->criticality = S1AP_Criticality_ignore; + ie->value.present = + S1AP_UEContextModificationResponseIEs__value_PR_ENB_UE_S1AP_ID; + + ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID; + + *MME_UE_S1AP_ID = mme_ue_s1ap_id; + *ENB_UE_S1AP_ID = enb_ue_s1ap_id; + + rv = s1ap_encode_pdu(pkbuf, &pdu); + s1ap_free_pdu(&pdu); + + if (rv != OGS_OK) { + ogs_error("s1ap_encode_pdu() failed"); + return OGS_ERROR; + } + + return OGS_OK; +} + int tests1ap_build_initial_context_setup_failure(ogs_pkbuf_t **pkbuf, int i) { char *payload[TESTS1AP_MAX_MESSAGE] = { @@ -1761,7 +1825,9 @@ int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, int i, "000c" "4038000005000800 020002001a00100f 17b51a57a504074c 000504e900a25200" "4300060009f10700 07006440080009f1 0707080140008640 0130", - "", + + "000d403900000500 0000020001000800 020001001a00100f 17b51a57a504074c" + "000504e900a25200 6440080009f10700 19b0100043400600 09f1070007", "", /* 21 */ @@ -1794,7 +1860,7 @@ int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, int i, 0, 60, - 0, + 61, 0, /* 21 */ @@ -1807,13 +1873,22 @@ int tests1ap_build_extended_service_request(ogs_pkbuf_t **pkbuf, int i, *pkbuf = ogs_pkbuf_alloc(NULL, MAX_SDU_LEN); ogs_pkbuf_put_data(*pkbuf, OGS_HEX(payload[i], strlen(payload[i]), hexbuf), len[i]); - memcpy((*pkbuf)->data + 26, &service_type, sizeof service_type); - m_tmsi = htonl(m_tmsi); - memcpy((*pkbuf)->data + 29, &m_tmsi, sizeof m_tmsi); + if (i == 18) { + memcpy((*pkbuf)->data + 26, &service_type, sizeof service_type); + m_tmsi = htonl(m_tmsi); + memcpy((*pkbuf)->data + 29, &m_tmsi, sizeof m_tmsi); - snow_3g_f9(knas_int, seq, (0 << 27), 0, - (*pkbuf)->data + 23, (10 << 3), - (*pkbuf)->data + 19); + snow_3g_f9(knas_int, seq, (0 << 27), 0, + (*pkbuf)->data + 23, (10 << 3), + (*pkbuf)->data + 19); + } else if (i == 19) { + memcpy((*pkbuf)->data + 32, &service_type, sizeof service_type); + m_tmsi = htonl(m_tmsi); + memcpy((*pkbuf)->data + 35, &m_tmsi, sizeof m_tmsi); + snow_3g_f9(knas_int, seq, (0 << 27), 0, + (*pkbuf)->data + 29, (10 << 3), + (*pkbuf)->data + 25); + } return OGS_OK; } diff --git a/tests/common/test-packet.h b/tests/common/test-packet.h index 4d84c02ad..d41992a1c 100644 --- a/tests/common/test-packet.h +++ b/tests/common/test-packet.h @@ -67,6 +67,9 @@ int tests1ap_build_initial_context_setup_response( ogs_pkbuf_t **pkbuf, uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id, uint8_t ebi, uint32_t teid, const char *ipstr); +int tests1ap_build_ue_context_modification_response( + ogs_pkbuf_t **pkbuf, + uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id); int tests1ap_build_initial_context_setup_failure( ogs_pkbuf_t **pkbuf, int i); int tests1ap_build_attach_complete(ogs_pkbuf_t **pkbuf, int i); diff --git a/tests/csfb/abts-main.c b/tests/csfb/abts-main.c index 32be69500..626ac4220 100644 --- a/tests/csfb/abts-main.c +++ b/tests/csfb/abts-main.c @@ -31,12 +31,14 @@ abts_suite *test_mo_idle(abts_suite *suite); abts_suite *test_mt_idle(abts_suite *suite); +abts_suite *test_mo_active(abts_suite *suite); const struct testlist { abts_suite *(*func)(abts_suite *suite); } alltests[] = { {test_mo_idle}, {test_mt_idle}, + {test_mo_active}, {NULL}, }; diff --git a/tests/csfb/mo-active-test.c b/tests/csfb/mo-active-test.c new file mode 100644 index 000000000..6b61ca63f --- /dev/null +++ b/tests/csfb/mo-active-test.c @@ -0,0 +1,273 @@ + +#include + +#include "core/abts.h" + +#include "app/context.h" +#include "mme/mme-context.h" +#include "mme/s1ap-build.h" +#include "asn1c/s1ap-message.h" + +#include "test-packet.h" + +extern ogs_socknode_t *sgsap; + +static void test1_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + s1ap_message_t message; + int i; + int msgindex = 18; + enb_ue_t *enb_ue = NULL; + mme_ue_t *mme_ue = NULL; + uint32_t m_tmsi = 0; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"262420000118139\", " + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 0, " + "\"pre_emption_capability\" : 0" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"70D49A71DD1A2B806A25ABE0EF749F1E\", " + "\"opc\" : \"6F1BF53D624B3A43AF6592854E2444C7\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"2374\" }, " + "\"rand\" : \"aa266700bc2887354e9f87368d5d0ae7\" " + "}, " + "\"__v\" : 0 " + "}"; + + /* eNB connects to MME */ + s1ap = testenb_s1ap_client("127.0.0.1"); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* Send S1-Setup Reqeust */ + rv = tests1ap_build_setup_req( + &sendbuf, S1AP_ENB_ID_PR_macroENB_ID, 0x0019b0, 7, 901, 70, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + rv = s1ap_decode_pdu(&message, recvbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + s1ap_free_pdu(&message); + ogs_pkbuf_free(recvbuf); + + collection = mongoc_client_get_collection( + context_self()->db.client, + context_self()->db.name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /********** Insert Subscriber in Database */ + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8("262420000118139")); + ABTS_PTR_NOTNULL(tc, doc); + do { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + /* Send Attach Request */ + mme_self()->mme_ue_s1ap_id = 0; + rv = tests1ap_build_initial_ue_msg(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity-Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Identity Response */ + rv = tests1ap_build_identity_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Authentication Response */ + rv = tests1ap_build_authentication_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Security mode Complete */ + rv = tests1ap_build_security_mode_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send ESM Information Response */ + rv = tests1ap_build_esm_information_response(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive SGsAP-Location-Update-Request */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send SGsAP-Location-Update-Accept */ + rv = testsgsap_location_update_accept(&sendbuf, 0); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testvlr_sgsap_send(sgsap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Initial Context Setup Response */ + rv = tests1ap_build_initial_context_setup_response(&sendbuf, + 1, 1, 5, 0x00460003, "127.0.0.5"); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + rv = tests1ap_build_attach_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Receive SGsAP TMSI-REALLOCATION-COMPLETE */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Retreive M-TMSI */ + enb_ue = enb_ue_find_by_mme_ue_s1ap_id(1); + ogs_assert(enb_ue); + mme_ue = enb_ue->mme_ue; + ogs_assert(mme_ue); + m_tmsi = mme_ue->guti.m_tmsi; + + /* Send Extended Service Request */ + rv = tests1ap_build_extended_service_request(&sendbuf, msgindex+1, + 0, m_tmsi, 4, mme_ue->knas_int); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive SGsAP MO-CSFB-INDICATION */ + recvbuf = testvlr_sgsap_read(sgsap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Receive UE Context Modification Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Modification Response */ + rv = tests1ap_build_ue_context_modification_response(&sendbuf, 1, 1); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UE Context Release Request */ + rv = tests1ap_build_ue_context_release_request(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UE Context Release Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send UE Context Release Complete */ + rv = tests1ap_build_ue_context_release_complete(&sendbuf, msgindex); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8("262420000118139")); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); +} + +abts_suite *test_mo_active(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test1_func, NULL); + + return suite; +}