From fd897f35a3994e775edf81bf2263732e52aff205 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Thu, 16 Oct 2025 21:45:09 +0900 Subject: [PATCH] MME: handle EPS Bearer Context Status mismatch when active_flag=0 (#4112) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the UE sends a Tracking Area Update (TAU) Request with active_flag=0, the MME previously sent TAU Accept without verifying the EPS Bearer Context Status (EBCS). This caused stale bearer sessions to remain in the MME even if the UE had already released them. According to 3GPP TS 24.301 §5.5.3.2, the MME should release any bearer not reported in the UE’s EBCS when active_flag=0. This patch introduces mme_send_delete_session_or_tau_accept(), which compares the UE’s EBCS bitmask with the MME session list and deletes any missing default bearer session before sending TAU Accept. If no mismatch is found, TAU Accept is sent immediately. The Delete Session response triggers TAU Accept when deletions are required. This ensures that the TAU Accept message reflects the UE’s current bearer context accurately. Also includes: - Added OGS_GTP_DELETE_SEND_TAU_ACCEPT handling in mme-s11-handler.c - Simplified EBCS structure (uint16_t value) for bitmask comparison - Updated TAU-related tests with realistic EBI bitmasks (0x20, 0x60) This change aligns TAU handling with 3GPP 24.301 and prevents bearer mismatch issues between UE and EPC during TAU. --- lib/gtp/xact.h | 1 + lib/nas/common/types.h | 37 ++-- src/mme/emm-sm.c | 21 ++- src/mme/mme-context.h | 5 +- src/mme/mme-path.c | 68 ++++++++ src/mme/mme-path.h | 2 + src/mme/mme-s11-handler.c | 16 ++ src/mme/mme-s6a-handler.c | 3 +- src/mme/sgsap-handler.c | 39 ++++- tests/attach/crash-test.c | 2 +- tests/attach/guti-test.c | 4 +- tests/attach/idle-test.c | 6 +- tests/common/context.h | 3 +- tests/common/emm-build.c | 12 +- tests/csfb/tau-test.c | 9 +- tests/handover/epc-s1-test.c | 3 +- tests/volte/session-test.c | 325 +++++++++++++++++++++++++++++++++++ 17 files changed, 508 insertions(+), 48 deletions(-) diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 56f105644..9a0779e70 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -133,6 +133,7 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_DELETE_SEND_RELEASE_WITH_S1_REMOVE_AND_UNLINK 6 #define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 7 #define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 8 +#define OGS_GTP_DELETE_SEND_TAU_ACCEPT 9 int delete_action; diff --git a/lib/nas/common/types.h b/lib/nas/common/types.h index cac70a6f0..70afe0c33 100644 --- a/lib/nas/common/types.h +++ b/lib/nas/common/types.h @@ -90,22 +90,27 @@ typedef struct ogs_nas_additional_information_s { * O TLV 4 */ typedef struct ogs_nas_eps_bearer_context_status_s { uint8_t length; -ED8(uint8_t ebi7:1;, - uint8_t ebi6:1;, - uint8_t ebi5:1;, - uint8_t ebi4:1;, - uint8_t ebi3:1;, - uint8_t ebi2:1;, - uint8_t ebi1:1;, - uint8_t ebi0:1;) -ED8(uint8_t ebi15:1;, - uint8_t ebi14:1;, - uint8_t ebi13:1;, - uint8_t ebi12:1;, - uint8_t ebi11:1;, - uint8_t ebi10:1;, - uint8_t ebi9:1;, - uint8_t ebi8:1;) + union { + struct { + ED8(uint8_t ebi7:1;, + uint8_t ebi6:1;, + uint8_t ebi5:1;, + uint8_t ebi4:1;, + uint8_t ebi3:1;, + uint8_t ebi2:1;, + uint8_t ebi1:1;, + uint8_t ebi0:1;) + ED8(uint8_t ebi15:1;, + uint8_t ebi14:1;, + uint8_t ebi13:1;, + uint8_t ebi12:1;, + uint8_t ebi11:1;, + uint8_t ebi10:1;, + uint8_t ebi9:1;, + uint8_t ebi8:1;) + }; + uint16_t value; + }; } __attribute__ ((packed)) ogs_nas_eps_bearer_context_status_t; typedef struct ogs_nas_mobile_identity_imeisv_s { diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 764106b9c..c1cea2deb 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -675,6 +675,13 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e, * 10. UplinkNASTransport + Tracking area update complete (Target) */ + /* Save tau-request message */ + mme_ue->tracking_area_update_request_presencemask = + message->emm.tracking_area_update_request.presencemask; + mme_ue->tracking_area_update_request_ebcs_value = + message->emm.tracking_area_update_request. + eps_bearer_context_status.value; + /* Update CSMAP from Tracking area update request */ mme_ue->csmap = mme_csmap_find_by_tai(&mme_ue->tai); if (mme_ue->csmap && @@ -722,19 +729,29 @@ 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 { + } 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)", + mme_ue->imsi_bcd); r = nas_eps_send_tau_accept(mme_ue, 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) { - ogs_debug(" Uplink NAS Transport"); + ogs_info("[%s] TAU accept(UplinkNASTransport)", + mme_ue->imsi_bcd); r = nas_eps_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_downlinkNASTransport); ogs_expect(r == OGS_OK); diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 669832dd2..586a2e566 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -433,8 +433,10 @@ struct mme_ue_s { #define MME_TAU_TYPE_INITIAL_UE_MESSAGE 1 #define MME_TAU_TYPE_UPLINK_NAS_TRANPORT 2 -#define MME_TAU_TYPE_UNPROTECTED_INGERITY 3 +#define MME_TAU_TYPE_UNPROTECTED_INTEGRITY 3 uint8_t tracking_area_update_request_type; + uint64_t tracking_area_update_request_presencemask; + uint16_t tracking_area_update_request_ebcs_value; /* 1. MME initiated detach request to the UE. * (nas_eps.type = MME_EPS_TYPE_DETACH_REQUEST_TO_UE) @@ -799,6 +801,7 @@ struct mme_ue_s { #define GTP_COUNTER_CREATE_SESSION_BY_PATH_SWITCH 1 #define GTP_COUNTER_DELETE_SESSION_BY_PATH_SWITCH 2 +#define GTP_COUNTER_DELETE_SESSION_BY_TAU 3 struct { uint8_t request; uint8_t response; diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index 7a9d813d8..0d020523a 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -325,3 +325,71 @@ cleanup: if (failed) mme_ue->paging.failed = true; } + +/* ---------------------------------------------------------------------- + * Function: mme_send_delete_session_or_tau_accept + * ---------------------------------------------------------------------- + * - If active_flag == 0, check UE's EPS Bearer Context Status (BCS) + * 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. + * ---------------------------------------------------------------------- */ +void mme_send_delete_session_or_tau_accept(enb_ue_t *enb_ue, mme_ue_t *mme_ue) +{ + int r; + sgw_ue_t *sgw_ue = NULL; + mme_sess_t *sess = NULL; + mme_bearer_t *def = NULL; + + uint16_t mask; + uint8_t ebi; + int deleted = 0; + + ogs_assert(enb_ue); + ogs_assert(mme_ue); + + mask = mme_ue->tracking_area_update_request_ebcs_value; + + ogs_list_for_each(&mme_ue->sess_list, sess) { + def = mme_default_bearer_in_sess(sess); + if (!def) { + ogs_warn("[%s] No default bearer; skip session", mme_ue->imsi_bcd); + continue; + } + + ebi = def->ebi; + if (ebi > 15) { + ogs_warn("[%s] Invalid EBI=%u; skip", mme_ue->imsi_bcd, ebi); + continue; + } + + /* If UE's BCS bit for this EBI is 0, + * delete the session */ + if (!(mask & (1 << ebi))) { + ogs_warn("[%s] BCS mismatch: UE missing EBI=%u", + mme_ue->imsi_bcd, ebi); + sgw_ue = sgw_ue_find_by_id(mme_ue->sgw_ue_id); + ogs_assert(sgw_ue); + + GTP_COUNTER_INCREMENT( + mme_ue, GTP_COUNTER_DELETE_SESSION_BY_TAU); + + mme_gtp_send_delete_session_request( + enb_ue, sgw_ue, sess, + OGS_GTP_DELETE_SEND_TAU_ACCEPT); + + deleted++; + } + } + + if (deleted > 0) { + ogs_warn("[%s] Deleted %d session(s) due to BCS mismatch", + mme_ue->imsi_bcd, deleted); + } else { + ogs_info("[%s] TAU accept(BCS match)", mme_ue->imsi_bcd); + r = nas_eps_send_tau_accept(mme_ue, + S1AP_ProcedureCode_id_downlinkNASTransport); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } +} diff --git a/src/mme/mme-path.h b/src/mme/mme-path.h index 10f8fe64c..9a34ba532 100644 --- a/src/mme/mme-path.h +++ b/src/mme/mme-path.h @@ -33,6 +33,8 @@ void mme_send_release_access_bearer_or_ue_context_release(enb_ue_t *enb_ue); void mme_send_after_paging(mme_ue_t *mme_ue, bool failed); +void mme_send_delete_session_or_tau_accept(enb_ue_t *enb_ue, mme_ue_t *mme_ue); + #ifdef __cplusplus } #endif diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index df639c34c..f65665f6f 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -880,6 +880,22 @@ void mme_s11_handle_delete_session_response( return; + } else if (action == OGS_GTP_DELETE_SEND_TAU_ACCEPT) { + + MME_SESS_CLEAR(sess); + + GTP_COUNTER_CHECK(mme_ue, GTP_COUNTER_DELETE_SESSION_BY_TAU, + + ogs_info("[%s] TAU accept(BCS mismatch)", mme_ue->imsi_bcd); + r = nas_eps_send_tau_accept(mme_ue, + S1AP_ProcedureCode_id_downlinkNASTransport); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + + ); + + return; + } else { ogs_fatal("Invalid action = %d", action); ogs_assert_if_reached(); diff --git a/src/mme/mme-s6a-handler.c b/src/mme/mme-s6a-handler.c index 8a3065f2d..589f654aa 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -138,10 +138,11 @@ uint8_t mme_s6a_handle_ula( OGS_NAS_EPS_UPDATE_TYPE_COMBINED_TA_LA_UPDATING_WITH_IMSI_ATTACH)) { mme_ue->tracking_area_update_request_type = - MME_TAU_TYPE_UNPROTECTED_INGERITY; + MME_TAU_TYPE_UNPROTECTED_INTEGRITY; ogs_assert(OGS_OK == sgsap_send_location_update_request(mme_ue)); } else { + ogs_info("[%s] TAU accept(Diameter ULA)", mme_ue->imsi_bcd); r = nas_eps_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_InitialContextSetup); ogs_expect(r == OGS_OK); diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index a30e681a7..639ba6261 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -150,26 +150,38 @@ 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 { + } 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); r = nas_eps_send_tau_accept(mme_ue, 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) { - ogs_debug(" Uplink NAS Transport"); + ogs_info("[%s] LU accept + accept(UplinkNASTransport)", + mme_ue->imsi_bcd); r = nas_eps_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_downlinkNASTransport); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } else if (mme_ue->tracking_area_update_request_type == - MME_TAU_TYPE_UNPROTECTED_INGERITY) { - ogs_debug(" Unprotected Integrity"); + MME_TAU_TYPE_UNPROTECTED_INTEGRITY) { + ogs_info("[%s] LU accept + TAU accept(Unprotected Integrity)", + mme_ue->imsi_bcd); r = nas_eps_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_InitialContextSetup); ogs_expect(r == OGS_OK); @@ -347,25 +359,40 @@ 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 { + } 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); r = nas_eps_send_tau_accept(mme_ue, 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)", + mme_ue->imsi_bcd); r = nas_eps_send_tau_accept(mme_ue, S1AP_ProcedureCode_id_downlinkNASTransport); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } else if (mme_ue->tracking_area_update_request_type == - MME_TAU_TYPE_UNPROTECTED_INGERITY) { + MME_TAU_TYPE_UNPROTECTED_INTEGRITY) { + ogs_fatal("[%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); diff --git a/tests/attach/crash-test.c b/tests/attach/crash-test.c index af6a69408..d71699c43 100644 --- a/tests/attach/crash-test.c +++ b/tests/attach/crash-test.c @@ -304,7 +304,7 @@ static void test4_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.ebcs_value = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; diff --git a/tests/attach/guti-test.c b/tests/attach/guti-test.c index fa6150b96..a283e098d 100644 --- a/tests/attach/guti-test.c +++ b/tests/attach/guti-test.c @@ -1065,7 +1065,7 @@ static void test3_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; @@ -1165,7 +1165,7 @@ static void test3_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; diff --git a/tests/attach/idle-test.c b/tests/attach/idle-test.c index b54835f6d..baa515a3f 100644 --- a/tests/attach/idle-test.c +++ b/tests/attach/idle-test.c @@ -241,7 +241,7 @@ static void test1_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; @@ -287,7 +287,7 @@ static void test1_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; @@ -527,7 +527,7 @@ static void test2_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; diff --git a/tests/common/context.h b/tests/common/context.h index 4fc63cf80..c9d5fed00 100644 --- a/tests/common/context.h +++ b/tests/common/context.h @@ -177,7 +177,7 @@ typedef struct test_attach_request_param_s { typedef struct test_tau_request_param_s { struct { ED8(uint8_t ue_network_capability:1;, - uint8_t eps_bearer_context_status:1;, + uint8_t reserved:1;, uint8_t guti:1;, uint8_t last_visited_registered_tai:1;, uint8_t drx_parameter:1;, @@ -200,6 +200,7 @@ typedef struct test_tau_request_param_s { uint8_t device_properties:1;, uint8_t spare2:6;) }; + uint8_t eps_bearer_context_status; } __attribute__ ((packed)) test_tau_request_param_t; typedef struct test_service_request_param_s { diff --git a/tests/common/emm-build.c b/tests/common/emm-build.c index 261ad5a2b..6dc4505b2 100644 --- a/tests/common/emm-build.c +++ b/tests/common/emm-build.c @@ -649,20 +649,12 @@ ogs_pkbuf_t *testemm_build_tau_request( } if (test_ue->tau_request_param.eps_bearer_context_status) { - test_sess_t *sess = NULL; - test_bearer_t *bearer = NULL; - tau_request->presencemask |= OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT; eps_bearer_context_status->length = 2; - ogs_list_for_each(&test_ue->sess_list, sess) { - ogs_list_for_each(&sess->bearer_list, bearer) { - if (bearer->ebi == 5) eps_bearer_context_status->ebi5 = 1; - else if (bearer->ebi == 6) eps_bearer_context_status->ebi6 = 1; - else if (bearer->ebi == 7) eps_bearer_context_status->ebi7 = 1; - } - } + eps_bearer_context_status->value = + test_ue->tau_request_param.eps_bearer_context_status; } if (test_ue->tau_request_param.ms_network_capability) { diff --git a/tests/csfb/tau-test.c b/tests/csfb/tau-test.c index 7c42303e3..deec3a6e2 100644 --- a/tests/csfb/tau-test.c +++ b/tests/csfb/tau-test.c @@ -215,7 +215,7 @@ static void test_simple_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; @@ -493,7 +493,7 @@ static void test_no_active_flag_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; @@ -773,7 +773,7 @@ static void test_integrity_unprotected_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = 0x20; /* EBI:5 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; @@ -1289,7 +1289,8 @@ static void test_uplink_transport_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = + 0x60; /* EBI:5, EBI:6 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; diff --git a/tests/handover/epc-s1-test.c b/tests/handover/epc-s1-test.c index ca2d205e4..6bc48b36c 100644 --- a/tests/handover/epc-s1-test.c +++ b/tests/handover/epc-s1-test.c @@ -393,7 +393,8 @@ static void test1_func(abts_case *tc, void *data) test_ue->tau_request_param.ue_network_capability = 1; test_ue->tau_request_param.last_visited_registered_tai = 1; test_ue->tau_request_param.drx_parameter = 1; - test_ue->tau_request_param.eps_bearer_context_status = 1; + test_ue->tau_request_param.eps_bearer_context_status = + 0x60; /* EBI:5, EBI:6 */ test_ue->tau_request_param.ms_network_capability = 1; test_ue->tau_request_param.tmsi_status = 1; test_ue->tau_request_param.mobile_station_classmark_2 = 1; diff --git a/tests/volte/session-test.c b/tests/volte/session-test.c index 7867c462d..aaa14c588 100644 --- a/tests/volte/session-test.c +++ b/tests/volte/session-test.c @@ -364,11 +364,336 @@ static void test1_func(abts_case *tc, void *data) test_ue_remove(test_ue); } +static void test2_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *emmbuf; + ogs_pkbuf_t *esmbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_s1ap_message_t message; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *bearer = NULL; + + uint32_t enb_ue_s1ap_id; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_PROTECTION_SCHEME_NULL; + mobile_identity_suci.home_network_pki_value = 0; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, "1032548691"); + ogs_assert(test_ue); + + test_ue->e_cgi.cell_id = 0x1079baf; + test_ue->nas.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + sess = test_sess_add_by_apn(test_ue, "internet", OGS_GTP2_RAT_TYPE_EUTRAN); + ogs_assert(sess); + + /* eNB connects to MME */ + s1ap = tests1ap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* eNB connects to SGW */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send S1-Setup Reqeust */ + sendbuf = test_s1ap_build_s1_setup_request( + S1AP_ENB_ID_PR_macroENB_ID, 0x54f64); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(NULL, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_session(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Attach Request */ + memset(&sess->pdn_connectivity_param, + 0, sizeof(sess->pdn_connectivity_param)); + sess->pdn_connectivity_param.eit = 1; + sess->pdn_connectivity_param.request_type = + OGS_NAS_EPS_REQUEST_TYPE_INITIAL; + esmbuf = testesm_build_pdn_connectivity_request( + sess, false, OGS_NAS_EPS_PDN_TYPE_IPV4V6); + ABTS_PTR_NOTNULL(tc, esmbuf); + + memset(&test_ue->attach_request_param, + 0, sizeof(test_ue->attach_request_param)); + test_ue->attach_request_param.drx_parameter = 1; + test_ue->attach_request_param.ms_network_capability = 1; + test_ue->attach_request_param.tmsi_status = 1; + test_ue->attach_request_param.mobile_station_classmark_2 = 1; + test_ue->attach_request_param.ue_usage_setting = 1; + emmbuf = testemm_build_attach_request(test_ue, esmbuf, true, false); + ABTS_PTR_NOTNULL(tc, emmbuf); + + memset(&test_ue->initial_ue_param, 0, sizeof(test_ue->initial_ue_param)); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, false); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + emmbuf = testemm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + test_ue->mobile_identity_imeisv_presence = true; + emmbuf = testemm_build_security_mode_complete(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send ESM Information Response */ + sess->esm_information_param.pco = 1; + esmbuf = testesm_build_esm_information_response(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Capability Info Indication */ + sendbuf = tests1ap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Initial Context Setup Response */ + sendbuf = test_s1ap_build_initial_context_setup_response(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + test_ue->nr_cgi.cell_id = 0x1234502; + bearer = test_bearer_find_by_ue_ebi(test_ue, 5); + ogs_assert(bearer); + esmbuf = testesm_build_activate_default_eps_bearer_context_accept( + bearer, false); + ABTS_PTR_NOTNULL(tc, esmbuf); + emmbuf = testemm_build_attach_complete(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send PDN Connectivity Request */ + sess = test_sess_add_by_apn(test_ue, "ims", OGS_GTP2_RAT_TYPE_EUTRAN); + ogs_assert(sess); + sess->pti = 5; + + sess->pdn_connectivity_param.apn = 1; + sess->pdn_connectivity_param.pco = 1; + sess->pdn_connectivity_param.request_type = + OGS_NAS_EPS_REQUEST_TYPE_INITIAL; + esmbuf = testesm_build_pdn_connectivity_request( + sess, true, OGS_NAS_EPS_PDN_TYPE_IPV4V6); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RABSetupRequest + + * Activate default EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + S1AP_ProcedureCode_id_E_RABSetup, + test_ue->s1ap_procedure_code); + + /* Send E-RABSetupResponse */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 6); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate default EPS bearer context accept */ + esmbuf = testesm_build_activate_default_eps_bearer_context_accept( + bearer, true); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RABSetupRequest + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + S1AP_ProcedureCode_id_E_RABSetup, + test_ue->s1ap_procedure_code); + + /* Send Activate dedicated EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RABSetupResponse */ + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send TAU Request */ + memset(&test_ue->tau_request_param, 0, sizeof(test_ue->tau_request_param)); + test_ue->tau_request_param.ue_network_capability = 1; + test_ue->tau_request_param.last_visited_registered_tai = 1; + test_ue->tau_request_param.drx_parameter = 1; + test_ue->tau_request_param.eps_bearer_context_status = + 0x20; /* EBI:5-ACTIVE, EBI:6-Inactive, EBI:7-Inactive */ + test_ue->tau_request_param.ms_network_capability = 1; + test_ue->tau_request_param.tmsi_status = 1; + test_ue->tau_request_param.mobile_station_classmark_2 = 1; + test_ue->tau_request_param.ue_usage_setting = 1; + test_ue->tau_request_param.device_properties = 1; + emmbuf = testemm_build_tau_request( + test_ue, false, + OGS_NAS_EPS_UPDATE_TYPE_COMBINED_TA_LA_UPDATING_WITH_IMSI_ATTACH, + true, true); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive OLD UEContextReleaseCommand */ + 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 UEContextReleaseComplete */ + 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; + + /* Receive TAU Accept */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive UEContextReleaseCommand */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send UEContextReleaseComplete */ + 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); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); + + /* eNB disonncect from SGW */ + test_gtpu_close(gtpu); + + test_ue_remove(test_ue); +} + abts_suite *test_session(abts_suite *suite) { suite = ADD_SUITE(suite) abts_run_test(suite, test1_func, NULL); + abts_run_test(suite, test2_func, NULL); return suite; }