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