From 9f4a9790e3cb1f7f05c8f97cf6a99c15752e05d5 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 8 Jan 2023 13:53:48 +0900 Subject: [PATCH] [AMF] Follow-up on #1987 [AMF] Implicit Network-initiated Deregistration Two timers are introduced (both with duration of T3512 + 4 min): -MOBILE_REACHABLE -IMPLICIT_DEREGISTRATION MOBILE_REACHABLE is set when NAS connection for the UE is released. IMPLICIT_DEREGISTRATION is set when MOBILE_REACHABLE expires. On MOBILE_REACHABLE expiry Paging is ignored. On IMPLICIT_DEREGISTRATION expiry: -UE's RM_State is set to DEREGISTERED -UE is Nudm_SDM_Unsubscribed -UE is Nudm_UECM_Deregistered -PDU sessions are released -AM policies are deleted Existing flag amf_ue->network_initiated_de_reg is used. --- src/amf/amf-sm.c | 4 ++ src/amf/context.c | 24 --------- src/amf/context.h | 7 --- src/amf/gmm-handler.c | 2 +- src/amf/gmm-sm.c | 113 +++++++++++++++++++++-------------------- src/amf/namf-handler.c | 50 +++++++++--------- src/amf/ngap-handler.c | 26 ++++++++++ src/amf/nsmf-handler.c | 13 +++-- src/amf/nudm-handler.c | 16 +++--- src/amf/nudm-handler.h | 2 +- src/amf/sbi-path.c | 4 +- src/amf/sbi-path.h | 14 +++-- 12 files changed, 143 insertions(+), 132 deletions(-) diff --git a/src/amf/amf-sm.c b/src/amf/amf-sm.c index 83f447863..6bb70ff1c 100644 --- a/src/amf/amf-sm.c +++ b/src/amf/amf-sm.c @@ -370,6 +370,8 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) break; } + state = sbi_xact->state; + amf_ue = (amf_ue_t *)sbi_xact->sbi_object; ogs_assert(amf_ue); @@ -382,6 +384,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) e->amf_ue = amf_ue; e->h.sbi.message = &sbi_message;; + e->h.sbi.state = state; ogs_fsm_dispatch(&amf_ue->sm, e); } else { @@ -542,6 +545,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e) e->amf_ue = amf_ue; e->sess = sess; e->h.sbi.message = &sbi_message;; + e->h.sbi.state = state; amf_nnssf_nsselection_handle_get(sess, &sbi_message); break; diff --git a/src/amf/context.c b/src/amf/context.c index c6cca0af2..3876ab1ce 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -1177,28 +1177,6 @@ void ran_ue_remove(ran_ue_t *ran_ue) ogs_pool_free(&ran_ue_pool, ran_ue); stats_remove_ran_ue(); - if (ran_ue->amf_ue) { - if (ran_ue->amf_ue->rm_state == RM_STATE_REGISTERED) { - /* Start AMF_TIMER_MOBILE_REACHABLE - * TS 24.501 - * 5.3.7 Handling of the periodic registration update timer and - * mobile reachable timer - * The network supervises the periodic registration update procedure - * of the UE by means of the mobile reachable timer. - * If the UE is not registered for emergency services, - * the mobile reachable timer shall be longer than the value of timer - * T3512. In this case, by default, the mobile reachable timer is - * 4 minutes greater than the value of timer T3512. - * The mobile reachable timer shall be reset and started with the - * value as indicated above, when the AMF releases the NAS signalling - * connection for the UE. - * TODO: If the UE is registered for emergency services, the AMF shall - * set the mobile reachable timer with a value equal to timer T3512. - */ - ogs_timer_start(ran_ue->amf_ue->mobile_reachable.timer, - ogs_time_from_sec(amf_self()->time.t3512.value + 240)); - } - } } void ran_ue_switch_to_gnb(ran_ue_t *ran_ue, amf_gnb_t *new_gnb) @@ -1434,8 +1412,6 @@ amf_ue_t *amf_ue_add(ran_ue_t *ran_ue) amf_ue->nas.amf.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; amf_ue->abba_len = 2; - amf_ue->rm_state = RM_STATE_DEREGISTERED; - amf_ue_fsm_init(amf_ue); ogs_list_add(&self.amf_ue_list, amf_ue); diff --git a/src/amf/context.h b/src/amf/context.h index 15b7359de..02842506f 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -403,17 +403,10 @@ struct amf_ue_s { long cause; } handover; - /* Network Initiated De-Registration */ - bool network_initiated_de_reg; - /* SubscriptionId of Subscription to Data Change Notification to UDM */ char *data_change_subscription_id; ogs_list_t sess_list; - -#define RM_STATE_DEREGISTERED 0 -#define RM_STATE_REGISTERED 1 - uint8_t rm_state; }; typedef struct amf_sess_s { diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index 47f103724..163a6c73e 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -740,7 +740,7 @@ int gmm_handle_authentication_response(amf_ue_t *amf_ue, ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate_confirmation, amf_ue, NULL)); + amf_nausf_auth_build_authenticate_confirmation, amf_ue, 0, NULL)); return OGS_OK; } diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index e5fd95d7b..2ce777a94 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -53,11 +53,15 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e); void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) { + int i; + amf_ue_t *amf_ue = NULL; amf_sess_t *sess = NULL; ogs_sbi_message_t *sbi_message = NULL; + int state = 0; + ogs_assert(e); if (e->sess) { @@ -71,6 +75,12 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) switch (e->h.id) { case OGS_FSM_ENTRY_SIG: + ogs_assert(amf_ue->num_of_slice <= OGS_MAX_NUM_OF_SLICE); + for (i = 0; i < amf_ue->num_of_slice; i++) { + amf_metrics_inst_by_slice_add(&amf_ue->nr_tai.plmn_id, + &amf_ue->slice[i].s_nssai, + AMF_METR_GAUGE_RM_REGISTEREDSUBNBR, -1); + } AMF_UE_CLEAR_PAGING_INFO(amf_ue); AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue); @@ -123,6 +133,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) case OGS_EVENT_SBI_CLIENT: sbi_message = e->h.sbi.message; ogs_assert(sbi_message); + state = e->h.sbi.state; SWITCH(sbi_message->h.service.name) CASE(OGS_SBI_SERVICE_NAME_NAUSF_AUTH) @@ -197,23 +208,24 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) ogs_free(amf_ue->data_change_subscription_id); amf_ue->data_change_subscription_id = NULL; } - if (amf_ue->network_initiated_de_reg) { - amf_sbi_send_release_all_sessions( - amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); + + if (state == AMF_NETWORK_INITIATED_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))) - { + (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, NULL)); + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL)); } } else { ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, amf_nausf_auth_build_authenticate_delete, - amf_ue, NULL)); + amf_ue, state, NULL)); } break; DEFAULT @@ -259,7 +271,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL, amf_nudm_uecm_build_registration_delete, - amf_ue, NULL)); + amf_ue, state, NULL)); break; DEFAULT ogs_warn("[%s] Ignore invalid HTTP method [%s]", @@ -283,11 +295,10 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) break; CASE(OGS_SBI_HTTP_METHOD_DELETE) - if (!amf_ue->network_initiated_de_reg) + if (state != AMF_NETWORK_INITIATED_DE_REGISTERED) ogs_assert(OGS_OK == nas_5gs_send_de_registration_accept(amf_ue)); - amf_ue->network_initiated_de_reg = false; PCF_AM_POLICY_CLEAR(amf_ue); break; @@ -317,6 +328,8 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) { + int i; + amf_ue_t *amf_ue = NULL; amf_sess_t *sess = NULL; @@ -335,6 +348,12 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) switch (e->h.id) { case OGS_FSM_ENTRY_SIG: + ogs_assert(amf_ue->num_of_slice <= OGS_MAX_NUM_OF_SLICE); + for (i = 0; i < amf_ue->num_of_slice; i++) { + amf_metrics_inst_by_slice_add(&amf_ue->nr_tai.plmn_id, + &amf_ue->slice[i].s_nssai, + AMF_METR_GAUGE_RM_REGISTEREDSUBNBR, 1); + } break; case OGS_FSM_EXIT_SIG: break; @@ -418,7 +437,7 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) break; case AMF_TIMER_MOBILE_REACHABLE: - ogs_info("[%s] Mobile Reachable timer expired", amf_ue->supi); + ogs_info("[%s] Mobile Reachable Timer Expired", amf_ue->supi); /* Clear mobile_reachable Timers */ CLEAR_AMF_UE_TIMER(amf_ue->mobile_reachable); /* Start AMF_TIMER_IMPLICIT_DEREGISTRATION @@ -434,8 +453,7 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) ogs_time_from_sec(amf_self()->time.t3512.value + 240)); break; case AMF_TIMER_IMPLICIT_DEREGISTRATION: - ogs_info("[%s] Implicit de-reg timer expired, de-register UE", - amf_ue->supi); + ogs_info("[%s] Do Network-Initiated De-Register UE", amf_ue->supi); /* Clear implicit_deregistration Timers */ CLEAR_AMF_UE_TIMER(amf_ue->implicit_deregistration); /* Implicitly de-register UE @@ -452,9 +470,8 @@ 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, NULL)); - amf_ue->network_initiated_de_reg = true; - amf_ue->rm_state = RM_STATE_DEREGISTERED; + amf_nudm_sdm_build_subscription_delete, + amf_ue, AMF_NETWORK_INITIATED_DE_REGISTERED, NULL)); OGS_FSM_TRAN(s, &gmm_state_de_registered); break; default: @@ -478,7 +495,7 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e) static void common_register_state(ogs_fsm_t *s, amf_event_t *e) { - int rv, i, xact_count = 0; + int rv, xact_count = 0; ogs_nas_5gmm_cause_t gmm_cause; amf_ue_t *amf_ue = NULL; @@ -560,7 +577,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, amf_npcf_am_policy_control_build_create, - amf_ue, NULL)); + amf_ue, 0, NULL)); OGS_FSM_TRAN(s, &gmm_state_initial_context_setup); break; } @@ -583,7 +600,8 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL)); } OGS_FSM_TRAN(s, &gmm_state_authentication); @@ -661,7 +679,8 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL)); } OGS_FSM_TRAN(s, &gmm_state_authentication); @@ -678,13 +697,6 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) gmm_handle_deregistration_request( amf_ue, &nas_message->gmm.deregistration_request_from_ue); - ogs_assert(amf_ue->num_of_slice <= OGS_MAX_NUM_OF_SLICE); - for (i = 0; i < amf_ue->num_of_slice; i++) { - amf_metrics_inst_by_slice_add(&amf_ue->nr_tai.plmn_id, - &amf_ue->slice[i].s_nssai, - AMF_METR_GAUGE_RM_REGISTEREDSUBNBR, -1); - } - amf_ue->rm_state = RM_STATE_DEREGISTERED; OGS_FSM_TRAN(s, &gmm_state_de_registered); break; @@ -700,13 +712,6 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) NGAP_Cause_PR_misc, NGAP_CauseMisc_om_intervention, NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0)); - ogs_assert(amf_ue->num_of_slice <= OGS_MAX_NUM_OF_SLICE); - for (i = 0; i < amf_ue->num_of_slice; i++) { - amf_metrics_inst_by_slice_add(&amf_ue->nr_tai.plmn_id, - &amf_ue->slice[i].s_nssai, - AMF_METR_GAUGE_RM_REGISTEREDSUBNBR, -1); - } - amf_ue->rm_state = RM_STATE_DEREGISTERED; OGS_FSM_TRAN(s, &gmm_state_de_registered); break; @@ -851,7 +856,8 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL)); return; case OGS_5GMM_CAUSE_SYNCH_FAILURE: @@ -865,7 +871,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e) amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, amf_nausf_auth_build_authenticate, - amf_ue, authentication_failure_parameter->auts)); + amf_ue, 0, authentication_failure_parameter->auts)); return; default: @@ -897,7 +903,7 @@ void gmm_state_authentication(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, amf_ue, 0, NULL)); break; case OGS_NAS_5GS_5GMM_STATUS: @@ -1106,7 +1112,7 @@ void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL, - amf_nudm_uecm_build_registration, amf_ue, NULL)); + amf_nudm_uecm_build_registration, amf_ue, 0, NULL)); if (amf_ue->nas.message_type == OGS_NAS_5GS_REGISTRATION_REQUEST) { OGS_FSM_TRAN(s, &gmm_state_initial_context_setup); @@ -1142,7 +1148,7 @@ void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, amf_ue, 0, NULL)); OGS_FSM_TRAN(s, &gmm_state_authentication); break; @@ -1209,7 +1215,7 @@ void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e) void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) { - int rv, xact_count = 0; + int rv, state, xact_count = 0; ogs_nas_5gmm_cause_t gmm_cause; amf_ue_t *amf_ue = NULL; @@ -1244,6 +1250,7 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) case OGS_EVENT_SBI_CLIENT: sbi_message = e->h.sbi.message; ogs_assert(sbi_message); + state = e->h.sbi.state; SWITCH(sbi_message->h.service.name) CASE(OGS_SBI_SERVICE_NAME_NUDM_UECM) @@ -1268,7 +1275,8 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, amf_nudm_sdm_build_get, - amf_ue, (char *)OGS_SBI_RESOURCE_NAME_AM_DATA)); + amf_ue, state, + (char *)OGS_SBI_RESOURCE_NAME_AM_DATA)); break; DEFAULT @@ -1303,7 +1311,8 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) break; } - rv = amf_nudm_sdm_handle_provisioned(amf_ue, sbi_message); + rv = amf_nudm_sdm_handle_provisioned( + amf_ue, state, sbi_message); if (rv != OGS_OK) { ogs_error("[%s] amf_nudm_sdm_handle_provisioned(%s) failed", amf_ue->supi, sbi_message->h.resource.component[1]); @@ -1388,16 +1397,6 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) switch (nas_message->gmm.h.message_type) { case OGS_NAS_5GS_REGISTRATION_COMPLETE: ogs_info("[%s] Registration complete", amf_ue->supi); - if (amf_ue->rm_state == RM_STATE_DEREGISTERED){ - int i; - ogs_assert(amf_ue->num_of_slice <= OGS_MAX_NUM_OF_SLICE); - for (i = 0; i < amf_ue->num_of_slice; i++) { - amf_metrics_inst_by_slice_add(&amf_ue->nr_tai.plmn_id, - &amf_ue->slice[i].s_nssai, - AMF_METR_GAUGE_RM_REGISTEREDSUBNBR, 1); - } - } - amf_ue->rm_state = RM_STATE_REGISTERED; CLEAR_AMF_UE_TIMER(amf_ue->t3550); @@ -1480,7 +1479,8 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL)); } OGS_FSM_TRAN(s, &gmm_state_authentication); break; @@ -1646,7 +1646,7 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, amf_npcf_am_policy_control_build_create, - amf_ue, NULL)); + amf_ue, 0, NULL)); OGS_FSM_TRAN(s, &gmm_state_initial_context_setup); break; } @@ -1669,7 +1669,8 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL)); } OGS_FSM_TRAN(s, &gmm_state_authentication); diff --git a/src/amf/namf-handler.c b/src/amf/namf-handler.c index f4fdb743a..3821b66b8 100644 --- a/src/amf/namf-handler.c +++ b/src/amf/namf-handler.c @@ -499,37 +499,38 @@ cleanup: return OGS_OK; } -static int network_deregister ( - amf_ue_t *amf_ue, OpenAPI_deregistration_reason_e dereg_reason) { +static int do_network_initiated_de_register( + amf_ue_t *amf_ue, OpenAPI_deregistration_reason_e dereg_reason) +{ if ((CM_CONNECTED(amf_ue)) && - (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered))) - { - amf_ue->network_initiated_de_reg = true; + (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered))) { ogs_assert(OGS_OK == nas_5gs_send_de_registration_request(amf_ue, dereg_reason)); amf_sbi_send_release_all_sessions( - amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE); + amf_ue, AMF_NETWORK_INITIATED_DE_REGISTERED); if ((ogs_list_count(&amf_ue->sess_list) == 0) && - (PCF_AM_POLICY_ASSOCIATED(amf_ue))) - { + (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, 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)) { + + } else if (CM_IDLE(amf_ue)) { /* TODO: need to page UE */ - /*ngap_send_paging(amf_ue);*/ - return OGS_OK; + ogs_error("Not implemented : need to page UE"); + return OGS_ERROR; } else { - return OGS_ERROR; + ogs_fatal("Invalid State"); + ogs_assert_if_reached(); + return OGS_ERROR; } } @@ -588,8 +589,8 @@ int amf_namf_callback_handle_dereg_notify( * session associated with non-emergency service as described in clause 4.3.4. */ - if (network_deregister( - amf_ue, DeregistrationData->dereg_reason) == -1) { + 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); @@ -823,8 +824,7 @@ int amf_namf_callback_handle_sdm_data_change_notify( } - OpenAPI_list_for_each(ModificationNotification->notify_items, node) - { + OpenAPI_list_for_each(ModificationNotification->notify_items, node) { OpenAPI_notify_item_t *item = node->data; char *saveptr = NULL; @@ -854,12 +854,11 @@ int amf_namf_callback_handle_sdm_data_change_notify( CASE(OGS_SBI_RESOURCE_NAME_AM_DATA) OpenAPI_lnode_t *node_ci; - OpenAPI_list_for_each(item->changes, node_ci) - { + OpenAPI_list_for_each(item->changes, node_ci) { OpenAPI_change_item_t *change_item = node_ci->data; - if (update_rat_res(change_item, amf_ue->rat_restrictions) - || update_ambr(change_item, &amf_ue->ue_ambr, - &ambr_changed)) { + if (update_rat_res(change_item, amf_ue->rat_restrictions) || + update_ambr(change_item, &amf_ue->ue_ambr, + &ambr_changed)) { status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; goto cleanup; } @@ -879,7 +878,8 @@ int amf_namf_callback_handle_sdm_data_change_notify( } if (amf_ue_is_rat_restricted(amf_ue)) { - if (network_deregister(amf_ue, OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED) == -1) { + 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); @@ -888,7 +888,7 @@ int amf_namf_callback_handle_sdm_data_change_notify( ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, - amf_nudm_sdm_build_subscription_delete, amf_ue, NULL)); + amf_nudm_sdm_build_subscription_delete, amf_ue, 0, NULL)); } else if (ambr_changed) { ogs_pkbuf_t *ngapbuf; diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index 225d46918..e0275ee4b 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -1571,6 +1571,32 @@ void ngap_handle_ue_context_release_action(ran_ue_t *ran_ue) * to prevent retransmission of NAS messages. */ CLEAR_AMF_UE_ALL_TIMERS(amf_ue); + + /* + * TS 24.501 + * 5.3.7 Handling of the periodic registration update timer and + * + * Start AMF_TIMER_MOBILE_REACHABLE + * mobile reachable timer + * The network supervises the periodic registration update procedure + * of the UE by means of the mobile reachable timer. + * If the UE is not registered for emergency services, + * the mobile reachable timer shall be longer than the value of timer + * T3512. In this case, by default, the mobile reachable timer is + * 4 minutes greater than the value of timer T3512. + * The mobile reachable timer shall be reset and started with the + * value as indicated above, when the AMF releases the NAS signalling + * connection for the UE. + * + * TODO: If the UE is registered for emergency services, the AMF shall + * set the mobile reachable timer with a value equal to timer T3512. + */ + if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered) && + ran_ue->ue_ctx_rel_action == NGAP_UE_CTX_REL_NG_REMOVE_AND_UNLINK) { + + ogs_timer_start(amf_ue->mobile_reachable.timer, + ogs_time_from_sec(amf_self()->time.t3512.value + 240)); + } } switch (ran_ue->ue_ctx_rel_action) { diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index 58ca9b2f4..de691cbec 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -236,7 +236,7 @@ int amf_nsmf_pdusession_handle_update_sm_context( OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, amf_npcf_am_policy_control_build_create, - amf_ue, NULL)); + amf_ue, 0, NULL)); } else { CLEAR_AMF_UE_TIMER(amf_ue->t3550); ogs_assert(OGS_OK == @@ -821,7 +821,8 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, - amf_npcf_am_policy_control_build_create, amf_ue, NULL)); + amf_npcf_am_policy_control_build_create, + amf_ue, 0, NULL)); } else { CLEAR_AMF_UE_TIMER(amf_ue->t3550); ogs_assert(OGS_OK == @@ -866,7 +867,8 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) /* Not reached here */ ogs_assert_if_reached(); - } else if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE) { + } else if (state == AMF_RELEASE_SM_CONTEXT_NO_STATE || + state == AMF_NETWORK_INITIATED_DE_REGISTERED) { /* NO_STATE */ if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_authentication)) { @@ -874,7 +876,8 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL, - amf_nausf_auth_build_authenticate, amf_ue, NULL)); + amf_nausf_auth_build_authenticate, + amf_ue, 0, NULL)); } else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_de_registered)) { @@ -893,7 +896,7 @@ int amf_nsmf_pdusession_handle_release_sm_context(amf_sess_t *sess, int state) amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, amf_npcf_am_policy_control_build_delete, - amf_ue, NULL)); + amf_ue, state, NULL)); } else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered)) { /* diff --git a/src/amf/nudm-handler.c b/src/amf/nudm-handler.c index 76e60399d..6f475a50d 100644 --- a/src/amf/nudm-handler.c +++ b/src/amf/nudm-handler.c @@ -23,7 +23,7 @@ #include "nas-path.h" int amf_nudm_sdm_handle_provisioned( - amf_ue_t *amf_ue, ogs_sbi_message_t *recvmsg) + amf_ue_t *amf_ue, int state, ogs_sbi_message_t *recvmsg) { int i; @@ -157,7 +157,7 @@ int amf_nudm_sdm_handle_provisioned( amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, amf_nudm_sdm_build_get, - amf_ue, (char *)OGS_SBI_RESOURCE_NAME_SMF_SELECT_DATA)); + amf_ue, state, (char *)OGS_SBI_RESOURCE_NAME_SMF_SELECT_DATA)); break; CASE(OGS_SBI_RESOURCE_NAME_SMF_SELECT_DATA) @@ -230,7 +230,8 @@ int amf_nudm_sdm_handle_provisioned( amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, amf_nudm_sdm_build_get, - amf_ue, (char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXT_IN_SMF_DATA)); + amf_ue, state, + (char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXT_IN_SMF_DATA)); break; CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXT_IN_SMF_DATA) @@ -241,14 +242,15 @@ int amf_nudm_sdm_handle_provisioned( ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, - amf_npcf_am_policy_control_build_create, amf_ue, NULL)); + amf_npcf_am_policy_control_build_create, + amf_ue, state, NULL)); } else { ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, - amf_nudm_sdm_build_subscription, amf_ue, - (char *)OGS_SBI_RESOURCE_NAME_AM_DATA)); + amf_nudm_sdm_build_subscription, + amf_ue, state, (char *)OGS_SBI_RESOURCE_NAME_AM_DATA)); } break; @@ -300,7 +302,7 @@ int amf_nudm_sdm_handle_provisioned( ogs_assert(true == amf_ue_sbi_discover_and_send( OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, NULL, - amf_npcf_am_policy_control_build_create, amf_ue, NULL)); + amf_npcf_am_policy_control_build_create, amf_ue, state, NULL)); break; DEFAULT diff --git a/src/amf/nudm-handler.h b/src/amf/nudm-handler.h index ed213de00..2ff6a80f2 100644 --- a/src/amf/nudm-handler.h +++ b/src/amf/nudm-handler.h @@ -27,7 +27,7 @@ extern "C" { #include "context.h" int amf_nudm_sdm_handle_provisioned( - amf_ue_t *amf_ue, ogs_sbi_message_t *recvmsg); + amf_ue_t *amf_ue, int state, ogs_sbi_message_t *recvmsg); #ifdef __cplusplus } diff --git a/src/amf/sbi-path.c b/src/amf/sbi-path.c index d8de0a57a..1d351c819 100644 --- a/src/amf/sbi-path.c +++ b/src/amf/sbi-path.c @@ -90,7 +90,7 @@ bool amf_ue_sbi_discover_and_send( ogs_sbi_service_type_e service_type, ogs_sbi_discovery_option_t *discovery_option, ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data), - amf_ue_t *amf_ue, void *data) + amf_ue_t *amf_ue, int state, void *data) { ogs_sbi_xact_t *xact = NULL; @@ -109,6 +109,8 @@ bool amf_ue_sbi_discover_and_send( return false; } + xact->state = state; + if (ogs_sbi_discover_and_send(xact) != true) { ogs_error("amf_ue_sbi_discover_and_send() failed"); ogs_sbi_xact_remove(xact); diff --git a/src/amf/sbi-path.h b/src/amf/sbi-path.h index deb3b9706..a847fd950 100644 --- a/src/amf/sbi-path.h +++ b/src/amf/sbi-path.h @@ -36,13 +36,11 @@ void amf_sbi_close(void); bool amf_sbi_send_request( ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_xact_t *xact); -bool amf_ue_sbi_discover_and_send( - ogs_sbi_service_type_e service_type, - ogs_sbi_discovery_option_t *discovery_option, - ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data), - amf_ue_t *amf_ue, void *data); #define AMF_CREATE_SM_CONTEXT_NO_STATE 0 + +#define AMF_NETWORK_INITIATED_DE_REGISTERED 1 + #define AMF_UPDATE_SM_CONTEXT_ACTIVATED 11 #define AMF_UPDATE_SM_CONTEXT_SETUP_FAIL 12 #define AMF_UPDATE_SM_CONTEXT_DEACTIVATED 13 @@ -64,6 +62,12 @@ bool amf_ue_sbi_discover_and_send( #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, + ogs_sbi_discovery_option_t *discovery_option, + ogs_sbi_request_t *(*build)(amf_ue_t *amf_ue, void *data), + amf_ue_t *amf_ue, int state, void *data); bool amf_sess_sbi_discover_and_send( ogs_sbi_service_type_e service_type, ogs_sbi_discovery_option_t *discovery_option,