diff --git a/lib/diameter/s6a/message.h b/lib/diameter/s6a/message.h index 943d20e8b..ae314dd10 100644 --- a/lib/diameter/s6a/message.h +++ b/lib/diameter/s6a/message.h @@ -59,9 +59,6 @@ extern "C" { #define OGS_DIAM_S6A_ULR_INITIAL_ATTACH_IND (1 << 5) #define OGS_DIAM_S6A_ULR_PS_LCS_SUPPORTED_BY_UE (1 << 6) -#define OGS_DIAM_S6A_CLR_S6A_S6D_INDICATOR (1) -#define OGS_DIAM_S6A_CLR_REATTACH_REQUIRED (1 << 1) - #define OGS_DIAM_S6A_UE_SRVCC_NOT_SUPPORTED (0) #define OGS_DIAM_S6A_UE_SRVCC_SUPPORTED (1) @@ -148,8 +145,8 @@ typedef struct ogs_diam_s6a_ula_message_s { } ogs_diam_s6a_ula_message_t; typedef struct ogs_diam_s6a_clr_message_s { -#define OGS_DIAM_S6A_CLR_FLAGS_S6A_S6D_INDICATOR (0) -#define OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED (1) +#define OGS_DIAM_S6A_CLR_FLAGS_S6A_S6D_INDICATOR (1) +#define OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED (1 << 1) uint32_t clr_flags; } ogs_diam_s6a_clr_message_t; diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index efcc36135..51f7a4b81 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_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_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 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 36f981d80..67a15a315 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -437,11 +437,12 @@ 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) +ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type) { ogs_nas_eps_message_t message; ogs_assert(mme_ue); + ogs_assert(detach_type); memset(&message, 0, sizeof(message)); message.h.security_header_type = @@ -451,7 +452,7 @@ ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue) 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 = mme_ue->mme_to_ue_detach_type; + message.emm.detach_request_to_ue.detach_type.value = detach_type; return nas_eps_security_encode(mme_ue, &message); } diff --git a/src/mme/emm-build.h b/src/mme/emm-build.h index 14f01e888..ba2dc793d 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); +ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type); 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 a6d72bdbe..34c89f733 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -403,8 +403,6 @@ int emm_handle_detach_request( if (detach_request->detach_type.switch_off) ogs_debug(" Switch-Off"); - ogs_info(" IMSI[%s]", mme_ue->imsi_bcd); - return OGS_OK; } diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 611d72a8a..24ed763a3 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -129,16 +129,6 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) break; } - if (mme_ue->mme_to_ue_detach_pending) { - ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue)); - mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); - if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { - ogs_assert(OGS_OK == - sgsap_send_detach_indication(mme_ue)); - } - break; - } - if (!MME_UE_HAVE_IMSI(mme_ue)) { ogs_info("Service request : Unknown UE"); ogs_assert(OGS_OK == @@ -540,8 +530,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)); + ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue)); } else { mme_send_delete_session_or_detach(mme_ue); } @@ -550,17 +539,16 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) break; case OGS_NAS_EPS_DETACH_ACCEPT: - ogs_debug("Detach accept"); + ogs_info("[%s] Detach accept", mme_ue->imsi_bcd); CLEAR_MME_UE_TIMER(mme_ue->t3422); - if (enb_ue) { - s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_detach, - S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); + if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { + ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue)); } else { - ogs_warn("[%s] No S1 Context", mme_ue->imsi_bcd); + mme_send_delete_session_or_detach(mme_ue); } + OGS_FSM_TRAN(s, &emm_state_de_registered); break; @@ -612,18 +600,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) mme_ue->imsi_bcd); CLEAR_MME_UE_TIMER(mme_ue->t3413); - mme_send_after_paging(mme_ue, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE); - - if (CS_CALL_SERVICE_INDICATOR(mme_ue) || - SMS_SERVICE_INDICATOR(mme_ue)) { - ogs_assert(OGS_OK == - sgsap_send_ue_unreachable(mme_ue, - SGSAP_SGS_CAUSE_UE_UNREACHABLE)); - - } - - CLEAR_SERVICE_INDICATOR(mme_ue); - + ogs_assert(MME_PAGING_ONGOING(mme_ue)); + mme_send_after_paging(mme_ue, true); } else { mme_ue->t3413.retry_count++; /* @@ -642,6 +620,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) "Stop retransmission"); OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); } else { + ogs_assert(mme_ue->t3470.pkbuf); rv = nas_eps_send_identity_request(mme_ue); if (rv == OGS_OK) { mme_ue->t3470.retry_count++; @@ -659,7 +638,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) "Stop retransmission"); OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception); } else { - rv = nas_eps_send_detach_request(mme_ue); + ogs_assert(mme_ue->t3422.pkbuf); + rv = nas_eps_send_detach_request(mme_ue, 0); 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 484378fb6..048f9f06c 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -321,9 +321,6 @@ struct mme_ue_s { }; } nas_eps; - bool mme_to_ue_detach_pending; - uint8_t mme_to_ue_detach_type; - /* UE identity */ #define MME_UE_HAVE_IMSI(__mME) \ ((__mME) && ((__mME)->imsi_len)) @@ -454,6 +451,34 @@ struct mme_ue_s { (((__mME)->enb_ue == NULL) || (enb_ue_cycle((__mME)->enb_ue) == NULL))) enb_ue_t *enb_ue; /* S1 UE context */ + struct { +#define MME_CLEAR_PAGING_INFO(__mME) \ + do { \ + ogs_assert(__mME); \ + (__mME)->paging.type = 0; \ + } while(0) + +#define MME_STORE_PAGING_INFO(__mME, __tYPE, __dATA) \ + do { \ + ogs_assert(__mME); \ + ogs_assert(__tYPE); \ + (__mME)->paging.type = __tYPE; \ + (__mME)->paging.data = __dATA; \ + } while(0) + +#define MME_PAGING_ONGOING(__mME) ((__mME) && ((__mME)->paging.type)) + +#define MME_PAGING_TYPE_DOWNLINK_DATA_NOTIFICATION 1 +#define MME_PAGING_TYPE_CREATE_BEARER 2 +#define MME_PAGING_TYPE_UPDATE_BEARER 3 +#define MME_PAGING_TYPE_DELETE_BEARER 4 +#define MME_PAGING_TYPE_CS_CALL_SERVICE 5 +#define MME_PAGING_TYPE_SMS_SERVICE 6 +#define MME_PAGING_TYPE_DETACH_TO_UE 7 + int type; + void *data; + } paging; + /* SGW UE context */ sgw_ue_t *sgw_ue; @@ -687,9 +712,10 @@ typedef struct mme_bearer_s { /* Related Context */ mme_ue_t *mme_ue; mme_sess_t *sess; + struct { ogs_gtp_xact_t *xact; - } create, update, delete, notify, current; + } create, update, delete, notify; } mme_bearer_t; void mme_context_init(void); diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index b5eeff8f0..7a1bfa9c8 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -19,19 +19,43 @@ #include "s1ap-path.h" #include "nas-path.h" +#include "sgsap-path.h" #include "mme-gtp-path.h" #include "mme-path.h" +#include "mme-sm.h" 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)); + 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); + } else { + 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_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_normal_release, + 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(); } } @@ -75,72 +99,131 @@ void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue) } } -void mme_send_after_paging(mme_ue_t *mme_ue, uint8_t cause_value) +void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) { - mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; ogs_assert(mme_ue); - ogs_list_for_each(&mme_ue->sess_list, sess) { - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_gtp_xact_t *xact = NULL; - uint8_t type; - - xact = ogs_gtp_xact_cycle(bearer->current.xact); - if (xact) { - /* - * It may conflict with GTP transaction already used. - * To avoid this, check `xact->step` to see if - * the transaction has already been committed. - */ - type = xact->seq[xact->step-1].type; - - switch (type) { - case OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE: - ogs_assert(OGS_OK == - mme_gtp_send_downlink_data_notification_ack( - bearer, cause_value)); - break; - case OGS_GTP2_CREATE_BEARER_REQUEST_TYPE: - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_assert(OGS_OK == - nas_eps_send_activate_dedicated_bearer_context_request( - bearer)); - } else { - ogs_assert(OGS_OK == - mme_gtp_send_create_bearer_response( - bearer, cause_value)); - } - break; - case OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE: - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_assert(OGS_OK == - nas_eps_send_modify_bearer_context_request(bearer, - (xact->update_flags & - OGS_GTP_MODIFY_QOS_UPDATE) ? 1 : 0, - (xact->update_flags & - OGS_GTP_MODIFY_TFT_UPDATE) ? 1 : 0)); - } else { - ogs_assert(OGS_OK == - mme_gtp_send_update_bearer_response( - bearer, cause_value)); - } - break; - case OGS_GTP2_DELETE_BEARER_REQUEST_TYPE: - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_assert(OGS_OK == - nas_eps_send_deactivate_bearer_context_request(bearer)); - } else { - ogs_assert(OGS_OK == - mme_gtp_send_delete_bearer_response( - bearer, cause_value)); - } - break; - default: - break; - } - } + switch (mme_ue->paging.type) { + case MME_PAGING_TYPE_DOWNLINK_DATA_NOTIFICATION: + bearer = mme_bearer_cycle(mme_ue->paging.data); + if (!bearer) { + ogs_error("No Bearer [%d]", mme_ue->paging.type); + goto cleanup; } + + if (failed == true) { + ogs_assert(OGS_OK == + mme_gtp_send_downlink_data_notification_ack( + bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + } else { + ogs_assert(OGS_OK == + mme_gtp_send_downlink_data_notification_ack( + bearer, OGS_GTP2_CAUSE_REQUEST_ACCEPTED)); + } + break; + case MME_PAGING_TYPE_CREATE_BEARER: + bearer = mme_bearer_cycle(mme_ue->paging.data); + if (!bearer) { + ogs_error("No Bearer [%d]", mme_ue->paging.type); + goto cleanup; + } + + if (failed == true) { + ogs_assert(OGS_OK == + mme_gtp_send_create_bearer_response( + bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + } else { + ogs_assert(OGS_OK == + nas_eps_send_activate_dedicated_bearer_context_request(bearer)); + } + break; + case MME_PAGING_TYPE_UPDATE_BEARER: + bearer = mme_bearer_cycle(mme_ue->paging.data); + if (!bearer) { + ogs_error("No Bearer [%d]", mme_ue->paging.type); + goto cleanup; + } + + if (failed == true) { + ogs_assert(OGS_OK == + mme_gtp_send_update_bearer_response( + bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + } else { + ogs_gtp_xact_t *xact = ogs_gtp_xact_cycle(bearer->update.xact); + if (!xact) { + ogs_error("No GTP xact"); + goto cleanup; + } + + ogs_assert(OGS_OK == + nas_eps_send_modify_bearer_context_request(bearer, + (xact->update_flags & + OGS_GTP_MODIFY_QOS_UPDATE) ? 1 : 0, + (xact->update_flags & + OGS_GTP_MODIFY_TFT_UPDATE) ? 1 : 0)); + } + break; + case MME_PAGING_TYPE_DELETE_BEARER: + bearer = mme_bearer_cycle(mme_ue->paging.data); + if (!bearer) { + ogs_error("No Bearer [%d]", mme_ue->paging.type); + goto cleanup; + } + + if (failed == true) { + ogs_assert(OGS_OK == + mme_gtp_send_delete_bearer_response( + bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + } else { + ogs_assert(OGS_OK == + nas_eps_send_deactivate_bearer_context_request(bearer)); + } + break; + case MME_PAGING_TYPE_CS_CALL_SERVICE: + if (failed == true) { + ogs_assert(OGS_OK == + sgsap_send_service_request( + mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE)); + } else { + /* Nothing */ + } + break; + case MME_PAGING_TYPE_SMS_SERVICE: + if (failed == true) { + ogs_assert(OGS_OK == + sgsap_send_service_request( + mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE)); + } else { + ogs_assert(OGS_OK == + sgsap_send_service_request( + mme_ue, SGSAP_EMM_CONNECTED_MODE)); + } + break; + case MME_PAGING_TYPE_DETACH_TO_UE: + if (failed == true) { + 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)); + } + break; + default: + ogs_fatal("Invalid Paging Type[%d]", mme_ue->paging.type); + ogs_assert_if_reached(); } + +cleanup: + CLEAR_SERVICE_INDICATOR(mme_ue); + MME_CLEAR_PAGING_INFO(mme_ue); } diff --git a/src/mme/mme-path.h b/src/mme/mme-path.h index 8d9b27391..afc6f13e8 100644 --- a/src/mme/mme-path.h +++ b/src/mme/mme-path.h @@ -30,7 +30,7 @@ void mme_send_delete_session_or_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); -void mme_send_after_paging(mme_ue_t *mme_ue, uint8_t cause_value); +void mme_send_after_paging(mme_ue_t *mme_ue, bool failed); #ifdef __cplusplus } diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index df248e31b..6a0de237b 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -603,6 +603,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,8 +650,6 @@ void mme_s11_handle_delete_session_response( return; - } else if (action == OGS_GTP_DELETE_NO_ACTION) { - } else { ogs_fatal("Invalid action = %d", action); ogs_assert_if_reached(); @@ -805,7 +817,6 @@ void mme_s11_handle_create_bearer_request( * If GTP-xact Holding timer is expired, * OLD bearer->xact memory will be automatically removed. */ - bearer->current.xact = xact; bearer->create.xact = xact; /* Before Activate DEDICATED bearer, check DEFAULT bearer status */ @@ -814,6 +825,8 @@ void mme_s11_handle_create_bearer_request( if (OGS_FSM_CHECK(&default_bearer->sm, esm_state_active)) { if (ECM_IDLE(mme_ue)) { + MME_STORE_PAGING_INFO(mme_ue, + MME_PAGING_TYPE_CREATE_BEARER, bearer); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); } else { ogs_assert(OGS_OK == @@ -906,7 +919,6 @@ void mme_s11_handle_update_bearer_request( * If GTP-xact Holding timer is expired, * OLD bearer->xact memory will be automatically removed. */ - bearer->current.xact = xact; bearer->update.xact = xact; if (req->bearer_contexts.bearer_level_qos.presence == 1) { @@ -938,6 +950,8 @@ void mme_s11_handle_update_bearer_request( if (req->bearer_contexts.bearer_level_qos.presence == 1 || req->bearer_contexts.tft.presence == 1) { if (ECM_IDLE(mme_ue)) { + MME_STORE_PAGING_INFO(mme_ue, + MME_PAGING_TYPE_UPDATE_BEARER, bearer); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); } else { ogs_assert(OGS_OK == @@ -1067,10 +1081,10 @@ void mme_s11_handle_delete_bearer_request( * If GTP-xact Holding timer is expired, * OLD bearer->xact memory will be automatically removed. */ - bearer->current.xact = xact; bearer->delete.xact = xact; if (ECM_IDLE(mme_ue)) { + MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DELETE_BEARER, bearer); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); } else { ogs_assert(OGS_OK == @@ -1295,7 +1309,6 @@ void mme_s11_handle_downlink_data_notification( * If GTP-xact Holding timer is expired, * OLD bearer->xact memory will be automatically removed. */ - bearer->current.xact = xact; bearer->notify.xact = xact; if (noti->cause.presence) { @@ -1319,6 +1332,8 @@ void mme_s11_handle_downlink_data_notification( * before step 9, the MME shall not send S1 interface paging messages */ if (ECM_IDLE(mme_ue)) { + MME_STORE_PAGING_INFO(mme_ue, + MME_PAGING_TYPE_DOWNLINK_DATA_NOTIFICATION, bearer); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); } else if (ECM_CONNECTED(mme_ue)) { diff --git a/src/mme/mme-s6a-handler.c b/src/mme/mme-s6a-handler.c index 14cf36490..4054045fd 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -105,23 +105,29 @@ void mme_s6a_handle_ula(mme_ue_t *mme_ue, 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); - if (clr_message->clr_flags & OGS_DIAM_S6A_CLR_REATTACH_REQUIRED) { - mme_ue->mme_to_ue_detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED; - } else { - mme_ue->mme_to_ue_detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED; - } + /* 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); + + if (clr_message->clr_flags & OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED) + detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED; + else + detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED; if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) { - // Remove all trace of subscriber even when detached. + /* 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); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); - mme_ue->mme_to_ue_detach_pending = true; } else { - ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue)); + ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue, detach_type)); } } diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 131397e3f..b76093bf2 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -460,8 +460,8 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]", mme_ue->imsi_bcd, emm_cause); ogs_assert(OGS_OK == - nas_eps_send_attach_reject(mme_ue, - emm_cause, OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED)); + nas_eps_send_attach_reject(mme_ue, emm_cause, + OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED)); ogs_assert(OGS_OK == s1ap_send_ue_context_release_command(enb_ue, @@ -508,14 +508,6 @@ 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); - - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue) && !mme_ue->mme_to_ue_detach_pending) { - mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); - } - if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { - ogs_assert(OGS_OK == - sgsap_send_detach_indication(mme_ue)); - } break; default: ogs_error("Invalid Type[%d]", s6a_message->cmd_code); diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index 7cd25cae3..d822174ef 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -256,24 +256,19 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue) return rv; } -int nas_eps_send_detach_request(mme_ue_t *mme_ue) +int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type) { int rv; - - enb_ue_t *enb_ue = NULL; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - ogs_expect_or_return_val(enb_ue, OGS_ERROR); - ogs_debug("[%s] Detach request to UE", mme_ue->imsi_bcd); if (mme_ue->t3422.pkbuf) { emmbuf = mme_ue->t3422.pkbuf; ogs_expect_or_return_val(emmbuf, OGS_ERROR); } else { - emmbuf = emm_build_identity_request(mme_ue); + ogs_assert(detach_type); + emmbuf = emm_build_detach_request(mme_ue, detach_type); ogs_expect_or_return_val(emmbuf, OGS_ERROR); } @@ -282,10 +277,6 @@ int nas_eps_send_detach_request(mme_ue_t *mme_ue) ogs_timer_start(mme_ue->t3422.timer, mme_timer_cfg(MME_TIMER_T3422)->duration); - /* send detach request */ - emmbuf = emm_build_detach_request(mme_ue); - ogs_expect_or_return_val(emmbuf, OGS_ERROR); - rv = nas_eps_send_to_downlink_nas_transport(mme_ue, emmbuf); ogs_expect_or_return_val(rv == OGS_OK, rv); diff --git a/src/mme/nas-path.h b/src/mme/nas-path.h index 3e3183485..56138d12d 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); +int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type); int nas_eps_send_detach_accept(mme_ue_t *mme_ue); int nas_eps_send_pdn_connectivity_reject( diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 539df1a4d..0ebdc57c1 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -764,15 +764,8 @@ void s1ap_handle_initial_context_setup_response( } } - if (mme_ue->nas_eps.type != MME_EPS_TYPE_ATTACH_REQUEST) - mme_send_after_paging(mme_ue, OGS_GTP2_CAUSE_REQUEST_ACCEPTED); - - if (SMS_SERVICE_INDICATOR(mme_ue)) { - ogs_assert(OGS_OK == - sgsap_send_service_request(mme_ue, SGSAP_EMM_CONNECTED_MODE)); - } - - CLEAR_SERVICE_INDICATOR(mme_ue); + if (MME_PAGING_ONGOING(mme_ue)) + mme_send_after_paging(mme_ue, false); } void s1ap_handle_initial_context_setup_failure( diff --git a/src/mme/sgsap-build.c b/src/mme/sgsap-build.c index 65c5cf315..c14967759 100644 --- a/src/mme/sgsap-build.c +++ b/src/mme/sgsap-build.c @@ -19,7 +19,6 @@ #include "mme-context.h" -#include "sgsap-types.h" #include "sgsap-build.h" #include "sgsap-conv.h" diff --git a/src/mme/sgsap-build.h b/src/mme/sgsap-build.h index 76287e346..12810e9c8 100644 --- a/src/mme/sgsap-build.h +++ b/src/mme/sgsap-build.h @@ -22,6 +22,8 @@ #include "mme-context.h" +#include "sgsap-types.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 458bc73b3..7d2a1b8ca 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -272,9 +272,7 @@ void sgsap_handle_detach_ack(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); - if (!mme_ue->mme_to_ue_detach_pending) { - mme_send_delete_session_or_detach(mme_ue); - } + mme_send_delete_session_or_detach(mme_ue); } void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) @@ -354,11 +352,15 @@ void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) if (ECM_IDLE(mme_ue)) { if (CS_CALL_SERVICE_INDICATOR(mme_ue)) { /* UE will respond Extended Service Request in PS CNDomain*/ + MME_STORE_PAGING_INFO(mme_ue, + MME_PAGING_TYPE_CS_CALL_SERVICE, NULL); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_cs)); } else if (SMS_SERVICE_INDICATOR(mme_ue)) { /* UE will respond Service Request in PS CNDomain*/ + MME_STORE_PAGING_INFO(mme_ue, + MME_PAGING_TYPE_SMS_SERVICE, NULL); ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); } else diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c index c61a718e3..073655905 100644 --- a/src/mme/sgsap-path.c +++ b/src/mme/sgsap-path.c @@ -22,8 +22,6 @@ #include "mme-event.h" #include "mme-sm.h" -#include "sgsap-types.h" -#include "sgsap-build.h" #include "sgsap-path.h" int sgsap_open() @@ -251,4 +249,4 @@ int sgsap_send_ue_unreachable(mme_ue_t *mme_ue, uint8_t sgs_cause) ogs_expect(rv == OGS_OK); return rv; -} \ No newline at end of file +} diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h index 1ecfb71a6..a1a9b35be 100644 --- a/src/mme/sgsap-path.h +++ b/src/mme/sgsap-path.h @@ -23,6 +23,8 @@ #include "mme-context.h" #include "mme-event.h" +#include "sgsap-build.h" + #ifdef __cplusplus extern "C" { #endif