diff --git a/lib/diameter/s6a/message.h b/lib/diameter/s6a/message.h index 573ad039f..707e0b085 100644 --- a/lib/diameter/s6a/message.h +++ b/lib/diameter/s6a/message.h @@ -168,8 +168,6 @@ typedef struct ogs_diam_s6a_message_s { uint32_t *err; uint32_t *exp_err; - bool isAnswer; - ogs_diam_s6a_clr_message_t clr_message; ogs_diam_s6a_aia_message_t aia_message; ogs_diam_s6a_ula_message_t ula_message; diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index efcc36135..8633f56dd 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -96,14 +96,15 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_MODIFY_QOS_UPDATE ((uint64_t)1<<1) uint64_t update_flags; -#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST 1 -#define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 2 -#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 3 -#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4 -#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5 -#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6 -#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 7 -#define OGS_GTP_DELETE_NO_ACTION 8 +#define OGS_GTP_DELETE_NO_ACTION 1 +#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST 2 +#define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 3 +#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 4 +#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 5 +#define OGS_GTP_DELETE_SEND_S1_REMOVE_AND_UNLINK 6 +#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 7 +#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 8 +#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 9 int delete_action; #define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1 diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index 67a15a315..1b7db9a3b 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -437,12 +437,11 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue) return nas_eps_security_encode(mme_ue, &message); } -ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type) +ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue) { ogs_nas_eps_message_t message; ogs_assert(mme_ue); - ogs_assert(detach_type); memset(&message, 0, sizeof(message)); message.h.security_header_type = @@ -452,7 +451,8 @@ ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type) message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; message.emm.h.message_type = OGS_NAS_EPS_DETACH_REQUEST; - message.emm.detach_request_to_ue.detach_type.value = detach_type; + message.emm.detach_request_to_ue.detach_type.value = + mme_ue->nas_eps.detach.value; return nas_eps_security_encode(mme_ue, &message); } diff --git a/src/mme/emm-build.h b/src/mme/emm-build.h index ba2dc793d..14f01e888 100644 --- a/src/mme/emm-build.h +++ b/src/mme/emm-build.h @@ -37,7 +37,7 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue); ogs_pkbuf_t *emm_build_authentication_request(mme_ue_t *mme_ue); ogs_pkbuf_t *emm_build_authentication_reject(void); -ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type); +ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue); ogs_pkbuf_t *emm_build_detach_accept(mme_ue_t *mme_ue); ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue); diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index 34c89f733..9ed359185 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -64,13 +64,17 @@ int emm_handle_attach_request(mme_ue_t *mme_ue, /* HashMME */ ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme); - /* Set EPS Attach Request Type */ + /* Set EPS Attach */ memcpy(&mme_ue->nas_eps.attach, eps_attach_type, sizeof(ogs_nas_eps_attach_type_t)); mme_ue->nas_eps.type = MME_EPS_TYPE_ATTACH_REQUEST; mme_ue->nas_eps.ksi = eps_attach_type->nas_key_set_identifier; - ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] ATTACH[0x%x]", - mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, mme_ue->nas_eps.data); + ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", + mme_ue->nas_eps.type, mme_ue->nas_eps.ksi); + ogs_debug(" ATTACH TSC[%d] KSI[%d] VALUE[%d]", + mme_ue->nas_eps.attach.tsc, + mme_ue->nas_eps.attach.nas_key_set_identifier, + mme_ue->nas_eps.attach.value); switch(mme_ue->nas_eps.attach.value){ case OGS_NAS_ATTACH_TYPE_EPS_ATTACH: ogs_debug(" Requested EPS_ATTACH_TYPE[1, EPS_ATTACH]"); @@ -373,12 +377,30 @@ int emm_handle_detach_request( detach_type = &detach_request->detach_type; - /* Set EPS Attach Type */ + /* Set EPS Detach */ memcpy(&mme_ue->nas_eps.detach, detach_type, sizeof(ogs_nas_detach_type_t)); - mme_ue->nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_FROM_UE; + + /* 1. MME initiated detach request to the UE. + * (nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE) + * 2. If UE is IDLE, Paging sent to the UE + * 3. If UE is wake-up, UE will send Server Request. + * (nas_eps.type = MME_EPS_TYPE_SERVICE_REQUEST) + * + * So, we will lose the MME_EPS_TYPE_DETACH_REQUEST_TO_UE. + * + * We need more variable(nas_eps.detach_type) + * to keep Detach-Type whether UE-initiated or MME-initiaed. */ + mme_ue->nas_eps.type = mme_ue->nas_eps.detach_type = + MME_EPS_TYPE_DETACH_REQUEST_FROM_UE; + mme_ue->nas_eps.ksi = detach_type->nas_key_set_identifier; - ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] DETACH[0x%x]", - mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, mme_ue->nas_eps.data); + ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", + mme_ue->nas_eps.type, mme_ue->nas_eps.ksi); + ogs_debug(" DETACH TSC[%d] KSI[%d] SWITCH_OFF[%d] VALUE[%d]", + mme_ue->nas_eps.attach.tsc, + mme_ue->nas_eps.detach.nas_key_set_identifier, + mme_ue->nas_eps.detach.switch_off, + mme_ue->nas_eps.attach.value); switch (detach_request->detach_type.value) { /* 0 0 1 : EPS detach */ @@ -414,11 +436,15 @@ int emm_handle_service_request( ogs_assert(mme_ue); - /* Set EPS Update Type */ + /* Set EPS Service */ mme_ue->nas_eps.type = MME_EPS_TYPE_SERVICE_REQUEST; mme_ue->nas_eps.ksi = ksi_and_sequence_number->ksi; ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", mme_ue->nas_eps.type, mme_ue->nas_eps.ksi); + ogs_debug(" SERVICE TSC[%d] KSI[%d] VALUE[%d]", + mme_ue->nas_eps.service.tsc, + mme_ue->nas_eps.service.nas_key_set_identifier, + mme_ue->nas_eps.service.value); /* * ATTACH_REQUEST @@ -469,15 +495,19 @@ int emm_handle_tau_request(mme_ue_t *mme_ue, /* HashMME */ ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme); - /* Set EPS Update Type */ + /* Set EPS Update */ memcpy(&mme_ue->nas_eps.update, eps_update_type, sizeof(ogs_nas_eps_update_type_t)); mme_ue->nas_eps.type = MME_EPS_TYPE_TAU_REQUEST; mme_ue->nas_eps.ksi = eps_update_type->nas_key_set_identifier; - ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] UPDATE[0x%x]", - mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, - mme_ue->nas_eps.data); - + ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", + mme_ue->nas_eps.type, mme_ue->nas_eps.ksi); + ogs_debug(" UPDATE TSC[%d] KSI[%d] Active-flag[%d] VALUE[%d]", + mme_ue->nas_eps.update.tsc, + mme_ue->nas_eps.update.nas_key_set_identifier, + mme_ue->nas_eps.update.active_flag, + mme_ue->nas_eps.update.value); + /* * ATTACH_REQUEST * TAU_REQUEST @@ -598,9 +628,8 @@ int emm_handle_extended_service_request(mme_ue_t *mme_ue, sizeof(ogs_nas_service_type_t)); mme_ue->nas_eps.type = MME_EPS_TYPE_EXTENDED_SERVICE_REQUEST; mme_ue->nas_eps.ksi = service_type->nas_key_set_identifier; - ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] SERVICE[0x%x]", - mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, - mme_ue->nas_eps.data); + ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", + mme_ue->nas_eps.type, mme_ue->nas_eps.ksi); /* * ATTACH_REQUEST diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 6789620a0..4881297ec 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -128,11 +128,6 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) OGS_FSM_TRAN(s, emm_state_exception); break; } - - if(mme_ue->paging.type == MME_PAGING_TYPE_DETACH_TO_UE) { - mme_send_after_paging(mme_ue, false); - break; - } if (!MME_UE_HAVE_IMSI(mme_ue)) { ogs_info("Service request : Unknown UE"); @@ -548,11 +543,10 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) CLEAR_MME_UE_TIMER(mme_ue->t3422); - if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { - ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue)); - } else { - mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue); - } + rv = s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_detach, + S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0); + ogs_expect(rv == OGS_OK); OGS_FSM_TRAN(s, &emm_state_de_registered); break; @@ -644,7 +638,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); } else { ogs_assert(mme_ue->t3422.pkbuf); - rv = nas_eps_send_detach_request(mme_ue, 0); + rv = nas_eps_send_detach_request(mme_ue); if (rv == OGS_OK) { mme_ue->t3422.retry_count++; } else { diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 048f9f06c..11405b71b 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -312,13 +312,22 @@ struct mme_ue_s { #define MME_EPS_TYPE_DETACH_REQUEST_TO_UE 6 uint8_t type; uint8_t ksi; - union { - ogs_nas_eps_attach_type_t attach; - ogs_nas_eps_update_type_t update; - ogs_nas_service_type_t service; - ogs_nas_detach_type_t detach; - uint8_t data; - }; + ogs_nas_eps_attach_type_t attach; + ogs_nas_eps_update_type_t update; + ogs_nas_service_type_t service; + ogs_nas_detach_type_t detach; + + /* 1. MME initiated detach request to the UE. + * (nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE) + * 2. If UE is IDLE, Paging sent to the UE + * 3. If UE is wake-up, UE will send Server Request. + * (nas_eps.type = MME_EPS_TYPE_SERVICE_REQUEST) + * + * So, we will lose the MME_EPS_TYPE_DETACH_REQUEST_TO_UE. + * + * We need more variable(nas_eps.detach_type) + * to keep Detach-Type whether UE-initiated or MME-initiaed. */ + uint8_t detach_type; } nas_eps; /* UE identity */ diff --git a/src/mme/mme-fd-path.c b/src/mme/mme-fd-path.c index ebb12ed1c..8f5ff5299 100644 --- a/src/mme/mme-fd-path.c +++ b/src/mme/mme-fd-path.c @@ -233,8 +233,6 @@ static void mme_s6a_aia_cb(void *data, struct msg **msg) ogs_assert(aia_message); e_utran_vector = &aia_message->e_utran_vector; ogs_assert(e_utran_vector); - - s6a_message->isAnswer = true; /* Value of Result Code */ ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp); @@ -644,8 +642,6 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg) subscription_data = &ula_message->subscription_data; ogs_assert(subscription_data); - s6a_message->isAnswer = true; - /* AVP: 'Result-Code'(268) * The Result-Code AVP indicates whether a particular request was completed * successfully or whether an error occurred. The Result-Code data field @@ -1441,8 +1437,6 @@ static int mme_ogs_diam_s6a_clr_cb( struct msg **msg, struct avp *avp, clr_message = &s6a_message->clr_message; ogs_assert(clr_message); - s6a_message->isAnswer = false; - /* Create answer header */ qry = *msg; ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0); diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index 59848a30b..03c261cdf 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -28,32 +28,23 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) { ogs_assert(mme_ue); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_DETACH_ACCEPT); - } else { - ogs_assert(OGS_OK == - nas_eps_send_detach_accept(mme_ue)); - } -} - -void mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue_t *mme_ue) -{ - ogs_assert(mme_ue); - - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions( - mme_ue, OGS_GTP_DELETE_NO_ACTION); - } else { - enb_ue_t *enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (enb_ue) { - ogs_assert(OGS_OK == - s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_detach, - S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0)); + switch (mme_ue->nas_eps.detach_type) { + case MME_EPS_TYPE_DETACH_REQUEST_FROM_UE: + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + mme_gtp_send_delete_all_sessions( + mme_ue, OGS_GTP_DELETE_SEND_DETACH_ACCEPT); } else { - ogs_warn("[%s] No S1 Context", mme_ue->imsi_bcd); + ogs_assert(OGS_OK == nas_eps_send_detach_accept(mme_ue)); } + break; + case MME_EPS_TYPE_DETACH_REQUEST_TO_UE: + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); + } + break; + default: + ogs_fatal(" Invalid OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); + ogs_assert_if_reached(); } } @@ -201,20 +192,17 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) break; case MME_PAGING_TYPE_DETACH_TO_UE: if (failed == true) { + /* Nothing */ + ogs_fatal("MME-initiated Detach should not be invoked " + "if Paging failed"); + ogs_assert_if_reached(); + } else { + ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue)); if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue)); } else { mme_send_delete_session_or_detach(mme_ue); } - - OGS_FSM_TRAN(&mme_ue->sm, &emm_state_de_registered); - } else { - uint8_t detach_type = (uintptr_t)mme_ue->paging.data; - ogs_assert(detach_type); - - ogs_assert(OGS_OK == - nas_eps_send_detach_request(mme_ue, detach_type)); - mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue); } break; default: diff --git a/src/mme/mme-path.h b/src/mme/mme-path.h index b9887bb46..afc6f13e8 100644 --- a/src/mme/mme-path.h +++ b/src/mme/mme-path.h @@ -27,7 +27,6 @@ extern "C" { #endif void mme_send_delete_session_or_detach(mme_ue_t *mme_ue); -void mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue_t *mme_ue); void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue); void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue); diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 8191c99b0..db80c976f 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -562,7 +562,11 @@ void mme_s11_handle_delete_session_response( ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, source_ue->sgw_s11_teid); - if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) { + if (action == OGS_GTP_DELETE_NO_ACTION) { + /* No Action to be taken after sessions are deleted during + * MME Initiated detach. S1 will be cleared after receipt + * of the detach accept from UE */ + } else if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { mme_s6a_send_air(mme_ue, NULL); } @@ -603,6 +607,20 @@ void mme_s11_handle_delete_session_response( ogs_error("ENB-S1 Context has already been removed"); } + } else if (action == OGS_GTP_DELETE_SEND_S1_REMOVE_AND_UNLINK) { + if (mme_sess_count(mme_ue) == 1) /* Last Session */ { + enb_ue_t *enb_ue = NULL; + + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + if (enb_ue) { + ogs_assert(OGS_OK == + s1ap_send_ue_context_release_command(enb_ue, + S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, + S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0)); + } else + ogs_error("ENB-S1 Context has already been removed"); + } + } else if (action == OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { rv = nas_eps_send_emm_to_esm(mme_ue, @@ -636,12 +654,6 @@ void mme_s11_handle_delete_session_response( return; - } else if (action == OGS_GTP_DELETE_NO_ACTION) { - /* - * No Action to be taken after sessions are deleted during - * MME Initiated detach. S1 will be cleared after receipt - * of the detach accept from UE */ - } else { ogs_fatal("Invalid action = %d", action); ogs_assert_if_reached(); diff --git a/src/mme/mme-s6a-handler.c b/src/mme/mme-s6a-handler.c index a094ab48d..6c54b9bf7 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -18,8 +18,9 @@ */ #include "nas-path.h" -#include "mme-path.h" #include "s1ap-path.h" +#include "sgsap-path.h" +#include "mme-path.h" #include "mme-sm.h" #include "mme-s6a-handler.h" @@ -140,16 +141,9 @@ uint8_t mme_s6a_handle_ula( ogs_assert(OGS_OK == nas_eps_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_InitialContextSetup)); - } else if (mme_ue->nas_eps.type == MME_EPS_TYPE_SERVICE_REQUEST) { - ogs_error("[%s] Service request", mme_ue->imsi_bcd); - return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED; - } else if (mme_ue->nas_eps.type == - MME_EPS_TYPE_DETACH_REQUEST_FROM_UE) { - ogs_error("[%s] Detach request", mme_ue->imsi_bcd); - return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED; } else { - ogs_fatal("Invalid Type[%d]", mme_ue->nas_eps.type); - ogs_assert_if_reached(); + ogs_error("Invalid Type[%d]", mme_ue->nas_eps.type); + return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED; } return OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED; @@ -158,31 +152,47 @@ uint8_t mme_s6a_handle_ula( void mme_s6a_handle_clr( mme_ue_t *mme_ue, ogs_diam_s6a_clr_message_t *clr_message) { - uint8_t detach_type = 0; - ogs_assert(mme_ue); ogs_assert(clr_message); - /* Set NAS EPS Type */ - mme_ue->nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE; - ogs_debug(" OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); + /* Set EPS Detach */ + memset(&mme_ue->nas_eps.detach, 0, sizeof(ogs_nas_detach_type_t)); if (clr_message->clr_flags & OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED) - detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED; + mme_ue->nas_eps.detach.value = + OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED; else - detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED; - + mme_ue->nas_eps.detach.value = + OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED; + + /* 1. MME initiated detach request to the UE. + * (nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE) + * 2. If UE is IDLE, Paging sent to the UE + * 3. If UE is wake-up, UE will send Server Request. + * (nas_eps.type = MME_EPS_TYPE_SERVICE_REQUEST) + * + * So, we will lose the MME_EPS_TYPE_DETACH_REQUEST_TO_UE. + * + * We need more variable(nas_eps.detach_type) + * to keep Detach-Type whether UE-initiated or MME-initiaed. */ + mme_ue->nas_eps.type = mme_ue->nas_eps.detach_type = + MME_EPS_TYPE_DETACH_REQUEST_TO_UE; + ogs_debug(" OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); + if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) { /* Remove all trace of subscriber even when detached. */ mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); } else if (ECM_IDLE(mme_ue)) { - MME_STORE_PAGING_INFO(mme_ue, - MME_PAGING_TYPE_DETACH_TO_UE, (void *)(uintptr_t)detach_type); + MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DETACH_TO_UE, NULL); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); } else { - ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue, detach_type)); - mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue); + ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue)); + if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { + ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue)); + } else { + mme_send_delete_session_or_detach(mme_ue); + } } } diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index f4796bbd3..5ebc666bb 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -390,24 +390,17 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) s6a_message = e->s6a_message; ogs_assert(s6a_message); - if (s6a_message->isAnswer) { - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (!enb_ue) { - ogs_error("S1 context has already been removed"); - - ogs_subscription_data_free( - &s6a_message->ula_message.subscription_data); - ogs_free(s6a_message); - break; - } - } - switch (s6a_message->cmd_code) { case OGS_DIAM_S6A_CMD_CODE_AUTHENTICATION_INFORMATION: emm_cause = mme_s6a_handle_aia(mme_ue, s6a_message); if (emm_cause != OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED) { ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]", mme_ue->imsi_bcd, emm_cause); + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + if (!enb_ue) { + ogs_error("S1 context has already been removed"); + break; + } ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, emm_cause, OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED)); @@ -423,6 +416,11 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) if (emm_cause != OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED) { ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]", mme_ue->imsi_bcd, emm_cause); + enb_ue = enb_ue_cycle(mme_ue->enb_ue); + if (!enb_ue) { + ogs_error("S1 context has already been removed"); + break; + } ogs_assert(OGS_OK == nas_eps_send_attach_reject(mme_ue, emm_cause, OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED)); diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index d822174ef..a14a817fc 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -256,7 +256,7 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue) return rv; } -int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type) +int nas_eps_send_detach_request(mme_ue_t *mme_ue) { int rv; ogs_pkbuf_t *emmbuf = NULL; @@ -267,8 +267,7 @@ int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type) emmbuf = mme_ue->t3422.pkbuf; ogs_expect_or_return_val(emmbuf, OGS_ERROR); } else { - ogs_assert(detach_type); - emmbuf = emm_build_detach_request(mme_ue, detach_type); + emmbuf = emm_build_detach_request(mme_ue); ogs_expect_or_return_val(emmbuf, OGS_ERROR); } diff --git a/src/mme/nas-path.h b/src/mme/nas-path.h index 56138d12d..3e3183485 100644 --- a/src/mme/nas-path.h +++ b/src/mme/nas-path.h @@ -43,7 +43,7 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue); int nas_eps_send_security_mode_command(mme_ue_t *mme_ue); -int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type); +int nas_eps_send_detach_request(mme_ue_t *mme_ue); int nas_eps_send_detach_accept(mme_ue_t *mme_ue); int nas_eps_send_pdn_connectivity_reject(