[MME] Follow-up Cancel Location Handling (#1698)
This commit is contained in:
parent
c98333bbfe
commit
a9694d6474
|
@ -168,8 +168,6 @@ typedef struct ogs_diam_s6a_message_s {
|
||||||
uint32_t *err;
|
uint32_t *err;
|
||||||
uint32_t *exp_err;
|
uint32_t *exp_err;
|
||||||
|
|
||||||
bool isAnswer;
|
|
||||||
|
|
||||||
ogs_diam_s6a_clr_message_t clr_message;
|
ogs_diam_s6a_clr_message_t clr_message;
|
||||||
ogs_diam_s6a_aia_message_t aia_message;
|
ogs_diam_s6a_aia_message_t aia_message;
|
||||||
ogs_diam_s6a_ula_message_t ula_message;
|
ogs_diam_s6a_ula_message_t ula_message;
|
||||||
|
|
|
@ -96,14 +96,15 @@ 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_SEND_AUTHENTICATION_REQUEST 1
|
#define OGS_GTP_DELETE_NO_ACTION 1
|
||||||
#define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 2
|
#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST 2
|
||||||
#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 3
|
#define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 3
|
||||||
#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4
|
#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 4
|
||||||
#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5
|
#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 5
|
||||||
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6
|
#define OGS_GTP_DELETE_SEND_S1_REMOVE_AND_UNLINK 6
|
||||||
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 7
|
#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 7
|
||||||
#define OGS_GTP_DELETE_NO_ACTION 8
|
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 8
|
||||||
|
#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 9
|
||||||
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
|
||||||
|
|
|
@ -437,12 +437,11 @@ ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue)
|
||||||
return nas_eps_security_encode(mme_ue, &message);
|
return nas_eps_security_encode(mme_ue, &message);
|
||||||
}
|
}
|
||||||
|
|
||||||
ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type)
|
ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue)
|
||||||
{
|
{
|
||||||
ogs_nas_eps_message_t message;
|
ogs_nas_eps_message_t message;
|
||||||
|
|
||||||
ogs_assert(mme_ue);
|
ogs_assert(mme_ue);
|
||||||
ogs_assert(detach_type);
|
|
||||||
|
|
||||||
memset(&message, 0, sizeof(message));
|
memset(&message, 0, sizeof(message));
|
||||||
message.h.security_header_type =
|
message.h.security_header_type =
|
||||||
|
@ -452,7 +451,8 @@ ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type)
|
||||||
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
|
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
|
||||||
message.emm.h.message_type = OGS_NAS_EPS_DETACH_REQUEST;
|
message.emm.h.message_type = OGS_NAS_EPS_DETACH_REQUEST;
|
||||||
|
|
||||||
message.emm.detach_request_to_ue.detach_type.value = detach_type;
|
message.emm.detach_request_to_ue.detach_type.value =
|
||||||
|
mme_ue->nas_eps.detach.value;
|
||||||
|
|
||||||
return nas_eps_security_encode(mme_ue, &message);
|
return nas_eps_security_encode(mme_ue, &message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_request(mme_ue_t *mme_ue);
|
||||||
ogs_pkbuf_t *emm_build_authentication_reject(void);
|
ogs_pkbuf_t *emm_build_authentication_reject(void);
|
||||||
|
|
||||||
ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue, uint8_t detach_type);
|
ogs_pkbuf_t *emm_build_detach_request(mme_ue_t *mme_ue);
|
||||||
ogs_pkbuf_t *emm_build_detach_accept(mme_ue_t *mme_ue);
|
ogs_pkbuf_t *emm_build_detach_accept(mme_ue_t *mme_ue);
|
||||||
|
|
||||||
ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue);
|
ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue);
|
||||||
|
|
|
@ -64,13 +64,17 @@ int emm_handle_attach_request(mme_ue_t *mme_ue,
|
||||||
/* HashMME */
|
/* HashMME */
|
||||||
ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme);
|
ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme);
|
||||||
|
|
||||||
/* Set EPS Attach Request Type */
|
/* Set EPS Attach */
|
||||||
memcpy(&mme_ue->nas_eps.attach, eps_attach_type,
|
memcpy(&mme_ue->nas_eps.attach, eps_attach_type,
|
||||||
sizeof(ogs_nas_eps_attach_type_t));
|
sizeof(ogs_nas_eps_attach_type_t));
|
||||||
mme_ue->nas_eps.type = MME_EPS_TYPE_ATTACH_REQUEST;
|
mme_ue->nas_eps.type = MME_EPS_TYPE_ATTACH_REQUEST;
|
||||||
mme_ue->nas_eps.ksi = eps_attach_type->nas_key_set_identifier;
|
mme_ue->nas_eps.ksi = eps_attach_type->nas_key_set_identifier;
|
||||||
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] ATTACH[0x%x]",
|
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",
|
||||||
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, mme_ue->nas_eps.data);
|
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi);
|
||||||
|
ogs_debug(" ATTACH TSC[%d] KSI[%d] VALUE[%d]",
|
||||||
|
mme_ue->nas_eps.attach.tsc,
|
||||||
|
mme_ue->nas_eps.attach.nas_key_set_identifier,
|
||||||
|
mme_ue->nas_eps.attach.value);
|
||||||
switch(mme_ue->nas_eps.attach.value){
|
switch(mme_ue->nas_eps.attach.value){
|
||||||
case OGS_NAS_ATTACH_TYPE_EPS_ATTACH:
|
case OGS_NAS_ATTACH_TYPE_EPS_ATTACH:
|
||||||
ogs_debug(" Requested EPS_ATTACH_TYPE[1, EPS_ATTACH]");
|
ogs_debug(" Requested EPS_ATTACH_TYPE[1, EPS_ATTACH]");
|
||||||
|
@ -373,12 +377,30 @@ int emm_handle_detach_request(
|
||||||
|
|
||||||
detach_type = &detach_request->detach_type;
|
detach_type = &detach_request->detach_type;
|
||||||
|
|
||||||
/* Set EPS Attach Type */
|
/* Set EPS Detach */
|
||||||
memcpy(&mme_ue->nas_eps.detach, detach_type, sizeof(ogs_nas_detach_type_t));
|
memcpy(&mme_ue->nas_eps.detach, detach_type, sizeof(ogs_nas_detach_type_t));
|
||||||
mme_ue->nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_FROM_UE;
|
|
||||||
|
/* 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. */
|
||||||
|
mme_ue->nas_eps.type = mme_ue->nas_eps.detach_type =
|
||||||
|
MME_EPS_TYPE_DETACH_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] DETACH[0x%x]",
|
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",
|
||||||
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, mme_ue->nas_eps.data);
|
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi);
|
||||||
|
ogs_debug(" DETACH TSC[%d] KSI[%d] SWITCH_OFF[%d] VALUE[%d]",
|
||||||
|
mme_ue->nas_eps.attach.tsc,
|
||||||
|
mme_ue->nas_eps.detach.nas_key_set_identifier,
|
||||||
|
mme_ue->nas_eps.detach.switch_off,
|
||||||
|
mme_ue->nas_eps.attach.value);
|
||||||
|
|
||||||
switch (detach_request->detach_type.value) {
|
switch (detach_request->detach_type.value) {
|
||||||
/* 0 0 1 : EPS detach */
|
/* 0 0 1 : EPS detach */
|
||||||
|
@ -414,11 +436,15 @@ int emm_handle_service_request(
|
||||||
|
|
||||||
ogs_assert(mme_ue);
|
ogs_assert(mme_ue);
|
||||||
|
|
||||||
/* Set EPS Update Type */
|
/* Set EPS Service */
|
||||||
mme_ue->nas_eps.type = MME_EPS_TYPE_SERVICE_REQUEST;
|
mme_ue->nas_eps.type = MME_EPS_TYPE_SERVICE_REQUEST;
|
||||||
mme_ue->nas_eps.ksi = ksi_and_sequence_number->ksi;
|
mme_ue->nas_eps.ksi = ksi_and_sequence_number->ksi;
|
||||||
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",
|
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",
|
||||||
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi);
|
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi);
|
||||||
|
ogs_debug(" SERVICE TSC[%d] KSI[%d] VALUE[%d]",
|
||||||
|
mme_ue->nas_eps.service.tsc,
|
||||||
|
mme_ue->nas_eps.service.nas_key_set_identifier,
|
||||||
|
mme_ue->nas_eps.service.value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ATTACH_REQUEST
|
* ATTACH_REQUEST
|
||||||
|
@ -469,15 +495,19 @@ int emm_handle_tau_request(mme_ue_t *mme_ue,
|
||||||
/* HashMME */
|
/* HashMME */
|
||||||
ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme);
|
ogs_kdf_hash_mme(pkbuf->data, pkbuf->len, mme_ue->hash_mme);
|
||||||
|
|
||||||
/* Set EPS Update Type */
|
/* Set EPS Update */
|
||||||
memcpy(&mme_ue->nas_eps.update, eps_update_type,
|
memcpy(&mme_ue->nas_eps.update, eps_update_type,
|
||||||
sizeof(ogs_nas_eps_update_type_t));
|
sizeof(ogs_nas_eps_update_type_t));
|
||||||
mme_ue->nas_eps.type = MME_EPS_TYPE_TAU_REQUEST;
|
mme_ue->nas_eps.type = MME_EPS_TYPE_TAU_REQUEST;
|
||||||
mme_ue->nas_eps.ksi = eps_update_type->nas_key_set_identifier;
|
mme_ue->nas_eps.ksi = eps_update_type->nas_key_set_identifier;
|
||||||
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] UPDATE[0x%x]",
|
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",
|
||||||
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi,
|
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi);
|
||||||
mme_ue->nas_eps.data);
|
ogs_debug(" UPDATE TSC[%d] KSI[%d] Active-flag[%d] VALUE[%d]",
|
||||||
|
mme_ue->nas_eps.update.tsc,
|
||||||
|
mme_ue->nas_eps.update.nas_key_set_identifier,
|
||||||
|
mme_ue->nas_eps.update.active_flag,
|
||||||
|
mme_ue->nas_eps.update.value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ATTACH_REQUEST
|
* ATTACH_REQUEST
|
||||||
* TAU_REQUEST
|
* TAU_REQUEST
|
||||||
|
@ -598,9 +628,8 @@ int emm_handle_extended_service_request(mme_ue_t *mme_ue,
|
||||||
sizeof(ogs_nas_service_type_t));
|
sizeof(ogs_nas_service_type_t));
|
||||||
mme_ue->nas_eps.type = MME_EPS_TYPE_EXTENDED_SERVICE_REQUEST;
|
mme_ue->nas_eps.type = MME_EPS_TYPE_EXTENDED_SERVICE_REQUEST;
|
||||||
mme_ue->nas_eps.ksi = service_type->nas_key_set_identifier;
|
mme_ue->nas_eps.ksi = service_type->nas_key_set_identifier;
|
||||||
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d] SERVICE[0x%x]",
|
ogs_debug(" OGS_NAS_EPS TYPE[%d] KSI[%d]",
|
||||||
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi,
|
mme_ue->nas_eps.type, mme_ue->nas_eps.ksi);
|
||||||
mme_ue->nas_eps.data);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ATTACH_REQUEST
|
* ATTACH_REQUEST
|
||||||
|
|
|
@ -128,11 +128,6 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
|
||||||
OGS_FSM_TRAN(s, emm_state_exception);
|
OGS_FSM_TRAN(s, emm_state_exception);
|
||||||
break;
|
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)) {
|
if (!MME_UE_HAVE_IMSI(mme_ue)) {
|
||||||
ogs_info("Service request : Unknown UE");
|
ogs_info("Service request : Unknown UE");
|
||||||
|
@ -548,11 +543,10 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
|
||||||
|
|
||||||
CLEAR_MME_UE_TIMER(mme_ue->t3422);
|
CLEAR_MME_UE_TIMER(mme_ue->t3422);
|
||||||
|
|
||||||
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
|
rv = s1ap_send_ue_context_release_command(enb_ue,
|
||||||
ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue));
|
S1AP_Cause_PR_nas, S1AP_CauseNas_detach,
|
||||||
} else {
|
S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0);
|
||||||
mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue);
|
ogs_expect(rv == OGS_OK);
|
||||||
}
|
|
||||||
|
|
||||||
OGS_FSM_TRAN(s, &emm_state_de_registered);
|
OGS_FSM_TRAN(s, &emm_state_de_registered);
|
||||||
break;
|
break;
|
||||||
|
@ -644,7 +638,7 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e)
|
||||||
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
OGS_FSM_TRAN(&mme_ue->sm, &emm_state_exception);
|
||||||
} else {
|
} else {
|
||||||
ogs_assert(mme_ue->t3422.pkbuf);
|
ogs_assert(mme_ue->t3422.pkbuf);
|
||||||
rv = nas_eps_send_detach_request(mme_ue, 0);
|
rv = nas_eps_send_detach_request(mme_ue);
|
||||||
if (rv == OGS_OK) {
|
if (rv == OGS_OK) {
|
||||||
mme_ue->t3422.retry_count++;
|
mme_ue->t3422.retry_count++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -312,13 +312,22 @@ struct mme_ue_s {
|
||||||
#define MME_EPS_TYPE_DETACH_REQUEST_TO_UE 6
|
#define MME_EPS_TYPE_DETACH_REQUEST_TO_UE 6
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t ksi;
|
uint8_t ksi;
|
||||||
union {
|
ogs_nas_eps_attach_type_t attach;
|
||||||
ogs_nas_eps_attach_type_t attach;
|
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;
|
|
||||||
uint8_t data;
|
/* 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;
|
||||||
|
|
||||||
/* UE identity */
|
/* UE identity */
|
||||||
|
|
|
@ -233,8 +233,6 @@ static void mme_s6a_aia_cb(void *data, struct msg **msg)
|
||||||
ogs_assert(aia_message);
|
ogs_assert(aia_message);
|
||||||
e_utran_vector = &aia_message->e_utran_vector;
|
e_utran_vector = &aia_message->e_utran_vector;
|
||||||
ogs_assert(e_utran_vector);
|
ogs_assert(e_utran_vector);
|
||||||
|
|
||||||
s6a_message->isAnswer = true;
|
|
||||||
|
|
||||||
/* Value of Result Code */
|
/* Value of Result Code */
|
||||||
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
|
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
|
||||||
|
@ -644,8 +642,6 @@ static void mme_s6a_ula_cb(void *data, struct msg **msg)
|
||||||
subscription_data = &ula_message->subscription_data;
|
subscription_data = &ula_message->subscription_data;
|
||||||
ogs_assert(subscription_data);
|
ogs_assert(subscription_data);
|
||||||
|
|
||||||
s6a_message->isAnswer = true;
|
|
||||||
|
|
||||||
/* AVP: 'Result-Code'(268)
|
/* AVP: 'Result-Code'(268)
|
||||||
* The Result-Code AVP indicates whether a particular request was completed
|
* The Result-Code AVP indicates whether a particular request was completed
|
||||||
* successfully or whether an error occurred. The Result-Code data field
|
* successfully or whether an error occurred. The Result-Code data field
|
||||||
|
@ -1441,8 +1437,6 @@ static int mme_ogs_diam_s6a_clr_cb( struct msg **msg, struct avp *avp,
|
||||||
clr_message = &s6a_message->clr_message;
|
clr_message = &s6a_message->clr_message;
|
||||||
ogs_assert(clr_message);
|
ogs_assert(clr_message);
|
||||||
|
|
||||||
s6a_message->isAnswer = false;
|
|
||||||
|
|
||||||
/* Create answer header */
|
/* Create answer header */
|
||||||
qry = *msg;
|
qry = *msg;
|
||||||
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
|
||||||
|
|
|
@ -28,32 +28,23 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue)
|
||||||
{
|
{
|
||||||
ogs_assert(mme_ue);
|
ogs_assert(mme_ue);
|
||||||
|
|
||||||
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
|
switch (mme_ue->nas_eps.detach_type) {
|
||||||
mme_gtp_send_delete_all_sessions(mme_ue,
|
case MME_EPS_TYPE_DETACH_REQUEST_FROM_UE:
|
||||||
OGS_GTP_DELETE_SEND_DETACH_ACCEPT);
|
if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) {
|
||||||
} else {
|
mme_gtp_send_delete_all_sessions(
|
||||||
ogs_assert(OGS_OK ==
|
mme_ue, OGS_GTP_DELETE_SEND_DETACH_ACCEPT);
|
||||||
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 {
|
} else {
|
||||||
ogs_warn("[%s] No S1 Context", mme_ue->imsi_bcd);
|
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_NO_ACTION);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ogs_fatal(" Invalid OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type);
|
||||||
|
ogs_assert_if_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,20 +192,17 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed)
|
||||||
break;
|
break;
|
||||||
case MME_PAGING_TYPE_DETACH_TO_UE:
|
case MME_PAGING_TYPE_DETACH_TO_UE:
|
||||||
if (failed == true) {
|
if (failed == true) {
|
||||||
|
/* Nothing */
|
||||||
|
ogs_fatal("MME-initiated Detach should not be invoked "
|
||||||
|
"if Paging failed");
|
||||||
|
ogs_assert_if_reached();
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
mme_send_delete_session_or_mme_ue_context_release_detach(mme_ue);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -27,7 +27,6 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void mme_send_delete_session_or_detach(mme_ue_t *mme_ue);
|
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_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_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue);
|
||||||
|
|
||||||
|
|
|
@ -562,7 +562,11 @@ void mme_s11_handle_delete_session_response(
|
||||||
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
|
||||||
mme_ue->mme_s11_teid, source_ue->sgw_s11_teid);
|
mme_ue->mme_s11_teid, source_ue->sgw_s11_teid);
|
||||||
|
|
||||||
if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) {
|
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 if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST) {
|
||||||
if (mme_sess_count(mme_ue) == 1) /* Last Session */ {
|
if (mme_sess_count(mme_ue) == 1) /* Last Session */ {
|
||||||
mme_s6a_send_air(mme_ue, NULL);
|
mme_s6a_send_air(mme_ue, NULL);
|
||||||
}
|
}
|
||||||
|
@ -603,6 +607,20 @@ void mme_s11_handle_delete_session_response(
|
||||||
ogs_error("ENB-S1 Context has already been removed");
|
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) {
|
} else if (action == OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST) {
|
||||||
if (mme_sess_count(mme_ue) == 1) /* Last Session */ {
|
if (mme_sess_count(mme_ue) == 1) /* Last Session */ {
|
||||||
rv = nas_eps_send_emm_to_esm(mme_ue,
|
rv = nas_eps_send_emm_to_esm(mme_ue,
|
||||||
|
@ -636,12 +654,6 @@ void mme_s11_handle_delete_session_response(
|
||||||
|
|
||||||
return;
|
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 {
|
} else {
|
||||||
ogs_fatal("Invalid action = %d", action);
|
ogs_fatal("Invalid action = %d", action);
|
||||||
ogs_assert_if_reached();
|
ogs_assert_if_reached();
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nas-path.h"
|
#include "nas-path.h"
|
||||||
#include "mme-path.h"
|
|
||||||
#include "s1ap-path.h"
|
#include "s1ap-path.h"
|
||||||
|
#include "sgsap-path.h"
|
||||||
|
#include "mme-path.h"
|
||||||
|
|
||||||
#include "mme-sm.h"
|
#include "mme-sm.h"
|
||||||
#include "mme-s6a-handler.h"
|
#include "mme-s6a-handler.h"
|
||||||
|
@ -140,16 +141,9 @@ uint8_t mme_s6a_handle_ula(
|
||||||
ogs_assert(OGS_OK ==
|
ogs_assert(OGS_OK ==
|
||||||
nas_eps_send_tau_accept(mme_ue,
|
nas_eps_send_tau_accept(mme_ue,
|
||||||
S1AP_ProcedureCode_id_InitialContextSetup));
|
S1AP_ProcedureCode_id_InitialContextSetup));
|
||||||
} else if (mme_ue->nas_eps.type == MME_EPS_TYPE_SERVICE_REQUEST) {
|
|
||||||
ogs_error("[%s] Service request", mme_ue->imsi_bcd);
|
|
||||||
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
|
|
||||||
} else if (mme_ue->nas_eps.type ==
|
|
||||||
MME_EPS_TYPE_DETACH_REQUEST_FROM_UE) {
|
|
||||||
ogs_error("[%s] Detach request", mme_ue->imsi_bcd);
|
|
||||||
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
|
|
||||||
} else {
|
} else {
|
||||||
ogs_fatal("Invalid Type[%d]", mme_ue->nas_eps.type);
|
ogs_error("Invalid Type[%d]", mme_ue->nas_eps.type);
|
||||||
ogs_assert_if_reached();
|
return OGS_NAS_EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED;
|
return OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED;
|
||||||
|
@ -158,31 +152,47 @@ uint8_t mme_s6a_handle_ula(
|
||||||
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_clr_message_t *clr_message)
|
||||||
{
|
{
|
||||||
uint8_t detach_type = 0;
|
|
||||||
|
|
||||||
ogs_assert(mme_ue);
|
ogs_assert(mme_ue);
|
||||||
ogs_assert(clr_message);
|
ogs_assert(clr_message);
|
||||||
|
|
||||||
/* Set NAS EPS Type */
|
/* Set EPS Detach */
|
||||||
mme_ue->nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE;
|
memset(&mme_ue->nas_eps.detach, 0, sizeof(ogs_nas_detach_type_t));
|
||||||
ogs_debug(" OGS_NAS_EPS TYPE[%d]", mme_ue->nas_eps.type);
|
|
||||||
|
|
||||||
if (clr_message->clr_flags & OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED)
|
if (clr_message->clr_flags & OGS_DIAM_S6A_CLR_FLAGS_REATTACH_REQUIRED)
|
||||||
detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED;
|
mme_ue->nas_eps.detach.value =
|
||||||
|
OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_REQUIRED;
|
||||||
else
|
else
|
||||||
detach_type = OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED;
|
mme_ue->nas_eps.detach.value =
|
||||||
|
OGS_NAS_DETACH_TYPE_TO_UE_RE_ATTACH_NOT_REQUIRED;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
mme_ue->nas_eps.type = mme_ue->nas_eps.detach_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)) {
|
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)) {
|
} else if (ECM_IDLE(mme_ue)) {
|
||||||
MME_STORE_PAGING_INFO(mme_ue,
|
MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DETACH_TO_UE, NULL);
|
||||||
MME_PAGING_TYPE_DETACH_TO_UE, (void *)(uintptr_t)detach_type);
|
|
||||||
ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps));
|
ogs_assert(OGS_OK == s1ap_send_paging(mme_ue, S1AP_CNDomain_ps));
|
||||||
} else {
|
} else {
|
||||||
ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue, detach_type));
|
ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue));
|
||||||
mme_send_delete_session_or_mme_ue_context_release_detach(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -390,24 +390,17 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
||||||
s6a_message = e->s6a_message;
|
s6a_message = e->s6a_message;
|
||||||
ogs_assert(s6a_message);
|
ogs_assert(s6a_message);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (s6a_message->cmd_code) {
|
switch (s6a_message->cmd_code) {
|
||||||
case OGS_DIAM_S6A_CMD_CODE_AUTHENTICATION_INFORMATION:
|
case OGS_DIAM_S6A_CMD_CODE_AUTHENTICATION_INFORMATION:
|
||||||
emm_cause = mme_s6a_handle_aia(mme_ue, s6a_message);
|
emm_cause = mme_s6a_handle_aia(mme_ue, s6a_message);
|
||||||
if (emm_cause != OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED) {
|
if (emm_cause != OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED) {
|
||||||
ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]",
|
ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]",
|
||||||
mme_ue->imsi_bcd, emm_cause);
|
mme_ue->imsi_bcd, emm_cause);
|
||||||
|
enb_ue = enb_ue_cycle(mme_ue->enb_ue);
|
||||||
|
if (!enb_ue) {
|
||||||
|
ogs_error("S1 context has already been removed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
ogs_assert(OGS_OK ==
|
ogs_assert(OGS_OK ==
|
||||||
nas_eps_send_attach_reject(mme_ue, emm_cause,
|
nas_eps_send_attach_reject(mme_ue, emm_cause,
|
||||||
OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED));
|
OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED));
|
||||||
|
@ -423,6 +416,11 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
||||||
if (emm_cause != OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED) {
|
if (emm_cause != OGS_NAS_EMM_CAUSE_REQUEST_ACCEPTED) {
|
||||||
ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]",
|
ogs_info("[%s] Attach reject [OGS_NAS_EMM_CAUSE:%d]",
|
||||||
mme_ue->imsi_bcd, emm_cause);
|
mme_ue->imsi_bcd, emm_cause);
|
||||||
|
enb_ue = enb_ue_cycle(mme_ue->enb_ue);
|
||||||
|
if (!enb_ue) {
|
||||||
|
ogs_error("S1 context has already been removed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
ogs_assert(OGS_OK ==
|
ogs_assert(OGS_OK ==
|
||||||
nas_eps_send_attach_reject(mme_ue, emm_cause,
|
nas_eps_send_attach_reject(mme_ue, emm_cause,
|
||||||
OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED));
|
OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED));
|
||||||
|
|
|
@ -256,7 +256,7 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type)
|
int nas_eps_send_detach_request(mme_ue_t *mme_ue)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
ogs_pkbuf_t *emmbuf = NULL;
|
ogs_pkbuf_t *emmbuf = NULL;
|
||||||
|
@ -267,8 +267,7 @@ int nas_eps_send_detach_request(mme_ue_t *mme_ue, uint8_t detach_type)
|
||||||
emmbuf = mme_ue->t3422.pkbuf;
|
emmbuf = mme_ue->t3422.pkbuf;
|
||||||
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
||||||
} else {
|
} else {
|
||||||
ogs_assert(detach_type);
|
emmbuf = emm_build_detach_request(mme_ue);
|
||||||
emmbuf = emm_build_detach_request(mme_ue, detach_type);
|
|
||||||
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
ogs_expect_or_return_val(emmbuf, OGS_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_security_mode_command(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_request(mme_ue_t *mme_ue);
|
||||||
int nas_eps_send_detach_accept(mme_ue_t *mme_ue);
|
int nas_eps_send_detach_accept(mme_ue_t *mme_ue);
|
||||||
|
|
||||||
int nas_eps_send_pdn_connectivity_reject(
|
int nas_eps_send_pdn_connectivity_reject(
|
||||||
|
|
Loading…
Reference in New Issue