diff --git a/src/smf/context.h b/src/smf/context.h index be7c3ef5b0..243d814691 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -427,6 +427,8 @@ typedef struct smf_sess_s { ogs_pfcp_node_t *pfcp_node; bool pfcp_established; + ogs_pfcp_xact_t *timeout_xact; + ogs_timer_t *timer_gx_cca; ogs_timer_t *timer_gy_cca; diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 6a23f113c8..68c1cf8fdb 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -720,8 +720,25 @@ void smf_gsm_state_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e) case SMF_EVT_N4_TIMER: switch (e->h.timer_id) { case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE: - OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject); + ogs_error("PFCP timeout waiting for Session Establishment Response"); + + if (timeout_xact->epc) { + ogs_gtp_xact_t *gtp_xact = (ogs_gtp_xact_t *) sess->timeout_xact->assoc_xact; + + switch (gtp_xact->gtp_version) { + case 1: + gtp_cause = OGS_GTP1_CAUSE_NETWORK_FAILURE; + break; + case 2: + gtp_cause = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; + break; + } + send_gtp_create_err_msg(sess, gtp_xact, gtp_cause); + } else { + OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject); + } break; + default: ogs_error("Unknown timer[%s:%d]", ogs_timer_get_name(e->h.timer_id), e->h.timer_id); @@ -1267,8 +1284,25 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) case SMF_EVT_N4_TIMER: switch (e->h.timer_id) { case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE: - OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject); + ogs_error("PFCP timeout waiting for Session Establishment Response"); + + if (timeout_xact->epc) { + ogs_gtp_xact_t *gtp_xact = (ogs_gtp_xact_t *) sess->timeout_xact->assoc_xact; + + switch (gtp_xact->gtp_version) { + case 1: + gtp_cause = OGS_GTP1_CAUSE_NETWORK_FAILURE; + break; + case 2: + gtp_cause = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; + break; + } + send_gtp_create_err_msg(sess, gtp_xact, gtp_cause); + } else { + OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject); + } break; + default: ogs_error("Unknown timer[%s:%d]", ogs_timer_get_name(e->h.timer_id), e->h.timer_id); @@ -1440,6 +1474,34 @@ void smf_gsm_state_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e) ogs_error("cannot handle PFCP message type[%d]", pfcp_message->h.type); } + break; + + case SMF_EVT_N4_TIMER: + switch(e->h.timer_id) { + case SMF_TIMER_PFCP_NO_DELETION_RESPONSE: + ogs_error("PFCP timeout waiting for Session Deletion Response"); + + if (timeout_xact->epc) { + gtp_xact = (ogs_gtp_xact_t *) sess->timeout_xact->assoc_xact; + + switch (gtp_xact->gtp_version) { + case 1: + gtp_cause = OGS_GTP1_CAUSE_NETWORK_FAILURE; + break; + case 2: + gtp_cause = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; + break; + } + send_gtp_delete_err_msg(sess, gtp_xact, gtp_cause); + } else { + ogs_error("5GC Session Deletion timeout not written"); + } + break; + + default: + ogs_error("Unknown timer[%s:%d]", + ogs_timer_get_name(e->h.timer_id), e->h.timer_id); } + break; } } diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index 116cf9f7eb..4242f70487 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -226,25 +226,15 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) ogs_assert(sess); smf_ue = sess->smf_ue; ogs_assert(smf_ue); - + sess->timeout_xact = xact; + stream = xact->assoc_stream; type = xact->seq[0].type; switch (type) { case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE: ogs_warn("No PFCP session establishment response"); - - e = smf_event_new(SMF_EVT_N4_TIMER); - ogs_assert(e); - e->sess = sess; - e->h.timer_id = SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE; - e->pfcp_node = sess->pfcp_node; - - rv = ogs_queue_push(ogs_app()->queue, e); - if (rv != OGS_OK) { - ogs_error("ogs_queue_push() failed:%d", (int)rv); - ogs_event_free(e); - } + smf_timeout_pfcp_no_establishment_response(data); break; case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: strerror = ogs_msprintf("[%s:%d] No PFCP session modification response", @@ -299,19 +289,26 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) static void sess_epc_timeout(ogs_pfcp_xact_t *xact, void *data) { uint8_t type; + smf_sess_t *sess; ogs_assert(xact); type = xact->seq[0].type; + sess = data; + sess->timeout_xact = xact; + switch (type) { case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE: ogs_warn("No PFCP session establishment response"); + smf_timeout_pfcp_no_establishment_response(data); break; case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: - ogs_error("No PFCP session modification response"); + ogs_warn("No PFCP session modification response"); + smf_timeout_pfcp_no_modification_response(data); break; case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: - ogs_error("No PFCP session deletion response"); + ogs_warn("No PFCP session deletion response"); + smf_timeout_pfcp_no_deletion_response(data); break; default: ogs_error("Not implemented [type:%d]", type); @@ -328,7 +325,8 @@ static void bearer_epc_timeout(ogs_pfcp_xact_t *xact, void *data) switch (type) { case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: - ogs_error("No PFCP session modification response"); + ogs_warn("No PFCP session modification response"); + smf_timeout_pfcp_no_modification_response(data); break; default: ogs_error("Not implemented [type:%d]", type); diff --git a/src/smf/pfcp-sm.c b/src/smf/pfcp-sm.c index 55d564d6ee..7a74a1da82 100644 --- a/src/smf/pfcp-sm.c +++ b/src/smf/pfcp-sm.c @@ -117,6 +117,8 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e) ogs_pfcp_cp_send_association_setup_request(node, node_timeout); break; case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE: + case SMF_TIMER_PFCP_NO_DELETION_RESPONSE: + case SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE: sess = e->sess; sess = smf_sess_cycle(sess); if (!sess) { @@ -402,6 +404,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) ogs_pfcp_send_heartbeat_request(node, node_timeout)); break; case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE: + case SMF_TIMER_PFCP_NO_DELETION_RESPONSE: + case SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE: sess = e->sess; sess = smf_sess_cycle(sess); if (!sess) { diff --git a/src/smf/timer.c b/src/smf/timer.c index d8dfd56211..fcd87e90c0 100644 --- a/src/smf/timer.c +++ b/src/smf/timer.c @@ -42,6 +42,10 @@ const char *smf_timer_get_name(int timer_id) return "SMF_TIMER_PFCP_NO_HEARTBEAT"; case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE: return "SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE"; + case SMF_TIMER_PFCP_NO_DELETION_RESPONSE: + return "SMF_TIMER_PFCP_NO_DELETION_RESPONSE"; + case SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE: + return "SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE"; default: break; } @@ -78,6 +82,16 @@ static void timer_send_event(int timer_id, void *data) e->gtp_xact = old_e->gtp_xact; break; + case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE: + case SMF_TIMER_PFCP_NO_DELETION_RESPONSE: + case SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE: + e = smf_event_new(SMF_EVT_N4_TIMER); + ogs_assert(e); + e->h.timer_id = timer_id; + e->sess = data; + e->pfcp_node = sess->pfcp_node; + break; + default: ogs_fatal("Unknown timer id[%d]", timer_id); ogs_assert_if_reached(); @@ -110,4 +124,19 @@ void smf_timer_gx_no_cca(void *data) void smf_timer_gy_no_cca(void *data) { timer_send_event(SMF_TIMER_GY_CCA, data); +} + +void smf_timeout_pfcp_no_establishment_response(void *data) +{ + timer_send_event(SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE, data); +} + +void smf_timeout_pfcp_no_deletion_response(void *data) +{ + timer_send_event(SMF_TIMER_PFCP_NO_DELETION_RESPONSE, data); +} + +void smf_timeout_pfcp_no_modification_response(void *data) +{ + timer_send_event(SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE, data); } \ No newline at end of file diff --git a/src/smf/timer.h b/src/smf/timer.h index e4c62b2164..5bf4c1f3c9 100644 --- a/src/smf/timer.h +++ b/src/smf/timer.h @@ -33,6 +33,8 @@ typedef enum { SMF_TIMER_PFCP_ASSOCIATION, SMF_TIMER_PFCP_NO_HEARTBEAT, SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE, + SMF_TIMER_PFCP_NO_DELETION_RESPONSE, + SMF_TIMER_PFCP_NO_MODIFICATION_RESPONSE, SMF_TIMER_GX_CCA, SMF_TIMER_GY_CCA, @@ -47,6 +49,10 @@ void smf_timer_pfcp_no_heartbeat(void *data); void smf_timer_gx_no_cca(void *data); void smf_timer_gy_no_cca(void *data); +void smf_timeout_pfcp_no_establishment_response(void *data); +void smf_timeout_pfcp_no_deletion_response(void *data); +void smf_timeout_pfcp_no_modification_response(void *data); + #ifdef __cplusplus } #endif