[AMF] Fix UE context transfer when only NRF is client (#3880)

* [AMF] Fix UE context transfer when only NRF is client

If UE context transfer is initiated and the new AMF does not get the
old AMF from NRF or no UE context is retrieved from the old AMF,
we do not want to reject UE registration. Send identity request instead.
Test "transfer-error-case" is added into the commit.

* [tests] Unite tests for UE context transfer

All tests for UE context transfer with different configs are placed
into test folder transfer.

* [tests] Make two binaries for UE context transfer tests

For each test config a different test binary is created.
This commit is contained in:
Matej Gradišar 2025-05-31 13:51:06 +02:00 committed by GitHub
parent e93bc6b5c8
commit 799103257b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 1281 additions and 51 deletions

View file

@ -41,6 +41,7 @@ example_conf = '''
srsenb.yaml
non3gpp.yaml
transfer.yaml
transfer-error-case.yaml
'''.split()
foreach file : example_conf

View file

@ -0,0 +1,266 @@
db_uri: mongodb://localhost/open5gs
logger:
test:
serving:
- plmn_id:
mcc: 999
mnc: 70
global:
parameter:
# no_nrf: true
no_scp: true
no_sepp: true
# no_amf: true
# no_smf: true
# no_upf: true
# no_ausf: true
# no_udm: true
# no_pcf: true
# no_nssf: true
# no_bsf: true
# no_udr: true
no_mme: true
no_sgwc: true
no_sgwu: true
no_pcrf: true
no_hss: true
smf:
sbi:
server:
- address: 127.0.0.4
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
pfcp:
server:
- address: 127.0.0.4
client:
upf:
- address: 127.0.0.7
gtpc:
server:
- address: 127.0.0.4
gtpu:
server:
- address: 127.0.0.4
metrics:
server:
- address: 127.0.0.4
port: 9090
session:
- subnet: 10.45.0.0/16
gateway: 10.45.0.1
- subnet: 2001:db8:cafe::/48
gateway: 2001:db8:cafe::1
dns:
- 8.8.8.8
- 8.8.4.4
- 2001:4860:4860::8888
- 2001:4860:4860::8844
mtu: 1400
freeDiameter:
identity: smf.localdomain
realm: localdomain
listen_on: 127.0.0.4
no_fwd: true
load_extension:
- module: @build_subprojects_freeDiameter_extensions_dir@/dbg_msg_dumps.fdx
conf: 0x8888
- module: @build_subprojects_freeDiameter_extensions_dir@/dict_rfc5777.fdx
- module: @build_subprojects_freeDiameter_extensions_dir@/dict_mip6i.fdx
- module: @build_subprojects_freeDiameter_extensions_dir@/dict_nasreq.fdx
- module: @build_subprojects_freeDiameter_extensions_dir@/dict_nas_mipv6.fdx
- module: @build_subprojects_freeDiameter_extensions_dir@/dict_dcca.fdx
- module: @build_subprojects_freeDiameter_extensions_dir@/dict_dcca_3gpp/dict_dcca_3gpp.fdx
connect:
- identity: pcrf.localdomain
address: 127.0.0.9
amf:
sbi:
server:
- address: 127.0.0.5
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
ngap:
server:
- address: 127.0.0.5
metrics:
server:
- address: 127.0.0.5
port: 9090
guami:
- plmn_id:
mcc: 999
mnc: 70
amf_id:
region: 2
set: 1
pointer: 31
tai:
- plmn_id:
mcc: 999
mnc: 70
tac: 1
plmn_support:
- plmn_id:
mcc: 999
mnc: 70
s_nssai:
- sst: 1
security:
integrity_order : [ NIA2, NIA1, NIA0 ]
ciphering_order : [ NEA0, NEA1, NEA2 ]
network_name:
full: Open5GS
amf_name: open5gs-amf0
time:
t3512:
value: 540 # 9 mintues * 60 = 540 seconds
# amf #2
amf:
sbi:
server:
- address: 127.0.0.50
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
ngap:
server:
- address: 127.0.0.50
metrics:
server:
- address: 127.0.0.50
port: 9090
guami:
- plmn_id:
mcc: 999
mnc: 70
amf_id:
region: 2
set: 1
pointer: 30
tai:
- plmn_id:
mcc: 999
mnc: 70
tac: 1
plmn_support:
- plmn_id:
mcc: 999
mnc: 70
s_nssai:
- sst: 1
security:
integrity_order : [ NIA2, NIA1, NIA0 ]
ciphering_order : [ NEA0, NEA1, NEA2 ]
network_name:
full: Open5GS
amf_name: open5gs-amf1
time:
t3512:
value: 540 # 9 mintues * 60 = 540 seconds
upf:
pfcp:
server:
- address: 127.0.0.7
gtpu:
server:
- address: 127.0.0.7
session:
- subnet: 10.45.0.0/16
gateway: 10.45.0.1
- subnet: 2001:db8:cafe::/48
gateway: 2001:db8:cafe::1
metrics:
server:
- address: 127.0.0.7
port: 9090
nrf:
sbi:
server:
- address: 127.0.0.10
port: 7777
serving:
- plmn_id:
mcc: 999
mnc: 70
ausf:
sbi:
server:
- address: 127.0.0.11
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
udm:
hnet:
- id: 1
scheme: 1
key: @build_configs_dir@/open5gs/hnet/curve25519-1.key
- id: 2
scheme: 2
key: @build_configs_dir@/open5gs/hnet/secp256r1-2.key
sbi:
server:
- address: 127.0.0.12
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
pcf:
sbi:
server:
- address: 127.0.0.13
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
metrics:
server:
- address: 127.0.0.13
port: 9090
nssf:
sbi:
server:
- address: 127.0.0.14
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
nsi:
- uri: http://127.0.0.10:7777
s_nssai:
sst: 1
bsf:
sbi:
server:
- address: 127.0.0.15
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777
udr:
sbi:
server:
- address: 127.0.0.20
port: 7777
client:
nrf:
- uri: http://127.0.0.10:7777

View file

@ -370,9 +370,15 @@ int ogs_proc_join(ogs_proc_t *const process, int *const out_return_code)
}
if (process->child != waitpid(process->child, &status, 0)) {
process->child = 0;
ogs_fatal("waitpid failed: %d", status);
return OGS_ERROR;
}
process->child = 0;
if (process->nf_name)
ogs_free(process->nf_name);
if (out_return_code) {
if (WIFEXITED(status)) {
*out_return_code = WEXITSTATUS(status);
@ -416,9 +422,13 @@ int ogs_proc_terminate(ogs_proc_t *const process)
return OGS_ERROR;
}
#else
if (kill(process->child, SIGTERM) == -1) {
return OGS_ERROR;
if (process->child) {
if (kill(process->child, SIGTERM) == -1) {
return OGS_ERROR;
}
}
#endif
return OGS_OK;

View file

@ -73,6 +73,10 @@ typedef struct ogs_proc_s {
unsigned long dwProcessId;
#else
pid_t child;
// to force kill the right NF in tests if needed.
char *nf_name;
int index;
#endif
} ogs_proc_t;

View file

@ -410,9 +410,11 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
CASE(OGS_SBI_HTTP_METHOD_GET)
if (sbi_message.res_status == OGS_SBI_HTTP_STATUS_OK)
amf_nnrf_handle_nf_discover(sbi_xact, &sbi_message);
else
else {
ogs_error("HTTP response error [%d]",
sbi_message.res_status);
amf_nnrf_handle_failed_amf_discovery(sbi_xact);
}
break;
DEFAULT
@ -718,6 +720,10 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
* To avoid double-free SBI xact,
* we need to check ogs_sbi_xact_find_by_id()
*/
OpenAPI_nf_type_e requester_nf_type = OpenAPI_nf_type_NULL;
ogs_sbi_discovery_option_t *discovery_option = NULL;
sbi_xact_id = OGS_POINTER_TO_UINT(e->h.sbi.data);
ogs_assert(sbi_xact_id >= OGS_MIN_POOL_ID &&
sbi_xact_id <= OGS_MAX_POOL_ID);
@ -737,6 +743,8 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
sbi_object_id <= OGS_MAX_POOL_ID);
service_type = sbi_xact->service_type;
requester_nf_type = sbi_xact->requester_nf_type;
discovery_option = sbi_xact->discovery_option;
ogs_sbi_xact_remove(sbi_xact);
@ -754,6 +762,32 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
ogs_error("[%s:%s] Cannot receive SBI message",
amf_ue->supi, amf_ue->suci);
/*
* TS 23.502
* 4.2.2.2.2 General Registration
* If the SUCI is not provided by the UE nor retrieved from the old AMF the Identity Request
* procedure is initiated by AMF sending an Identity Request message to the UE requesting the SUCI.
*/
if (amf_ue->nas.message_type == OGS_NAS_5GS_REGISTRATION_REQUEST &&
amf_ue->nas.registration.value == OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL &&
requester_nf_type == OpenAPI_nf_type_AMF &&
discovery_option->guami_presence) {
amf_ue->amf_ue_context_transfer_state =
UE_CONTEXT_INITIAL_STATE;
if (!(AMF_UE_HAVE_SUCI(amf_ue) ||
AMF_UE_HAVE_SUPI(amf_ue))) {
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
rv = nas_5gs_send_identity_request(amf_ue);
ogs_expect(rv == OGS_OK);
ogs_assert(rv != OGS_ERROR);
break;
}
}
r = nas_5gs_send_gmm_reject_from_sbi(amf_ue,
OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT);
ogs_expect(r == OGS_OK);

View file

@ -49,6 +49,7 @@ void amf_nnrf_handle_nf_discover(
SearchResult = recvmsg->SearchResult;
if (!SearchResult) {
ogs_error("No SearchResult");
amf_nnrf_handle_failed_amf_discovery(xact);
return;
}
@ -72,6 +73,34 @@ void amf_nnrf_handle_nf_discover(
ogs_assert(amf_ue);
ogs_error("[%s] (NF discover) No [%s]", amf_ue->suci,
ogs_sbi_service_type_to_name(service_type));
/*
* TS 23.502
* 4.2.2.2.2 General Registration
* If the SUCI is not provided by the UE nor retrieved from the old AMF the Identity Request
* procedure is initiated by AMF sending an Identity Request message to the UE requesting the SUCI.
*/
if (amf_ue->nas.message_type == OGS_NAS_5GS_REGISTRATION_REQUEST &&
amf_ue->nas.registration.value == OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL &&
requester_nf_type == OpenAPI_nf_type_AMF &&
discovery_option->guami_presence) {
amf_ue->amf_ue_context_transfer_state =
UE_CONTEXT_INITIAL_STATE;
ogs_sbi_xact_remove(xact);
if (!(AMF_UE_HAVE_SUCI(amf_ue) ||
AMF_UE_HAVE_SUPI(amf_ue))) {
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
r = nas_5gs_send_identity_request(amf_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
break;
}
}
r = nas_5gs_send_gmm_reject_from_sbi(amf_ue,
OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT);
ogs_expect(r == OGS_OK);
@ -110,3 +139,62 @@ void amf_nnrf_handle_nf_discover(
ogs_expect(true == amf_sbi_send_request(nf_instance, xact));
}
void amf_nnrf_handle_failed_amf_discovery(
ogs_sbi_xact_t *sbi_xact)
{
int r;
OpenAPI_nf_type_e requester_nf_type = OpenAPI_nf_type_NULL;
ogs_sbi_discovery_option_t *discovery_option = NULL;
ogs_sbi_service_type_e service_type = OGS_SBI_SERVICE_TYPE_NULL;
ogs_sbi_object_t *sbi_object = NULL;
amf_ue_t *amf_ue = NULL;
ogs_assert(sbi_xact);
sbi_object = sbi_xact->sbi_object;
ogs_assert(sbi_object);
service_type = sbi_xact->service_type;
ogs_assert(service_type);
requester_nf_type = sbi_xact->requester_nf_type;
ogs_assert(requester_nf_type);
discovery_option = sbi_xact->discovery_option;
ogs_assert(sbi_object->type > OGS_SBI_OBJ_BASE &&
sbi_object->type < OGS_SBI_OBJ_TOP);
if (sbi_object->type == OGS_SBI_OBJ_UE_TYPE) {
amf_ue = (amf_ue_t *)sbi_object;
ogs_assert(amf_ue);
/*
* TS 23.502
* 4.2.2.2.2 General Registration
* If the SUCI is not provided by the UE nor retrieved from the old AMF the Identity Request
* procedure is initiated by AMF sending an Identity Request message to the UE requesting the SUCI.
*/
if (amf_ue->nas.message_type == OGS_NAS_5GS_REGISTRATION_REQUEST &&
amf_ue->nas.registration.value == OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL &&
requester_nf_type == OpenAPI_nf_type_AMF &&
discovery_option->guami_presence) {
amf_ue->amf_ue_context_transfer_state =
UE_CONTEXT_INITIAL_STATE;
ogs_sbi_xact_remove(sbi_xact);
if (!(AMF_UE_HAVE_SUCI(amf_ue) ||
AMF_UE_HAVE_SUPI(amf_ue))) {
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
r = nas_5gs_send_identity_request(amf_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
}
}
return;
}

View file

@ -28,6 +28,8 @@ extern "C" {
void amf_nnrf_handle_nf_discover(
ogs_sbi_xact_t *xact, ogs_sbi_message_t *recvmsg);
void amf_nnrf_handle_failed_amf_discovery(
ogs_sbi_xact_t *sbi_xact);
#ifdef __cplusplus
}

View file

@ -42,7 +42,7 @@ static void run_threads(const char *nf_name, int count,
{
int i;
threads[0] = test_child_create(nf_name, argv_out);
threads[0] = test_child_create(nf_name, 0, argv_out);
for (i = 1; i < count; i++) {
const char *idx_string = NULL;;
@ -62,7 +62,7 @@ static void run_threads(const char *nf_name, int count,
argv_out[argv_out_idx + 1] = idx_string;
argv_out[argv_out_idx + 2] = NULL;
threads[i] = test_child_create(nf_name, argv_out);
threads[i] = test_child_create(nf_name, i, argv_out);
}
// reset argv_out and remove the added "-k" parameter
@ -90,11 +90,11 @@ int app_initialize(const char *const argv[])
}
if (ogs_global_conf()->parameter.no_nrf == 0)
nrf_thread = test_child_create("nrf", argv_out);
nrf_thread = test_child_create("nrf", 0, argv_out);
if (ogs_global_conf()->parameter.no_scp == 0)
scp_thread = test_child_create("scp", argv_out);
scp_thread = test_child_create("scp", 0, argv_out);
if (ogs_global_conf()->parameter.no_sepp == 0)
sepp_thread = test_child_create("sepp", argv_out);
sepp_thread = test_child_create("sepp", 0, argv_out);
if (ogs_global_conf()->parameter.no_upf == 0)
run_threads("upf", ogs_global_conf()->parameter.upf_count,
@ -139,29 +139,55 @@ void app_terminate(void)
int i;
for (i = 0; i < OGS_MAX_NF_INSTANCES; i++) {
if (amf_threads[i])
if (amf_threads[i]) {
ogs_thread_destroy(amf_threads[i]);
if (smf_threads[i])
amf_threads[i] = NULL;
}
if (smf_threads[i]) {
ogs_thread_destroy(smf_threads[i]);
if (upf_threads[i])
smf_threads[i] = NULL;
}
if (upf_threads[i]) {
ogs_thread_destroy(upf_threads[i]);
if (udr_threads[i])
upf_threads[i] = NULL;
}
if (udr_threads[i]) {
ogs_thread_destroy(udr_threads[i]);
if (nssf_threads[i])
udr_threads[i] = NULL;
}
if (nssf_threads[i]) {
ogs_thread_destroy(nssf_threads[i]);
if (bsf_threads[i])
nssf_threads[i] = NULL;
}
if (bsf_threads[i]) {
ogs_thread_destroy(bsf_threads[i]);
if (pcf_threads[i])
bsf_threads[i] = NULL;
}
if (pcf_threads[i]) {
ogs_thread_destroy(pcf_threads[i]);
if (udm_threads[i])
pcf_threads[i] = NULL;
}
if (udm_threads[i]) {
ogs_thread_destroy(udm_threads[i]);
if (ausf_threads[i])
udm_threads[i] = NULL;
}
if (ausf_threads[i]) {
ogs_thread_destroy(ausf_threads[i]);
ausf_threads[i] = NULL;
}
}
if (sepp_thread) {
ogs_thread_destroy(sepp_thread);
sepp_thread = NULL;
}
if (scp_thread) {
ogs_thread_destroy(scp_thread);
scp_thread = NULL;
}
if (nrf_thread) {
ogs_thread_destroy(nrf_thread);
nrf_thread = NULL;
}
if (sepp_thread) ogs_thread_destroy(sepp_thread);
if (scp_thread) ogs_thread_destroy(scp_thread);
if (nrf_thread) ogs_thread_destroy(nrf_thread);
}
void test_5gc_init(void)

View file

@ -58,43 +58,43 @@ int app_initialize(const char *const argv[])
}
if (ogs_global_conf()->parameter.no_nrf == 0)
nrf_thread = test_child_create("nrf", argv_out);
nrf_thread = test_child_create("nrf", 0, argv_out);
if (ogs_global_conf()->parameter.no_scp == 0)
scp_thread = test_child_create("scp", argv_out);
scp_thread = test_child_create("scp", 0, argv_out);
if (ogs_global_conf()->parameter.no_sepp == 0)
sepp_thread = test_child_create("sepp", argv_out);
sepp_thread = test_child_create("sepp", 0, argv_out);
if (ogs_global_conf()->parameter.no_hss == 0)
hss_thread = test_child_create("hss", argv_out);
hss_thread = test_child_create("hss", 0, argv_out);
if (ogs_global_conf()->parameter.no_pcrf == 0)
pcrf_thread = test_child_create("pcrf", argv_out);
pcrf_thread = test_child_create("pcrf", 0, argv_out);
if (ogs_global_conf()->parameter.no_upf == 0)
upf_thread = test_child_create("upf", argv_out);
upf_thread = test_child_create("upf", 0, argv_out);
if (ogs_global_conf()->parameter.no_sgwu == 0)
sgwu_thread = test_child_create("sgwu", argv_out);
sgwu_thread = test_child_create("sgwu", 0, argv_out);
if (ogs_global_conf()->parameter.no_smf == 0)
smf_thread = test_child_create("smf", argv_out);
smf_thread = test_child_create("smf", 0, argv_out);
if (ogs_global_conf()->parameter.no_sgwc == 0)
sgwc_thread = test_child_create("sgwc", argv_out);
sgwc_thread = test_child_create("sgwc", 0, argv_out);
if (ogs_global_conf()->parameter.no_mme == 0)
mme_thread = test_child_create("mme", argv_out);
mme_thread = test_child_create("mme", 0, argv_out);
if (ogs_global_conf()->parameter.no_amf == 0)
amf_thread = test_child_create("amf", argv_out);
amf_thread = test_child_create("amf", 0, argv_out);
if (ogs_global_conf()->parameter.no_ausf == 0)
ausf_thread = test_child_create("ausf", argv_out);
ausf_thread = test_child_create("ausf", 0, argv_out);
if (ogs_global_conf()->parameter.no_udm == 0)
udm_thread = test_child_create("udm", argv_out);
udm_thread = test_child_create("udm", 0, argv_out);
if (ogs_global_conf()->parameter.no_pcf == 0)
pcf_thread = test_child_create("pcf", argv_out);
pcf_thread = test_child_create("pcf", 0, argv_out);
if (ogs_global_conf()->parameter.no_nssf == 0)
nssf_thread = test_child_create("nssf", argv_out);
nssf_thread = test_child_create("nssf", 0, argv_out);
if (ogs_global_conf()->parameter.no_bsf == 0)
bsf_thread = test_child_create("bsf", argv_out);
bsf_thread = test_child_create("bsf", 0, argv_out);
if (ogs_global_conf()->parameter.no_udr == 0)
udr_thread = test_child_create("udr", argv_out);
udr_thread = test_child_create("udr", 0, argv_out);
/*
* Wait for all sockets listening

View file

@ -48,22 +48,22 @@ int app_initialize(const char *const argv[])
}
if (ogs_global_conf()->parameter.no_hss == 0)
hss_thread = test_child_create("hss", argv_out);
hss_thread = test_child_create("hss", 0, argv_out);
if (ogs_global_conf()->parameter.no_pcrf == 0)
pcrf_thread = test_child_create("pcrf", argv_out);
pcrf_thread = test_child_create("pcrf", 0, argv_out);
if (ogs_global_conf()->parameter.no_upf == 0)
upf_thread = test_child_create("upf", argv_out);
upf_thread = test_child_create("upf", 0, argv_out);
if (ogs_global_conf()->parameter.no_sgwu == 0)
sgwu_thread = test_child_create("sgwu", argv_out);
sgwu_thread = test_child_create("sgwu", 0, argv_out);
if (ogs_global_conf()->parameter.no_smf == 0)
smf_thread = test_child_create("smf", argv_out);
smf_thread = test_child_create("smf", 0, argv_out);
if (ogs_global_conf()->parameter.no_sgwc == 0)
sgwc_thread = test_child_create("sgwc", argv_out);
sgwc_thread = test_child_create("sgwc", 0, argv_out);
if (ogs_global_conf()->parameter.no_mme == 0)
mme_thread = test_child_create("mme", argv_out);
mme_thread = test_child_create("mme", 0, argv_out);
/*
* Wait for all sockets listening

View file

@ -85,7 +85,8 @@ static int process_num = 0;
static void child_main(void *data)
{
const char **commandLine = data;
thread_data_t *thread_data = data;
const char **commandLine = thread_data->commandLine;
ogs_proc_t *current = NULL;
FILE *out = NULL;
char buf[OGS_HUGE_LEN];
@ -93,6 +94,10 @@ static void child_main(void *data)
current = &process[process_num++];
// get name and index of NF into the process.
current->nf_name = ogs_strdup(thread_data->nf_name);
current->index = thread_data->index;
if (process_num > MAX_CHILD_PROCESS) {
ogs_fatal("Process limit reached");
ogs_assert_if_reached();
@ -118,13 +123,17 @@ static void child_main(void *data)
ogs_assert(ret == 0);
}
ogs_thread_t *test_child_create(const char *name, const char *const argv[])
ogs_thread_t *test_child_create(const char *name, int index, const char *const argv[])
{
ogs_thread_t *child = NULL;
thread_data_t thread_data;
const char *commandLine[OGS_ARG_MAX];
int i = 0;
char command[OGS_MAX_FILEPATH_LEN];
memset(&thread_data, 0, sizeof(thread_data));
while(argv[i] && i < 32) {
commandLine[i] = argv[i];
i++;
@ -137,7 +146,11 @@ ogs_thread_t *test_child_create(const char *name, const char *const argv[])
name, OGS_DIR_SEPARATOR_S "open5gs-", name);
commandLine[0] = command;
child = ogs_thread_create(child_main, commandLine);
thread_data.commandLine = commandLine;
thread_data.nf_name = name;
thread_data.index = index;
child = ogs_thread_create(child_main, &thread_data);
ogs_msleep(50);
@ -150,6 +163,26 @@ void test_child_terminate(void)
ogs_proc_t *current = NULL;
for (i = 0; i < process_num; i++) {
current = &process[i];
ogs_proc_terminate(current);
if (current->stdin_file != 0 && current->child != 0) {
ogs_proc_terminate(current);
}
}
}
void test_child_terminate_with_name(char *name, int index)
{
int i;
ogs_proc_t *current = NULL;
for (i = 0; i < process_num; i++) {
current = &process[i];
if (!strcmp(current->nf_name, name) &&
current->index == index &&
current->stdin_file != 0 &&
current->child != 0) {
ogs_proc_terminate(current);
break;
}
}
}

View file

@ -28,10 +28,18 @@
extern "C" {
#endif
typedef struct {
const char **commandLine;
const char *nf_name;
int index;
pid_t child;
} thread_data_t;
void test_app_run(int argc, const char *const argv[],
const char *name, void (*init)(const char * const argv[]));
void test_child_terminate(void);
ogs_thread_t *test_child_create(const char *name, const char *const argv[]);
void test_child_terminate_with_name(char *name, int index);
ogs_thread_t *test_child_create(const char *name, int index, const char *const argv[]);
#ifdef __cplusplus
}

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) 2019 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-app.h"
abts_suite * test_ue_context_transfer_error_case(abts_suite *suite);
const struct testlist {
abts_suite *(*func)(abts_suite *suite);
} alltests_error[] = {
{test_ue_context_transfer_error_case},
{NULL},
};
static void terminate(void)
{
ogs_msleep(50);
test_child_terminate();
app_terminate();
test_5gc_final();
ogs_app_terminate();
}
static void initialize(const char *const argv[])
{
int rv;
rv = ogs_app_initialize(NULL, NULL, argv);
ogs_assert(rv == OGS_OK);
test_5gc_init();
rv = app_initialize(argv);
ogs_assert(rv == OGS_OK);
}
int main(int argc, const char *const argv[])
{
int i;
abts_suite *suite = NULL;
atexit(terminate);
test_app_run(argc, argv, "transfer-error-case.yaml", initialize);
for (i = 0; alltests_error[i].func; i++)
suite = alltests_error[i].func(suite);
return abts_report(suite);
}

View file

@ -63,4 +63,4 @@ int main(int argc, const char *const argv[])
suite = alltests[i].func(suite);
return abts_report(suite);
}
}

View file

@ -20,9 +20,20 @@ testapp_transfer_sources = files('''
ue-context-transfer-test.c
'''.split())
testapp_transfer_error_sources = files('''
abts-error-main.c
ue-context-transfer-error-case-test.c
'''.split())
testapp_transfer_exe = executable('transfer',
sources : testapp_transfer_sources,
c_args : testunit_core_cc_flags,
dependencies : libtest5gc_dep)
testapp_transfer_error_exe = executable('transfer-error',
sources : testapp_transfer_error_sources,
c_args : testunit_core_cc_flags,
dependencies : libtest5gc_dep)
test('transfer', testapp_transfer_exe, is_parallel : false, suite: '5gc')
test('transfer-error', testapp_transfer_error_exe, is_parallel : false, suite: '5gc')

View file

@ -0,0 +1,681 @@
/*
* 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"
static void test1_func_error(abts_case *tc, void *data)
{
int rv;
ogs_socknode_t *ngap1, *ngap2;
ogs_socknode_t *gtpu1, *gtpu2;
ogs_pkbuf_t *gmmbuf;
ogs_pkbuf_t *gsmbuf;
ogs_pkbuf_t *nasbuf;
ogs_pkbuf_t *sendbuf;
ogs_pkbuf_t *recvbuf;
ogs_pkbuf_t *recvbuf_target;
ogs_ngap_message_t message;
int i;
uint8_t tmp[OGS_HUGE_LEN];
char *_gtp_payload = "34ff0024"
"0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002"
"00000964cd7c291f";
#define NUM_OF_TEST_UE_1 1
/* ERROR case simulation, when no SCP in 5G core */
/* Test: 1 UE, Old AMF, Target AMF,
* register to Old AMF, PDU session establishment, session release, deregister,
* old AMF is killed (main point of this test)
* send registation request to Target AMF with Old AMF's 5G GUTI,
* UE context transfer can not be finished because old AMF is not found
* new AMF sends Identity Request and registration continues
* PDU session establishment, session release, deregister
*/
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
test_ue_t *test_ue[NUM_OF_TEST_UE_1];
test_ue_t *test_ue_target[NUM_OF_TEST_UE_1];
test_sess_t *sess = NULL;
test_bearer_t *qos_flow = NULL;
bson_t *doc = NULL;
/* First gNB connects to Target AMF */
ngap2 = testngap_client(2, AF_INET);
ABTS_PTR_NOTNULL(tc, ngap2);
/* Second gNB connects to Old AMF */
ngap1 = testngap_client(1, AF_INET);
ABTS_PTR_NOTNULL(tc, ngap1);
/* Two gNB connects to UPF */
gtpu1 = test_gtpu_server(1, AF_INET);
ABTS_PTR_NOTNULL(tc, gtpu1);
gtpu2 = test_gtpu_server(2, AF_INET);
ABTS_PTR_NOTNULL(tc, gtpu2);
/* NG-Setup Reqeust/Response for Target gNB - with Target AMF */
sendbuf = testngap_build_ng_setup_request(0x4000, 28);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
recvbuf = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
/* NG-Setup Reqeust/Response for Source gNB - with Old AMF */
sendbuf = testngap_build_ng_setup_request(0x4001, 28);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
recvbuf_target = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue, recvbuf_target);
/* Register to Old AMF */
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
const char *scheme_output[] = {
"0000000001",
"0000000002",
"0000000003",
"0000000004",
"0000000005",
};
/* 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[i] = test_ue_add_by_suci(
&mobile_identity_suci, scheme_output[i]);
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_1; 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;
/* pdu_id == 5 */
/* 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 - with SUCI */
// 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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#if 0
/* Receive Identity request */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
#endif
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Security mode command */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive InitialContextSetupRequest +
* Registration accept */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, 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(ngap1, 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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Configuration update command */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDUSessionResourceSetupRequest +
* DL NAS transport +
* PDU session establishment accept */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
/* Send PDU session release 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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDUSessionResourceReleaseCommand +
* DL NAS transport +
* PDU session release command */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, 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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
for (i = 0; i < NUM_OF_TEST_UE_1; 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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UEContextReleaseCommand */
recvbuf = testgnb_ngap_read(ngap1);
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(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
/*
* Terminate Old AMF to simulate any kind of situation, where UE
* registers with GUTI from Old AMF which is not present anymore.
* Registration must not be rejected and must continue with
* identity request
*/
test_child_terminate_with_name("amf", 0);
ogs_msleep(300);
/* Register to Target AMF */
/* Make the same UE from scratch and give it the 5G GUTI from Old AMF */
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
const char *scheme_output_target[] = {
"0000000001",
"0000000002",
"0000000003",
"0000000004",
"0000000005",
};
/* 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_target[i] = test_ue_add_by_suci(
&mobile_identity_suci, scheme_output_target[i]);
ogs_assert(test_ue_target[i]);
test_ue_target[i]->nr_cgi.cell_id = 0x40000;
test_ue_target[i]->nas.registration.tsc = 0;
test_ue_target[i]->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue_target[i]->nas.registration.follow_on_request = 1;
test_ue_target[i]->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL;
test_ue_target[i]->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
test_ue_target[i]->opc_string = "e8ed289deba952e4283b54e88e6183ca";
}
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
if (i > 0)
test_ue_target[i]->ran_ue_ngap_id = test_ue_target[i-1]->ran_ue_ngap_id;
else
test_ue_target[i]->ran_ue_ngap_id = 0;
/* pdu_id == 6 */
/* Send PDU session establishment request */
sess = test_sess_add_by_dnn_and_psi(test_ue_target[i], "internet", 6);
ogs_assert(sess);
/********** Insert Subscriber in Database */
doc = test_db_new_simple(test_ue_target[i]);
ABTS_PTR_NOTNULL(tc, doc);
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue_target[i], doc));
/* Set the 5G GUTI to Old AMF's 5G GUTI */
test_ue_target[i]->nas_5gs_guti = test_ue[i]->nas_5gs_guti;
/* Send Registration request */
test_ue_target[i]->registration_request_param.guti = 1;
gmmbuf = testgmm_build_registration_request(test_ue_target[i], NULL, false, false);
ABTS_PTR_NOTNULL(tc, gmmbuf);
test_ue_target[i]->registration_request_param.gmm_capability = 1;
test_ue_target[i]->registration_request_param.s1_ue_network_capability = 1;
test_ue_target[i]->registration_request_param.requested_nssai = 1;
test_ue_target[i]->registration_request_param.last_visited_registered_tai = 1;
test_ue_target[i]->registration_request_param.ue_usage_setting = 1;
nasbuf = testgmm_build_registration_request(test_ue_target[i], NULL, false, false);
ABTS_PTR_NOTNULL(tc, nasbuf);
sendbuf = testngap_build_initial_ue_message(test_ue_target[i], gmmbuf,
NGAP_RRCEstablishmentCause_mo_Signalling, false, true);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Identity request */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
/* Send Identity response */
gmmbuf = testgmm_build_identity_response(test_ue_target[i]);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Authentication request */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
/* Send Authentication response */
gmmbuf = testgmm_build_authentication_response(test_ue_target[i]);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Security mode command */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
/* Send Security mode complete */
gmmbuf = testgmm_build_security_mode_complete(test_ue_target[i], nasbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive InitialContextSetupRequest +
* Registration accept */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_InitialContextSetup,
test_ue_target[i]->ngap_procedure_code);
/* Send UERadioCapabilityInfoIndication */
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue_target[i]);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send InitialContextSetupResponse */
sendbuf = testngap_build_initial_context_setup_response(test_ue_target[i], false);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Registration complete */
gmmbuf = testgmm_build_registration_complete(test_ue_target[i]);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Configuration update command */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
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_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDUSessionResourceSetupRequest +
* DL NAS transport +
* PDU session establishment accept */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
test_ue_target[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(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
/* Send PDU session release request */
sess = test_sess_find_by_psi(test_ue_target[i], 6);
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_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive PDUSessionResourceReleaseCommand +
* DL NAS transport +
* PDU session release command */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_PDUSessionResourceRelease,
test_ue_target[i]->ngap_procedure_code);
/* Send PDUSessionResourceReleaseResponse */
sendbuf = testngap_build_pdu_session_resource_release_response(sess);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, 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_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
/* Send De-registration request */
gmmbuf = testgmm_build_de_registration_request(test_ue_target[i], 1, true, true);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue_target[i], gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UEContextReleaseCommand */
recvbuf_target = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf_target);
testngap_recv(test_ue_target[i], recvbuf_target);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_UEContextRelease,
test_ue_target[i]->ngap_procedure_code);
/* Send UEContextReleaseComplete */
sendbuf = testngap_build_ue_context_release_complete(test_ue_target[i]);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
}
ogs_msleep(300);
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
/********** Remove Subscriber in Database */
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue_target[i]));
}
for (i = 0; i < NUM_OF_TEST_UE_1; i++) {
/********** Remove Subscriber in Database */
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue[i]));
}
/* Clear Test UE Context */
test_ue_remove_all();
/* gNB disonncect from UPF */
testgnb_gtpu_close(gtpu2);
/* gNB disonncect from UPF */
testgnb_gtpu_close(gtpu1);
/* gNB disonncect from Target AMF */
testgnb_ngap_close(ngap2);
/* gNB disonncect from Old AMF */
testgnb_ngap_close(ngap1);
}
abts_suite *test_ue_context_transfer_error_case(abts_suite *suite)
{
suite = ADD_SUITE(suite)
abts_run_test(suite, test1_func_error, NULL);
return suite;
}