From c98333bbfefc3bd4180205c58282bd6636c0d7b0 Mon Sep 17 00:00:00 2001 From: jmasterfunk84 <48972964+jmasterfunk84@users.noreply.github.com> Date: Fri, 19 Aug 2022 01:44:06 -0600 Subject: [PATCH] [MME] Cancel Location Handling (#1698) * CLR while idle is broken after https://github.com/open5gs/open5gs/commit/7031856cd779af0129ca444e18bbe2ed5db9ff32 Cancel Location Request arriving while UE is idle will not proceed to paging due to this check for S1 connection. Using new flag "isAnswer" to bypass this check to allow paging to occur when we are not doing a AIA/ULA related procedure. * No Context Setup is required when sending the detach request. If the paging was due to wanting to send a Detach Request to the UE, then we fast track to sending the detach request. * emm-sm.c: In the case of MME initiated detach while UE is idle, there is no initial conext setup. We go right from the service request after paging into sending the detach request. TS23.401 mme-path.c: Using nas_eps.type in the case of MME Initiated Detach while UE is idle does not work. nas_eps.type would represent the service request. mme-s11-handler.c: After S11 action, no action should be taken. We want to wait for the detach accept from the UE before proceeding with the S1 release (detach). * InitialContextSetup should occur for detach. --- lib/diameter/s6a/message.h | 2 ++ lib/gtp/xact.h | 8 +++--- src/mme/emm-sm.c | 7 +++++- src/mme/mme-fd-path.c | 8 +++++- src/mme/mme-path.c | 51 +++++++++++++++++++------------------- src/mme/mme-path.h | 1 + src/mme/mme-s11-handler.c | 20 +++++---------- src/mme/mme-s6a-handler.c | 2 ++ src/mme/mme-sm.c | 16 ++++++------ 9 files changed, 62 insertions(+), 53 deletions(-) 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) {