mirror of
https://github.com/open5gs/open5gs.git
synced 2025-11-03 05:23:38 +00:00
Merge branch 'main' into home-routed
This commit is contained in:
@@ -161,7 +161,7 @@ ogs_sbi_client_t *ogs_sbi_client_add(
|
|||||||
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, client);
|
curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, client);
|
||||||
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
|
curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb);
|
||||||
curl_multi_setopt(multi, CURLMOPT_TIMERDATA, client);
|
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,
|
curl_multi_setopt(multi, CURLMOPT_MAX_CONCURRENT_STREAMS,
|
||||||
ogs_app()->pool.stream);
|
ogs_app()->pool.stream);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3210,6 +3210,11 @@ static int parse_multipart(
|
|||||||
ogs_assert(message);
|
ogs_assert(message);
|
||||||
ogs_assert(http);
|
ogs_assert(http);
|
||||||
|
|
||||||
|
if (!http->content) {
|
||||||
|
ogs_error("HTTP content NULL [%d]", (int)http->content_length);
|
||||||
|
return OGS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&settings, 0, sizeof(settings));
|
memset(&settings, 0, sizeof(settings));
|
||||||
settings.on_header_field = &on_header_field;
|
settings.on_header_field = &on_header_field;
|
||||||
settings.on_header_value = &on_header_value;
|
settings.on_header_value = &on_header_value;
|
||||||
|
|||||||
@@ -332,10 +332,33 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -4054,6 +4054,7 @@ void ngap_handle_handover_notification(
|
|||||||
{
|
{
|
||||||
char buf[OGS_ADDRSTRLEN];
|
char buf[OGS_ADDRSTRLEN];
|
||||||
int i, r;
|
int i, r;
|
||||||
|
int xact_count;
|
||||||
|
|
||||||
amf_ue_t *amf_ue = NULL;
|
amf_ue_t *amf_ue = NULL;
|
||||||
amf_sess_t *sess = NULL;
|
amf_sess_t *sess = NULL;
|
||||||
@@ -4213,15 +4214,14 @@ void ngap_handle_handover_notification(
|
|||||||
ogs_expect(r == OGS_OK);
|
ogs_expect(r == OGS_OK);
|
||||||
ogs_assert(r != OGS_ERROR);
|
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) {
|
ogs_list_for_each(&amf_ue->sess_list, sess) {
|
||||||
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
if (!SESSION_CONTEXT_IN_SMF(sess)) {
|
||||||
ogs_error("Session Context is not in SMF [%d]", sess->psi);
|
/* Warn if this UE session is not handled by SMF and skip it */
|
||||||
r = ngap_send_error_indication2(source_ue,
|
ogs_warn("Session Context is not in SMF [%d]", sess->psi);
|
||||||
NGAP_Cause_PR_radioNetwork,
|
continue;
|
||||||
NGAP_CauseRadioNetwork_partial_handover);
|
|
||||||
ogs_expect(r == OGS_OK);
|
|
||||||
ogs_assert(r != OGS_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(¶m, 0, sizeof(param));
|
memset(¶m, 0, sizeof(param));
|
||||||
@@ -4234,6 +4234,19 @@ void ngap_handle_handover_notification(
|
|||||||
ogs_expect(r == OGS_OK);
|
ogs_expect(r == OGS_OK);
|
||||||
ogs_assert(r != OGS_ERROR);
|
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(
|
void ngap_handle_ran_configuration_update(
|
||||||
|
|||||||
@@ -215,10 +215,33 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -234,10 +234,33 @@ void bsf_state_operational(ogs_fsm_t *s, bsf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -221,10 +221,33 @@ void nssf_state_operational(ogs_fsm_t *s, nssf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -381,10 +381,33 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -167,10 +167,33 @@ void scp_state_operational(ogs_fsm_t *s, scp_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -241,11 +241,32 @@ void sepp_state_operational(ogs_fsm_t *s, sepp_event_t *e)
|
|||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
ogs_assert(nf_instance);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guard against dispatching to an FSM that may have been finalized
|
||||||
|
* by an asynchronous shutdown triggered by SIGTERM.
|
||||||
|
*
|
||||||
|
* In init.c’s 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 instance’s 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);
|
old_state = OGS_FSM_STATE(&nf_instance->sm);
|
||||||
ogs_assert(old_state);
|
if (old_state) {
|
||||||
|
e->h.sbi.message = &message;
|
||||||
e->h.sbi.message = &message;
|
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||||
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
|
* The SEPP on the H-PLMN should send a n32c-handshake message
|
||||||
|
|||||||
@@ -836,10 +836,33 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -288,10 +288,33 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -225,10 +225,33 @@ void udr_state_operational(ogs_fsm_t *s, udr_event_t *e)
|
|||||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||||
nf_instance = e->h.sbi.data;
|
nf_instance = e->h.sbi.data;
|
||||||
ogs_assert(nf_instance);
|
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.c’s 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 instance’s 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;
|
break;
|
||||||
|
|
||||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||||
|
|||||||
@@ -2714,6 +2714,361 @@ static void indirect_cancel_func(abts_case *tc, void *data)
|
|||||||
test_ue_remove(test_ue);
|
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)
|
abts_suite *test_5gc_n2(abts_suite *suite)
|
||||||
{
|
{
|
||||||
suite = ADD_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, direct_cancel_func, NULL);
|
||||||
abts_run_test(suite, indirect_complete_func, NULL);
|
abts_run_test(suite, indirect_complete_func, NULL);
|
||||||
abts_run_test(suite, indirect_cancel_func, NULL);
|
abts_run_test(suite, indirect_cancel_func, NULL);
|
||||||
|
abts_run_test(suite, partial_handover_func, NULL);
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user