fix the 5GC test program

This commit is contained in:
Sukchan Lee 2020-07-29 23:26:12 -04:00
parent c72414481e
commit 2b2c51722f
24 changed files with 496 additions and 120 deletions

View File

@ -67,6 +67,8 @@ typedef unsigned int ogs_index_t;
#define ogs_pool_index(pool, node) (((node) - (pool)->array)+1)
#define ogs_pool_find(pool, _index) \
(_index > 0 && _index <= (pool)->size) ? (pool)->index[_index-1] : NULL
#define ogs_pool_cycle(pool, node) \
ogs_pool_find((pool), ogs_pool_index((pool), (node)))
#define ogs_pool_alloc(pool, node) do { \
*(node) = NULL; \

View File

@ -113,7 +113,7 @@ typedef struct ogs_sbi_object_s {
ogs_time_t duration;
} client_wait;
bool running;
int running_count;
OpenAPI_nf_type_e nf_type;
ogs_sbi_request_t *request;

View File

@ -121,7 +121,7 @@ bool ogs_sbi_discover_and_send(
ogs_assert(nf_type);
ogs_assert(build);
sbi_object->running = true;
sbi_object->running_count++;
sbi_object->nf_type = nf_type;
if (sbi_object->request)

View File

@ -344,9 +344,6 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
sbi_object = e->sbi.data;
ogs_assert(sbi_object);
sbi_object->running = false;
ogs_timer_stop(sbi_object->client_wait.timer);
SWITCH(sbi_message.h.method)
CASE(OGS_SBI_HTTP_METHOD_GET)
if (sbi_message.res_status == OGS_SBI_HTTP_STATUS_OK)
@ -374,12 +371,14 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
CASE(OGS_SBI_SERVICE_NAME_NUDM_SDM)
amf_ue = e->sbi.data;
ogs_assert(amf_ue);
amf_ue = amf_ue_cycle(amf_ue);
ogs_assert(amf_ue);
ogs_assert(OGS_FSM_STATE(&amf_ue->sm));
e->amf_ue = amf_ue;
e->sbi.message = &sbi_message;;
amf_ue->sbi.running = false;
amf_ue->sbi.running_count--;
ogs_timer_stop(amf_ue->sbi.client_wait.timer);
ogs_fsm_dispatch(&amf_ue->sm, e);
@ -388,15 +387,19 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
CASE(OGS_SBI_SERVICE_NAME_NSMF_PDUSESSION)
sess = e->sbi.data;
ogs_assert(sess);
sess = amf_sess_cycle(sess);
ogs_assert(sess);
amf_ue = sess->amf_ue;
ogs_assert(amf_ue);
amf_ue = amf_ue_cycle(amf_ue);
ogs_assert(amf_ue);
ogs_assert(OGS_FSM_STATE(&amf_ue->sm));
e->amf_ue = amf_ue;
e->sess = sess;
e->sbi.message = &sbi_message;;
sess->sbi.running = false;
sess->sbi.running_count--;
ogs_timer_stop(sess->sbi.client_wait.timer);
SWITCH(sbi_message.h.resource.component[2])
@ -466,7 +469,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
sbi_object = e->sbi.data;
ogs_assert(sbi_object);
sbi_object->running = false;
sbi_object->running_count--;
switch(sbi_object->nf_type) {
case OpenAPI_nf_type_AUSF:

View File

@ -1197,6 +1197,9 @@ void amf_ue_remove(amf_ue_t *amf_ue)
ogs_timer_delete(amf_ue->t3570.timer);
/* Free SBI object memory */
if (amf_ue->sbi.running_count)
ogs_error("[%s] SBI running [%d]",
amf_ue->supi, amf_ue->sbi.running_count);
ogs_sbi_object_free(&amf_ue->sbi);
ogs_timer_delete(amf_ue->sbi.client_wait.timer);
@ -1492,6 +1495,9 @@ void amf_sess_remove(amf_sess_t *sess)
ogs_list_remove(&sess->amf_ue->sess_list, sess);
/* Free SBI object memory */
if (sess->sbi.running_count)
ogs_error("[%s:%d] SBI running [%d]",
sess->amf_ue->supi, sess->psi, sess->sbi.running_count);
ogs_sbi_object_free(&sess->sbi);
ogs_timer_delete(sess->sbi.client_wait.timer);
@ -1529,12 +1535,33 @@ amf_sess_t *amf_sess_find_by_psi(amf_ue_t *amf_ue, uint8_t psi)
return NULL;
}
bool amf_sess_sync_done(amf_ue_t *amf_ue)
amf_ue_t *amf_ue_cycle(amf_ue_t *amf_ue)
{
return ogs_pool_cycle(&amf_ue_pool, amf_ue);
}
amf_sess_t *amf_sess_cycle(amf_sess_t *sess)
{
return ogs_pool_cycle(&amf_sess_pool, sess);
}
bool amf_ue_sync_done(amf_ue_t *amf_ue)
{
amf_sess_t *sess = NULL;
ogs_assert(amf_ue);
if (amf_ue->sbi.running_count) return false;
ogs_list_for_each(&amf_ue->sess_list, sess)
if (sess->sbi.running) return false;
if (sess->sbi.running_count) return false;
return true;
}
bool amf_sess_sync_done(amf_sess_t *sess)
{
ogs_assert(sess);
if (sess->sbi.running_count) return false;
return true;
}

View File

@ -399,12 +399,14 @@ typedef struct amf_sess_s {
char *sm_context_ref; /* smContextRef from SMF */
#define SESSION_SYNC_DONE(__aMF) \
(amf_sess_sync_done(__aMF) == true)
(amf_ue_sync_done(__aMF) == true)
/* UE session context is activated or not */
OpenAPI_up_cnx_state_e ueUpCnxState;
/* SMF session context is activated or not */
OpenAPI_up_cnx_state_e smfUpCnxState;
/* SMF notify status when PDU session release complete is received */
OpenAPI_resource_status_e resource_status;
ogs_pkbuf_t *n2smbuf;
@ -533,7 +535,11 @@ void amf_sess_remove_all(amf_ue_t *amf_ue);
amf_sess_t *amf_sess_find_by_psi(amf_ue_t *amf_ue, uint8_t psi);
amf_sess_t *amf_sess_find_by_dnn(amf_ue_t *amf_ue, char *dnn);
bool amf_sess_sync_done(amf_ue_t *amf_ue);
amf_ue_t *amf_ue_cycle(amf_ue_t *amf_ue);
amf_sess_t *amf_sess_cycle(amf_sess_t *sess);
bool amf_ue_sync_done(amf_ue_t *amf_ue);
bool amf_sess_sync_done(amf_sess_t *sess);
int amf_find_served_tai(ogs_5gs_tai_t *tai);
ogs_s_nssai_t *amf_find_s_nssai(

View File

@ -227,9 +227,24 @@ int amf_namf_callback_handle_sm_context_status(
goto cleanup;
}
if (StatusInfo->resource_status == OpenAPI_resource_status_RELEASED) {
sess->resource_status = StatusInfo->resource_status;
if (sess->resource_status == OpenAPI_resource_status_RELEASED) {
ogs_info("[%s:%d] SM context status released", amf_ue->supi, sess->psi);
amf_nsmf_pdu_session_handle_release_sm_context(sess);
/*
* Race condition for PDU session release complete
* - CLIENT : /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* - SERVER : /namf-callback/v1/{supi}/sm-context-status/{psi})
*
* If NOTIFICATION is received before the CLIENT response is received,
* CLIENT sync is not finished. In this case, the session context
* should not be removed.
*
* If NOTIFICATION comes after the CLIENT response is received,
* sync is done. So, the session context can be removed.
*/
if (amf_sess_sync_done(sess))
amf_nsmf_pdu_session_handle_release_sm_context(sess);
}
cleanup:

View File

@ -235,7 +235,21 @@ int amf_nsmf_pdu_session_handle_update_sm_context(
} else {
if (sess->ueUpCnxState == OpenAPI_up_cnx_state_ACTIVATED) {
if (!SESSION_CONTEXT_IN_SMF(sess)) {
/*
* 1. PDU session release complete
* CLEAR_SM_CONTEXT_REF(sess) in gmm-handler.c
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
*
* If resource-status has already been updated by
* notify(/namf-callback/v1/{supi}/sm-context-status/{psi})
* Remove 'amf_sess_t' context to call
* amf_nsmf_pdu_session_handle_release_sm_context().
*/
if (sess->resource_status == OpenAPI_resource_status_RELEASED)
amf_nsmf_pdu_session_handle_release_sm_context(sess);
} else if (sess->ueUpCnxState == OpenAPI_up_cnx_state_ACTIVATED) {
/*
* 1. PDUSessionResourceSetupResponse
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
@ -391,10 +405,6 @@ int amf_nsmf_pdu_session_handle_release_sm_context(amf_sess_t *sess)
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
NGAP_UE_CTX_REL_NG_CONTEXT_REMOVE, 0);
} else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered)) {
nas_5gs_send_accept(amf_ue);
} else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_exception)) {
/*
@ -407,13 +417,17 @@ int amf_nsmf_pdu_session_handle_release_sm_context(amf_sess_t *sess)
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release,
NGAP_UE_CTX_REL_UE_CONTEXT_REMOVE, 0);
} else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_registered)) {
ogs_debug("Release SM Context in registered STATE");
} else if (OGS_FSM_CHECK(&amf_ue->sm, gmm_state_security_mode)) {
ogs_error("Releasing SM Context in security-mode STATE");
ogs_error("Release SM Context in security-mode STATE");
} else {
ogs_error("Releasing SM Context : INVALID STATE");
ogs_error("Release SM Context : INVALID STATE");
}
}

View File

@ -253,10 +253,6 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
sbi_object = e->sbi.data;
ogs_assert(sbi_object);
ogs_timer_stop(sbi_object->client_wait.timer);
sbi_object->running = false;
SWITCH(message.h.method)
CASE(OGS_SBI_HTTP_METHOD_GET)
if (message.res_status == OGS_SBI_HTTP_STATUS_OK)
@ -282,12 +278,15 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
CASE(OGS_SBI_SERVICE_NAME_NUDM_UEAU)
ausf_ue = e->sbi.data;
ogs_assert(ausf_ue);
ausf_ue = ausf_ue_cycle(ausf_ue);
ogs_assert(ausf_ue);
ogs_assert(OGS_FSM_STATE(&ausf_ue->sm));
e->ausf_ue = ausf_ue;
e->sbi.message = &message;
ausf_ue->sbi.running = false;
ausf_ue->sbi.running_count--;
ogs_timer_stop(ausf_ue->sbi.client_wait.timer);
ogs_fsm_dispatch(&ausf_ue->sm, e);
if (OGS_FSM_CHECK(&ausf_ue->sm, ausf_ue_state_exception)) {
@ -340,7 +339,7 @@ void ausf_state_operational(ogs_fsm_t *s, ausf_event_t *e)
session = sbi_object->session;
ogs_assert(session);
sbi_object->running = false;
sbi_object->running_count--;
ogs_error("Cannot receive SBI message");
ogs_sbi_server_send_error(session,

View File

@ -165,6 +165,9 @@ void ausf_ue_remove(ausf_ue_t *ausf_ue)
ogs_fsm_delete(&ausf_ue->sm);
/* Free SBI object memory */
if (ausf_ue->sbi.running_count)
ogs_error("[%s] SBI running [%d]",
ausf_ue->supi, ausf_ue->sbi.running_count);
ogs_sbi_object_free(&ausf_ue->sbi);
ogs_timer_delete(ausf_ue->sbi.client_wait.timer);
@ -222,3 +225,8 @@ ausf_ue_t *ausf_ue_find_by_ctx_id(char *ctx_id)
ogs_assert(ctx_id);
return ogs_pool_find(&ausf_ue_pool, atoll(ctx_id));
}
ausf_ue_t *ausf_ue_cycle(ausf_ue_t *ausf_ue)
{
return ogs_pool_cycle(&ausf_ue_pool, ausf_ue);
}

View File

@ -101,6 +101,8 @@ ausf_ue_t *ausf_ue_find_by_supi(char *supi);
ausf_ue_t *ausf_ue_find_by_suci_or_supi(char *suci_or_supi);
ausf_ue_t *ausf_ue_find_by_ctx_id(char *ctx_id);
ausf_ue_t *ausf_ue_cycle(ausf_ue_t *ausf_ue);
#ifdef __cplusplus
}
#endif

View File

@ -121,8 +121,6 @@ void ausf_ue_state_operational(ogs_fsm_t *s, ausf_event_t *e)
SWITCH(message->h.service.name)
CASE(OGS_SBI_SERVICE_NAME_NUDM_UEAU)
ogs_timer_stop(ausf_ue->sbi.client_wait.timer);
if (message->res_status != OGS_SBI_HTTP_STATUS_OK &&
message->res_status != OGS_SBI_HTTP_STATUS_CREATED) {
if (message->res_status == OGS_SBI_HTTP_STATUS_NOT_FOUND) {

View File

@ -695,9 +695,11 @@ smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn)
/* Set APN */
ogs_cpystrn(sess->pdn.apn, apn, OGS_MAX_APN_LEN+1);
/* Setup SBI */
/* Setup Timer */
sess->sbi.client_wait.timer = ogs_timer_add(
self.timer_mgr, smf_timer_sbi_client_wait_expire, sess);
sess->t_release_holding = ogs_timer_add(
self.timer_mgr, smf_timer_release_holding_expire, sess);
memset(&e, 0, sizeof(e));
e.sess = sess;
@ -806,9 +808,11 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi)
sess->smf_n4_teid = sess->index;
sess->smf_n4_seid = sess->index;
/* Setup SBI */
/* Setup Timer */
sess->sbi.client_wait.timer = ogs_timer_add(
self.timer_mgr, smf_timer_sbi_client_wait_expire, sess);
sess->t_release_holding = ogs_timer_add(
self.timer_mgr, smf_timer_release_holding_expire, sess);
memset(&e, 0, sizeof(e));
e.sess = sess;
@ -979,8 +983,13 @@ void smf_sess_remove(smf_sess_t *sess)
ogs_freeaddrinfo(sess->upf_n3_addr6);
/* Free SBI object memory */
if (sess->sbi.running_count)
ogs_error("[%s:%d] SBI running [%d]",
smf_ue->supi, sess->psi, sess->sbi.running_count);
ogs_sbi_object_free(&sess->sbi);
ogs_timer_delete(sess->sbi.client_wait.timer);
ogs_timer_delete(sess->t_release_holding);
smf_bearer_remove_all(sess);
@ -1062,6 +1071,16 @@ smf_sess_t *smf_sess_find_by_ipv6(uint32_t *addr6)
return (smf_sess_t *)ogs_hash_get(self.ipv6_hash, addr6, OGS_IPV6_LEN);
}
smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue)
{
return ogs_pool_cycle(&smf_ue_pool, smf_ue);
}
smf_sess_t *smf_sess_cycle(smf_sess_t *sess)
{
return ogs_pool_cycle(&smf_sess_pool, sess);
}
smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess)
{
smf_bearer_t *qos_flow = NULL;

View File

@ -246,6 +246,9 @@ typedef struct smf_sess_s {
/* SMF session context is activated or not */
OpenAPI_up_cnx_state_e smfUpCnxState;
/* Release Holding timer of SMF session context */
ogs_timer_t *t_release_holding;
ogs_list_t bearer_list;
ogs_gtp_node_t *gnode;
@ -334,6 +337,9 @@ smf_sess_t *smf_sess_find_by_sm_context_ref(char *sm_context_ref);
smf_sess_t *smf_sess_find_by_ipv4(uint32_t addr);
smf_sess_t *smf_sess_find_by_ipv6(uint32_t *addr6);
smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue);
smf_sess_t *smf_sess_cycle(smf_sess_t *sess);
smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess);
smf_bearer_t *smf_qos_flow_find_by_qfi(smf_sess_t *sess, uint8_t qfi);

View File

@ -103,8 +103,6 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
ogs_timer_stop(sess->sbi.client_wait.timer);
SWITCH(sbi_message->h.service.name)
CASE(OGS_SBI_SERVICE_NAME_NUDM_SDM)
SWITCH(sbi_message->h.resource.component[1])
@ -188,9 +186,22 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE:
smf_sbi_send_response(sess, OGS_SBI_HTTP_STATUS_NO_CONTENT);
smf_sbi_send_sm_context_status_notify(sess);
OGS_FSM_TRAN(s, smf_gsm_state_released);
/*
* Race condition for PDU session release complete
* - CLIENT : /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
* - SERVER : /namf-callback/v1/{supi}/sm-context-status/{psi})
*
* smf_sbi_send_response(sess, OGS_SBI_HTTP_STATUS_NO_CONTENT);
* smf_sbi_send_sm_context_status_notify(sess);
*
* When executed as above,
* NOTIFY transmits first, and Modify's Response transmits later.
*
* Use the Release Timer to send Notify
* later than Modify's Response.
*/
ogs_timer_start(sess->t_release_holding, ogs_time_from_msec(1));
break;
default:
@ -242,30 +253,6 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
}
}
void smf_gsm_state_released(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;
ogs_assert(s);
ogs_assert(e);
smf_sm_debug(e);
sess = e->sess;
ogs_assert(sess);
switch (e->id) {
case OGS_FSM_ENTRY_SIG:
break;
case OGS_FSM_EXIT_SIG:
break;
default:
ogs_error("Unknown event %s", smf_event_get_name(e));
break;
}
}
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;

View File

@ -487,10 +487,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
sbi_object = e->sbi.data;
ogs_assert(sbi_object);
ogs_timer_stop(sbi_object->client_wait.timer);
sbi_object->running = false;
SWITCH(sbi_message.h.method)
CASE(OGS_SBI_HTTP_METHOD_GET)
if (sbi_message.res_status == OGS_SBI_HTTP_STATUS_OK)
@ -517,14 +513,19 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
sess = e->sbi.data;
ogs_assert(sess);
sess = smf_sess_cycle(sess);
ogs_assert(sess);
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
smf_ue = smf_ue_cycle(smf_ue);
ogs_assert(smf_ue);
ogs_assert(OGS_FSM_STATE(&sess->sm));
e->sess = sess;
e->sbi.message = &sbi_message;;
sess->sbi.running = false;
sess->sbi.running_count--;
ogs_timer_stop(sess->sbi.client_wait.timer);
ogs_fsm_dispatch(&sess->sm, e);
if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
@ -576,7 +577,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
session = sbi_object->session;
ogs_assert(session);
sbi_object->running = false;
sbi_object->running_count--;
ogs_error("Cannot receive SBI message");
ogs_sbi_server_send_error(session,
@ -584,6 +585,16 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
"Cannot receive SBI message", NULL);
break;
case SMF_TIMER_RELEASE_HOLDING:
sess = e->sbi.data;
ogs_assert(sess);
sess = smf_sess_cycle(sess);
ogs_assert(sess);
smf_sbi_send_sm_context_status_notify(sess);
SMF_SESS_CLEAR(sess);
break;
default:
ogs_error("Unknown timer[%s:%d]",
smf_timer_get_name(e->timer_id), e->timer_id);
@ -609,10 +620,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
e->nas.message = &nas_message;
ogs_fsm_dispatch(&sess->sm, e);
if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_released)) {
SMF_SESS_CLEAR(sess);
} else if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) {
ogs_error("State machine exception");
SMF_SESS_CLEAR(sess);
}

View File

@ -44,7 +44,6 @@ void smf_nf_state_exception(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_released(ogs_fsm_t *s, smf_event_t *e);
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e);
void smf_pfcp_state_initial(ogs_fsm_t *s, smf_event_t *e);

View File

@ -40,6 +40,8 @@ const char *smf_timer_get_name(smf_timer_e id)
return "SMF_TIMER_SUBSCRIPTION_VALIDITY";
case SMF_TIMER_SBI_CLIENT_WAIT:
return "SMF_TIMER_SBI_CLIENT_WAIT";
case SMF_TIMER_RELEASE_HOLDING:
return "SMF_TIMER_RELEASE_HOLDING";
default:
break;
}
@ -66,12 +68,8 @@ static void timer_send_event(int timer_id, void *data)
case SMF_TIMER_NF_INSTANCE_NO_HEARTBEAT:
case SMF_TIMER_NF_INSTANCE_VALIDITY:
case SMF_TIMER_SUBSCRIPTION_VALIDITY:
e = smf_event_new(SMF_EVT_SBI_TIMER);
ogs_assert(e);
e->timer_id = timer_id;
e->sbi.data = data;
break;
case SMF_TIMER_SBI_CLIENT_WAIT:
case SMF_TIMER_RELEASE_HOLDING:
e = smf_event_new(SMF_EVT_SBI_TIMER);
ogs_assert(e);
e->timer_id = timer_id;
@ -130,3 +128,8 @@ void smf_timer_sbi_client_wait_expire(void *data)
{
timer_send_event(SMF_TIMER_SBI_CLIENT_WAIT, data);
}
void smf_timer_release_holding_expire(void *data)
{
timer_send_event(SMF_TIMER_RELEASE_HOLDING, data);
}

View File

@ -39,6 +39,7 @@ typedef enum {
SMF_TIMER_NF_INSTANCE_VALIDITY,
SMF_TIMER_SUBSCRIPTION_VALIDITY,
SMF_TIMER_SBI_CLIENT_WAIT,
SMF_TIMER_RELEASE_HOLDING,
MAX_NUM_OF_SMF_TIMER,
@ -55,6 +56,7 @@ void smf_timer_nf_instance_no_heartbeat(void *data);
void smf_timer_nf_instance_validity(void *data);
void smf_timer_subscription_validity(void *data);
void smf_timer_sbi_client_wait_expire(void *data);
void smf_timer_release_holding_expire(void *data);
#ifdef __cplusplus
}

View File

@ -165,6 +165,9 @@ void udm_ue_remove(udm_ue_t *udm_ue)
ogs_fsm_delete(&udm_ue->sm);
/* Free SBI object memory */
if (udm_ue->sbi.running_count)
ogs_error("[%s] SBI running [%d]",
udm_ue->supi, udm_ue->sbi.running_count);
ogs_sbi_object_free(&udm_ue->sbi);
ogs_timer_delete(udm_ue->sbi.client_wait.timer);
OpenAPI_auth_event_free(udm_ue->auth_event);
@ -228,3 +231,8 @@ udm_ue_t *udm_ue_find_by_ctx_id(char *ctx_id)
ogs_assert(ctx_id);
return ogs_pool_find(&udm_ue_pool, atoll(ctx_id));
}
udm_ue_t *udm_ue_cycle(udm_ue_t *udm_ue)
{
return ogs_pool_cycle(&udm_ue_pool, udm_ue);
}

View File

@ -109,6 +109,8 @@ udm_ue_t *udm_ue_find_by_supi(char *supi);
udm_ue_t *udm_ue_find_by_suci_or_supi(char *suci_or_supi);
udm_ue_t *udm_ue_find_by_ctx_id(char *ctx_id);
udm_ue_t *udm_ue_cycle(udm_ue_t *udm_ue);
#ifdef __cplusplus
}
#endif

View File

@ -280,10 +280,6 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
sbi_object = e->sbi.data;
ogs_assert(sbi_object);
ogs_timer_stop(sbi_object->client_wait.timer);
sbi_object->running = false;
SWITCH(message.h.method)
CASE(OGS_SBI_HTTP_METHOD_GET)
if (message.res_status == OGS_SBI_HTTP_STATUS_OK)
@ -311,11 +307,14 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTION_DATA)
udm_ue = e->sbi.data;
ogs_assert(udm_ue);
udm_ue = udm_ue_cycle(udm_ue);
ogs_assert(udm_ue);
e->udm_ue = udm_ue;
e->sbi.message = &message;
udm_ue->sbi.running = false;
udm_ue->sbi.running_count--;
ogs_timer_stop(udm_ue->sbi.client_wait.timer);
ogs_fsm_dispatch(&udm_ue->sm, e);
if (OGS_FSM_CHECK(&udm_ue->sm, udm_ue_state_exception)) {
@ -375,7 +374,7 @@ void udm_state_operational(ogs_fsm_t *s, udm_event_t *e)
session = sbi_object->session;
ogs_assert(session);
sbi_object->running = false;
sbi_object->running_count--;
ogs_error("Cannot receive SBI message");
ogs_sbi_server_send_error(session,

View File

@ -167,8 +167,6 @@ void udm_ue_state_operational(ogs_fsm_t *s, udm_event_t *e)
session = udm_ue->sbi.session;
ogs_assert(session);
ogs_timer_stop(udm_ue->sbi.client_wait.timer);
SWITCH(message->h.service.name)
CASE(OGS_SBI_SERVICE_NAME_NUDR_DR)
SWITCH(message->h.resource.component[0])

View File

@ -410,6 +410,309 @@ static void test2_func(abts_case *tc, void *data)
const char *_opc_string = "6f1bf53d624b3a43af6592854e2444c7";
uint8_t opc[OGS_KEY_LEN];
mongoc_collection_t *collection = NULL;
bson_t *doc = NULL;
int64_t count = 0;
bson_error_t error;
const char *json =
"{"
"\"_id\" : { \"$oid\" : \"597223158b8861d7605378c6\" }, "
"\"imsi\" : \"901700000021309\","
#if 0
"\"msisdn\" : [\"821012345678\", \"82107654321\" ], "
"\"msisdn\" : [\"82107654321\", \"821012345678\" ], "
#endif
"\"ambr\" : { "
"\"uplink\" : { \"$numberLong\" : \"1024000\" }, "
"\"downlink\" : { \"$numberLong\" : \"1024000\" } "
"},"
"\"pdn\" : ["
"{"
"\"apn\" : \"internet\", "
"\"_id\" : { \"$oid\" : \"597223158b8861d7605378c7\" }, "
"\"ambr\" : {"
"\"uplink\" : { \"$numberLong\" : \"1024000\" }, "
"\"downlink\" : { \"$numberLong\" : \"1024000\" } "
"},"
"\"qos\" : { "
"\"qci\" : 9, "
"\"arp\" : { "
"\"priority_level\" : 8,"
"\"pre_emption_vulnerability\" : 1, "
"\"pre_emption_capability\" : 1"
"} "
"}, "
"\"type\" : 2"
"}"
"],"
"\"security\" : { "
"\"k\" : \"70d49a71dd1a2b806a25abe0ef749f1e\", "
"\"opc\" : \"6f1bf53d624b3a43af6592854e2444c7\", "
"\"amf\" : \"8000\", "
"\"sqn\" : { \"$numberLong\" : \"25235952177090\" } "
"}, "
"\"subscribed_rau_tau_timer\" : 12,"
"\"network_access_mode\" : 2, "
"\"subscriber_status\" : 0, "
"\"access_restriction_data\" : 32, "
"\"__v\" : 0 "
"}";
/* Setup Test UE & Session Context */
memset(&test_ue, 0, sizeof(test_ue));
memset(&test_sess, 0, sizeof(test_sess));
test_sess.test_ue = &test_ue;
test_ue.sess = &test_sess;
test_ue.nas.registration.type = 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;
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;
ogs_nas_from_plmn_id(&mobile_identity_suci.nas_plmn_id,
&test_self()->tai.plmn_id);
mobile_identity_suci.routing_indicator1 = 0;
mobile_identity_suci.routing_indicator2 = 0xf;
mobile_identity_suci.routing_indicator3 = 0xf;
mobile_identity_suci.routing_indicator4 = 0xf;
mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME;
mobile_identity_suci.home_network_pki_value = 0;
mobile_identity_suci.scheme_output[0] = 0;
mobile_identity_suci.scheme_output[1] = 0;
mobile_identity_suci.scheme_output[2] = 0x20;
mobile_identity_suci.scheme_output[3] = 0x31;
mobile_identity_suci.scheme_output[4] = 0x90;
test_ue_set_mobile_identity_suci(&test_ue, &mobile_identity_suci, 13);
memset(&test_ue.mobile_identity_imeisv, 0,
sizeof(ogs_nas_mobile_identity_imeisv_t));
test_ue.mobile_identity_imeisv.type = OGS_NAS_5GS_MOBILE_IDENTITY_IMEISV;
test_ue.mobile_identity_imeisv.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN;
test_ue.mobile_identity_imeisv.digit1 = 8;
test_ue.mobile_identity_imeisv.digit2 = 6;
test_ue.mobile_identity_imeisv.digit3 = 6;
test_ue.mobile_identity_imeisv.digit4 = 5;
test_ue.mobile_identity_imeisv.digit5 = 0;
test_ue.mobile_identity_imeisv.digit6 = 7;
test_ue.mobile_identity_imeisv.digit7 = 0;
test_ue.mobile_identity_imeisv.digit8 = 4;
test_ue.mobile_identity_imeisv.digit9 = 0;
test_ue.mobile_identity_imeisv.digit10 = 0;
test_ue.mobile_identity_imeisv.digit11 = 4;
test_ue.mobile_identity_imeisv.digit12 = 0;
test_ue.mobile_identity_imeisv.digit13 = 5;
test_ue.mobile_identity_imeisv.digit14 = 3;
test_ue.mobile_identity_imeisv.digit15 = 0;
test_ue.mobile_identity_imeisv.digit16 = 1;
test_ue.mobile_identity_imeisv.digit17 = 0xf;
test_ue.nas.access_type = OGS_ACCESS_TYPE_3GPP;
test_ue.abba_len = 2;
OGS_HEX(_k_string, strlen(_k_string), test_ue.k);
OGS_HEX(_opc_string, strlen(_opc_string), test_ue.opc);
test_sess.psi = 5;
test_sess.pti = 1;
test_sess.pdu_session_type = OGS_PDU_SESSION_TYPE_IPV4V6;
test_sess.dnn = (char *)"internet";
memset(&test_sess.gnb_n3_ip, 0, sizeof(test_sess.gnb_n3_ip));
test_sess.gnb_n3_ip.ipv4 = true;
test_sess.gnb_n3_ip.addr = inet_addr("127.0.0.5");
test_sess.gnb_n3_teid = 0;
/* gNB connects to AMF */
ngap = testgnb_ngap_client("127.0.0.2");
ABTS_PTR_NOTNULL(tc, ngap);
/* gNB connects to UPF */
gtpu = testgnb_gtpu_server("127.0.0.5");
ABTS_PTR_NOTNULL(tc, gtpu);
/* Send NG-Setup Reqeust */
sendbuf = testngap_build_ng_setup_request(0x4000, 26);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive NG-Setup Response */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/********** Insert Subscriber in Database */
collection = mongoc_client_get_collection(
ogs_mongoc()->client, ogs_mongoc()->name, "subscribers");
ABTS_PTR_NOTNULL(tc, collection);
doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi));
ABTS_PTR_NOTNULL(tc, doc);
count = mongoc_collection_count (
collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
if (count) {
ABTS_TRUE(tc, mongoc_collection_remove(collection,
MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error))
}
bson_destroy(doc);
doc = bson_new_from_json((const uint8_t *)json, -1, &error);;
ABTS_PTR_NOTNULL(tc, doc);
ABTS_TRUE(tc, mongoc_collection_insert(collection,
MONGOC_INSERT_NONE, doc, NULL, &error));
bson_destroy(doc);
doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi));
ABTS_PTR_NOTNULL(tc, doc);
do {
count = mongoc_collection_count (
collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
} while (count == 0);
bson_destroy(doc);
/* Send Registration request */
gmmbuf = testgmm_build_registration_request(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, gmmbuf);
test_ue.registration_request_param.gmm_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);
ABTS_PTR_NOTNULL(tc, nasbuf);
sendbuf = testngap_build_initial_ue_message(&test_ue, gmmbuf, false);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Authentication request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, 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(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Security mode command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, 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(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Initial context setup request */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send UE radio capability info indication */
sendbuf = testngap_build_ue_radio_capability_info_indication(&test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Initial context setup response */
sendbuf = testngap_build_initial_context_setup_response(&test_ue, NULL);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/* 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(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Configuration update command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send De-registration request */
gmmbuf = testgmm_build_de_registration_request(&test_ue, 1);
ABTS_PTR_NOTNULL(tc, gmmbuf);
sendbuf = testngap_build_uplink_nas_transport(&test_ue, gmmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UE context release command */
recvbuf = testgnb_ngap_read(ngap);
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send UE context release complete */
sendbuf = testngap_build_ue_context_release_complete(&test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/********** Remove Subscriber in Database */
doc = BCON_NEW("imsi", BCON_UTF8(test_ue.imsi));
ABTS_PTR_NOTNULL(tc, doc);
ABTS_TRUE(tc, mongoc_collection_remove(collection,
MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error))
bson_destroy(doc);
mongoc_collection_destroy(collection);
/* gNB disonncect from UPF */
testgnb_gtpu_close(gtpu);
/* gNB disonncect from AMF */
testgnb_ngap_close(ngap);
/* Clear Test UE Context */
test_ue_remove(&test_ue);
}
static void test3_func(abts_case *tc, void *data)
{
int rv;
ogs_socknode_t *ngap;
ogs_socknode_t *gtpu;
ogs_pkbuf_t *gmmbuf;
ogs_pkbuf_t *gsmbuf;
ogs_pkbuf_t *nasbuf;
ogs_pkbuf_t *sendbuf;
ogs_pkbuf_t *recvbuf;
ogs_ngap_message_t message;
int i;
int msgindex = 0;
ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci;
test_ue_t test_ue;
test_sess_t test_sess;
uint8_t tmp[OGS_MAX_SDU_LEN];
const char *_k_string = "70d49a71dd1a2b806a25abe0ef749f1e";
uint8_t k[OGS_KEY_LEN];
const char *_opc_string = "6f1bf53d624b3a43af6592854e2444c7";
uint8_t opc[OGS_KEY_LEN];
mongoc_collection_t *collection = NULL;
bson_t *doc = NULL;
int64_t count = 0;
@ -739,6 +1042,8 @@ static void test2_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/* Send De-registration request */
gmmbuf = testgmm_build_de_registration_request(&test_ue, 1);
ABTS_PTR_NOTNULL(tc, gmmbuf);
@ -870,8 +1175,7 @@ static void test2_func(abts_case *tc, void *data)
test_ue_remove(&test_ue);
}
#if 0
static void test3_func(abts_case *tc, void *data)
static void test4_func(abts_case *tc, void *data)
{
int rv;
ogs_socknode_t *ngap;
@ -1056,7 +1360,7 @@ static void test3_func(abts_case *tc, void *data)
} while (count == 0);
bson_destroy(doc);
for (i = 0; i < 1; i++) {
for (i = 0; i < 5; i++) {
/* Send Registration request */
test_ue.registration_request_param.gmm_capability = 0;
gmmbuf = testgmm_build_registration_request(&test_ue, NULL);
@ -1117,8 +1421,6 @@ static void test3_func(abts_case *tc, void *data)
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
/* Send Registration complete */
gmmbuf = testgmm_build_registration_complete(&test_ue);
ABTS_PTR_NOTNULL(tc, gmmbuf);
@ -1153,39 +1455,12 @@ static void test3_func(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, recvbuf);
testngap_recv(&test_ue, recvbuf);
/* Send GTP-U ICMP Packet */
rv = test_gtpu_build_ping(&sendbuf, &test_sess, "10.45.0.1");
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testgnb_gtpu_send(gtpu, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send PDU session resource setup response */
ogs_msleep(100);
sendbuf =
testngap_build_pdu_session_resource_setup_response(&test_sess);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive GTP-U ICMP Packet */
recvbuf = testgnb_gtpu_read(gtpu);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Send GTP-U ICMP Packet */
rv = test_gtpu_build_ping(&sendbuf, &test_sess, "10.45.0.1");
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testgnb_gtpu_send(gtpu, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive GTP-U ICMP Packet */
recvbuf = testgnb_gtpu_read(gtpu);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
ogs_msleep(100);
/* Send PDU Session release request */
test_sess.ul_nas_transport_param.request_type = 0;
test_sess.ul_nas_transport_param.dnn = 0;
@ -1246,8 +1521,6 @@ static void test3_func(abts_case *tc, void *data)
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testgnb_ngap_send(ngap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(100);
}
/********** Remove Subscriber in Database */
@ -1268,7 +1541,6 @@ static void test3_func(abts_case *tc, void *data)
/* Clear Test UE Context */
test_ue_remove(&test_ue);
}
#endif
abts_suite *test_dereg(abts_suite *suite)
{
@ -1276,9 +1548,8 @@ abts_suite *test_dereg(abts_suite *suite)
abts_run_test(suite, test1_func, NULL);
abts_run_test(suite, test2_func, NULL);
#if 0
abts_run_test(suite, test3_func, NULL);
#endif
abts_run_test(suite, test4_func, NULL);
return suite;
}