diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index d3d365666..81ccecbc9 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -1043,9 +1043,14 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } else { - ogs_error("[%s:%d] No PolicyAssociationId", - smf_ue->supi, sess->psi); - OGS_FSM_TRAN(s, smf_gsm_state_exception); + ogs_warn("[%s:%d] No PolicyAssociationId. " + "Forcibly remove SESSION", smf_ue->supi, sess->psi); + r = smf_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL, + smf_nudm_uecm_build_deregistration, sess, stream, + SMF_UECM_STATE_DEREGISTERED_BY_AMF, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); } break; @@ -1516,6 +1521,9 @@ void smf_gsm_state_wait_5gc_n1_n2_release(ogs_fsm_t *s, smf_event_t *e) CASE(OGS_SBI_RESOURCE_NAME_MODIFY) smf_nsmf_handle_update_sm_context(sess, stream, sbi_message); break; + CASE(OGS_SBI_RESOURCE_NAME_RELEASE) + smf_nsmf_handle_release_sm_context(sess, stream, sbi_message); + break; DEFAULT ogs_error("Invalid resource name [%s]", sbi_message->h.resource.component[2]); diff --git a/src/smf/nsmf-handler.c b/src/smf/nsmf-handler.c index f248ec054..f9f9903b1 100644 --- a/src/smf/nsmf-handler.c +++ b/src/smf/nsmf-handler.c @@ -682,12 +682,14 @@ bool smf_nsmf_handle_update_sm_context( ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } else { - ogs_error("[%s:%d] No PolicyAssociationId. Forcibly remove SESSION", + ogs_warn("[%s:%d] No PolicyAssociationId. Forcibly remove SESSION", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error_log( - stream, OGS_SBI_HTTP_STATUS_NOT_FOUND, - "No PolicyAssociationId", NULL); - SMF_SESS_CLEAR(sess); + r = smf_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL, + smf_nudm_uecm_build_deregistration, sess, stream, + SMF_UECM_STATE_DEREGISTERED_BY_AMF, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); } } else if (SmContextUpdateData->serving_nf_id) { ogs_debug("Old serving_nf_id: %s, new serving_nf_id: %s", @@ -779,13 +781,14 @@ bool smf_nsmf_handle_release_sm_context( ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } else { - ogs_error("[%s:%d] No PolicyAssociationId. Forcibly remove SESSION", + ogs_warn("[%s:%d] No PolicyAssociationId. Forcibly remove SESSION", smf_ue->supi, sess->psi); - ogs_assert(true == - ogs_sbi_server_send_error( - stream, OGS_SBI_HTTP_STATUS_NOT_FOUND, - NULL, "No PolicyAssociationId", NULL)); - SMF_SESS_CLEAR(sess); + r = smf_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL, + smf_nudm_uecm_build_deregistration, sess, stream, + SMF_UECM_STATE_DEREGISTERED_BY_AMF, NULL); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); } return true; diff --git a/tests/vonr/session-test.c b/tests/vonr/session-test.c index 25a334e34..a046f0ecd 100644 --- a/tests/vonr/session-test.c +++ b/tests/vonr/session-test.c @@ -2301,6 +2301,368 @@ static void test6_func(abts_case *tc, void *data) test_ue_remove(test_ue); } +static void test7_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_HUGE_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_flow = NULL; + + bson_t *doc = NULL; + + /* 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_PROTECTION_SCHEME_NULL; + mobile_identity_suci.home_network_pki_value = 0; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, "0000203190"); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = 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; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* 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 */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false); + 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, false, false); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, + NGAP_RRCEstablishmentCause_mo_Signalling, 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 InitialContextSetupRequest + + * 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 UERadioCapabilityInfoIndication */ + 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 InitialContextSetupResponse */ + 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; + + sess5->pdu_session_establishment_param.ssc_mode = 1; + sess5->pdu_session_establishment_param.epco = 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; + + sess6->pdu_session_establishment_param.ssc_mode = 1; + sess6->pdu_session_establishment_param.epco = 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 sess6ion establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess6); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU Session release request */ + sess6->pti = 38; + sess6->ul_nas_transport_param.request_type = 0; + sess6->ul_nas_transport_param.dnn = 0; + sess6->ul_nas_transport_param.s_nssai = 0; + + sess6->pdu_session_establishment_param.ssc_mode = 0; + sess6->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_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); + + /* Send PDU Session release request */ + sess5->pti = 39; + sess5->ul_nas_transport_param.request_type = 0; + sess5->ul_nas_transport_param.dnn = 0; + sess5->ul_nas_transport_param.s_nssai = 0; + + sess5->pdu_session_establishment_param.ssc_mode = 0; + sess5->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_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 PDUSessionResourceReleaseCommand + + * DL NAS transport + + * PDU session release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceRelease, + test_ue->ngap_procedure_code); + + /* Receive PDUSessionResourceReleaseCommand + + * DL NAS transport + + * PDU session release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceRelease, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceReleaseResponse */ + sendbuf = testngap_build_pdu_session_resource_release_response(sess6); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UplinkNASTransport + + * UL NAS trasnport + + * PDU session resource release complete */ + sess6->ul_nas_transport_param.request_type = 0; + sess6->ul_nas_transport_param.dnn = 0; + sess6->ul_nas_transport_param.s_nssai = 0; + + sess6->pdu_session_establishment_param.ssc_mode = 0; + sess6->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_complete(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); + + /* Test Session Remove */ + test_sess_remove(sess6); + + ogs_msleep(100); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1, true, true); + 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); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* 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) @@ -2311,6 +2673,7 @@ abts_suite *test_session(abts_suite *suite) abts_run_test(suite, test4_func, NULL); abts_run_test(suite, test5_func, NULL); abts_run_test(suite, test6_func, NULL); + abts_run_test(suite, test7_func, NULL); return suite; }