diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 6d76dad52..711c2824d 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -86,6 +86,13 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_MODIFY_TFT_UPDATE ((uint64_t)1<<0) #define OGS_GTP_MODIFY_QOS_UPDATE ((uint64_t)1<<1) uint64_t update_flags; + +#define OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST 1 +#define OGS_GTP_DELETE_SEND_DETACH_ACCEPT 2 +#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 3 +#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4 +#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5 + int delete_action; } ogs_gtp_xact_t; int ogs_gtp_xact_init(void); diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index d403370ff..0cc32f590 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -180,7 +180,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue); + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); } else { mme_s6a_send_air(mme_ue, NULL); } @@ -204,20 +205,26 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) } if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(mme_ue)) { - rv = nas_eps_send_emm_to_esm(mme_ue, - &mme_ue->pdn_connectivity_request); - if (rv != OGS_OK) { - ogs_error("nas_eps_send_emm_to_esm() failed"); - nas_eps_send_attach_reject(mme_ue, - EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, - ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - OGS_FSM_TRAN(s, &emm_state_exception); + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST); } else { - OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + rv = nas_eps_send_emm_to_esm(mme_ue, + &mme_ue->pdn_connectivity_request); + if (rv != OGS_OK) { + ogs_error("nas_eps_send_emm_to_esm() failed"); + nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, + ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + } } + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); } else { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue); + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); } else { mme_s6a_send_air(mme_ue, NULL); } @@ -874,7 +881,8 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) break; } - mme_gtp_send_delete_all_sessions(mme_ue); + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); OGS_FSM_TRAN(s, &emm_state_authentication); break; case OGS_NAS_EPS_EMM_STATUS: @@ -971,20 +979,26 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) } if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(mme_ue)) { - rv = nas_eps_send_emm_to_esm(mme_ue, - &mme_ue->pdn_connectivity_request); - if (rv != OGS_OK) { - ogs_error("nas_eps_send_emm_to_esm() failed"); - nas_eps_send_attach_reject(mme_ue, - EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, - ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); - OGS_FSM_TRAN(s, &emm_state_exception); + if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST); } else { - OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + rv = nas_eps_send_emm_to_esm(mme_ue, + &mme_ue->pdn_connectivity_request); + if (rv != OGS_OK) { + ogs_error("nas_eps_send_emm_to_esm() failed"); + nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, + ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + OGS_FSM_TRAN(s, &emm_state_exception); + break; + } } + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); } else { if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue); + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST); } else { mme_s6a_send_air(mme_ue, NULL); } diff --git a/src/mme/esm-build.c b/src/mme/esm-build.c index 6901dd6ae..b1e50b913 100644 --- a/src/mme/esm-build.c +++ b/src/mme/esm-build.c @@ -121,6 +121,7 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request( ogs_assert(pdn); bearer = mme_default_bearer_in_sess(sess); ogs_assert(bearer); + ogs_assert(mme_bearer_next(bearer) == NULL); ogs_debug("Activate default bearer context request"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index ab1c3f8b4..0e42cd64c 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -212,7 +212,8 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e) ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", mme_ue->imsi_bcd, sess->pti, bearer->ebi); if (MME_HAVE_SGW_S1U_PATH(sess)) { - mme_gtp_send_delete_session_request(sess); + mme_gtp_send_delete_session_request(sess, + OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST); } else { nas_eps_send_deactivate_bearer_context_request(bearer); } diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index f06924b79..12752a6bb 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -218,7 +218,7 @@ void mme_gtp_send_modify_bearer_request( ogs_expect(rv == OGS_OK); } -void mme_gtp_send_delete_session_request(mme_sess_t *sess) +void mme_gtp_send_delete_session_request(mme_sess_t *sess, int action) { int rv; ogs_pkbuf_t *s11buf = NULL; @@ -226,6 +226,7 @@ void mme_gtp_send_delete_session_request(mme_sess_t *sess) ogs_gtp_xact_t *xact = NULL; mme_ue_t *mme_ue = NULL; + ogs_assert(action); ogs_assert(sess); mme_ue = sess->mme_ue; ogs_assert(mme_ue); @@ -239,16 +240,18 @@ void mme_gtp_send_delete_session_request(mme_sess_t *sess) xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, s11buf, timeout, sess); ogs_expect_or_return(xact); + xact->delete_action = action; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); } -void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue) +void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action) { mme_sess_t *sess = NULL, *next_sess = NULL; ogs_assert(mme_ue); + ogs_assert(action); if (SESSION_CONTEXT_WILL_DELETED(mme_ue)) { ogs_warn("[%s] Delete-Session-Request has already sent", @@ -270,7 +273,7 @@ void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue) OGS_FSM_CHECK(&bearer->sm, esm_state_pdn_will_disconnect)) { ogs_warn("PDN will disconnect[EBI:%d]", bearer->ebi); } else { - mme_gtp_send_delete_session_request(sess); + mme_gtp_send_delete_session_request(sess, action); } } else { mme_sess_remove(sess); diff --git a/src/mme/mme-gtp-path.h b/src/mme/mme-gtp-path.h index 76ae61ebc..4362b10e3 100644 --- a/src/mme/mme-gtp-path.h +++ b/src/mme/mme-gtp-path.h @@ -32,8 +32,8 @@ void mme_gtp_close(void); void mme_gtp_send_create_session_request(mme_sess_t *sess); void mme_gtp_send_modify_bearer_request( mme_bearer_t *bearer, int uli_presence); -void mme_gtp_send_delete_session_request(mme_sess_t *sess); -void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue); +void mme_gtp_send_delete_session_request(mme_sess_t *sess, int action); +void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action); void mme_gtp_send_create_bearer_response(mme_bearer_t *bearer); void mme_gtp_send_update_bearer_response(mme_bearer_t *bearer); void mme_gtp_send_delete_bearer_response(mme_bearer_t *bearer); diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index bc71d522c..6398a6639 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -27,7 +27,8 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) ogs_assert(mme_ue); if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue); + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_DETACH_ACCEPT); } else { nas_eps_send_detach_accept(mme_ue); } @@ -38,7 +39,8 @@ void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue) ogs_assert(mme_ue); if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue); + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND); } else { enb_ue_t *enb_ue = mme_ue->enb_ue; if (enb_ue) { diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 55639fb2e..2cb6d02bb 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -267,10 +267,13 @@ void mme_s11_handle_delete_session_response( { int rv; uint8_t cause_value = 0; + int action = 0; mme_sess_t *sess = NULL; ogs_assert(xact); ogs_assert(rsp); + action = xact->delete_action; + ogs_assert(action); ogs_debug("[MME] Delete Session Response"); @@ -294,56 +297,32 @@ void mme_s11_handle_delete_session_response( ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]", mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid); - if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_authentication)) { + if (action == OGS_GTP_DELETE_SEND_AUTHENTICATION_REUQEST) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { mme_s6a_send_air(mme_ue, NULL); } - } else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) { + + } else if (action == OGS_GTP_DELETE_SEND_DETACH_ACCEPT) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { nas_eps_send_detach_accept(mme_ue); } - } else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) { + + } else if (action == + OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST) { mme_bearer_t *bearer = mme_default_bearer_in_sess(sess); ogs_expect_or_return(bearer); - if (OGS_FSM_CHECK(&bearer->sm, esm_state_pdn_will_disconnect)) { - nas_eps_send_deactivate_bearer_context_request(bearer); - - /* - * mme_sess_remove() should not be called here. - * - * Session will be removed if Deactivate bearer context - * accept is received */ - CLEAR_SGW_S1U_PATH(sess); - return; - } else if (OGS_FSM_CHECK(&bearer->sm, esm_state_active) || - /* - * MME sends InitialContextSetupRequest to eNB. - * eNB sends InitialContextSetupFailure to MME. - * - * In this case, ESM state is INACTIVE. - * - * So, if Delete-Session-Response is received, - * MME needs to send UEContextReleaseCommand to eNB. - */ - OGS_FSM_CHECK(&bearer->sm, esm_state_inactive)) { + nas_eps_send_deactivate_bearer_context_request(bearer); - if (mme_sess_count(mme_ue) == 1) /* Last Session */ { - enb_ue_t *enb_ue = NULL; + /* + * mme_sess_remove() should not be called here. + * + * if Deactivate bearer context accept is received, + * Session will be removed */ + CLEAR_SGW_S1U_PATH(sess); + return; - enb_ue = mme_ue->enb_ue; - if (enb_ue) { - s1ap_send_ue_context_release_command(enb_ue, - S1AP_Cause_PR_nas, S1AP_CauseNas_normal_release, - S1AP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0); - } else - ogs_warn("ENB-S1 Context has already been removed"); - } - } else - ogs_assert_if_reached(); - - } else if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_initial_context_setup) || - OGS_FSM_CHECK(&mme_ue->sm, emm_state_exception)) { + } else if (action == OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND) { if (mme_sess_count(mme_ue) == 1) /* Last Session */ { enb_ue_t *enb_ue = NULL; @@ -355,8 +334,23 @@ void mme_s11_handle_delete_session_response( } else ogs_warn("ENB-S1 Context has already been removed"); } - } else + + } else if (action == OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST) { + if (mme_sess_count(mme_ue) == 1) /* Last Session */ { + rv = nas_eps_send_emm_to_esm(mme_ue, + &mme_ue->pdn_connectivity_request); + if (rv != OGS_OK) { + ogs_error("nas_eps_send_emm_to_esm() failed"); + nas_eps_send_attach_reject(mme_ue, + EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, + ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED); + } + } + + } else { + ogs_fatal("Invalid action = %d", action); ogs_assert_if_reached(); + } if (mme_sess_count(mme_ue) == 1) /* Last Session */ CLEAR_SESSION_CONTEXT(mme_ue); diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index 2d8543554..c3cb4eded 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -104,8 +104,10 @@ void nas_eps_send_attach_accept(mme_ue_t *mme_ue) ogs_assert(mme_ue); sess = mme_sess_first(mme_ue); ogs_assert(sess); + ogs_assert(mme_sess_next(sess) == NULL); bearer = mme_default_bearer_in_sess(sess); ogs_assert(bearer); + ogs_assert(mme_bearer_next(bearer) == NULL); esmbuf = esm_build_activate_default_bearer_context_request(sess); ogs_expect_or_return(esmbuf); diff --git a/tests/volte/rx-test.c b/tests/volte/rx-test.c index c60ef3f18..2f8250c04 100644 --- a/tests/volte/rx-test.c +++ b/tests/volte/rx-test.c @@ -1433,6 +1433,7 @@ static void test3_func(abts_case *tc, void *data) /* DELAY is needed for receiving AA-Answer */ ogs_msleep(100); + /* Send Session-Termination-Request */ pcscf_rx_send_str(rx_sid); /* DELAY is needed for receiving Session-Termination-Answer */ @@ -1565,6 +1566,544 @@ static void test3_func(abts_case *tc, void *data) test_ue_remove(test_ue); } +static void test4_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; + + uint8_t *rx_sid = NULL; + + 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; + uint64_t mme_ue_s1ap_id; + + const char *_k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "e8ed289deba952e4283b54e88e6183ca"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"001010123456819\", " + "\"pdn\" : [" + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd32\" }," + "\"apn\" : \"internet\"," + "\"qos\" : {" + "\"qci\" : 9," + "\"arp\" : {" + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1" + "}" + "}," + "\"type\" : 2" + "}," + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"apn\" : \"ims\", " + "\"pcc_rule\" : [" + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2d\" }," + "\"qos\" : {" + "\"qci\" : 1," + "\"gbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"64\" }," + "\"uplink\" : { \"$numberLong\" : \"44\" }" + "}," + "\"mbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"64\" }," + "\"uplink\" : { \"$numberLong\" : \"44\" }" + "}," + "\"arp\" : {" + "\"priority_level\" : 3," + "\"pre_emption_vulnerability\" : 0," + "\"pre_emption_capability\" : 0 }" + "}" + "}" + "]," + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 5, " + "\"arp\" : { " + "\"priority_level\" : 1," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"465B5CE8 B199B49F AA5F0A2E E238A6BC\", " + "\"opc\" : \"E8ED289D EBA952E4 283B54E8 8E6183CA\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"64\" } " + "}, " + "\"__v\" : 0 " + "}"; + + /* 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_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0x10; + mobile_identity_suci.scheme_output[1] = 0x32; + mobile_identity_suci.scheme_output[2] = 0x54; + mobile_identity_suci.scheme_output[3] = 0x86; + mobile_identity_suci.scheme_output[4] = 0x91; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->e_cgi.cell_id = 0x1079baf; + test_ue->nas.ksi = 0; + test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH; + + OGS_HEX(_k_string, strlen(_k_string), test_ue->k); + OGS_HEX(_opc_string, strlen(_opc_string), test_ue->opc); + + sess = test_sess_add_by_apn(test_ue, "internet"); + 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 */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + do { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /* Send Attach Request */ + memset(&sess->pdn_connectivity_param, + 0, sizeof(sess->pdn_connectivity_param)); + sess->pdn_connectivity_param.eit = 1; + esmbuf = testesm_build_pdn_connectivity_request(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + + memset(&test_ue->attach_request_param, + 0, sizeof(test_ue->attach_request_param)); + test_ue->attach_request_param.integrity_protected = 1; + 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); + 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 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 PDN Connectivity Request */ + sess = test_sess_add_by_apn(test_ue, "ims"); + ogs_assert(sess); + sess->pti = 9; + + sess->pdn_connectivity_param.integrity_protected = 1; + sess->pdn_connectivity_param.ciphered = 1; + sess->pdn_connectivity_param.apn = 1; + sess->pdn_connectivity_param.pco = 1; + esmbuf = testesm_build_pdn_connectivity_request(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 E-RAB Setup Request + + * Activate default EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + 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); + + /* DELAY is needed in default EPS bearer */ + ogs_msleep(100); + + /* Send AA-Request */ + sess = test_sess_find_by_apn(test_ue, "ims"); + ogs_assert(sess); + pcscf_rx_send_aar_audio(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + 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 dedicated EPS bearer context accept */ + 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); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + esmbuf = testesm_build_deactivate_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); + + /* DELAY is needed in deactivate EPS bearer */ + ogs_msleep(100); + + /* Send UE Context Release Request */ + sendbuf = test_s1ap_build_ue_context_release_request(test_ue, + S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UE Context Release Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send 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); + + /* Send Attach Request */ + sess = test_sess_find_by_apn(test_ue, "internet"); + ogs_assert(sess); + + memset(&sess->pdn_connectivity_param, + 0, sizeof(sess->pdn_connectivity_param)); + sess->pdn_connectivity_param.eit = 1; + esmbuf = testesm_build_pdn_connectivity_request(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + + memset(&test_ue->attach_request_param, + 0, sizeof(test_ue->attach_request_param)); + test_ue->attach_request_param.integrity_protected = 1; + test_ue->attach_request_param.guti = 1; + test_ue->attach_request_param.last_visited_registered_tai = 1; + 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.mobile_station_classmark_3 = 1; + test_ue->attach_request_param.supported_codecs = 1; + test_ue->attach_request_param.ue_usage_setting = 1; + test_ue->attach_request_param.old_guti_type = 1; + test_ue->attach_request_param.ms_network_feature_support = 1; + emmbuf = testemm_build_attach_request(test_ue, esmbuf); + 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 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 */ + 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 UE Context Release Request */ + sendbuf = test_s1ap_build_ue_context_release_request(test_ue, + S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UE Context Release Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send 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); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); + + /* eNB disonncect from SGW */ + test_gtpu_close(gtpu); + + test_ue_remove(test_ue); +} + abts_suite *test_rx(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -1572,6 +2111,7 @@ abts_suite *test_rx(abts_suite *suite) abts_run_test(suite, test1_func, NULL); abts_run_test(suite, test2_func, NULL); abts_run_test(suite, test3_func, NULL); + abts_run_test(suite, test4_func, NULL); return suite; }