[MME] Cancel Location Handling (#1698)

* CLR while idle is broken after 7031856cd7

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.
This commit is contained in:
jmasterfunk84 2022-08-19 01:44:06 -06:00 committed by GitHub
parent 444e182288
commit c98333bbfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 62 additions and 53 deletions

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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);

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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) {