forked from acouzens/open5gs
[AMF] Handle namf-callback DeregNotify message from UDM
UDM may send a Deregistration Notification to AMF, to deregister specific UE from the network - Network-Initiated Deregistration. Deregistration procedure includes sending Deregistration Request to UE, starting a timer T3522, releasing PDU sessions from SMF, releasing PCF policies from PCF, and waiting for Deregistration Accept from UE. Not yet implemented is: - to prevent deregistration of UE in case it has any emergency sessions, - page UE when UE is in IDLE mode.
This commit is contained in:
parent
0633774972
commit
aa3cded11a
|
@ -209,11 +209,10 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||
stream, &sbi_message);
|
||||
break;
|
||||
|
||||
/* TODO */
|
||||
#if 0
|
||||
CASE(OGS_SBI_RESOURCE_NAME_DEREG_NOTIFY)
|
||||
amf_namf_callback_handle_dereg_notify(stream, &sbi_message);
|
||||
break;
|
||||
#endif
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_AM_POLICY_NOTIFY)
|
||||
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
||||
break;
|
||||
|
|
|
@ -408,6 +408,9 @@ struct amf_ue_s {
|
|||
long cause;
|
||||
} handover;
|
||||
|
||||
/* Network Initiated De-Registration */
|
||||
bool network_initiated_de_reg;
|
||||
|
||||
ogs_list_t sess_list;
|
||||
};
|
||||
|
||||
|
|
|
@ -276,6 +276,35 @@ 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)
|
||||
{
|
||||
ogs_nas_5gs_message_t message;
|
||||
ogs_nas_5gs_deregistration_request_to_ue_t *dereg_req =
|
||||
&message.gmm.deregistration_request_to_ue;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.security_header_type =
|
||||
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
|
||||
message.h.extended_protocol_discriminator =
|
||||
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM;
|
||||
|
||||
message.gmm.h.extended_protocol_discriminator =
|
||||
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM;
|
||||
message.gmm.h.message_type = OGS_NAS_5GS_DEREGISTRATION_REQUEST_TO_UE;
|
||||
|
||||
dereg_req->de_registration_type.switch_off = 1;
|
||||
dereg_req->de_registration_type.re_registration_required = 0;
|
||||
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 = OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED;
|
||||
|
||||
return nas_5gs_security_encode(amf_ue, &message);
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *gmm_build_identity_request(amf_ue_t *amf_ue)
|
||||
{
|
||||
ogs_nas_5gs_message_t message;
|
||||
|
|
|
@ -34,6 +34,7 @@ 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);
|
||||
|
||||
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);
|
||||
|
|
|
@ -286,6 +286,21 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
|
|||
OGS_FSM_TRAN(s, &gmm_state_de_registered);
|
||||
break;
|
||||
|
||||
case OGS_NAS_5GS_DEREGISTRATION_ACCEPT_TO_UE:
|
||||
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);
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
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_FSM_TRAN(s, &gmm_state_de_registered);
|
||||
break;
|
||||
|
||||
case OGS_NAS_5GS_CONFIGURATION_UPDATE_COMPLETE:
|
||||
ogs_debug("[%s] Configuration update complete", amf_ue->supi);
|
||||
|
||||
|
@ -414,6 +429,20 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
|
|||
}
|
||||
break;
|
||||
|
||||
case AMF_TIMER_T3522:
|
||||
if (amf_ue->t3522.retry_count >=
|
||||
amf_timer_cfg(AMF_TIMER_T3522)->max_count) {
|
||||
ogs_warn("Retransmission of Deregistration-Request failed. "
|
||||
"Stop retransmission");
|
||||
CLEAR_AMF_UE_TIMER(amf_ue->t3522);
|
||||
OGS_FSM_TRAN(&amf_ue->t3522, &gmm_state_exception);
|
||||
} else {
|
||||
amf_ue->t3522.retry_count++;
|
||||
ogs_assert(OGS_OK ==
|
||||
nas_5gs_send_de_registration_request(amf_ue));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
amf_timer_get_name(e->timer_id), e->timer_id);
|
||||
|
@ -432,8 +461,10 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
|
|||
CASE(OGS_SBI_RESOURCE_NAME_POLICIES)
|
||||
SWITCH(sbi_message->h.method)
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
ogs_assert(OGS_OK ==
|
||||
nas_5gs_send_de_registration_accept(amf_ue));
|
||||
|
||||
if (!amf_ue->network_initiated_de_reg)
|
||||
ogs_assert(OGS_OK ==
|
||||
nas_5gs_send_de_registration_accept(amf_ue));
|
||||
|
||||
PCF_AM_POLICY_CLEAR(amf_ue);
|
||||
break;
|
||||
|
|
|
@ -508,3 +508,92 @@ cleanup:
|
|||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
amf_ue_t *amf_ue = NULL;
|
||||
|
||||
ogs_sbi_message_t sendmsg;
|
||||
ogs_sbi_response_t *response = NULL;
|
||||
|
||||
OpenAPI_deregistration_data_t *DeregistrationData;
|
||||
|
||||
ogs_assert(stream);
|
||||
ogs_assert(recvmsg);
|
||||
|
||||
if (!recvmsg->h.resource.component[0]) {
|
||||
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
||||
ogs_error("No SUPI");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
amf_ue = amf_ue_find_by_supi(recvmsg->h.resource.component[0]);
|
||||
if (!amf_ue) {
|
||||
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
|
||||
ogs_error("Cannot find SUPI [%s]", recvmsg->h.resource.component[0]);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
DeregistrationData = recvmsg->DeregistrationData;
|
||||
if (!DeregistrationData) {
|
||||
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
||||
ogs_error("[%s] No DeregistrationData", amf_ue->supi);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (DeregistrationData->access_type != OpenAPI_access_type_3GPP_ACCESS)
|
||||
{
|
||||
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
|
||||
ogs_error("[%s] Deregistration access type not 3GPP", amf_ue->supi);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ogs_info("Deregistration notify reason: %s:%s:%s",
|
||||
amf_ue->supi,
|
||||
OpenAPI_deregistration_reason_ToString(DeregistrationData->dereg_reason),
|
||||
OpenAPI_access_type_ToString(DeregistrationData->access_type));
|
||||
|
||||
/*
|
||||
* TODO: do not start deregistration if UE has emergency sessions
|
||||
* 4.2.2.3.3
|
||||
* If the UE has established PDU Session associated with emergency service, the AMF shall not initiate
|
||||
* 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))
|
||||
{
|
||||
amf_ue->network_initiated_de_reg = true;
|
||||
|
||||
ogs_assert(OGS_OK ==
|
||||
nas_5gs_send_de_registration_request(amf_ue));
|
||||
|
||||
amf_sbi_send_release_all_sessions(
|
||||
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
|
||||
|
||||
if (ogs_list_count(&amf_ue->sess_list) == 0)
|
||||
ogs_assert(true ==
|
||||
amf_ue_sbi_discover_and_send(
|
||||
OpenAPI_nf_type_PCF, amf_ue,
|
||||
NULL, amf_npcf_am_policy_control_build_delete));
|
||||
|
||||
OGS_FSM_TRAN(&amf_ue->sm, &gmm_state_de_registered);
|
||||
}
|
||||
else if (CM_IDLE(amf_ue)) {
|
||||
/* TODO: need to page UE */
|
||||
/*ngap_send_paging(amf_ue);*/
|
||||
}
|
||||
|
||||
cleanup:
|
||||
memset(&sendmsg, 0, sizeof(sendmsg));
|
||||
|
||||
response = ogs_sbi_build_response(&sendmsg, status);
|
||||
ogs_assert(response);
|
||||
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ int amf_namf_comm_handle_n1_n2_message_transfer(
|
|||
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
|
||||
int amf_namf_callback_handle_sm_context_status(
|
||||
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
|
||||
int amf_namf_callback_handle_dereg_notify(
|
||||
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -276,6 +276,38 @@ 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)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ran_ue_t *ran_ue = NULL;
|
||||
ogs_pkbuf_t *gmmbuf = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
|
||||
ogs_expect_or_return_val(ran_ue, OGS_ERROR);
|
||||
|
||||
ogs_debug("[%s] De-registration request", amf_ue->supi);
|
||||
|
||||
if (amf_ue->t3522.pkbuf) {
|
||||
gmmbuf = amf_ue->t3522.pkbuf;
|
||||
ogs_expect_or_return_val(gmmbuf, OGS_ERROR);
|
||||
} else {
|
||||
gmmbuf = gmm_build_de_registration_request(amf_ue);
|
||||
ogs_expect_or_return_val(gmmbuf, OGS_ERROR);
|
||||
}
|
||||
|
||||
amf_ue->t3522.pkbuf = ogs_pkbuf_copy(gmmbuf);
|
||||
ogs_expect_or_return_val(amf_ue->t3522.pkbuf, OGS_ERROR);
|
||||
ogs_timer_start(amf_ue->t3522.timer,
|
||||
amf_timer_cfg(AMF_TIMER_T3522)->duration);
|
||||
|
||||
rv = nas_5gs_send_to_downlink_nas_transport(amf_ue, gmmbuf);
|
||||
ogs_expect_or_return_val(rv == OGS_OK, OGS_ERROR);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int nas_5gs_send_identity_request(amf_ue_t *amf_ue)
|
||||
{
|
||||
int rv;
|
||||
|
|
|
@ -41,6 +41,7 @@ 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);
|
||||
|
||||
int nas_5gs_send_identity_request(amf_ue_t *amf_ue);
|
||||
|
||||
|
|
Loading…
Reference in New Issue