[MME] Cancel Location while Idle (#1797)

* Cancel Location while Idle Fix

* Forgot about SGSAP on MME Change.

Added "action" to sgsap_send_detach..

* Make handle_clr uniform with other handlers

* Added Robustness for Any Detach Type

* Memory wasn't freed upon CLR for unknown IMSIs

* Moving MME Detach to new PR
This commit is contained in:
jmasterfunk84 2022-10-04 20:06:01 -06:00 committed by GitHub
parent 7c8722d9d4
commit 15680003b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 102 additions and 40 deletions

View File

@ -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_S6A_S6D_INDICATOR (1)
#define OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED (1 << 1) #define OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED (1 << 1)
uint32_t clr_flags; uint32_t clr_flags;
uint32_t cancellation_type;
} ogs_diam_s6a_clr_message_t; } ogs_diam_s6a_clr_message_t;
typedef struct ogs_diam_s6a_idr_message_s { typedef struct ogs_diam_s6a_idr_message_s {

View File

@ -96,15 +96,17 @@ typedef struct ogs_gtp_xact_s {
#define OGS_GTP_MODIFY_QOS_UPDATE ((uint64_t)1<<1) #define OGS_GTP_MODIFY_QOS_UPDATE ((uint64_t)1<<1)
uint64_t update_flags; uint64_t update_flags;
#define OGS_GTP_DELETE_NO_ACTION 1 #define OGS_GTP_DELETE_NO_ACTION 1
#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST 2 #define OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST 2
#define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 3 #define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 3
#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 4 #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_UE_CONTEXT_RELEASE_COMMAND 5
#define OGS_GTP_DELETE_SEND_S1_REMOVE_AND_UNLINK 6 #define OGS_GTP_DELETE_SEND_S1_REMOVE_AND_UNLINK 6
#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 7 #define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 7
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 8 #define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 8
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 9 #define OGS_GTP_DELETE_UE_CONTEXT_COMPLETE_REMOVE 9
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 10
int delete_action; int delete_action;
#define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1 #define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1

View File

@ -389,10 +389,10 @@ int emm_handle_detach_request(
* *
* So, we will lose the MME_EPS_TYPE_DETACH_REQUEST_TO_UE. * 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. */ * to keep Detach-Type whether UE-initiated or MME-initiaed. */
mme_ue->nas_eps.type = mme_ue->nas_eps.detach_type = mme_ue->nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_FROM_UE;
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; mme_ue->nas_eps.ksi = detach_type->nas_key_set_identifier;
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]", ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",

View File

@ -316,20 +316,25 @@ struct mme_ue_s {
ogs_nas_eps_update_type_t update; ogs_nas_eps_update_type_t update;
ogs_nas_service_type_t service; ogs_nas_service_type_t service;
ogs_nas_detach_type_t detach; 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; } 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 */ /* UE identity */
#define MME_UE_HAVE_IMSI(__mME) \ #define MME_UE_HAVE_IMSI(__mME) \
((__mME) && ((__mME)->imsi_len)) ((__mME) && ((__mME)->imsi_len))

View File

@ -1510,6 +1510,7 @@ static int mme_ogs_diam_s6a_clr_cb( struct msg **msg, struct avp *avp,
ogs_assert(ret == 0); ogs_assert(ret == 0);
ret = fd_msg_avp_hdr(avp, &hdr); ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0); ogs_assert(ret == 0);
clr_message->cancellation_type = hdr->avp_value->i32;
/* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */ /* Set the Origin-Host, Origin-Realm, andResult-Code AVPs */
ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1); ret = fd_msg_rescode_set(ans, (char*)"DIAMETER_SUCCESS", NULL, NULL, 1);
@ -1583,7 +1584,9 @@ out:
/* Send the answer */ /* Send the answer */
ret = fd_msg_send(msg, NULL, NULL); ret = fd_msg_send(msg, NULL, NULL);
ogs_assert(ret == 0); ogs_assert(ret == 0);
ogs_free(s6a_message);
return 0; return 0;
} }

View File

@ -28,8 +28,9 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue)
{ {
ogs_assert(mme_ue); ogs_assert(mme_ue);
switch (mme_ue->nas_eps.detach_type) { switch (mme_ue->detach_type) {
case MME_EPS_TYPE_DETACH_REQUEST_FROM_UE: case MME_DETACH_TYPE_REQUEST_FROM_UE:
ogs_debug("Detach Request from UE");
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
mme_gtp_send_delete_all_sessions( mme_gtp_send_delete_all_sessions(
mme_ue, OGS_GTP_DELETE_SEND_DETACH_ACCEPT); 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)); ogs_assert(OGS_OK == nas_eps_send_detach_accept(mme_ue));
} }
break; 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)) { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION);
} }
break; 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: default:
ogs_fatal(" Invalid OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); ogs_fatal(" Invalid OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type);
ogs_assert_if_reached(); ogs_assert_if_reached();

View File

@ -639,6 +639,12 @@ void mme_s11_handle_delete_session_response(
mme_ue_remove(mme_ue); mme_ue_remove(mme_ue);
return; 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) { } else if (action == OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST) {
/* Don't have to remove Session in X2 Handover with SGW relocation */ /* Don't have to remove Session in X2 Handover with SGW relocation */

View File

@ -170,11 +170,13 @@ uint8_t mme_s6a_handle_idr(
return OGS_OK; return OGS_OK;
} }
void mme_s6a_handle_clr( void mme_s6a_handle_clr(mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message)
mme_ue_t *mme_ue, ogs_diam_s6a_clr_message_t *clr_message)
{ {
ogs_diam_s6a_clr_message_t *clr_message = NULL;
ogs_assert(mme_ue); 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 */ /* Set EPS Detach */
memset(&mme_ue->nas_eps.detach, 0, sizeof(ogs_nas_detach_type_t)); 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. * 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. */ * to keep Detach-Type whether UE-initiated or MME-initiaed. */
mme_ue->nas_eps.type = mme_ue->nas_eps.detach_type = mme_ue->nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE;
MME_EPS_TYPE_DETACH_REQUEST_TO_UE;
ogs_debug(" OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type); ogs_debug(" OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type);
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) { 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_hash_remove(mme_ue);
mme_ue_remove(mme_ue); mme_ue_remove(mme_ue);
} else if (ECM_IDLE(mme_ue)) { return;
MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DETACH_TO_UE, NULL); } else if (clr_message->cancellation_type ==
ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps)); OGS_DIAM_S6A_CT_MME_UPDATE_PROCEDURE) {
} else { mme_ue->detach_type = MME_DETACH_TYPE_HSS_IMPLICIT;
ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue));
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { 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 { } else {
mme_send_delete_session_or_detach(mme_ue); 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);
} }
} }

View File

@ -33,7 +33,7 @@ uint8_t mme_s6a_handle_ula(
uint8_t mme_s6a_handle_idr( uint8_t mme_s6a_handle_idr(
mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message); mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message);
void mme_s6a_handle_clr( 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 #ifdef __cplusplus
} }

View File

@ -432,7 +432,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
} }
break; break;
case OGS_DIAM_S6A_CMD_CODE_CANCEL_LOCATION: 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; break;
case OGS_DIAM_S6A_CMD_CODE_INSERT_SUBSCRIBER_DATA: case OGS_DIAM_S6A_CMD_CODE_INSERT_SUBSCRIBER_DATA:
mme_s6a_handle_idr(mme_ue, s6a_message); mme_s6a_handle_idr(mme_ue, s6a_message);