diff --git a/lib/core/ogs-list.h b/lib/core/ogs-list.h index 269918e9b..443cc5094 100644 --- a/lib/core/ogs-list.h +++ b/lib/core/ogs-list.h @@ -206,6 +206,19 @@ static ogs_inline int ogs_list_count(const ogs_list_t *list) return i; } +static ogs_inline bool ogs_list_exists(const ogs_list_t *list, void *lnode) +{ + ogs_list_t *node = (ogs_list_t *)lnode; + void *iter = NULL; + + ogs_list_for_each(list, iter) { + if (node == (ogs_list_t *)iter) + return true; + } + + return false; +} + #ifdef __cplusplus } #endif diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index 024a0a74c..2c0b58f93 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -1046,8 +1046,14 @@ void s1ap_handle_initial_context_setup_response( ogs_debug(" ### ULI PRESENT ###"); uli_presence = 1; } - ogs_list_add(&mme_ue->bearer_to_modify_list, - &bearer->to_modify_node); + if (ogs_list_exists( + &mme_ue->bearer_to_modify_list, + &bearer->to_modify_node) == false) + ogs_list_add( + &mme_ue->bearer_to_modify_list, + &bearer->to_modify_node); + else + ogs_warn("Bearer [%d] Duplicated", (int)e_rab->e_RAB_ID); } } @@ -2195,7 +2201,13 @@ void s1ap_handle_e_rab_modification_indication( return; } - ogs_list_add(&mme_ue->bearer_to_modify_list, &bearer->to_modify_node); + if (ogs_list_exists( + &mme_ue->bearer_to_modify_list, + &bearer->to_modify_node) == false) + ogs_list_add( + &mme_ue->bearer_to_modify_list, &bearer->to_modify_node); + else + ogs_warn("Bearer [%d] Duplicated", (int)e_rab->e_RAB_ID); } if (ogs_list_count(&mme_ue->bearer_to_modify_list)) { @@ -2623,8 +2635,13 @@ void s1ap_handle_path_switch_request( return; } - ogs_list_add( - &mme_ue->bearer_to_modify_list, &bearer->to_modify_node); + if (ogs_list_exists( + &mme_ue->bearer_to_modify_list, + &bearer->to_modify_node) == false) + ogs_list_add( + &mme_ue->bearer_to_modify_list, &bearer->to_modify_node); + else + ogs_warn("Bearer [%d] Duplicated", (int)e_rab->e_RAB_ID); } relocation = sgw_ue_check_if_relocated(mme_ue); diff --git a/tests/handover/epc-x2-test.c b/tests/handover/epc-x2-test.c index 67993e528..24811c103 100644 --- a/tests/handover/epc-x2-test.c +++ b/tests/handover/epc-x2-test.c @@ -370,11 +370,268 @@ 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 *s1ap1, *s1ap2; + ogs_socknode_t *gtpu1, *gtpu2; + 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; + + 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, "3746000006"); + ogs_assert(test_ue); + + test_ue->e_cgi.cell_id = 0x1234560; + 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); + + /* Two eNB connects to MME */ + s1ap1 = tests1ap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, s1ap1); + + s1ap2 = tests1ap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, s1ap2); + + /* Two eNB connects to SGW */ + gtpu1 = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu1); + + gtpu2 = test_gtpu_server(2, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu2); + + /* S1-Setup Reqeust/Response for Source eNB */ + sendbuf = test_s1ap_build_s1_setup_request( + S1AP_ENB_ID_PR_macroENB_ID, 0x54f64); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + recvbuf = testenb_s1ap_read(s1ap1); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(NULL, recvbuf); + + /* S1-Setup Reqeust/Response for Target eNB */ + sendbuf = test_s1ap_build_s1_setup_request( + S1AP_ENB_ID_PR_macroENB_ID, 0x54f65); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap2, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + recvbuf = testenb_s1ap_read(s1ap2); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(NULL, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_qos_flow(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.pco = 1; + sess->pdn_connectivity_param.request_type = + OGS_NAS_EPS_REQUEST_TYPE_INITIAL; + esmbuf = testesm_build_pdn_connectivity_request(sess, false); + 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.tmsi_status = 1; + test_ue->attach_request_param.mobile_station_classmark_2 = 1; + test_ue->attach_request_param.additional_update_type = 1; + test_ue->attach_request_param.ue_usage_setting = 1; + emmbuf = testemm_build_attach_request(test_ue, esmbuf, false, 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(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap1); + 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(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap1); + 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(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = testenb_s1ap_read(s1ap1); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send ESM Information Response */ + 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(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap1); + 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(s1ap1, 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(s1ap1, 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(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap1); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap1); + 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(s1ap1, 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(s1ap1, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(100); + + /* Send Path Switch Request */ + test_ue->e_cgi.cell_id = 0xabcdef0; + test_ue->enb_ue_s1ap_id++; + bearer = ogs_list_first(&sess->bearer_list); + bearer->ebi = 5; + bearer->enb_s1u_addr = test_self()->gnb2_addr; + bearer->enb_s1u_addr6 = test_self()->gnb2_addr6; + bearer = ogs_list_next(bearer); + bearer->ebi = 5; /* Invalid Bearer with same EBI = 5 */ + bearer->enb_s1u_addr = test_self()->gnb2_addr; + bearer->enb_s1u_addr6 = test_self()->gnb2_addr6; + + sendbuf = test_s1ap_build_path_switch_request(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap2, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Path Switch Ack */ + recvbuf = testenb_s1ap_read(s1ap2); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive End Mark */ + recvbuf = test_gtpu_read(gtpu1); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* Two eNB disonncect from SGW */ + testgnb_gtpu_close(gtpu1); + testgnb_gtpu_close(gtpu2); + + /* Two eNB disonncect from MME */ + testenb_s1ap_close(s1ap1); + testenb_s1ap_close(s1ap2); + + test_ue_remove(test_ue); +} + abts_suite *test_epc_x2(abts_suite *suite) { suite = ADD_SUITE(suite) abts_run_test(suite, test1_func, NULL); + abts_run_test(suite, test2_func, NULL); return suite; }