diff --git a/src/sgwc/pfcp-path.c b/src/sgwc/pfcp-path.c index 7e67db6670..aa2e870664 100644 --- a/src/sgwc/pfcp-path.c +++ b/src/sgwc/pfcp-path.c @@ -160,25 +160,71 @@ void sgwc_pfcp_close(void) ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list6); } -static void sess_timeout(ogs_pfcp_xact_t *xact, void *data) +static void sess_timeout(ogs_pfcp_xact_t *pfcp_xact, void *data) { - uint8_t type; + uint8_t pfcp_type; - ogs_assert(xact); - type = xact->seq[0].type; + uint8_t gtp_cause; + uint8_t gtp_type; + ogs_gtp_xact_t * s11_xact = NULL; + sgwc_sess_t *sess = data; + sgwc_ue_t *sgwc_ue = NULL; - switch (type) { + ogs_assert(pfcp_xact); + ogs_assert(sess); + + s11_xact = pfcp_xact->assoc_xact; + ogs_assert(s11_xact); + + switch (s11_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; + } + + sgwc_ue = sess->sgwc_ue; + + pfcp_type = pfcp_xact->seq[0].type; + switch (pfcp_type) { case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE: - ogs_error("No PFCP session establishment response"); + ogs_error("Timeout: No PFCP session establishment response"); + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, gtp_cause); break; case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: - ogs_error("No PFCP session modification response"); + ogs_error("Timeout: No PFCP session modification response"); + + // multiple gtp message-types are translated to pfcp session mod request + switch (s11_xact->seq[0].type) { + case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: + gtp_type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; + break; + case OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE: + gtp_type = OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE; + break; + default: + ogs_error("GTP request type not implemented: %d", s11_xact->seq[0].type); + gtp_type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE; + break; + } + + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + gtp_type, gtp_cause); break; case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: - ogs_error("No PFCP session deletion response"); + ogs_error("Timeout: No PFCP session deletion response"); + ogs_gtp_send_error_message( + s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp_cause); + sgwc_sess_remove(sess); break; default: - ogs_error("Not implemented [type:%d]", type); + ogs_error("PFCP request type not implemented [type:%d]", pfcp_type); break; } } diff --git a/src/smf/context.h b/src/smf/context.h index 51f4f43d19..672d30a384 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -412,6 +412,8 @@ typedef struct smf_sess_s { ogs_gtp_node_t *gnode; 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/event.h b/src/smf/event.h index 64effdbe67..8ca4ae6f31 100644 --- a/src/smf/event.h +++ b/src/smf/event.h @@ -52,7 +52,8 @@ typedef enum { SMF_EVT_GX_MESSAGE, SMF_EVT_GY_MESSAGE, SMF_EVT_DIAMETER_TIMER, - + SMF_EVT_PFCP_TIMEOUT, + SMF_EVT_N4_MESSAGE, SMF_EVT_N4_TIMER, SMF_EVT_N4_NO_HEARTBEAT, diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 15a8caa042..43fa97c63e 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -691,6 +691,8 @@ void smf_gsm_state_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e) ogs_pfcp_message_t *pfcp_message = NULL; int rv; + ogs_gtp_xact_t *gtp_xact = NULL; + ogs_assert(s); ogs_assert(e); @@ -779,6 +781,29 @@ void smf_gsm_state_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e) ogs_error("cannot handle PFCP message type[%d]", pfcp_message->h.type); } + break; + + case SMF_EVT_PFCP_TIMEOUT: + switch(e->h.timer_id) { + case SMF_TIMEOUT_PFCP_SER: + ogs_error("PFCP timeout waiting for Session Establishment Response"); + + 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); + break; + + default: + ogs_error("Unknown SMF_EVT_PFCP_TIMEOUT timer id [%d]", e->h.timer_id); + } } } @@ -1369,6 +1394,30 @@ 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_PFCP_TIMEOUT: + switch(e->h.timer_id) { + case SMF_TIMEOUT_PFCP_SDR: + ogs_error("PFCP timeout waiting for Session Deletion Response"); + + 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); + break; + + default: + ogs_error("Unknown SMF_EVT_PFCP_TIMEOUT timer id [%d]", e->h.timer_id); + } + break; } } diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index ac9b3dd6c9..cebfb5b234 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -277,19 +277,23 @@ 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_ser(data); break; case OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE: - ogs_error("No PFCP session modification response"); + smf_timeout_pfcp_no_smr(data); break; case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: - ogs_error("No PFCP session deletion response"); + smf_timeout_pfcp_no_sdr(data); break; default: ogs_error("Not implemented [type:%d]", type); @@ -306,7 +310,7 @@ 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"); + smf_timeout_pfcp_no_smr(data); break; default: ogs_error("Not implemented [type:%d]", type); diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index c6befa43ab..67ca2f2303 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -366,6 +366,15 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) } break; + case SMF_EVT_PFCP_TIMEOUT: + ogs_assert(e); + sess = e->sess; + if (sess) { + ogs_assert(OGS_FSM_STATE(&sess->sm)); + ogs_fsm_dispatch(&sess->sm, e); + } + break; + case SMF_EVT_S6B_MESSAGE: ogs_assert(e); s6b_message = e->s6b_message; diff --git a/src/smf/timer.c b/src/smf/timer.c index 31a6b94956..ece92836bb 100644 --- a/src/smf/timer.c +++ b/src/smf/timer.c @@ -72,6 +72,14 @@ static void timer_send_event(int timer_id, void *data) e->gx_message = old_e->gx_message; e->gtp_xact = old_e->gtp_xact; break; + case SMF_TIMEOUT_PFCP_SER: + case SMF_TIMEOUT_PFCP_SDR: + case SMF_TIMEOUT_PFCP_SMR: + e = smf_event_new(SMF_EVT_PFCP_TIMEOUT); + ogs_assert(e); + e->h.timer_id = timer_id; + e->sess = data; + break; default: ogs_fatal("Unknown timer id[%d]", timer_id); ogs_assert_if_reached(); @@ -105,3 +113,18 @@ void smf_timer_gy_no_cca(void *data) { timer_send_event(SMF_TIMER_GY_CCA, data); } + +void smf_timeout_pfcp_no_ser(void *data) +{ + timer_send_event(SMF_TIMEOUT_PFCP_SER, data); +} + +void smf_timeout_pfcp_no_sdr(void *data) +{ + timer_send_event(SMF_TIMEOUT_PFCP_SDR, data); +} + +void smf_timeout_pfcp_no_smr(void *data) +{ + timer_send_event(SMF_TIMEOUT_PFCP_SMR, data); +} diff --git a/src/smf/timer.h b/src/smf/timer.h index b35702e1cb..89f5a30508 100644 --- a/src/smf/timer.h +++ b/src/smf/timer.h @@ -34,6 +34,9 @@ typedef enum { SMF_TIMER_PFCP_NO_HEARTBEAT, SMF_TIMER_GX_CCA, SMF_TIMER_GY_CCA, + SMF_TIMEOUT_PFCP_SER, + SMF_TIMEOUT_PFCP_SDR, + SMF_TIMEOUT_PFCP_SMR, MAX_NUM_OF_SMF_TIMER, @@ -46,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_ser(void *data); +void smf_timeout_pfcp_no_sdr(void *data); +void smf_timeout_pfcp_no_smr(void *data); + #ifdef __cplusplus } #endif