diff --git a/lib/core/ogs-list.h b/lib/core/ogs-list.h index da6af540e..849c39b31 100644 --- a/lib/core/ogs-list.h +++ b/lib/core/ogs-list.h @@ -75,6 +75,10 @@ static ogs_inline void *ogs_list_prev(void *lnode) for (node = ogs_list_first(list); (node); \ node = ogs_list_next(node)) +#define ogs_list_reverse_for_each(list, node) \ + for (node = ogs_list_last(list); (node); \ + node = ogs_list_prev(node)) + #define ogs_list_for_each_entry(list, node, member) \ for (node = ogs_list_entry(ogs_list_first(list), typeof(*node), member); \ (&node->member); \ diff --git a/lib/pfcp/xact.h b/lib/pfcp/xact.h index eb77fd436..113b6048d 100644 --- a/lib/pfcp/xact.h +++ b/lib/pfcp/xact.h @@ -107,12 +107,13 @@ typedef struct ogs_pfcp_xact_s { uint64_t modify_flags; -#define OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED 1 -#define OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED 2 -#define OGS_PFCP_DELETE_TRIGGER_RAN_INITIATED 3 -#define OGS_PFCP_DELETE_TRIGGER_SMF_INITIATED 4 -#define OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT 5 -#define OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT 6 +#define OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED 1 +#define OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED 2 +#define OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED 3 +#define OGS_PFCP_DELETE_TRIGGER_RAN_INITIATED 4 +#define OGS_PFCP_DELETE_TRIGGER_SMF_INITIATED 5 +#define OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT 6 +#define OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT 7 int delete_trigger; ogs_list_t pdr_to_create_list; diff --git a/src/smf/context.c b/src/smf/context.c index 07e05e8c1..c267debbe 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -18,6 +18,7 @@ */ #include "context.h" +#include "pfcp-path.h" static smf_context_t self; static ogs_diam_config_t g_diam_conf; @@ -1138,7 +1139,7 @@ smf_sess_t *smf_sess_add_by_gtp1_message(ogs_gtp1_message_t *message) sess = smf_sess_find_by_apn(smf_ue, apn, req->rat_type.u8); if (sess) { - ogs_warn("OLD Session Release [IMSI:%s,APN:%s]", + ogs_warn("OLD Session Will Release [IMSI:%s,APN:%s]", smf_ue->imsi_bcd, sess->session.name); smf_sess_remove(sess); } @@ -1202,7 +1203,7 @@ smf_sess_t *smf_sess_add_by_gtp2_message(ogs_gtp2_message_t *message) sess = smf_sess_find_by_apn(smf_ue, apn, req->rat_type.u8); if (sess) { - ogs_info("OLD Session Release [IMSI:%s,APN:%s]", + ogs_info("OLD Session Will Release [IMSI:%s,APN:%s]", smf_ue->imsi_bcd, sess->session.name); smf_sess_remove(sess); } @@ -1308,7 +1309,7 @@ smf_sess_t *smf_sess_add_by_sbi_message(ogs_sbi_message_t *message) sess = smf_sess_find_by_psi(smf_ue, SmContextCreateData->pdu_session_id); if (sess) { - ogs_warn("OLD Session Release [SUPI:%s,PDU Session identity:%d]", + ogs_warn("OLD Session Will Release [SUPI:%s,PDU Session identity:%d]", SmContextCreateData->supi, SmContextCreateData->pdu_session_id); smf_sess_remove(sess); } @@ -1503,7 +1504,7 @@ smf_sess_t *smf_sess_find_by_error_indication_report( return NULL; } - ogs_list_for_each(&smf_ue->sess_list, sess) { + ogs_list_reverse_for_each(&smf_ue->sess_list, sess) { if (teid == sess->gnb_n3_teid) { if (len == OGS_IPV4_LEN && sess->gnb_n3_ip.ipv4 && memcmp(addr, &sess->gnb_n3_ip.addr, len) == 0) { @@ -1656,7 +1657,7 @@ smf_sess_t *smf_sess_find_by_apn(smf_ue_t *smf_ue, char *apn, uint8_t rat_type) ogs_assert(smf_ue); ogs_assert(apn); - ogs_list_for_each(&smf_ue->sess_list, sess) { + ogs_list_reverse_for_each(&smf_ue->sess_list, sess) { if (ogs_strcasecmp(sess->session.name, apn) == 0 && sess->gtp_rat_type == rat_type) return sess; @@ -1672,7 +1673,7 @@ smf_sess_t *smf_sess_find_by_psi(smf_ue_t *smf_ue, uint8_t psi) ogs_assert(smf_ue); ogs_assert(psi != OGS_NAS_PDU_SESSION_IDENTITY_UNASSIGNED); - ogs_list_for_each(&smf_ue->sess_list, sess) { + ogs_list_reverse_for_each(&smf_ue->sess_list, sess) { if (sess->psi == psi) return sess; } diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 6df57a3ca..7433ad16f 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -160,7 +160,11 @@ static bool send_sbi_message_from_delete_trigger( ogs_sbi_message_t sendmsg; ogs_sbi_response_t *response = NULL; - if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) { + if (trigger == OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED) { + + /* Nothing */ + + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) { ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL; n1smbuf = gsm_build_pdu_session_release_command( @@ -1215,14 +1219,23 @@ void smf_gsm_state_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e) &pfcp_message->pfcp_session_deletion_response); if (status != OGS_SBI_HTTP_STATUS_OK) { ogs_error( - "smf_5gc_n4_handle_session_deletion_response() failed"); + "[%d] smf_5gc_n4_handle_session_deletion_response() " + "failed", trigger); + + OGS_FSM_TRAN(s, smf_gsm_state_session_will_release); break; } if (send_sbi_message_from_delete_trigger( sess, stream, trigger) == true) { - if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || + if (trigger == OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED) { + + ogs_warn("OLD Session Released"); + OGS_FSM_TRAN(s, smf_gsm_state_session_will_release); + + } else if ( + trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) { OGS_FSM_TRAN(s, smf_gsm_state_wait_5gc_n1_n2_release); @@ -1234,9 +1247,6 @@ void smf_gsm_state_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e) OGS_FSM_TRAN(s, smf_gsm_state_session_will_release); - } else if (trigger == - OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) { - } else { ogs_fatal("Unknown trigger [%d]", trigger); ogs_assert_if_reached(); diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 948075b75..c88482c41 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -641,9 +641,13 @@ int smf_5gc_n4_handle_session_deletion_response( if (status != OGS_SBI_HTTP_STATUS_OK) { char *strerror = ogs_msprintf( - "PFCP Cause [%d] : Not Accepted", rsp->cause.u8); + "[%d] PFCP Cause [%d] : Not Accepted", trigger, rsp->cause.u8); - if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || + if (trigger == OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED) { + + /* Nothing */ + + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || trigger == OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT) { ogs_assert(stream); smf_sbi_send_sm_context_update_error( diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index b306dd0da..a3d326497 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -169,6 +169,7 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) smf_sess_t *sess = NULL; ogs_sbi_stream_t *stream = NULL; uint8_t type; + int trigger; char *strerror = NULL; ogs_assert(xact); @@ -176,12 +177,12 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) sess = data; ogs_assert(sess); - stream = xact->assoc_stream; - ogs_assert(stream); smf_ue = sess->smf_ue; ogs_assert(smf_ue); + stream = xact->assoc_stream; type = xact->seq[0].type; + switch (type) { case OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE: ogs_error("No PFCP session establishment response"); @@ -192,21 +193,43 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) ogs_assert(strerror); ogs_error("%s", strerror); + ogs_assert(stream); smf_sbi_send_sm_context_update_error(stream, OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, strerror, NULL, NULL, NULL); ogs_free(strerror); break; case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: - strerror = ogs_msprintf("[%s:%d] No PFCP session deletion response", - smf_ue->supi, sess->psi); + trigger = xact->delete_trigger; + ogs_assert(trigger); + + strerror = ogs_msprintf("[%s:%d] No PFCP session deletion response[%d]", + smf_ue->supi, sess->psi, trigger); ogs_assert(strerror); ogs_error("%s", strerror); - ogs_assert(true == - ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, strerror, NULL)); + + if (trigger == OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED || + trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) { + + /* Nothing */ + + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || + trigger == OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT || + trigger == OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) { + + ogs_assert(stream); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, strerror, NULL)); + } else { + ogs_fatal("Unknown trigger [%d]", trigger); + ogs_assert_if_reached(); + } + ogs_free(strerror); + + smf_sess_remove(sess); break; default: ogs_error("Not implemented [type:%d]", type); diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index 066b8ef28..578aa1d03 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -211,7 +211,7 @@ uint8_t smf_s5c_handle_create_session_request( if (eutran_sess) { /* Need to check handover is possible */ int eutran_session_count = 0; - ogs_list_for_each(&smf_ue->sess_list, eutran_sess) { + ogs_list_reverse_for_each(&smf_ue->sess_list, eutran_sess) { if (eutran_sess->gtp_rat_type != OGS_GTP2_RAT_TYPE_EUTRAN) continue; if (strcmp(eutran_sess->session.name, sess->session.name) == 0)