From 8a6c36dacab5fcd882f08b8cb335c040e248198f Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Jan 2023 22:44:44 +0900 Subject: [PATCH] [AMF] Network Initiated De-Register (#2014, #2021) Resolved Network Initiated Implicit/Explicit De-Registration --- src/amf/context.h | 18 ++++++++ src/amf/gmm-build.c | 17 +++---- src/amf/gmm-build.h | 6 ++- src/amf/gmm-sm.c | 49 ++++++++++++++------ src/amf/namf-handler.c | 102 +++++++++++++++++++---------------------- src/amf/nas-path.c | 9 ++-- src/amf/nas-path.h | 6 ++- src/amf/nsmf-handler.c | 3 +- src/amf/sbi-path.h | 45 +++++++++--------- 9 files changed, 149 insertions(+), 106 deletions(-) diff --git a/src/amf/context.h b/src/amf/context.h index 02842506f..247537107 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -406,6 +406,24 @@ struct amf_ue_s { /* SubscriptionId of Subscription to Data Change Notification to UDM */ char *data_change_subscription_id; + struct { + /* + * De-Registered Request + * De-Registered Accept + */ + bool n1_done; + + /* + * Nudm_SDM_Unsubscribe + * PATCH Nudm_UECM/registration/amf-3gpp-access + * PDU Session Release + * N4 Release + * DELETE Nbpsf-management + * DELETE Npcf-am_policy-control + */ + bool sbi_done; + } explict_de_registered; + ogs_list_t sess_list; }; diff --git a/src/amf/gmm-build.c b/src/amf/gmm-build.c index f38bc71c4..d4bbc3f92 100644 --- a/src/amf/gmm-build.c +++ b/src/amf/gmm-build.c @@ -283,8 +283,10 @@ ogs_pkbuf_t *gmm_build_de_registration_accept(amf_ue_t *amf_ue) return nas_5gs_security_encode(amf_ue, &message); } -ogs_pkbuf_t *gmm_build_de_registration_request(amf_ue_t *amf_ue, - OpenAPI_deregistration_reason_e dereg_reason) +ogs_pkbuf_t *gmm_build_de_registration_request( + amf_ue_t *amf_ue, + OpenAPI_deregistration_reason_e dereg_reason, + ogs_nas_5gmm_cause_t gmm_cause) { ogs_nas_5gs_message_t message; ogs_nas_5gs_deregistration_request_to_ue_t *dereg_req = @@ -307,12 +309,11 @@ ogs_pkbuf_t *gmm_build_de_registration_request(amf_ue_t *amf_ue, dereg_reason == OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED; dereg_req->de_registration_type.access_type = OGS_ACCESS_TYPE_3GPP; - dereg_req->presencemask |= - OGS_NAS_5GS_DEREGISTRATION_REQUEST_TO_UE_5GMM_CAUSE_PRESENT; - dereg_req->gmm_cause = - (dereg_reason == OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED - ? OGS_5GMM_CAUSE_IMPLICITLY_DE_REGISTERED - : OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED); + if (gmm_cause) { + dereg_req->presencemask |= + OGS_NAS_5GS_DEREGISTRATION_REQUEST_TO_UE_5GMM_CAUSE_PRESENT; + dereg_req->gmm_cause = gmm_cause; + } return nas_5gs_security_encode(amf_ue, &message); } diff --git a/src/amf/gmm-build.h b/src/amf/gmm-build.h index cf5fd9159..6cc6d480f 100644 --- a/src/amf/gmm-build.h +++ b/src/amf/gmm-build.h @@ -34,8 +34,10 @@ ogs_pkbuf_t *gmm_build_service_reject( amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t gmm_cause); ogs_pkbuf_t *gmm_build_de_registration_accept(amf_ue_t *amf_ue); -ogs_pkbuf_t *gmm_build_de_registration_request(amf_ue_t *amf_ue, - OpenAPI_deregistration_reason_e dereg_reason); +ogs_pkbuf_t *gmm_build_de_registration_request( + amf_ue_t *amf_ue, + OpenAPI_deregistration_reason_e dereg_reason, + ogs_nas_5gmm_cause_t gmm_cause); ogs_pkbuf_t *gmm_build_identity_request(amf_ue_t *amf_ue); ogs_pkbuf_t *gmm_build_security_mode_command(amf_ue_t *amf_ue); diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 56a2b3ad8..6ba7898fd 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -115,7 +115,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) } else { amf_ue->t3522.retry_count++; r = nas_5gs_send_de_registration_request(amf_ue, - OpenAPI_deregistration_reason_NULL); + OpenAPI_deregistration_reason_NULL, 0); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } @@ -206,7 +206,10 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) amf_ue->data_change_subscription_id = NULL; } - if (state == AMF_NETWORK_INITIATED_DE_REGISTERED) { + if (state == + AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED || + state == + AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) { amf_sbi_send_release_all_sessions(amf_ue, state); if ((ogs_list_count(&amf_ue->sess_list) == 0) && (PCF_AM_POLICY_ASSOCIATED(amf_ue))) { @@ -292,10 +295,27 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) break; CASE(OGS_SBI_HTTP_METHOD_DELETE) - if (state == AMF_NETWORK_INITIATED_DE_REGISTERED) { - ogs_warn("[%s] AMF-UE Context Removed", amf_ue->supi); + if (state == AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED) { + ogs_warn("[%s] Implicit De-registered", amf_ue->supi); OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_ue_context_will_remove); + + } else if (state == + AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) { + ogs_warn("[%s] Explicit De-registered", amf_ue->supi); + + amf_ue->explict_de_registered.sbi_done = true; + + if (amf_ue->explict_de_registered.n1_done == true) { + r = ngap_send_ran_ue_context_release_command( + amf_ue->ran_ue, + NGAP_Cause_PR_misc, + NGAP_CauseMisc_om_intervention, + NGAP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + } else { r = nas_5gs_send_de_registration_accept(amf_ue); ogs_expect(r == OGS_OK); @@ -501,7 +521,9 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, amf_nudm_sdm_build_subscription_delete, - amf_ue, AMF_NETWORK_INITIATED_DE_REGISTERED, NULL)); + amf_ue, + AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED, NULL)); + OGS_FSM_TRAN(s, &gmm_state_de_registered); break; default: @@ -740,16 +762,15 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) ogs_info("[%s] Deregistration accept", amf_ue->supi); CLEAR_AMF_UE_TIMER(amf_ue->t3522); - /* De-associate NG with NAS/EMM */ - ran_ue_deassociate(amf_ue->ran_ue); + amf_ue->explict_de_registered.n1_done = true; - r = ngap_send_ran_ue_context_release_command(amf_ue->ran_ue, - NGAP_Cause_PR_misc, NGAP_CauseMisc_om_intervention, - NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - - OGS_FSM_TRAN(s, &gmm_state_de_registered); + if (amf_ue->explict_de_registered.sbi_done == true) { + r = ngap_send_ran_ue_context_release_command(amf_ue->ran_ue, + NGAP_Cause_PR_misc, NGAP_CauseMisc_om_intervention, + NGAP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } break; case OGS_NAS_5GS_CONFIGURATION_UPDATE_COMPLETE: diff --git a/src/amf/namf-handler.c b/src/amf/namf-handler.c index 0c2325f4b..0c36b04d0 100644 --- a/src/amf/namf-handler.c +++ b/src/amf/namf-handler.c @@ -518,47 +518,10 @@ cleanup: return OGS_OK; } -static int do_network_initiated_de_register( - amf_ue_t *amf_ue, OpenAPI_deregistration_reason_e dereg_reason) -{ - int r; - if ((CM_CONNECTED(amf_ue)) && - (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered))) { - - r = nas_5gs_send_de_registration_request(amf_ue, dereg_reason); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - - amf_sbi_send_release_all_sessions( - amf_ue, AMF_NETWORK_INITIATED_DE_REGISTERED); - - if ((ogs_list_count(&amf_ue->sess_list) == 0) && - (PCF_AM_POLICY_ASSOCIATED(amf_ue))) { - ogs_assert(true == - amf_ue_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, - amf_npcf_am_policy_control_build_delete, - amf_ue, AMF_NETWORK_INITIATED_DE_REGISTERED, NULL)); - } - - OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_de_registered); - return OGS_OK; - - } else if (CM_IDLE(amf_ue)) { - /* TODO: need to page UE */ - ogs_error("Not implemented : need to page UE"); - return OGS_ERROR; - } else { - ogs_fatal("Invalid State"); - ogs_assert_if_reached(); - return OGS_ERROR; - } -} - int amf_namf_callback_handle_dereg_notify( ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { - int status = OGS_SBI_HTTP_STATUS_NO_CONTENT; + int r, status = OGS_SBI_HTTP_STATUS_NO_CONTENT; amf_ue_t *amf_ue = NULL; @@ -609,13 +572,30 @@ int amf_namf_callback_handle_dereg_notify( * Deregistration procedure. In this case, the AMF performs network requested PDU Session Release for any PDU * session associated with non-emergency service as described in clause 4.3.4. */ + if (CM_CONNECTED(amf_ue)) { + r = nas_5gs_send_de_registration_request( + amf_ue, + DeregistrationData->dereg_reason, + OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); - if (do_network_initiated_de_register( - amf_ue, DeregistrationData->dereg_reason) != OGS_OK) { - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - ogs_error("[%s] Deregistration notification for UE in wrong state", - amf_ue->supi); - goto cleanup; + ogs_assert(true == amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, + amf_nudm_sdm_build_subscription_delete, + amf_ue, + AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED, NULL)); + } else if (CM_IDLE(amf_ue)) { + ogs_error("Not implemented : Use Implicit De-registration"); + + ogs_assert(true == amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, + amf_nudm_sdm_build_subscription_delete, + amf_ue, + AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED, NULL)); + } else { + ogs_fatal("Invalid State"); + ogs_assert_if_reached(); } cleanup: @@ -900,17 +880,31 @@ int amf_namf_callback_handle_sdm_data_change_notify( } if (amf_ue_is_rat_restricted(amf_ue)) { - if (do_network_initiated_de_register(amf_ue, - OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED) != OGS_OK) { - status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - ogs_error("[%s] Deregistration notification for UE in wrong state", - amf_ue->supi); - goto cleanup; - } - ogs_assert(true == - amf_ue_sbi_discover_and_send( + if (CM_CONNECTED(amf_ue)) { + r = nas_5gs_send_de_registration_request( + amf_ue, + OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED, 0); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + + ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, - amf_nudm_sdm_build_subscription_delete, amf_ue, 0, NULL)); + amf_nudm_sdm_build_subscription_delete, + amf_ue, + AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED, NULL)); + } else if (CM_IDLE(amf_ue)) { + ogs_error("Not implemented : Use Implicit De-registration"); + + ogs_assert(true == amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, + amf_nudm_sdm_build_subscription_delete, + amf_ue, + AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED, NULL)); + } else { + ogs_fatal("Invalid State"); + ogs_assert_if_reached(); + } + } else if (ambr_changed) { ogs_pkbuf_t *ngapbuf; diff --git a/src/amf/nas-path.c b/src/amf/nas-path.c index 262834299..d799382bb 100644 --- a/src/amf/nas-path.c +++ b/src/amf/nas-path.c @@ -344,8 +344,10 @@ int nas_5gs_send_de_registration_accept(amf_ue_t *amf_ue) return rv; } -int nas_5gs_send_de_registration_request(amf_ue_t *amf_ue, - OpenAPI_deregistration_reason_e dereg_reason) +int nas_5gs_send_de_registration_request( + amf_ue_t *amf_ue, + OpenAPI_deregistration_reason_e dereg_reason, + ogs_nas_5gmm_cause_t gmm_cause) { int rv; @@ -364,7 +366,8 @@ int nas_5gs_send_de_registration_request(amf_ue_t *amf_ue, if (amf_ue->t3522.pkbuf) { gmmbuf = amf_ue->t3522.pkbuf; } else { - gmmbuf = gmm_build_de_registration_request(amf_ue, dereg_reason); + gmmbuf = gmm_build_de_registration_request( + amf_ue, dereg_reason, gmm_cause); if (!gmmbuf) { ogs_error("gmm_build_de_registration_request() failed"); return OGS_ERROR; diff --git a/src/amf/nas-path.h b/src/amf/nas-path.h index bf8848041..9b5715bb1 100644 --- a/src/amf/nas-path.h +++ b/src/amf/nas-path.h @@ -41,8 +41,10 @@ int nas_5gs_send_service_reject( amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t gmm_cause); int nas_5gs_send_de_registration_accept(amf_ue_t *amf_ue); -int nas_5gs_send_de_registration_request(amf_ue_t *amf_ue, - OpenAPI_deregistration_reason_e dereg_reason); +int nas_5gs_send_de_registration_request( + amf_ue_t *amf_ue, + OpenAPI_deregistration_reason_e dereg_reason, + ogs_nas_5gmm_cause_t gmm_cause); int nas_5gs_send_identity_request(amf_ue_t *amf_ue); diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index a20f2c717..b9527e036 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -911,7 +911,8 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) ogs_assert_if_reached(); } else if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE || - state == AMF_NETWORK_INITIATED_DE_REGISTERED) { + state == AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED || + state == AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) { /* NO_STATE */ if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_authentication)) { diff --git a/src/amf/sbi-path.h b/src/amf/sbi-path.h index a847fd950..4116b53e4 100644 --- a/src/amf/sbi-path.h +++ b/src/amf/sbi-path.h @@ -37,31 +37,32 @@ void amf_sbi_close(void); bool amf_sbi_send_request( ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); -#define AMF_CREATE_SM_CONTEXT_NO_STATE 0 +#define AMF_CREATE_SM_CONTEXT_NO_STATE 0 -#define AMF_NETWORK_INITIATED_DE_REGISTERED 1 +#define AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED 1 +#define AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED 2 -#define AMF_UPDATE_SM_CONTEXT_ACTIVATED 11 -#define AMF_UPDATE_SM_CONTEXT_SETUP_FAIL 12 -#define AMF_UPDATE_SM_CONTEXT_DEACTIVATED 13 -#define AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST 14 -#define AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST 15 -#define AMF_UPDATE_SM_CONTEXT_MODIFIED 16 -#define AMF_UPDATE_SM_CONTEXT_N2_RELEASED 17 -#define AMF_UPDATE_SM_CONTEXT_N1_RELEASED 18 +#define AMF_UPDATE_SM_CONTEXT_ACTIVATED 11 +#define AMF_UPDATE_SM_CONTEXT_SETUP_FAIL 12 +#define AMF_UPDATE_SM_CONTEXT_DEACTIVATED 13 +#define AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST 14 +#define AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST 15 +#define AMF_UPDATE_SM_CONTEXT_MODIFIED 16 +#define AMF_UPDATE_SM_CONTEXT_N2_RELEASED 17 +#define AMF_UPDATE_SM_CONTEXT_N1_RELEASED 18 #define AMF_UPDATE_SM_CONTEXT_DUPLICATED_PDU_SESSION_ID 19 -#define AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST 20 -#define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED 21 -#define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK 22 -#define AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY 23 -#define AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL 24 -#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 +#define AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST 20 +#define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED 21 +#define AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK 22 +#define AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY 23 +#define AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL 24 +#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 bool amf_ue_sbi_discover_and_send( ogs_sbi_service_type_e service_type,