Merge branch 'main' into home-routed

This commit is contained in:
Sukchan Lee
2025-06-30 10:02:57 +09:00
14 changed files with 641 additions and 39 deletions

View File

@@ -161,7 +161,7 @@ ogs_sbi_client_t *ogs_sbi_client_add(
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, client);
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, client);
#ifdef CURLMOPT_MAX_CONCURRENT_STREAMS
#if CURL_AT_LEAST_VERSION(7,67,0)
curl_multi_setopt(multi, CURLMOPT_MAX_CONCURRENT_STREAMS,
ogs_app()->pool.stream);
#endif

View File

@@ -3210,6 +3210,11 @@ static int parse_multipart(
ogs_assert(message);
ogs_assert(http);
if (!http->content) {
ogs_error("HTTP content NULL [%d]", (int)http->content_length);
return OGS_ERROR;
}
memset(&settings, 0, sizeof(settings));
settings.on_header_field = &on_header_field;
settings.on_header_value = &on_header_value;

View File

@@ -332,10 +332,33 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &sbi_message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &sbi_message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -4054,6 +4054,7 @@ void ngap_handle_handover_notification(
{
char buf[OGS_ADDRSTRLEN];
int i, r;
int xact_count;
amf_ue_t *amf_ue = NULL;
amf_sess_t *sess = NULL;
@@ -4213,15 +4214,14 @@ void ngap_handle_handover_notification(
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
/* Save the number of ongoing SMF transactions before processing sessions */
xact_count = amf_sess_xact_count(amf_ue);
ogs_list_for_each(&amf_ue->sess_list, sess) {
if (!SESSION_CONTEXT_IN_SMF(sess)) {
ogs_error("Session Context is not in SMF [%d]", sess->psi);
r = ngap_send_error_indication2(source_ue,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_partial_handover);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
return;
/* Warn if this UE session is not handled by SMF and skip it */
ogs_warn("Session Context is not in SMF [%d]", sess->psi);
continue;
}
memset(&param, 0, sizeof(param));
@@ -4234,6 +4234,19 @@ void ngap_handle_handover_notification(
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
/*
* If no SMF sessions were processed (transaction count unchanged),
* send partial-handover error
*/
if (xact_count == amf_sess_xact_count(amf_ue)) {
ogs_error("No SMF session were processed [%d]", sess->psi);
r = ngap_send_error_indication2(source_ue,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_partial_handover);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
}
void ngap_handle_ran_configuration_update(

View File

@@ -215,10 +215,33 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -234,10 +234,33 @@ void bsf_state_operational(ogs_fsm_t *s, bsf_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -221,10 +221,33 @@ void nssf_state_operational(ogs_fsm_t *s, nssf_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -381,10 +381,33 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -167,10 +167,33 @@ void scp_state_operational(ogs_fsm_t *s, scp_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -241,11 +241,32 @@ void sepp_state_operational(ogs_fsm_t *s, sepp_event_t *e)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
old_state = OGS_FSM_STATE(&nf_instance->sm);
ogs_assert(old_state);
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
if (old_state) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
/*
* The SEPP on the H-PLMN should send a n32c-handshake message

View File

@@ -836,10 +836,33 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &sbi_message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &sbi_message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -288,10 +288,33 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -225,10 +225,33 @@ void udr_state_operational(ogs_fsm_t *s, udr_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
nf_instance = e->h.sbi.data;
ogs_assert(nf_instance);
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
/*
* Guard against dispatching to an FSM that may have been finalized
* by an asynchronous shutdown triggered by SIGTERM.
*
* In init.cs event_termination(), which can be invoked asynchronously
* when the process receives SIGTERM, we iterate over all NF instances:
* ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
* ogs_sbi_nf_fsm_fini(nf_instance);
* and call ogs_fsm_fini() on each instances FSM. That finalizes the FSM
* and its state is reset to zero.
*
* After event_termination(), any incoming SBI response—such as an NRF
* client callback arriving after deregistration—would otherwise be
* dispatched into a dead FSM and trigger an assertion failure.
*
* To avoid this, we check OGS_FSM_STATE(&nf_instance->sm):
* - If non-zero, the FSM is still active and can safely handle the event.
* - If zero, the FSM has already been finalized by event_termination(),
* so we log and drop the event to allow graceful shutdown.
*/
if (OGS_FSM_STATE(&nf_instance->sm)) {
e->h.sbi.message = &message;
ogs_fsm_dispatch(&nf_instance->sm, e);
} else
ogs_error("NF instance FSM has been finalized");
break;
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)

View File

@@ -2714,6 +2714,361 @@ static void indirect_cancel_func(abts_case *tc, void *data)
test_ue_remove(test_ue);
}
static void partial_handover_func(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 *pkbuf;
ogs_ngap_message_t message;
int i;
uint8_t tmp[OGS_HUGE_LEN];
char *_gtp_payload = "34ff0024"
"0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002"
"00000964cd7c291f";
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
test_ue_t *test_ue = NULL;
test_sess_t *sess = NULL;
test_bearer_t *qos_flow = NULL;
uint64_t ran_ue_ngap_id;
uint64_t amf_ue_ngap_id;
bson_t *doc = NULL;
/* Setup Test UE & Session Context */
memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci));
mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI;
mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI;
mobile_identity_suci.routing_indicator1 = 0;
mobile_identity_suci.routing_indicator2 = 0xf;
mobile_identity_suci.routing_indicator3 = 0xf;
mobile_identity_suci.routing_indicator4 = 0xf;
mobile_identity_suci.protection_scheme_id = OGS_PROTECTION_SCHEME_NULL;
mobile_identity_suci.home_network_pki_value = 0;
test_ue = test_ue_add_by_suci(&mobile_identity_suci, "0000203190");
ogs_assert(test_ue);
test_ue->nr_cgi.cell_id = 0x40001;
test_ue->nas.registration.tsc = 0;
test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE;
test_ue->nas.registration.follow_on_request = 1;
test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL;
test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc";
test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca";
/* Two gNB connects to AMF */
ngap1 = testngap_client(1, AF_INET);
ABTS_PTR_NOTNULL(tc, ngap1);
ngap2 = testngap_client(1, AF_INET);
ABTS_PTR_NOTNULL(tc, ngap2);
/* 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 Source gNB */
sendbuf = testngap_build_ng_setup_request(0x4000, 28);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
recvbuf = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
/* NG-Setup Reqeust/Response for Target gNB */
sendbuf = testngap_build_ng_setup_request(0x4001, 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);
/********** Insert Subscriber in Database */
doc = test_db_new_simple(test_ue);
ABTS_PTR_NOTNULL(tc, doc);
ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc));
/* Send Registration request */
test_ue->registration_request_param.guti = 1;
gmmbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
ABTS_PTR_NOTNULL(tc, gmmbuf);
test_ue->registration_request_param.gmm_capability = 1;
test_ue->registration_request_param.s1_ue_network_capability = 1;
test_ue->registration_request_param.requested_nssai = 1;
test_ue->registration_request_param.last_visited_registered_tai = 1;
test_ue->registration_request_param.ue_usage_setting = 1;
nasbuf = testgmm_build_registration_request(test_ue, NULL, false, false);
ABTS_PTR_NOTNULL(tc, nasbuf);
sendbuf = testngap_build_initial_ue_message(test_ue, 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);
/* Receive Identity request */
recvbuf = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
/* Send Identity response */
gmmbuf = testgmm_build_identity_response(test_ue);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
/* Send Authentication response */
gmmbuf = testgmm_build_authentication_response(test_ue);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue, 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, recvbuf);
/* Send Security mode complete */
gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue, 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, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_InitialContextSetup,
test_ue->ngap_procedure_code);
/* Send UERadioCapabilityInfoIndication */
sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue);
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, 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);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(test_ue, 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, recvbuf);
/* Send PDU session establishment request */
sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5);
ogs_assert(sess);
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 = 1;
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, 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, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_PDUSessionResourceSetup,
test_ue->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);
/* Send PDU session establishment request */
sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6);
ogs_assert(sess);
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 = 1;
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, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive 5GMM status */
recvbuf = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_DownlinkNASTransport,
test_ue->ngap_procedure_code);
/* Remove ims session in test context */
test_sess_remove(sess);
/* Send HandoverRequired */
sendbuf = testngap_build_handover_required(
test_ue, NGAP_HandoverType_intra5gs,
0x4001, 28,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_handover_desirable_for_radio_reason,
false);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive HandoverRequest */
recvbuf = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_HandoverResourceAllocation,
test_ue->ngap_procedure_code);
/* Send HandoverRequestAcknowledge */
ogs_list_for_each(&test_ue->sess_list, sess)
sess->gnb_n3_addr = test_self()->gnb2_addr;
sendbuf = testngap_build_handover_request_ack(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive HandoverCommand */
recvbuf = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_HandoverPreparation,
test_ue->ngap_procedure_code);
/* Send UplinkRANStatusTransfer */
sendbuf = testngap_build_uplink_ran_status_transfer(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive DownlinkRANStatusTransfer */
recvbuf = testgnb_ngap_read(ngap2);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_DownlinkRANStatusTransfer,
test_ue->ngap_procedure_code);
/* Send HandoverNotify */
test_ue->nr_cgi.cell_id = 0x40011;
sendbuf = testngap_build_handover_notify(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap2, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive End Mark */
recvbuf = test_gtpu_read(gtpu1);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Receive UEContextReleaseCommand */
amf_ue_ngap_id = test_ue->amf_ue_ngap_id;
ran_ue_ngap_id = test_ue->ran_ue_ngap_id;
recvbuf = testgnb_ngap_read(ngap1);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(test_ue, recvbuf);
ABTS_INT_EQUAL(tc,
NGAP_ProcedureCode_id_UEContextRelease,
test_ue->ngap_procedure_code);
/* Send UEContextReleaseComplete */
sendbuf = testngap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap1, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
test_ue->amf_ue_ngap_id = amf_ue_ngap_id;
test_ue->ran_ue_ngap_id = ran_ue_ngap_id;
ogs_msleep(300);
/********** Remove Subscriber in Database */
ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue));
/* Two gNB disonncect from UPF */
testgnb_gtpu_close(gtpu1);
testgnb_gtpu_close(gtpu2);
/* Two gNB disonncect from AMF */
testgnb_ngap_close(ngap1);
testgnb_ngap_close(ngap2);
/* Clear Test UE Context */
test_ue_remove(test_ue);
}
abts_suite *test_5gc_n2(abts_suite *suite)
{
suite = ADD_SUITE(suite)
@@ -2723,6 +3078,7 @@ abts_suite *test_5gc_n2(abts_suite *suite)
abts_run_test(suite, direct_cancel_func, NULL);
abts_run_test(suite, indirect_complete_func, NULL);
abts_run_test(suite, indirect_cancel_func, NULL);
abts_run_test(suite, partial_handover_func, NULL);
return suite;
}