diff --git a/lib/diameter/s6a/message.h b/lib/diameter/s6a/message.h index 707e0b085..573ad039f 100644 --- a/lib/diameter/s6a/message.h +++ b/lib/diameter/s6a/message.h @@ -168,6 +168,8 @@ 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 51f7a4b81..efcc36135 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -100,10 +100,10 @@ typedef struct ogs_gtp_xact_s { #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_SEND_S1_REMOVE_AND_UNLINK 5 -#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 6 -#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 7 -#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 8 +#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 int delete_action; #define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1 diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index acfa232ed..6789620a0 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -128,6 +128,11 @@ 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"); @@ -546,7 +551,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) 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); + mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue); } OGS_FSM_TRAN(s, &emm_state_de_registered); diff --git a/src/mme/mme-fd-path.c b/src/mme/mme-fd-path.c index f2d2bef61..ebb12ed1c 100644 --- a/src/mme/mme-fd-path.c +++ b/src/mme/mme-fd-path.c @@ -233,6 +233,8 @@ 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); @@ -642,6 +644,8 @@ 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 @@ -1435,7 +1439,9 @@ static int mme_ogs_diam_s6a_clr_cb( struct msg **msg, struct avp *avp, ogs_assert(s6a_message); s6a_message->cmd_code = OGS_DIAM_S6A_CMD_CODE_CANCEL_LOCATION; clr_message = &s6a_message->clr_message; - ogs_assert(clr_message); + ogs_assert(clr_message); + + s6a_message->isAnswer = false; /* Create answer header */ qry = *msg; diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index d9293299b..59848a30b 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -28,34 +28,32 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) { ogs_assert(mme_ue); - switch (mme_ue->nas_eps.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); + 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)); } else { - ogs_assert(OGS_OK == nas_eps_send_detach_accept(mme_ue)); + ogs_warn("[%s] No S1 Context", mme_ue->imsi_bcd); } - 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_SEND_S1_REMOVE_AND_UNLINK); - } 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_S1_REMOVE_AND_UNLINK, 0)); - } else { - ogs_warn("[%s] No S1 Context", mme_ue->imsi_bcd); - } - } - break; - default: - ogs_fatal(" Invalid OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); - ogs_assert_if_reached(); } } @@ -216,6 +214,7 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) 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 afc6f13e8..b9887bb46 100644 --- a/src/mme/mme-path.h +++ b/src/mme/mme-path.h @@ -27,6 +27,7 @@ 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 65c93fa1d..8191c99b0 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -603,20 +603,6 @@ 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_detach, - 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, @@ -650,6 +636,12 @@ 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 8828efcc5..a094ab48d 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -18,6 +18,7 @@ */ #include "nas-path.h" +#include "mme-path.h" #include "s1ap-path.h" #include "mme-sm.h" @@ -181,6 +182,7 @@ void mme_s6a_handle_clr( 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); } } diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 765305358..f4796bbd3 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -390,14 +390,16 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) s6a_message = e->s6a_message; ogs_assert(s6a_message); - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (!enb_ue) { - ogs_error("S1 context has already been removed"); + 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; + ogs_subscription_data_free( + &s6a_message->ula_message.subscription_data); + ogs_free(s6a_message); + break; + } } switch (s6a_message->cmd_code) {