diff --git a/lib/diameter/s6a/message.h b/lib/diameter/s6a/message.h index cb5ae6108..a347365d3 100644 --- a/lib/diameter/s6a/message.h +++ b/lib/diameter/s6a/message.h @@ -179,6 +179,7 @@ typedef struct ogs_diam_s6a_clr_message_s { #define OGS_DIAM_S6A_CLR_FLAGS_S6A_S6D_INDICATOR (1) #define OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED (1 << 1) uint32_t clr_flags; + uint32_t cancellation_type; } ogs_diam_s6a_clr_message_t; typedef struct ogs_diam_s6a_idr_message_s { diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 8633f56dd..455e8372a 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -96,15 +96,17 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_MODIFY_QOS_UPDATE ((uint64_t)1<<1) uint64_t update_flags; -#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_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 +#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_UE_CONTEXT_COMPLETE_REMOVE 9 +#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 10 + int delete_action; #define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1 diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index 9838db80b..435887d8f 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -389,10 +389,10 @@ int emm_handle_detach_request( * * So, we will lose the MME_EPS_TYPE_DETACH_REQUEST_TO_UE. * - * We need more variable(nas_eps.detach_type) + * We need more variable(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.type = MME_EPS_TYPE_DETACH_REQUEST_FROM_UE; + mme_ue->detach_type = MME_DETACH_TYPE_REQUEST_FROM_UE; mme_ue->nas_eps.ksi = detach_type->nas_key_set_identifier; ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index d407e77e6..58f1cdfd7 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -316,20 +316,25 @@ struct mme_ue_s { 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; + /* 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(detach_type) + * to keep Detach-Type whether UE-initiated or MME-initiaed. */ +#define MME_DETACH_TYPE_REQUEST_FROM_UE 1 +#define MME_DETACH_TYPE_MME_EXPLICIT 2 +#define MME_DETACH_TYPE_HSS_EXPLICIT 3 +#define MME_DETACH_TYPE_MME_IMPLICIT 4 +#define MME_DETACH_TYPE_HSS_IMPLICIT 5 + uint8_t detach_type; + /* UE identity */ #define MME_UE_HAVE_IMSI(__mME) \ ((__mME) && ((__mME)->imsi_len)) diff --git a/src/mme/mme-fd-path.c b/src/mme/mme-fd-path.c index 281be44b5..c7eb0bf93 100644 --- a/src/mme/mme-fd-path.c +++ b/src/mme/mme-fd-path.c @@ -1510,6 +1510,7 @@ static int mme_ogs_diam_s6a_clr_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); ret = fd_msg_avp_hdr(avp, &hdr); ogs_assert(ret == 0); + clr_message->cancellation_type = hdr->avp_value->i32; /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1); @@ -1583,7 +1584,9 @@ out: /* Send the answer */ ret = fd_msg_send(msg, NULL, NULL); - ogs_assert(ret == 0); + ogs_assert(ret == 0); + + ogs_free(s6a_message); return 0; } diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index 32b439376..211465a22 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -28,8 +28,9 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) { ogs_assert(mme_ue); - switch (mme_ue->nas_eps.detach_type) { - case MME_EPS_TYPE_DETACH_REQUEST_FROM_UE: + switch (mme_ue->detach_type) { + case MME_DETACH_TYPE_REQUEST_FROM_UE: + ogs_debug("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); @@ -37,11 +38,37 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) ogs_assert(OGS_OK == nas_eps_send_detach_accept(mme_ue)); } break; - case MME_EPS_TYPE_DETACH_REQUEST_TO_UE: + + /* MME Explicit Detach, ie: O&M Procedures */ + case MME_DETACH_TYPE_MME_EXPLICIT: + break; + + /* HSS Explicit Detach, ie: Subscription Withdrawl Cancel Location */ + case MME_DETACH_TYPE_HSS_EXPLICIT: + ogs_debug("Explicit HSS Detach"); if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); } break; + + /* MME Implicit Detach, ie: Lost Communication */ + case MME_DETACH_TYPE_MME_IMPLICIT: + break; + + /* HSS Implicit Detach, ie: MME-UPDATE-PROCEDURE */ + case MME_DETACH_TYPE_HSS_IMPLICIT: + ogs_debug("Implicit HSS Detach"); + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + if (ECM_IDLE(mme_ue)) { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_UE_CONTEXT_COMPLETE_REMOVE); + } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND); + } + } + break; + default: ogs_fatal(" Invalid OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); ogs_assert_if_reached(); diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index c6febf92b..6d2497d2d 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -639,6 +639,12 @@ void mme_s11_handle_delete_session_response( mme_ue_remove(mme_ue); return; + } else if (action == OGS_GTP_DELETE_UE_CONTEXT_COMPLETE_REMOVE) { + /* Remove MME-UE Context and hash after Implicit Detach */ + mme_ue_hash_remove(mme_ue); + mme_ue_remove(mme_ue); + return; + } else if (action == OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST) { /* Don't have to remove Session in X2 Handover with SGW relocation */ diff --git a/src/mme/mme-s6a-handler.c b/src/mme/mme-s6a-handler.c index 7dcf52678..78183f882 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -170,11 +170,13 @@ uint8_t mme_s6a_handle_idr( return OGS_OK; } -void mme_s6a_handle_clr( - mme_ue_t *mme_ue, ogs_diam_s6a_clr_message_t *clr_message) +void mme_s6a_handle_clr(mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message) { + ogs_diam_s6a_clr_message_t *clr_message = NULL; ogs_assert(mme_ue); - ogs_assert(clr_message); + ogs_assert(s6a_message); + clr_message = &s6a_message->clr_message; + ogs_assert(clr_message); /* Set EPS Detach */ memset(&mme_ue->nas_eps.detach, 0, sizeof(ogs_nas_detach_type_t)); @@ -194,26 +196,42 @@ void mme_s6a_handle_clr( * * So, we will lose the MME_EPS_TYPE_DETACH_REQUEST_TO_UE. * - * We need more variable(nas_eps.detach_type) + * We need more variable(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; + mme_ue->nas_eps.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, 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)); + return; + } else if (clr_message->cancellation_type == + OGS_DIAM_S6A_CT_MME_UPDATE_PROCEDURE) { + mme_ue->detach_type = MME_DETACH_TYPE_HSS_IMPLICIT; 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); } + } else if (clr_message->cancellation_type == + OGS_DIAM_S6A_CT_SUBSCRIPTION_WITHDRAWL) { + mme_ue->detach_type = MME_DETACH_TYPE_HSS_EXPLICIT; + if (ECM_IDLE(mme_ue)) { + 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)); + 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); + } + } + } else { + ogs_error("Unsupported Cancellation-Type [%d]", + clr_message->cancellation_type); } } diff --git a/src/mme/mme-s6a-handler.h b/src/mme/mme-s6a-handler.h index 33094ea8a..3cf0a3463 100644 --- a/src/mme/mme-s6a-handler.h +++ b/src/mme/mme-s6a-handler.h @@ -33,7 +33,7 @@ uint8_t mme_s6a_handle_ula( uint8_t mme_s6a_handle_idr( mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message); void mme_s6a_handle_clr( - mme_ue_t *mme_ue, ogs_diam_s6a_clr_message_t *clr_message); + mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message); #ifdef __cplusplus } diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 22aeca369..259623c20 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -432,7 +432,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) } break; case OGS_DIAM_S6A_CMD_CODE_CANCEL_LOCATION: - mme_s6a_handle_clr(mme_ue, &s6a_message->clr_message); + mme_s6a_handle_clr(mme_ue, s6a_message); break; case OGS_DIAM_S6A_CMD_CODE_INSERT_SUBSCRIBER_DATA: mme_s6a_handle_idr(mme_ue, s6a_message);