[MME] unify EPS Bearer Context Status (BCS) check for both active_flag=0 and 1

Previously, TAU procedure validated EPS Bearer Context Status (BCS)
only when active_flag == 0. When active_flag == 1, the MME skipped BCS
validation and sent TAU ACCEPT directly via InitialContextSetup.

This patch unifies BCS validation so both active_flag paths handle
bearer mismatches consistently. It also selects the correct S1AP
procedure (InitialContextSetup or DownlinkNASTransport) depending on
the UE active state.

Changes:
- emm-sm.c / sgsap-handler.c:
  * Always check EPS_BEARER_CONTEXT_STATUS_TYPE presence.
  * Invoke mme_send_delete_session_or_tau_accept() for both
    active_flag=0 and 1.
  * Send TAU ACCEPT directly only when BCS is not present.

- mme-path.c:
  * Select S1AP procedure in TAU ACCEPT based on active_flag.

- mme-s11-handler.c:
  * After Delete Session Response (OGS_GTP_DELETE_SEND_TAU_ACCEPT),
    send TAU ACCEPT using proper S1AP procedure by active_flag.

This aligns MME TAU behavior with 3GPP TS 24.301 section 5.3.3.0a,
ensuring consistent BCS synchronization regardless of UE activity.
This commit is contained in:
Sukchan Lee
2025-10-22 22:53:32 +09:00
parent b7cd0d6a7c
commit f3f010b36c
4 changed files with 68 additions and 54 deletions

View File

@@ -729,24 +729,27 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->kenb, mme_ue->nh);
mme_ue->nhcc = 1;
ogs_info("[%s] TAU accept(active_flag=1)",
mme_ue->imsi_bcd);
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_InitialContextSetup);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else if (!(mme_ue->tracking_area_update_request_presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE)) {
ogs_info("[%s] TAU accept(NO Bearer Context Status)",
ogs_info("[%s] KDF update(active_flag=1)",
mme_ue->imsi_bcd);
}
/* check BCS regardless of active_flag */
if (mme_ue->tracking_area_update_request_presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE) {
ogs_info("[%s] TAU accept(active_flag=%d, BCS check)",
mme_ue->imsi_bcd,
mme_ue->nas_eps.update.active_flag);
mme_send_delete_session_or_tau_accept(enb_ue, mme_ue);
} else {
ogs_info("[%s] TAU accept(active_flag=%d, No BCS)",
mme_ue->imsi_bcd,
mme_ue->nas_eps.update.active_flag);
r = nas_eps_send_tau_accept(mme_ue,
mme_ue->nas_eps.update.active_flag ?
S1AP_ProcedureCode_id_InitialContextSetup :
S1AP_ProcedureCode_id_downlinkNASTransport);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_info("[%s] TAU accept(WITH Bearer Context Status)",
mme_ue->imsi_bcd);
mme_send_delete_session_or_tau_accept(enb_ue, mme_ue);
}
} else if (e->s1ap_code ==
S1AP_ProcedureCode_id_uplinkNASTransport) {

View File

@@ -329,7 +329,7 @@ cleanup:
/* ----------------------------------------------------------------------
* Function: mme_send_delete_session_or_tau_accept
* ----------------------------------------------------------------------
* - If active_flag == 0, check UE's EPS Bearer Context Status (BCS)
* - Check UE's EPS Bearer Context Status (BCS) regardless of active_flag
* against MME's sessions before sending TAU ACCEPT.
* - If UE does not report the default bearer EBI, delete that session.
* - Otherwise, send TAU ACCEPT immediately.
@@ -383,11 +383,21 @@ void mme_send_delete_session_or_tau_accept(enb_ue_t *enb_ue, mme_ue_t *mme_ue)
}
if (deleted > 0) {
ogs_warn("[%s] Deleted %d session(s) due to BCS mismatch",
mme_ue->imsi_bcd, deleted);
ogs_warn("[%s] Deleted %d session(s) due to BCS mismatch, "
"active_flag=%d",
mme_ue->imsi_bcd, deleted,
mme_ue->nas_eps.update.active_flag);
} else {
ogs_info("[%s] TAU accept(BCS match)", mme_ue->imsi_bcd);
/*
* Choose S1AP procedure based on active_flag:
* - active_flag==1 : InitialContextSetup
* - active_flag==0 : DownlinkNASTransport
*/
ogs_info("[%s] Send TAU accept(BCS match, active_flag=%d)",
mme_ue->imsi_bcd, mme_ue->nas_eps.update.active_flag);
r = nas_eps_send_tau_accept(mme_ue,
mme_ue->nas_eps.update.active_flag ?
S1AP_ProcedureCode_id_InitialContextSetup :
S1AP_ProcedureCode_id_downlinkNASTransport);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);

View File

@@ -886,8 +886,11 @@ void mme_s11_handle_delete_session_response(
GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_DELETE_SESSION_BY_TAU,
ogs_info("[%s] TAU accept(BCS mismatch)", mme_ue->imsi_bcd);
ogs_info("[%s] Send TAU accept(BCS match, active_flag=%d)",
mme_ue->imsi_bcd, mme_ue->nas_eps.update.active_flag);
r = nas_eps_send_tau_accept(mme_ue,
mme_ue->nas_eps.update.active_flag ?
S1AP_ProcedureCode_id_InitialContextSetup :
S1AP_ProcedureCode_id_downlinkNASTransport);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);

View File

@@ -150,25 +150,26 @@ void sgsap_handle_location_update_accept(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->kenb, mme_ue->nh);
mme_ue->nhcc = 1;
ogs_info("[%s] LU accept + TAU accept(active_flag==1)",
mme_ue->imsi_bcd);
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_InitialContextSetup);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else if (!(mme_ue->tracking_area_update_request_presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE)) {
ogs_info("[%s] LU accept + TAU accept(NO Bearer Context Status)",
mme_ue->imsi_bcd);
ogs_info("[%s] KDF update(active_flag=1)", mme_ue->imsi_bcd);
}
/* check BCS regardless of active_flag */
if (mme_ue->tracking_area_update_request_presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE) {
ogs_info("[%s] LU accept + TAU accept(active_flag=%d, BCS)",
mme_ue->imsi_bcd,
mme_ue->nas_eps.update.active_flag);
mme_send_delete_session_or_tau_accept(enb_ue, mme_ue);
} else {
ogs_info("[%s] LU accept + TAU accept(active_flag=%d, No BCS)",
mme_ue->imsi_bcd,
mme_ue->nas_eps.update.active_flag);
r = nas_eps_send_tau_accept(mme_ue,
mme_ue->nas_eps.update.active_flag ?
S1AP_ProcedureCode_id_InitialContextSetup :
S1AP_ProcedureCode_id_downlinkNASTransport);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_info("[%s] LU accept + TAU accept"
"(WITH Bearer Context Status)",
mme_ue->imsi_bcd);
mme_send_delete_session_or_tau_accept(enb_ue, mme_ue);
}
} else if (mme_ue->tracking_area_update_request_type ==
MME_TAU_TYPE_UPLINK_NAS_TRANPORT) {
@@ -359,31 +360,30 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
ogs_kdf_nh_enb(mme_ue->kasme, mme_ue->kenb, mme_ue->nh);
mme_ue->nhcc = 1;
ogs_fatal("[%s] LU reject + TAU accept(active_flag==1)",
mme_ue->imsi_bcd);
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_InitialContextSetup);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else if (!(mme_ue->tracking_area_update_request_presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE)) {
ogs_fatal("[%s] LU reject + TAU accept"
"(NO Bearer Context Status)",
mme_ue->imsi_bcd);
ogs_info("[%s] KDF update(active_flag=1)", mme_ue->imsi_bcd);
}
/* check BCS regardless of active_flag */
if (mme_ue->tracking_area_update_request_presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_TYPE) {
ogs_info("[%s] LU reject + TAU accept(active_flag=%d, BCS)",
mme_ue->imsi_bcd,
mme_ue->nas_eps.update.active_flag);
mme_send_delete_session_or_tau_accept(enb_ue, mme_ue);
} else {
ogs_info("[%s] LU reject + TAU accept(active_flag=%d, No BCS)",
mme_ue->imsi_bcd,
mme_ue->nas_eps.update.active_flag);
r = nas_eps_send_tau_accept(mme_ue,
mme_ue->nas_eps.update.active_flag ?
S1AP_ProcedureCode_id_InitialContextSetup :
S1AP_ProcedureCode_id_downlinkNASTransport);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_fatal("[%s] LU reject + TAU accept"
"(WITH Bearer Context Status)",
mme_ue->imsi_bcd);
mme_send_delete_session_or_tau_accept(enb_ue, mme_ue);
}
} else if (mme_ue->tracking_area_update_request_type ==
MME_TAU_TYPE_UPLINK_NAS_TRANPORT) {
ogs_debug(" Uplink NAS Transport");
ogs_fatal("[%s] LU reject + TAU accept(UplinkNASTransport)",
ogs_info("[%s] LU reject + TAU accept(UplinkNASTransport)",
mme_ue->imsi_bcd);
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_downlinkNASTransport);
@@ -391,9 +391,8 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
ogs_assert(r != OGS_ERROR);
} else if (mme_ue->tracking_area_update_request_type ==
MME_TAU_TYPE_UNPROTECTED_INTEGRITY) {
ogs_fatal("[%s] LU reject + TAU accept(Unprotected Integrity)",
ogs_info("[%s] LU reject + TAU accept(Unprotected Integrity)",
mme_ue->imsi_bcd);
ogs_debug(" Unprotected Integrity");
r = nas_eps_send_tau_accept(mme_ue,
S1AP_ProcedureCode_id_InitialContextSetup);
ogs_expect(r == OGS_OK);
@@ -414,7 +413,6 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
*/
if (!mme_ue->nas_eps.update.active_flag &&
!MME_NEXT_P_TMSI_IS_AVAILABLE(mme_ue)) {
ogs_fatal("NEXT = %d", MME_NEXT_P_TMSI_IS_AVAILABLE(mme_ue));
enb_ue->relcause.group = S1AP_Cause_PR_nas;
enb_ue->relcause.cause = S1AP_CauseNas_normal_release;
mme_send_release_access_bearer_or_ue_context_release(enb_ue);