[SMF] Deregister issue during sess release (#2537)

A situation in which you establish two sessions and release both of them.

In the first SESSION, the UE normally sent PDUSessionResourceReleaseResponse
and PDU session release complete. However, these were not sent when releasing
the second SESSION.

At this point, when the UE tried to do a deregistration,
the SMF was not properly handling the exception.

I've just fixed this.
This commit is contained in:
Sukchan Lee 2023-08-24 21:20:25 +09:00
parent 5469ae9855
commit 04f7958420
3 changed files with 388 additions and 14 deletions

View File

@ -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]);

View File

@ -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;

View File

@ -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;
}