[AMF/MME] UEContextReleaseCommand after Interity Protected (#2786) (#2794)

* [AMF/MME] UEContextReleaseCommand in Integrity (#2786)

Modified not to send UEContextReleaseCommand in Integrity Unprotected
NAS message such like Registration or Service request.

* [AMF/MME] UEContextReleaseCommand after Interity Protected (#2786)

Modified not to send UEContextReleaseCommand in Integrity Unprotected
NAS message such like Registration or Service request.
This commit is contained in:
Sukchan Lee 2023-12-13 17:54:37 +09:00 committed by GitHub
parent b0f381416b
commit 1ba3fd3cf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 440 additions and 107 deletions

View File

@ -891,19 +891,19 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
ogs_pkbuf_free(pkbuf);
break;
}
ogs_assert(CM_IDLE(amf_ue));
} else {
/* Here, if the AMF_UE Context is found,
* the integrity check is not performed
* For example, REGISTRATION_REQUEST,
* TRACKING_AREA_UPDATE_REQUEST message
* For example, REGISTRATION_REQUEST, SERVICE_REQUEST message
*
* Now, We will check the MAC in the NAS message*/
ogs_nas_security_header_type_t h;
h.type = e->nas.type;
if (h.integrity_protected) {
/* Decryption was performed in NGAP handler.
* So, we disabled 'ciphered'
* not to decrypt NAS message */
* So, we disabled 'ciphered' not to decrypt NAS message */
h.ciphered = 0;
if (nas_5gs_security_decode(amf_ue, h, pkbuf) != OGS_OK) {
ogs_error("[%s] nas_security_decode() failed",
@ -912,42 +912,45 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
break;
}
}
}
/*
* TS23.502
* 4.2.3.2 UE Triggered Service Request
*
* 4. [Conditional]
* AMF to SMF: Nsmf_PDUSession_UpdateSMContext Request
*
* The AMF may receive a Service Request to establish another
* NAS signalling connection via a NG-RAN while it has maintained
* an old NAS signalling connection for UE still via NG-RAN.
* In this case, AMF shall trigger the AN release procedure toward
* the old NG-RAN to release the old NAS signalling connection
* as defined in clause 4.2.6 with following logic: */
/*
* TS23.502
* 4.2.3.2 UE Triggered Service Request
*
* 4. [Conditional]
* AMF to SMF: Nsmf_PDUSession_UpdateSMContext Request
*
* The AMF may receive a Service Request to establish another
* NAS signalling connection via a NG-RAN while it has
* maintained an old NAS signalling connection for UE still
* via NG-RAN. In this case, AMF shall trigger the AN release
* procedure toward the old NG-RAN to release the old NAS
* signalling connection as defined in clause 4.2.6
* with following logic:
*/
/* If NAS(amf_ue_t) has already been associated with
* older NG(ran_ue_t) context */
if (CM_CONNECTED(amf_ue)) {
/* Previous NG(ran_ue_t) context the holding timer(30secs)
* is started.
* Newly associated NG(ran_ue_t) context holding timer
* is stopped. */
ogs_debug("[%s] Start NG Holding Timer", amf_ue->suci);
ogs_debug("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
amf_ue->suci, amf_ue->ran_ue->ran_ue_ngap_id,
(long long)amf_ue->ran_ue->amf_ue_ngap_id);
/* De-associate NG with NAS/EMM */
ran_ue_deassociate(amf_ue->ran_ue);
r = ngap_send_ran_ue_context_release_command(amf_ue->ran_ue,
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
/* If NAS(amf_ue_t) has already been associated with
* older NG(ran_ue_t) context */
if (CM_CONNECTED(amf_ue)) {
/*
* Issue #2786
*
* In cases where the UE sends an Integrity Un-Protected Registration
* Request or Service Request, there is an issue of sending
* a UEContextReleaseCommand for the OLD RAN Context.
*
* For example, if the UE switchs off and power-on after
* the first connection, the 5G Core sends a UEContextReleaseCommand.
*
* However, since there is no RAN context for this on the gNB,
* the gNB does not send a UEContextReleaseComplete,
* so the deletion of the RAN Context does not function properly.
*
* To solve this problem, the 5G Core has been modified to implicitly
* delete the RAN Context instead of sending a UEContextReleaseCommand.
*/
HOLDING_NG_CONTEXT(amf_ue);
}
}
amf_ue_associate_ran_ue(amf_ue, ran_ue);

View File

@ -1973,8 +1973,8 @@ void amf_ue_set_suci(amf_ue_t *amf_ue,
ogs_warn("[%s] OLD UE Context Release", suci);
if (CM_CONNECTED(old_amf_ue)) {
/* Implcit NG release */
ogs_info("[%s] Implicit NG release", suci);
ogs_info("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
ogs_warn("[%s] Implicit NG release", suci);
ogs_warn("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
old_amf_ue->suci, old_amf_ue->ran_ue->ran_ue_ngap_id,
(long long)old_amf_ue->ran_ue->amf_ue_ngap_id);
ran_ue_remove(old_amf_ue->ran_ue);

View File

@ -107,7 +107,7 @@ typedef struct amf_context_s {
ogs_hash_t *gnb_addr_hash; /* hash table for GNB Address */
ogs_hash_t *gnb_id_hash; /* hash table for GNB-ID */
ogs_hash_t *guti_ue_hash; /* hash table (GUTI : AMF_UE) */
ogs_hash_t *guti_ue_hash; /* hash table (GUTI : AMF_UE) */
ogs_hash_t *suci_hash; /* hash table (SUCI) */
ogs_hash_t *supi_hash; /* hash table (SUPI) */
@ -382,6 +382,45 @@ struct amf_ue_s {
/* NG UE context */
ran_ue_t *ran_ue;
#define HOLDING_NG_CONTEXT(__aMF) \
do { \
ran_ue_deassociate((__aMF)->ran_ue); \
\
(__aMF)->ran_ue_holding = ran_ue_cycle((__aMF)->ran_ue); \
if ((__aMF)->ran_ue_holding) { \
ogs_warn("[%s] Holding NG Context", (__aMF)->suci); \
ogs_warn("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]", \
(__aMF)->suci, (__aMF)->ran_ue_holding->ran_ue_ngap_id, \
(long long)(__aMF)->ran_ue_holding->amf_ue_ngap_id); \
\
(__aMF)->ran_ue_holding->ue_ctx_rel_action = \
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE; \
ogs_timer_start((__aMF)->ran_ue_holding->t_ng_holding, \
amf_timer_cfg(AMF_TIMER_NG_HOLDING)->duration); \
} else \
ogs_error("[%s] NG Context has already been removed", \
(__aMF)->suci); \
} while(0)
#define CLEAR_NG_CONTEXT(__aMF) \
do { \
if (ran_ue_cycle((__aMF)->ran_ue_holding)) { \
int r; \
ogs_warn("[%s] Clear NG Context", (__aMF)->suci); \
ogs_warn("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]", \
(__aMF)->suci, (__aMF)->ran_ue_holding->ran_ue_ngap_id, \
(long long)(__aMF)->ran_ue_holding->amf_ue_ngap_id); \
\
r = ngap_send_ran_ue_context_release_command( \
(__aMF)->ran_ue_holding, \
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release, \
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0); \
ogs_expect(r == OGS_OK); \
ogs_assert(r != OGS_ERROR); \
} \
(__aMF)->ran_ue_holding = NULL; \
} while(0)
ran_ue_t *ran_ue_holding;
#define CLEAR_AMF_UE_ALL_TIMERS(__aMF) \
do { \
CLEAR_AMF_UE_TIMER((__aMF)->t3513); \

View File

@ -1204,6 +1204,13 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(amf_ue)) {
/*
* If the OLD RAN_UE is being maintained in AMF-UE Context,
* it deletes the NG Context after exchanging
* the UEContextReleaseCommand/Complete with the gNB
*/
CLEAR_NG_CONTEXT(amf_ue);
gmm_cause = gmm_handle_registration_update(
amf_ue, &nas_message->gmm.registration_request);
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
@ -1325,6 +1332,13 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
break;
}
/*
* If the OLD RAN_UE is being maintained in AMF-UE Context,
* it deletes the NG Context after exchanging
* the UEContextReleaseCommand/Complete with the gNB
*/
CLEAR_NG_CONTEXT(amf_ue);
gmm_cause = gmm_handle_service_update(
amf_ue, &nas_message->gmm.service_request);
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
@ -1391,6 +1405,19 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
case OGS_NAS_5GS_DEREGISTRATION_REQUEST_FROM_UE:
ogs_info("[%s] Deregistration request", amf_ue->supi);
if (!h.integrity_protected || !SECURITY_CONTEXT_IS_VALID(amf_ue)) {
ogs_error("No Security Context");
OGS_FSM_TRAN(s, gmm_state_exception);
break;
}
/*
* If the OLD RAN_UE is being maintained in AMF-UE Context,
* it deletes the NG Context after exchanging
* the UEContextReleaseCommand/Complete with the gNB
*/
CLEAR_NG_CONTEXT(amf_ue);
gmm_handle_deregistration_request(
amf_ue, &nas_message->gmm.deregistration_request_from_ue);
OGS_FSM_TRAN(s, &gmm_state_de_registered);
@ -1831,6 +1858,13 @@ void gmm_state_security_mode(ogs_fsm_t *s, amf_event_t *e)
break;
}
/*
* If the OLD RAN_UE is being maintained in AMF-UE Context,
* it deletes the NG Context after exchanging
* the UEContextReleaseCommand/Complete with the gNB
*/
CLEAR_NG_CONTEXT(amf_ue);
CLEAR_AMF_UE_TIMER(amf_ue->t3560);
gmm_cause = gmm_handle_security_mode_complete(
@ -2429,6 +2463,13 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e)
if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(amf_ue)) {
/*
* If the OLD RAN_UE is being maintained in AMF-UE Context,
* it deletes the NG Context after exchanging
* the UEContextReleaseCommand/Complete with the gNB
*/
CLEAR_NG_CONTEXT(amf_ue);
gmm_cause = gmm_handle_registration_update(
amf_ue, &nas_message->gmm.registration_request);
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {

View File

@ -486,24 +486,24 @@ void ngap_handle_initial_ue_message(amf_gnb_t *gnb, ogs_ngap_message_t *message)
/* If NAS(amf_ue_t) has already been associated with
* older NG(ran_ue_t) context */
if (CM_CONNECTED(amf_ue)) {
/* Previous NG(ran_ue_t) context the holding timer(30secs)
* is started.
* Newly associated NG(ran_ue_t) context holding timer
* is stopped. */
ogs_debug("[%s] Start NG Holding Timer", amf_ue->suci);
ogs_debug("[%s] RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]",
amf_ue->suci, amf_ue->ran_ue->ran_ue_ngap_id,
(long long)amf_ue->ran_ue->amf_ue_ngap_id);
/* De-associate NG with NAS/EMM */
ran_ue_deassociate(amf_ue->ran_ue);
r = ngap_send_ran_ue_context_release_command(
amf_ue->ran_ue,
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
/*
* Issue #2786
*
* In cases where the UE sends an Integrity Un-Protected Registration
* Request or Service Request, there is an issue of sending
* a UEContextReleaseCommand for the OLD RAN Context.
*
* For example, if the UE switchs off and power-on after
* the first connection, the 5G Core sends a UEContextReleaseCommand.
*
* However, since there is no RAN context for this on the gNB,
* the gNB does not send a UEContextReleaseComplete,
* so the deletion of the RAN Context does not function properly.
*
* To solve this problem, the 5G Core has been modified to implicitly
* delete the RAN Context instead of sending a UEContextReleaseCommand.
*/
HOLDING_NG_CONTEXT(amf_ue);
}
amf_ue_associate_ran_ue(amf_ue, ran_ue);

View File

@ -370,6 +370,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
r = s1ap_send_initial_context_setup_request(mme_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -427,6 +434,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
}
if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(mme_ue)) {
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
mme_gtp_send_delete_all_sessions(mme_ue,
OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST);
@ -510,6 +524,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
/*
* <EMM-IDLE State>
* 1. InitialUEMessage + Tracking area update request
@ -669,6 +690,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
if (e->s1ap_code == S1AP_ProcedureCode_id_initialUEMessage) {
ogs_debug(" Initial UE Message");
@ -795,6 +823,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue));
} else {
@ -1010,6 +1045,13 @@ void emm_state_authentication(ogs_fsm_t *s, mme_event_t *e)
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue));
} else {
@ -1127,6 +1169,13 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e)
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
emm_handle_security_mode_complete(
mme_ue, &message->emm.security_mode_complete);
@ -1210,6 +1259,13 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e)
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue));
} else {
@ -1324,6 +1380,13 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e)
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
CLEAR_MME_UE_TIMER(mme_ue->t3450);
rv = emm_handle_attach_complete(
@ -1376,6 +1439,13 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e)
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
CLEAR_MME_UE_TIMER(mme_ue->t3450);
/* Confirm GUTI */
@ -1441,6 +1511,13 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e)
break;
}
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
ogs_assert(OGS_OK == sgsap_send_detach_indication(mme_ue));
} else {
@ -1560,6 +1637,13 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e)
}
if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(mme_ue)) {
/*
* If the OLD ENB_UE is being maintained in MME-UE Context,
* it deletes the S1 Context after exchanging
* the UEContextReleaseCommand/Complete with the eNB
*/
CLEAR_S1_CONTEXT(mme_ue);
mme_gtp_send_delete_all_sessions(mme_ue,
OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST);

View File

@ -3671,8 +3671,8 @@ int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd)
ogs_warn("[%s] OLD UE Context Release", mme_ue->imsi_bcd);
if (ECM_CONNECTED(old_mme_ue)) {
/* Implcit S1 release */
ogs_info("[%s] Implicit S1 release", mme_ue->imsi_bcd);
ogs_info("[%s] ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
ogs_warn("[%s] Implicit S1 release", mme_ue->imsi_bcd);
ogs_warn("[%s] ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
old_mme_ue->imsi_bcd,
old_mme_ue->enb_ue->enb_ue_s1ap_id,
old_mme_ue->enb_ue->mme_ue_s1ap_id);

View File

@ -531,11 +531,50 @@ struct mme_ue_s {
(((__mME)->enb_ue == NULL) || (enb_ue_cycle((__mME)->enb_ue) == NULL)))
enb_ue_t *enb_ue; /* S1 UE context */
#define HOLDING_S1_CONTEXT(__mME) \
do { \
enb_ue_deassociate((__mME)->enb_ue); \
\
(__mME)->enb_ue_holding = enb_ue_cycle((__mME)->enb_ue); \
if ((__mME)->enb_ue_holding) { \
ogs_warn("[%s] Holding S1 Context", (__mME)->imsi_bcd); \
ogs_warn("[%s] ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", \
(__mME)->imsi_bcd, (__mME)->enb_ue_holding->enb_ue_s1ap_id, \
(__mME)->enb_ue_holding->mme_ue_s1ap_id); \
\
(__mME)->enb_ue_holding->ue_ctx_rel_action = \
S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE; \
ogs_timer_start((__mME)->enb_ue_holding->t_s1_holding, \
mme_timer_cfg(MME_TIMER_S1_HOLDING)->duration); \
} else \
ogs_error("[%s] S1 Context has already been removed", \
(__mME)->imsi_bcd); \
} while(0)
#define CLEAR_S1_CONTEXT(__mME) \
do { \
if (enb_ue_cycle((__mME)->enb_ue_holding)) { \
int r; \
ogs_warn("[%s] Clear S1 Context", (__mME)->imsi_bcd); \
ogs_warn("[%s] ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", \
(__mME)->imsi_bcd, (__mME)->enb_ue_holding->enb_ue_s1ap_id, \
(__mME)->enb_ue_holding->mme_ue_s1ap_id); \
\
r = s1ap_send_ue_context_release_command( \
(__mME)->enb_ue_holding, \
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, \
S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0); \
ogs_expect(r == OGS_OK); \
ogs_assert(r != OGS_ERROR); \
} \
(__mME)->enb_ue_holding = NULL; \
} while(0)
enb_ue_t *enb_ue_holding;
struct {
#define MME_CLEAR_PAGING_INFO(__mME) \
do { \
ogs_assert(__mME); \
ogs_debug("[%s] Clear Paging Info", mme_ue->imsi_bcd); \
ogs_debug("[%s] Clear Paging Info", (__mME)->imsi_bcd); \
(__mME)->paging.type = 0; \
} while(0)

View File

@ -265,6 +265,8 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
ogs_pkbuf_free(pkbuf);
return;
}
ogs_assert(ECM_IDLE(mme_ue));
} else {
/* Here, if the MME_UE Context is found,
* the integrity check is not performed
@ -285,29 +287,31 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
return;
}
}
/* If NAS(mme_ue_t) has already been associated with
* older S1(enb_ue_t) context */
if (ECM_CONNECTED(mme_ue)) {
/*
* Issue #2786
*
* In cases where the UE sends an Integrity Un-Protected Attach
* Request or Service Request, there is an issue of sending
* a UEContextReleaseCommand for the OLD ENB Context.
*
* For example, if the UE switchs off and power-on after
* the first connection, the EPC sends a UEContextReleaseCommand.
*
* However, since there is no ENB context for this on the eNB,
* the eNB does not send a UEContextReleaseComplete,
* so the deletion of the ENB Context does not function properly.
*
* To solve this problem, the EPC has been modified to implicitly
* delete the ENB Context instead of sending a UEContextReleaseCommand.
*/
HOLDING_S1_CONTEXT(mme_ue);
}
}
/* If NAS(mme_ue_t) has already been associated with
* older S1(enb_ue_t) context */
if (ECM_CONNECTED(mme_ue)) {
/* Previous S1(enb_ue_t) context the holding timer(30secs)
* is started.
* Newly associated S1(enb_ue_t) context holding timer
* is stopped. */
ogs_debug("Start S1 Holding Timer");
ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
mme_ue->enb_ue->enb_ue_s1ap_id,
mme_ue->enb_ue->mme_ue_s1ap_id);
/* De-associate S1 with NAS/EMM */
enb_ue_deassociate(mme_ue->enb_ue);
r = s1ap_send_ue_context_release_command(mme_ue->enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
enb_ue_associate_mme_ue(enb_ue, mme_ue);
ogs_debug("Mobile Reachable timer stopped for IMSI[%s]",
mme_ue->imsi_bcd);

View File

@ -496,23 +496,24 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
/* If NAS(mme_ue_t) has already been associated with
* older S1(enb_ue_t) context */
if (ECM_CONNECTED(mme_ue)) {
/* Previous S1(enb_ue_t) context the holding timer(30secs)
* is started.
* Newly associated S1(enb_ue_t) context holding timer
* is stopped. */
ogs_debug("Start S1 Holding Timer");
ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]",
mme_ue->enb_ue->enb_ue_s1ap_id,
mme_ue->enb_ue->mme_ue_s1ap_id);
/* De-associate S1 with NAS/EMM */
enb_ue_deassociate(mme_ue->enb_ue);
r = s1ap_send_ue_context_release_command(mme_ue->enb_ue,
S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release,
S1AP_UE_CTX_REL_S1_CONTEXT_REMOVE, 0);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
/*
* Issue #2786
*
* In cases where the UE sends an Integrity Un-Protected Attach
* Request or Service Request, there is an issue of sending
* a UEContextReleaseCommand for the OLD ENB Context.
*
* For example, if the UE switchs off and power-on after
* the first connection, the EPC sends a UEContextReleaseCommand.
*
* However, since there is no ENB context for this on the eNB,
* the eNB does not send a UEContextReleaseComplete,
* so the deletion of the ENB Context does not function properly.
*
* To solve this problem, the EPC has been modified to implicitly
* delete the ENB Context instead of sending a UEContextReleaseCommand.
*/
HOLDING_S1_CONTEXT(mme_ue);
}
enb_ue_associate_mme_ue(enb_ue, mme_ue);
ogs_debug("Mobile Reachable timer stopped for IMSI[%s]",

View File

@ -288,6 +288,7 @@ static void test1_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -302,6 +303,7 @@ static void test1_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication request */
recvbuf = testenb_s1ap_read(s1ap);
@ -361,6 +363,7 @@ static void test1_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -375,6 +378,7 @@ static void test1_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication request */
recvbuf = testenb_s1ap_read(s1ap);

View File

@ -638,6 +638,7 @@ static void test2_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -652,6 +653,7 @@ static void test2_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication request */
recvbuf = testenb_s1ap_read(s1ap);
@ -680,6 +682,23 @@ static void test2_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send OLD UE Context Release Complete */
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive ESM Information Request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -1047,6 +1066,7 @@ static void test3_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -1061,6 +1081,7 @@ static void test3_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication Request */
recvbuf = testenb_s1ap_read(s1ap);
@ -1089,6 +1110,23 @@ static void test3_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send OLD UE Context Release Complete */
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive InitialContextSetupResponse + TAU Accept */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -1369,6 +1407,7 @@ static void test4_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -1383,6 +1422,7 @@ static void test4_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication Request */
recvbuf = testenb_s1ap_read(s1ap);
@ -1411,6 +1451,23 @@ static void test4_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send OLD UE Context Release Complete */
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Initial Context Setup Request +
* Attach Accept +
* Activate Default Bearer Context Request */

View File

@ -362,6 +362,7 @@ static void test2_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -376,6 +377,7 @@ static void test2_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication Request */
recvbuf = testenb_s1ap_read(s1ap);
@ -404,6 +406,23 @@ static void test2_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send OLD UE Context Release Complete */
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Initial Context Setup Request +
* Attach Accept +
* Activate Default Bearer Context Request */
@ -642,6 +661,7 @@ static void test3_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
@ -656,6 +676,7 @@ static void test3_func(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Authentication Request */
recvbuf = testenb_s1ap_read(s1ap);
@ -684,6 +705,23 @@ static void test3_func(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED
/* Receive OLD UE Context Release Command */
enb_ue_s1ap_id = test_ue->enb_ue_s1ap_id;
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send OLD UE Context Release Complete */
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->enb_ue_s1ap_id = enb_ue_s1ap_id;
#endif
/* Receive Initial Context Setup Request +
* Attach Accept +
* Activate Default Bearer Context Request */

View File

@ -327,7 +327,7 @@ int test_context_parse_config(void)
ogs_5gs_tai1_list_t *list1 = NULL;
ogs_5gs_tai2_list_t *list2 = NULL;
ogs_assert(self.num_of_nr_served_tai <=
ogs_assert(self.num_of_nr_served_tai <
OGS_MAX_NUM_OF_SUPPORTED_TA);
list0 =
&self.nr_served_tai[self.num_of_nr_served_tai].list0;
@ -512,7 +512,7 @@ int test_context_parse_config(void)
ogs_yaml_iter_recurse(&amf_iter, &plmn_support_array);
do {
const char *mnc = NULL, *mcc = NULL;
ogs_assert(self.num_of_plmn_support <=
ogs_assert(self.num_of_plmn_support <
OGS_MAX_NUM_OF_PLMN);
if (ogs_yaml_iter_type(&plmn_support_array) ==
@ -570,7 +570,7 @@ int test_context_parse_config(void)
ogs_assert(
self.plmn_support[
self.num_of_plmn_support].
num_of_s_nssai <=
num_of_s_nssai <
OGS_MAX_NUM_OF_SLICE_SUPPORT);
s_nssai = &self.plmn_support[
self.num_of_plmn_support].s_nssai[
@ -807,7 +807,7 @@ int test_context_parse_config(void)
ogs_eps_tai1_list_t *list1 = NULL;
ogs_eps_tai2_list_t *list2 = NULL;
ogs_assert(self.num_of_e_served_tai <=
ogs_assert(self.num_of_e_served_tai <
OGS_MAX_NUM_OF_SUPPORTED_TA);
list0 = &self.e_served_tai[self.num_of_e_served_tai].list0;
list1 = &self.e_served_tai[self.num_of_e_served_tai].list1;

View File

@ -65,7 +65,7 @@ typedef struct test_context_s {
ogs_list_t gtpc_list; /* SMF GTPC Client List */
/* 5G PLMN Support */
uint8_t num_of_plmn_support;
int num_of_plmn_support;
struct {
ogs_plmn_id_t plmn_id;
int num_of_s_nssai;
@ -73,7 +73,7 @@ typedef struct test_context_s {
} plmn_support[OGS_MAX_NUM_OF_PLMN];
/* Served EPC TAI */
uint8_t num_of_e_served_tai;
int num_of_e_served_tai;
struct {
ogs_eps_tai0_list_t list0;
ogs_eps_tai1_list_t list1;
@ -83,7 +83,7 @@ typedef struct test_context_s {
ogs_eps_tai_t e_tai;
/* Served 5GC TAI */
uint8_t num_of_nr_served_tai;
int num_of_nr_served_tai;
struct {
ogs_5gs_tai0_list_t list0;
ogs_5gs_tai1_list_t list1;

View File

@ -74,6 +74,9 @@ extern "C" {
#undef OGS_LOG_DOMAIN
#define OGS_LOG_DOMAIN 1
#define SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED 0
#define SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED 1
#undef OGS_TEST_INSIDE
#ifdef __cplusplus

View File

@ -146,6 +146,7 @@ static void test1_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* OLD Receive UEContextReleaseCommand */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -159,6 +160,7 @@ static void test1_func(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#endif
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap);

View File

@ -317,6 +317,7 @@ static void test2_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_UNPROTECTED
/* OLD Receive UEContextReleaseCommand */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
@ -330,6 +331,7 @@ static void test2_func(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#endif
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap);
@ -357,6 +359,22 @@ static void test2_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if SEND_UE_CONTEXT_RELEASE_COMMAND_IN_INTEGRITY_PROTECTED
/* OLD Receive UEContextReleaseCommand */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_UEContextRelease,
test_ue->ngap_procedure_code);
/* Send OLD UE Context Release Complete */
sendbuf = testngap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#endif
/* Receive InitialContextSetupRequest +
* Registration accept */
recvbuf = testgnb_ngap_read(ngap);