[5GC] Fixed session deletion in a BSF (#1725)

This commit is contained in:
Sukchan Lee 2022-10-01 13:11:13 +09:00
parent f71022ad4a
commit 773c7df3e6
10 changed files with 439 additions and 71 deletions

View File

@ -10,7 +10,7 @@ permalink: /support/
Open5GS is licensed under a dual licensing model designed to meet the development and distribution needs of both commercial and open source projects.
The commercial Open5GS license gives you the full rights to create and distribute software on your own terms without any open source license obligations. With the commercial license you also have access to the official NeoPlane Support and close strategic relationship with [NeoPlane](https://neoplane.io) to make sure your development goals are met.
The commercial Open5GS license gives you the full rights to create and distribute software on your own terms without any open source license obligations. With the commercial license, you also have access to the official NeoPlane Support and close strategic relationship with [NeoPlane](https://neoplane.io) to make sure your development goals are met.
Open5GS is also available under AGPL-3.0 open source licenses. The Open5GS open source licensing is ideal for use cases such as open source projects with open source distribution, student/academic purposes, hobby projects, internal research projects without external distribution, or other projects where all AGPL-3.0 obligations can be met.
@ -24,6 +24,6 @@ We work with leading partners in mobile communications to offer our customers co
Please contact [sales@nextepc.com](mailto:sales@nextepc.com) for more informations.
**[sysmocom](https://sysmocom.de/)**: Sysmocom was founded in Berlin, Germany by two veterans of the Free / Open Source Software (FOSS) community. They is providing commercial services around Open5GS open source software including support, development, consulting, training and system integration.
**[sysmocom](https://sysmocom.de/)**: Sysmocom was founded in Berlin, Germany by two veterans of the Free / Open Source Software (FOSS) community. They are providing commercial services around Open5GS open source software including support, development, consulting, training and system integration.
Please contact [Harald Welte \<sales@sysmocom.de\>](mailto:sales@sysmocom.de) for any related inquiries.

View File

@ -130,25 +130,26 @@ void bsf_state_operational(ogs_fsm_t *s, bsf_event_t *e)
SWITCH(message.h.method)
CASE(OGS_SBI_HTTP_METHOD_POST)
if (message.PcfBinding &&
message.PcfBinding->snssai &&
message.PcfBinding->dnn) {
ogs_s_nssai_t s_nssai;
(message.PcfBinding->ipv4_addr ||
message.PcfBinding->ipv6_prefix)) {
s_nssai.sst = message.PcfBinding->snssai->sst;
s_nssai.sd = ogs_s_nssai_sd_from_string(
message.PcfBinding->snssai->sd);
if (message.PcfBinding->ipv4_addr)
sess = bsf_sess_find_by_ipv4addr(
message.PcfBinding->ipv4_addr);
if (!sess && message.PcfBinding->ipv6_prefix)
sess = bsf_sess_find_by_ipv6prefix(
message.PcfBinding->ipv6_prefix);
sess = bsf_sess_find_by_snssai_and_dnn(
&s_nssai, message.PcfBinding->dnn);
if (!sess) {
sess = bsf_sess_add_by_snssai_and_dnn(
&s_nssai, message.PcfBinding->dnn);
sess = bsf_sess_add_by_ip_address(
message.PcfBinding->ipv4_addr,
message.PcfBinding->ipv6_prefix);
ogs_assert(sess);
}
}
break;
CASE(OGS_SBI_HTTP_METHOD_GET)
if (!sess && message.param.ipv4addr)
if (message.param.ipv4addr)
sess = bsf_sess_find_by_ipv4addr(
message.param.ipv4addr);
if (!sess && message.param.ipv6prefix)

View File

@ -27,9 +27,6 @@ static OGS_POOL(bsf_sess_pool, bsf_sess_t);
static int context_initialized = 0;
static void clear_ipv4addr(bsf_sess_t *sess);
static void clear_ipv6prefix(bsf_sess_t *sess);
void bsf_context_init(void)
{
ogs_assert(context_initialized == 0);
@ -120,13 +117,12 @@ int bsf_context_parse_config(void)
return OGS_OK;
}
bsf_sess_t *bsf_sess_add_by_snssai_and_dnn(ogs_s_nssai_t *s_nssai, char *dnn)
bsf_sess_t *bsf_sess_add_by_ip_address(
char *ipv4addr_string, char *ipv6prefix_string)
{
bsf_sess_t *sess = NULL;
ogs_assert(s_nssai);
ogs_assert(s_nssai->sst);
ogs_assert(dnn);
ogs_assert(ipv4addr_string || ipv6prefix_string);
ogs_pool_alloc(&bsf_sess_pool, &sess);
if (!sess) {
@ -136,16 +132,23 @@ bsf_sess_t *bsf_sess_add_by_snssai_and_dnn(ogs_s_nssai_t *s_nssai, char *dnn)
}
memset(sess, 0, sizeof *sess);
if (ipv4addr_string &&
bsf_sess_set_ipv4addr(sess, ipv4addr_string) == false) {
ogs_error("bsf_sess_set_ipv4addr[%s] failed", ipv4addr_string);
ogs_pool_free(&bsf_sess_pool, sess);
return NULL;
}
if (ipv6prefix_string &&
bsf_sess_set_ipv6prefix(sess, ipv6prefix_string) == false) {
ogs_error("bsf_sess_set_ipv6prefix[%s] failed", ipv4addr_string);
ogs_pool_free(&bsf_sess_pool, sess);
return NULL;
}
/* SBI Features */
OGS_SBI_FEATURES_SET(sess->management_features,
OGS_SBI_NBSF_MANAGEMENT_BINDING_UPDATE);
sess->s_nssai.sst = s_nssai->sst;
sess->s_nssai.sd.v = s_nssai->sd.v;
sess->dnn = ogs_strdup(dnn);
ogs_assert(sess->dnn);
sess->binding_id = ogs_msprintf("%d",
(int)ogs_pool_index(&bsf_sess_pool, sess));
ogs_assert(sess->binding_id);
@ -174,8 +177,16 @@ void bsf_sess_remove(bsf_sess_t *sess)
if (sess->gpsi)
ogs_free(sess->gpsi);
clear_ipv4addr(sess);
clear_ipv6prefix(sess);
if (sess->ipv4addr_string) {
ogs_hash_set(self.ipv4addr_hash,
&sess->ipv4addr, sizeof(sess->ipv4addr), NULL);
ogs_free(sess->ipv4addr_string);
}
if (sess->ipv6prefix_string) {
ogs_hash_set(self.ipv6prefix_hash,
&sess->ipv6prefix, (sess->ipv6prefix.len >> 3) + 1, NULL);
ogs_free(sess->ipv6prefix_string);
}
ogs_assert(sess->dnn);
ogs_free(sess->dnn);
@ -202,28 +213,6 @@ void bsf_sess_remove_all(void)
bsf_sess_remove(sess);
}
static void clear_ipv4addr(bsf_sess_t *sess)
{
ogs_assert(sess);
if (sess->ipv4addr_string) {
ogs_hash_set(self.ipv4addr_hash,
&sess->ipv4addr, sizeof(sess->ipv4addr), NULL);
ogs_free(sess->ipv4addr_string);
}
}
static void clear_ipv6prefix(bsf_sess_t *sess)
{
ogs_assert(sess);
if (sess->ipv6prefix_string) {
ogs_hash_set(self.ipv6prefix_hash,
&sess->ipv6prefix, (sess->ipv6prefix.len >> 3) + 1, NULL);
ogs_free(sess->ipv6prefix_string);
}
}
bool bsf_sess_set_ipv4addr(bsf_sess_t *sess, char *ipv4addr_string)
{
int rv;
@ -231,8 +220,11 @@ bool bsf_sess_set_ipv4addr(bsf_sess_t *sess, char *ipv4addr_string)
ogs_assert(sess);
ogs_assert(ipv4addr_string);
clear_ipv4addr(sess);
if (sess->ipv4addr_string) {
ogs_hash_set(self.ipv4addr_hash,
&sess->ipv4addr, sizeof(sess->ipv4addr), NULL);
ogs_free(sess->ipv4addr_string);
}
rv = ogs_ipv4_from_string(&sess->ipv4addr, ipv4addr_string);
ogs_expect_or_return_val(rv == OGS_OK, false);
@ -252,8 +244,11 @@ bool bsf_sess_set_ipv6prefix(bsf_sess_t *sess, char *ipv6prefix_string)
ogs_assert(sess);
ogs_assert(ipv6prefix_string);
clear_ipv6prefix(sess);
if (sess->ipv6prefix_string) {
ogs_hash_set(self.ipv6prefix_hash,
&sess->ipv6prefix, (sess->ipv6prefix.len >> 3) + 1, NULL);
ogs_free(sess->ipv6prefix_string);
}
rv = ogs_ipv6prefix_from_string(
sess->ipv6prefix.addr6, &sess->ipv6prefix.len, ipv6prefix_string);
ogs_expect_or_return_val(rv == OGS_OK, false);

View File

@ -41,8 +41,6 @@ typedef struct bsf_context_s {
ogs_list_t sess_list;
} bsf_context_t;
typedef struct bsf_sess_s bsf_sess_t;
typedef struct bsf_sess_s {
ogs_sbi_object_t sbi;
@ -84,7 +82,8 @@ bsf_context_t *bsf_self(void);
int bsf_context_parse_config(void);
bsf_sess_t *bsf_sess_add_by_snssai_and_dnn(ogs_s_nssai_t *s_nssai, char *dnn);
bsf_sess_t *bsf_sess_add_by_ip_address(
char *ipv4addr_string, char *ipv6prefix_string);
void bsf_sess_remove(bsf_sess_t *sess);
void bsf_sess_remove_all(void);

View File

@ -75,11 +75,14 @@ bool bsf_nbsf_management_handle_pcf_binding(
RecvPcfBinding = recvmsg->PcfBinding;
ogs_assert(RecvPcfBinding);
if (!RecvPcfBinding->ipv4_addr && !RecvPcfBinding->ipv6_prefix) {
strerror = ogs_msprintf(
"No IPv4 address or IPv6 prefix[%p:%p]",
RecvPcfBinding->ipv4_addr,
RecvPcfBinding->ipv6_prefix);
if (!RecvPcfBinding->snssai) {
strerror = ogs_msprintf("No S-NSSAI");
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
goto cleanup;
}
if (!RecvPcfBinding->dnn) {
strerror = ogs_msprintf("No DNN");
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
goto cleanup;
}
@ -93,11 +96,6 @@ bool bsf_nbsf_management_handle_pcf_binding(
goto cleanup;
}
if (RecvPcfBinding->ipv4_addr)
bsf_sess_set_ipv4addr(sess, RecvPcfBinding->ipv4_addr);
if (RecvPcfBinding->ipv6_prefix)
bsf_sess_set_ipv6prefix(sess, RecvPcfBinding->ipv6_prefix);
if (RecvPcfBinding->pcf_fqdn) {
if (sess->pcf_fqdn)
ogs_free(sess->pcf_fqdn);
@ -105,6 +103,13 @@ bool bsf_nbsf_management_handle_pcf_binding(
ogs_assert(sess->pcf_fqdn);
}
sess->s_nssai.sst = RecvPcfBinding->snssai->sst;
sess->s_nssai.sd =
ogs_s_nssai_sd_from_string(RecvPcfBinding->snssai->sd);
sess->dnn = ogs_strdup(RecvPcfBinding->dnn);
ogs_assert(sess->dnn);
PcfIpEndPointList = RecvPcfBinding->pcf_ip_end_points;
if (PcfIpEndPointList) {

View File

@ -214,14 +214,23 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e)
CASE(OGS_SBI_HTTP_METHOD_DELETE)
if (message->res_status !=
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
ogs_error("[%s:%d] HTTP response error [%d]",
ogs_warn("[%s:%d] HTTP response error [%d]",
pcf_ue->supi, sess->psi, message->res_status);
/*
* The PCfBindings resource for that UE may not exist in the BSF
* for reasons such as restarting the BSF.
*
* So, session Release continues even if there is no resource in BSF.
*/
#if 0
ogs_assert(true ==
ogs_sbi_server_send_error(stream,
message->res_status,
NULL, "HTTP response error", pcf_ue->supi));
OGS_FSM_TRAN(s, pcf_sm_state_exception);
break;
#endif
}
pcf_nbsf_management_handle_de_register(

View File

@ -336,9 +336,6 @@ static void test2_func(abts_case *tc, void *data)
test_ue[i] = test_ue_add_by_suci(&mobile_identity_suci, 13);
ogs_assert(test_ue[i]);
/* Multiple eNB-UE-S1AP-UD */
test_ue[i]->enb_ue_s1ap_id = i;
test_ue[i]->e_cgi.cell_id = 0x54f6401;
test_ue[i]->nas.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue[i]->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH;
@ -357,6 +354,11 @@ static void test2_func(abts_case *tc, void *data)
}
for (i = 0; i < NUM_OF_TEST_UE; i++) {
if (i > 0)
test_ue[i]->enb_ue_s1ap_id = test_ue[i-1]->enb_ue_s1ap_id;
else
test_ue[i]->enb_ue_s1ap_id = 0;
sess = test_sess_find_by_apn(
test_ue[i], "internet", OGS_GTP2_RAT_TYPE_EUTRAN);
ogs_assert(sess);
@ -584,6 +586,11 @@ static void test3_func(abts_case *tc, void *data)
}
for (i = 0; i < NUM_OF_TEST_UE; i++) {
if (i > 0)
test_ue[i]->enb_ue_s1ap_id = test_ue[i-1]->enb_ue_s1ap_id;
else
test_ue[i]->enb_ue_s1ap_id = 0;
sess = test_sess_find_by_apn(
test_ue[i], "internet", OGS_GTP2_RAT_TYPE_EUTRAN);
ogs_assert(sess);

View File

@ -29,6 +29,7 @@ abts_suite *test_identity(abts_suite *suite);
abts_suite *test_gmm_status(abts_suite *suite);
abts_suite *test_ue_context(abts_suite *suite);
abts_suite *test_reset(abts_suite *suite);
abts_suite *test_multi_ue(abts_suite *suite);
abts_suite *test_crash(abts_suite *suite);
const struct testlist {
@ -44,6 +45,7 @@ const struct testlist {
{test_gmm_status},
{test_ue_context},
{test_reset},
{test_multi_ue},
#if 0 /* Since there is error LOG, we disabled the following test */
{test_crash},
#endif

View File

@ -27,6 +27,7 @@ test5gc_registration_sources = files('''
gmm-status-test.c
ue-context-test.c
reset-test.c
multi-ue-test.c
crash-test.c
'''.split())

View File

@ -0,0 +1,349 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "test-common.h"
#define NUM_OF_TEST_UE 3
static void test1_func(abts_case *tc, void *data)
{
int rv;
ogs_socknode_t *ngap;
ogs_socknode_t *gtpu;
ogs_pkbuf_t *gmmbuf;
ogs_pkbuf_t *gsmbuf;
ogs_pkbuf_t *nasbuf;
ogs_pkbuf_t *sendbuf;
ogs_pkbuf_t *recvbuf;
ogs_ngap_message_t message;
int i;
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
test_ue_t *test_ue[NUM_OF_TEST_UE];
test_sess_t *sess = NULL;
test_bearer_t *qos_flow = NULL;
bson_t *doc = NULL;
/* gNB connects to AMF */
ngap = testngap_client(AF_INET);
ABTS_PTR_NOTNULL(tc, ngap);
/* gNB connects to UPF */
gtpu = test_gtpu_server(1, AF_INET);
ABTS_PTR_NOTNULL(tc, gtpu);
/* Send NG-Setup Reqeust */
sendbuf = testngap_build_ng_setup_request(0x4000, 22);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive NG-Setup Response */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
for (i = 0; i < NUM_OF_TEST_UE; i++) {
uint64_t imsi_index;
/* 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] = 0;
mobile_identity_suci.scheme_output[1] = 0;
mobile_identity_suci.scheme_output[2] = 0x20;
mobile_identity_suci.scheme_output[3] = 0x31;
mobile_identity_suci.scheme_output[4] = 0x90;
imsi_index = i + 1;
ogs_uint64_to_buffer(imsi_index, 5, mobile_identity_suci.scheme_output);
test_ue[i] = test_ue_add_by_suci(&mobile_identity_suci, 13);
ogs_assert(test_ue[i]);
test_ue[i]->nr_cgi.cell_id = 0x40001;
test_ue[i]->nas.registration.tsc = 0;
test_ue[i]->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue[i]->nas.registration.follow_on_request = 1;
test_ue[i]->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL;
test_ue[i]->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
test_ue[i]->opc_string = "e8ed289deba952e4283b54e88e6183ca";
}
for (i = 0; i < NUM_OF_TEST_UE; i++) {
if (i > 0)
test_ue[i]->ran_ue_ngap_id = test_ue[i-1]->ran_ue_ngap_id;
else
test_ue[i]->ran_ue_ngap_id = 0;
/* Send PDU session establishment request */
sess = test_sess_add_by_dnn_and_psi(test_ue[i], "internet", 5);
ogs_assert(sess);
/********** Insert Subscriber in Database */
doc = test_db_new_simple(test_ue[i]);
ABTS_PTR_NOTNULL(tc, doc);
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue[i], doc));
/* Send Registration request */
test_ue[i]->registration_request_param.guti = 1;
gmmbuf = testgmm_build_registration_request(test_ue[i], NULL, false, false);
ABTS_PTR_NOTNULL(tc, gmmbuf);
test_ue[i]->registration_request_param.gmm_capability = 1;
test_ue[i]->registration_request_param.s1_ue_network_capability = 1;
test_ue[i]->registration_request_param.requested_nssai = 1;
test_ue[i]->registration_request_param.last_visited_registered_tai = 1;
test_ue[i]->registration_request_param.ue_usage_setting = 1;
nasbuf = testgmm_build_registration_request(test_ue[i], NULL, false, false);
ABTS_PTR_NOTNULL(tc, nasbuf);
sendbuf = testngap_build_initial_ue_message(test_ue[i], gmmbuf,
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Identity request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
/* Send Identity response */
gmmbuf = testgmm_build_identity_response(test_ue[i]);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
/* Send Authentication response */
gmmbuf = testgmm_build_authentication_response(test_ue[i]);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Security mode command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
/* Send Security mode complete */
gmmbuf = testgmm_build_security_mode_complete(test_ue[i], nasbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive InitialContextSetupRequest +
* Registration accept */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_InitialContextSetup,
test_ue[i]->ngap_procedure_code);
/* Send UERadioCapabilityInfoIndication */
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue[i]);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send InitialContextSetupResponse */
sendbuf = testngap_build_initial_context_setup_response(test_ue[i], false);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Registration complete */
gmmbuf = testgmm_build_registration_complete(test_ue[i]);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Configuration update command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
sess->ul_nas_transport_param.request_type =
OGS_NAS_5GS_REQUEST_TYPE_INITIAL;
sess->ul_nas_transport_param.dnn = 1;
sess->ul_nas_transport_param.s_nssai = 0;
sess->pdu_session_establishment_param.ssc_mode = 1;
sess->pdu_session_establishment_param.epco = 1;
gsmbuf = testgsm_build_pdu_session_establishment_request(sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDUSessionResourceSetupRequest +
* DL NAS transport +
* PDU session establishment accept */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
test_ue[i]->ngap_procedure_code);
/* Send PDUSessionResourceSetupResponse */
sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
for (i = 0; i < NUM_OF_TEST_UE; i++) {
/* Send PDU session establishment request */
sess = test_sess_find_by_psi(test_ue[i], 5);
ogs_assert(sess);
/* Send PDU Session release request */
sess->ul_nas_transport_param.request_type = 0;
sess->ul_nas_transport_param.dnn = 0;
sess->ul_nas_transport_param.s_nssai = 0;
sess->pdu_session_establishment_param.ssc_mode = 0;
sess->pdu_session_establishment_param.epco = 0;
gsmbuf = testgsm_build_pdu_session_release_request(sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDUSessionResourceReleaseCommand +
* DL NAS transport +
* PDU session release command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_PDUSessionResourceRelease,
test_ue[i]->ngap_procedure_code);
/* Send PDUSessionResourceReleaseResponse */
sendbuf = testngap_build_pdu_session_resource_release_response(sess);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send UplinkNASTransport +
* UL NAS trasnport +
* PDU session resource release complete */
sess->ul_nas_transport_param.request_type = 0;
sess->ul_nas_transport_param.dnn = 0;
sess->ul_nas_transport_param.s_nssai = 0;
sess->pdu_session_establishment_param.ssc_mode = 0;
sess->pdu_session_establishment_param.epco = 0;
gsmbuf = testgsm_build_pdu_session_release_complete(sess);
ABTS_PTR_NOTNULL(tc, gsmbuf);
gmmbuf = testgmm_build_ul_nas_transport(sess,
OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
for (i = 0; i < NUM_OF_TEST_UE; i++) {
/* Send De-registration request */
gmmbuf = testgmm_build_de_registration_request(test_ue[i], 1, true, true);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UEContextReleaseCommand */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue[i], recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_UEContextRelease,
test_ue[i]->ngap_procedure_code);
/* Send UEContextReleaseComplete */
sendbuf = testngap_build_ue_context_release_complete(test_ue[i]);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
ogs_msleep(300);
for (i = 0; i < NUM_OF_TEST_UE; i++) {
/********** Remove Subscriber in Database */
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue[i]));
}
/* gNB disonncect from UPF */
testgnb_gtpu_close(gtpu);
/* gNB disonncect from AMF */
testgnb_ngap_close(ngap);
/* Clear Test UE Context */
test_ue_remove_all();
}
abts_suite *test_multi_ue(abts_suite *suite)
{
suite = ADD_SUITE(suite)
abts_run_test(suite, test1_func, NULL);
return suite;
}