diff --git a/src/amf/amf-sm.c b/src/amf/amf-sm.c index 1ef0fdc0b..cabeb0404 100644 --- a/src/amf/amf-sm.c +++ b/src/amf/amf-sm.c @@ -64,7 +64,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) ogs_sbi_object_t *sbi_object = NULL; ogs_sbi_xact_t *sbi_xact = NULL; - int state = AMF_SESS_SM_CONTEXT_NO_STATE; + int state = AMF_CREATE_SM_CONTEXT_NO_STATE; ogs_sbi_stream_t *stream = NULL; ogs_sbi_request_t *sbi_request = NULL; @@ -436,8 +436,32 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) break; DEFAULT - amf_nsmf_pdusession_handle_create_sm_context( + rv = amf_nsmf_pdusession_handle_create_sm_context( sess, &sbi_message); + if (rv != OGS_OK) { + /* + * 1. First PDU session establishment request + * (PSI:5, internet) + * 2. First session created + * 3. Seconds PDU session establishment request + * (PSI:5, ims) + * 4. AMF sends DUPLICATED_PDU_SESSION_ID to the SMF + * 5. AMF try to create second PDU session. + * 6. But, Second session rejected due to Subscription Info. + * + * In above situation, AMF need to clear SM_CONTEXT_REF. + * Otherwise, AMF have redundant PDU session. + * + * Moreover, AMF could send UEContextReleaseRequest + * with deactivating this redundant session. + * + * So, if CreateSMContext is failed, + * we'll clear SM_CONTEXT_REF. + */ + if (SESSION_CONTEXT_IN_SMF(sess)) { + CLEAR_SM_CONTEXT_REF(sess); + } + } END break; diff --git a/src/amf/context.c b/src/amf/context.c index f5dbe61ee..9ee19fadc 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -1143,6 +1143,9 @@ void amf_ue_remove(amf_ue_t *amf_ue) amf_ue_fsm_fini(amf_ue); + /* Remove all session context */ + amf_sess_remove_all(amf_ue); + /* Clear hash table */ if (amf_ue->m_tmsi) { ogs_hash_set(self.guti_ue_hash, @@ -1203,8 +1206,6 @@ void amf_ue_remove(amf_ue_t *amf_ue) amf_ue_deassociate(amf_ue); - amf_sess_remove_all(amf_ue); - ogs_pool_free(&amf_ue_pool, amf_ue); ogs_info("[Removed] Number of AMF-UEs is now %d", diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index 0276f9123..953919780 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -512,7 +512,7 @@ int gmm_handle_deregistration_request(amf_ue_t *amf_ue, ogs_info("[%s] SUCI", amf_ue->suci); - amf_sbi_send_release_all_sessions(amf_ue, AMF_SESS_SM_CONTEXT_NO_STATE); + amf_sbi_send_release_all_sessions(amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); if (ogs_list_count(&amf_ue->sess_list) == 0) nas_5gs_send_de_registration_accept(amf_ue); @@ -679,8 +679,6 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, ogs_nas_dnn_t *dnn = NULL; ogs_nas_5gsm_header_t *gsm_header = NULL; - bool duplicated_pdu_session_id = false; - ogs_assert(amf_ue); ogs_assert(ul_nas_transport); @@ -743,8 +741,6 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, if (!sess) { sess = amf_sess_add(amf_ue, *pdu_session_id); ogs_assert(sess); - } else { - duplicated_pdu_session_id = true; } } else { sess = amf_sess_find_by_psi(amf_ue, *pdu_session_id); @@ -786,7 +782,7 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, } if (!selected_s_nssai) { - ogs_error("No S_NSSAI : Set default S_NSSAI using AMF config"); + ogs_warn("No S_NSSAI : Set default S_NSSAI using AMF config"); selected_s_nssai = &amf_self()->plmn_support[0].s_nssai[0]; ogs_assert(selected_s_nssai); } @@ -814,9 +810,9 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, ogs_info("UE SUPI[%s] DNN[%s] S_NSSAI[SST:%d SD:0x%x]", amf_ue->supi, sess->dnn, sess->s_nssai.sst, sess->s_nssai.sd.v); - if (duplicated_pdu_session_id == false) { + if (!SESSION_CONTEXT_IN_SMF(sess)) { amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF, - sess, AMF_SESS_SM_CONTEXT_NO_STATE, NULL, + sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL, amf_nsmf_pdusession_build_create_sm_context); } else { memset(¶m, 0, sizeof(param)); diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 688838bd1..405718498 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -161,7 +161,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) } else { amf_sbi_send_release_all_sessions( - amf_ue, AMF_SESS_SM_CONTEXT_NO_STATE); + amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); if (amf_sess_xact_count(amf_ue) == xact_count) { amf_ue_sbi_discover_and_send( OpenAPI_nf_type_AUSF, amf_ue, NULL, @@ -228,7 +228,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) } amf_sbi_send_release_all_sessions( - amf_ue, AMF_SESS_SM_CONTEXT_NO_STATE); + amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); if (amf_sess_xact_count(amf_ue) == xact_count) { amf_ue_sbi_discover_and_send(OpenAPI_nf_type_AUSF, amf_ue, NULL, amf_nausf_auth_build_authenticate); @@ -1002,7 +1002,7 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) } amf_sbi_send_release_all_sessions( - amf_ue, AMF_SESS_SM_CONTEXT_NO_STATE); + amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); if (amf_sess_xact_count(amf_ue) == xact_count) { amf_ue_sbi_discover_and_send(OpenAPI_nf_type_AUSF, amf_ue, NULL, amf_nausf_auth_build_authenticate); @@ -1071,7 +1071,8 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); CLEAR_AMF_UE_ALL_TIMERS(amf_ue); - amf_sbi_send_release_all_sessions(amf_ue, AMF_SESS_SM_CONTEXT_NO_STATE); + amf_sbi_send_release_all_sessions( + amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); if (ogs_list_count(&amf_ue->sess_list) == 0) ngap_send_amf_ue_context_release_command(amf_ue, @@ -1128,7 +1129,7 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) } else { amf_sbi_send_release_all_sessions( - amf_ue, AMF_SESS_SM_CONTEXT_NO_STATE); + amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); if (amf_sess_xact_count(amf_ue) == xact_count) { amf_ue_sbi_discover_and_send( OpenAPI_nf_type_AUSF, amf_ue, NULL, diff --git a/src/amf/namf-handler.c b/src/amf/namf-handler.c index 819177b62..afacdd9cf 100644 --- a/src/amf/namf-handler.c +++ b/src/amf/namf-handler.c @@ -465,7 +465,7 @@ int amf_namf_callback_handle_sm_context_status( ogs_debug("[%s:%d] SM context remove", amf_ue->supi, sess->psi); amf_nsmf_pdusession_handle_release_sm_context( - sess, AMF_SESS_SM_CONTEXT_NO_STATE); + sess, AMF_RELEASE_SM_CONTEXT_NO_STATE); } cleanup: diff --git a/src/amf/ngap-path.c b/src/amf/ngap-path.c index 612a2b554..56414b66e 100644 --- a/src/amf/ngap-path.c +++ b/src/amf/ngap-path.c @@ -53,7 +53,12 @@ int ngap_send_to_gnb(amf_gnb_t *gnb, ogs_pkbuf_t *pkbuf, uint16_t stream_no) ogs_assert(gnb); ogs_assert(pkbuf); ogs_assert(gnb->sctp.sock); - ogs_assert(gnb->sctp.sock->fd != INVALID_SOCKET); + if (gnb->sctp.sock->fd == INVALID_SOCKET) { + ogs_fatal("gNB SCTP socket has already been destroyed"); + ogs_log_hexdump(OGS_LOG_FATAL, pkbuf->data, pkbuf->len); + ogs_assert_if_reached(); + return OGS_ERROR; + } ogs_debug(" IP[%s] RAN_ID[%d]", OGS_ADDR(gnb->sctp.addr, buf), gnb->gnb_id); diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index 66063242e..50784adc3 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -135,7 +135,6 @@ int amf_nsmf_pdusession_handle_create_sm_context( } nas_5gs_send_back_5gsm_message_from_sbi(sess, recvmsg->res_status); - return OGS_ERROR; } @@ -398,7 +397,7 @@ int amf_nsmf_pdusession_handle_update_sm_context( "(DUPLICATED_PDU_SESSION_ID)", amf_ue->supi, sess->psi); amf_sess_sbi_discover_and_send(OpenAPI_nf_type_SMF, - sess, AMF_SESS_SM_CONTEXT_NO_STATE, NULL, + sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL, amf_nsmf_pdusession_build_create_sm_context); } else if (state == AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST) { @@ -527,7 +526,7 @@ int amf_nsmf_pdusession_handle_update_sm_context( ogs_debug("[%s:%d] SM context remove", amf_ue->supi, sess->psi); amf_nsmf_pdusession_handle_release_sm_context( - sess, AMF_SESS_SM_CONTEXT_NO_STATE); + sess, AMF_RELEASE_SM_CONTEXT_NO_STATE); } } } else { @@ -547,13 +546,15 @@ int amf_nsmf_pdusession_handle_update_sm_context( SmContextUpdateError = recvmsg->SmContextUpdateError; if (!SmContextUpdateError) { - ogs_error("[%d:%d] No SmContextUpdateError", sess->psi, sess->pti); + ogs_error("[%d:%d] No SmContextUpdateError [%d]", + sess->psi, sess->pti, recvmsg->res_status); ngap_send_error_indication2(amf_ue, NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error); return OGS_ERROR; } if (!SmContextUpdateError->error) { - ogs_error("[%d:%d] No Error", sess->psi, sess->pti); + ogs_error("[%d:%d] No Error [%d]", + sess->psi, sess->pti, recvmsg->res_status); ngap_send_error_indication2(amf_ue, NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error); return OGS_ERROR; @@ -597,8 +598,12 @@ int amf_nsmf_pdusession_handle_update_sm_context( } #endif + ogs_error("[%d:%d] HTTP response error [%d]", + sess->psi, sess->pti, recvmsg->res_status); +#if 0 /* Is it needed */ ngap_send_error_indication2(amf_ue, NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error); +#endif return OGS_ERROR; } @@ -640,8 +645,7 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) } else { - /* Check last session */ - if (ogs_list_count(&amf_ue->sess_list) == 0) { + if (SESSION_SYNC_DONE(amf_ue, state)) { if (state == AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE) { /* @@ -664,7 +668,7 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) /* Not reached here */ ogs_assert_if_reached(); - } else { + } else if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE) { /* NO_STATE */ if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_authentication)) { @@ -723,6 +727,9 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) ogs_fatal("Release SM Context : INVALID STATE"); ogs_assert_if_reached(); } + } else { + ogs_fatal("Release SM STATE undefined"); + ogs_assert_if_reached(); } } } diff --git a/src/amf/sbi-path.h b/src/amf/sbi-path.h index b7bdc7eaf..8f0cc7d56 100644 --- a/src/amf/sbi-path.h +++ b/src/amf/sbi-path.h @@ -37,7 +37,7 @@ void amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, amf_ue_t *amf_ue, void *data, ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data)); -#define AMF_SESS_SM_CONTEXT_NO_STATE 0 +#define AMF_CREATE_SM_CONTEXT_NO_STATE 0 #define AMF_UPDATE_SM_CONTEXT_ACTIVATED 11 #define AMF_UPDATE_SM_CONTEXT_DEACTIVATED 12 #define AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST 13 @@ -51,9 +51,10 @@ void amf_ue_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, #define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK 21 #define AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY 22 #define AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL 23 -#define AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE 31 -#define AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT 32 -#define AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT 33 +#define AMF_RELEASE_SM_CONTEXT_NO_STATE 31 +#define AMF_RELEASE_SM_CONTEXT_NG_CONTEXT_REMOVE 32 +#define AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT 33 +#define AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT 34 #define AMF_REMOVE_S1_CONTEXT_BY_LO_CONNREFUSED 51 #define AMF_REMOVE_S1_CONTEXT_BY_RESET_ALL 52 #define AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL 53 diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index 35965b0ed..aaa469f30 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -54,7 +54,12 @@ int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no) ogs_assert(enb); ogs_assert(pkbuf); ogs_assert(enb->sctp.sock); - ogs_assert(enb->sctp.sock->fd != INVALID_SOCKET); + if (enb->sctp.sock->fd == INVALID_SOCKET) { + ogs_fatal("eNB SCTP socket has already been destroyed"); + ogs_log_hexdump(OGS_LOG_FATAL, pkbuf->data, pkbuf->len); + ogs_assert_if_reached(); + return OGS_ERROR; + } ogs_debug(" IP[%s] ENB_ID[%d]", OGS_ADDR(enb->sctp.addr, buf), enb->enb_id); diff --git a/src/smf/context.c b/src/smf/context.c index b09e72baf..e7b7325d3 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -570,6 +570,8 @@ void smf_ue_remove(smf_ue_t *smf_ue) ogs_list_remove(&self.smf_ue_list, smf_ue); + smf_sess_remove_all(smf_ue); + if (smf_ue->supi) { ogs_hash_set(self.supi_hash, smf_ue->supi, strlen(smf_ue->supi), NULL); ogs_free(smf_ue->supi); @@ -579,8 +581,6 @@ void smf_ue_remove(smf_ue_t *smf_ue) ogs_hash_set(self.imsi_hash, smf_ue->imsi, smf_ue->imsi_len, NULL); } - smf_sess_remove_all(smf_ue); - ogs_pool_free(&smf_ue_pool, smf_ue); ogs_info("[Removed] Number of SMF-UEs is now %d", @@ -1112,11 +1112,11 @@ void smf_sess_remove(smf_sess_t *sess) smf_ue = sess->smf_ue; ogs_assert(smf_ue); - ogs_info("Removed Session: UE IMSI:[%s] DNN:[%s] IPv4:[%s] IPv6:[%s]", - smf_ue->imsi_bcd, - sess->pdn.dnn, - sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "", - sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : ""); + ogs_info("Removed Session: UE IMSI:[%s] DNN:[%s:%d] IPv4:[%s] IPv6:[%s]", + smf_ue->supi ? smf_ue->supi : smf_ue->imsi_bcd, + sess->pdn.dnn, sess->psi, + sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "", + sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : ""); ogs_list_remove(&smf_ue->sess_list, sess); diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 2a8119b61..bcbd5904b 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -121,14 +121,14 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_sbi_server_send_error(stream, sbi_message->res_status, sbi_message, strerror, NULL); ogs_free(strerror); + + OGS_FSM_TRAN(s, smf_gsm_state_exception); break; } if (smf_nudm_sdm_handle_get( sess, stream, sbi_message) != true) { - ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, - sbi_message, "HTTP response error", smf_ue->supi); + OGS_FSM_TRAN(s, smf_gsm_state_session_will_release); } break; @@ -143,6 +143,7 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message, strerror, NULL); ogs_free(strerror); + OGS_FSM_TRAN(s, smf_gsm_state_exception); END break; @@ -365,6 +366,30 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) } } +void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e) +{ + smf_sess_t *sess = NULL; + ogs_assert(s); + ogs_assert(e); + + smf_sm_debug(e); + + sess = e->sess; + ogs_assert(sess); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + break; + + case OGS_FSM_EXIT_SIG: + break; + + default: + ogs_error("Unknown event %s", smf_event_get_name(e)); + break; + } +} + void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e) { smf_sess_t *sess = NULL; diff --git a/src/smf/nudm-handler.c b/src/smf/nudm-handler.c index ee997f385..e0051585d 100644 --- a/src/smf/nudm-handler.c +++ b/src/smf/nudm-handler.c @@ -25,6 +25,7 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream, { char *strerror = NULL; smf_ue_t *smf_ue = NULL; + ogs_pkbuf_t *n1smbuf = NULL; OpenAPI_sm_context_created_data_t SmContextCreatedData; @@ -68,7 +69,18 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream, if (!dnnConfigurationList) { strerror = ogs_msprintf("[%s:%d] No dnnConfigurations", smf_ue->supi, sess->psi); - goto cleanup; + ogs_assert(strerror); + + n1smbuf = gsm_build_pdu_session_establishment_reject(sess, + OGS_5GSM_CAUSE_MISSING_OR_UNKNOWN_DNN); + ogs_assert(n1smbuf); + + ogs_warn("%s", strerror); + smf_sbi_send_sm_context_create_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, strerror, NULL, n1smbuf); + ogs_free(strerror); + + return false; } OpenAPI_list_for_each(dnnConfigurationList, node) { diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 2148a383c..fc43a453a 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -554,6 +554,9 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) { ogs_error("[%s] State machine exception", smf_ue->supi); SMF_SESS_CLEAR(sess); + } else if (OGS_FSM_CHECK( + &sess->sm, smf_gsm_state_session_will_release)) { + SMF_SESS_CLEAR(sess); } break; diff --git a/src/smf/smf-sm.h b/src/smf/smf-sm.h index 3369ac935..2a7914b5b 100644 --- a/src/smf/smf-sm.h +++ b/src/smf/smf-sm.h @@ -44,6 +44,7 @@ void smf_nf_state_exception(ogs_fsm_t *s, smf_event_t *e); void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e); void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e); void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e); +void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e); void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e); void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e); diff --git a/tests/common/nas-path.c b/tests/common/nas-path.c index fedaac266..7e4bd1a1a 100644 --- a/tests/common/nas-path.c +++ b/tests/common/nas-path.c @@ -90,6 +90,8 @@ void testgsm_recv(test_sess_t *sess, ogs_pkbuf_t *pkbuf) testgsm_handle_pdu_session_establishment_accept(sess, &message.gsm.pdu_session_establishment_accept); break; + case OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_REJECT: + break; case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND: testgsm_handle_pdu_session_modification_command(sess, &message.gsm.pdu_session_modification_command); diff --git a/tests/vonr/session-test.c b/tests/vonr/session-test.c index 6f24f9e07..b267aae99 100644 --- a/tests/vonr/session-test.c +++ b/tests/vonr/session-test.c @@ -2144,6 +2144,831 @@ static void test4_func(abts_case *tc, void *data) test_ue_remove(test_ue); } +static void test5_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess5 = NULL, *sess6 = NULL; + test_bearer_t *qos_flow1 = NULL, *qos_flow2 = NULL; + + const char *_k_string = "70d49a71dd1a2b806a25abe0ef749f1e"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "6f1bf53d624b3a43af6592854e2444c7"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"597223158b8861d7605378c6\" }, " + "\"imsi\" : \"901700000021309\"," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1024000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1024000\" } " + "}," + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"597223158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1024000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1024000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"security\" : { " + "\"k\" : \"70d49a71dd1a2b806a25abe0ef749f1e\", " + "\"opc\" : \"6f1bf53d624b3a43af6592854e2444c7\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"25235952177090\" } " + "}, " + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"__v\" : 0 " + "}"; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.type = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + OGS_HEX(_k_string, strlen(_k_string), test_ue->k); + OGS_HEX(_opc_string, strlen(_opc_string), test_ue->opc); + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + 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(test_ue->imsi)); + 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 Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial context setup request + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UE radio capability info indication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Initial context setup response */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess5 = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess5); + + sess5->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess5->ul_nas_transport_param.dnn = 1; + sess5->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess5); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess5, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess5); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session establishment request */ + sess6 = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess6); + + sess6->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess6->ul_nas_transport_param.dnn = 1; + sess6->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess6); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess6, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment reject */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + +#if 0 + /* Send PDU session establishment request */ + sess5 = test_sess_add_by_dnn_and_psi(test_ue, "ims", 5); + ogs_assert(sess5); + + sess5->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess5->ul_nas_transport_param.dnn = 1; + sess5->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess5); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess5, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment reject */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Test Session Remove */ + test_sess_remove(sess5); + + /* Send PDU session establishment request */ + sess6 = test_sess_add_by_dnn_and_psi(test_ue, "internet", 6); + ogs_assert(sess6); + + sess6->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess6->ul_nas_transport_param.dnn = 1; + sess6->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess6); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess6, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); +#endif + +#if 0 + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); +#endif + +#if 0 + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); +#endif + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + 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); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test6_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess5 = NULL, *sess6 = NULL; + test_bearer_t *qos_flow1 = NULL, *qos_flow2 = NULL; + + const char *_k_string = "70d49a71dd1a2b806a25abe0ef749f1e"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "6f1bf53d624b3a43af6592854e2444c7"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"597223158b8861d7605378c6\" }, " + "\"imsi\" : \"901700000021309\"," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1024000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1024000\" } " + "}," + "\"pdn\" : [" + "{" + "\"apn\" : \"internet\", " + "\"_id\" : { \"$oid\" : \"597223158b8861d7605378c7\" }, " + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1024000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1024000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 9, " + "\"arp\" : { " + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"security\" : { " + "\"k\" : \"70d49a71dd1a2b806a25abe0ef749f1e\", " + "\"opc\" : \"6f1bf53d624b3a43af6592854e2444c7\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"25235952177090\" } " + "}, " + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"__v\" : 0 " + "}"; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.type = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + OGS_HEX(_k_string, strlen(_k_string), test_ue->k); + OGS_HEX(_opc_string, strlen(_opc_string), test_ue->opc); + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + 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(test_ue->imsi)); + 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 Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial context setup request + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UE radio capability info indication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Initial context setup response */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess5 = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess5); + + sess5->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess5->ul_nas_transport_param.dnn = 1; + sess5->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess5); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess5, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess5); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session establishment request */ + sess6 = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess6); + + sess6->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess6->ul_nas_transport_param.dnn = 1; + sess6->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess6); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess6, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment reject */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Remove All Test Session */ + test_sess_remove(sess6); + + /* Send PDU session establishment request */ + sess5 = test_sess_add_by_dnn_and_psi(test_ue, "ims", 5); + ogs_assert(sess5); + + sess5->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess5->ul_nas_transport_param.dnn = 1; + sess5->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess5); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess5, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment reject */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Test Session Remove */ + test_sess_remove(sess5); + + /* Send PDU session establishment request */ + sess6 = test_sess_add_by_dnn_and_psi(test_ue, "internet", 6); + ogs_assert(sess6); + + sess6->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess6->ul_nas_transport_param.dnn = 1; + sess6->ul_nas_transport_param.s_nssai = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess6); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess6, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + 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); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + abts_suite *test_session(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -2152,6 +2977,8 @@ abts_suite *test_session(abts_suite *suite) abts_run_test(suite, test2_func, NULL); abts_run_test(suite, test3_func, NULL); abts_run_test(suite, test4_func, NULL); + abts_run_test(suite, test5_func, NULL); + abts_run_test(suite, test6_func, NULL); return suite; }