diff --git a/lib/diameter/s6b/message.h b/lib/diameter/s6b/message.h index d33ef167e..25e19e26d 100644 --- a/lib/diameter/s6b/message.h +++ b/lib/diameter/s6b/message.h @@ -34,6 +34,14 @@ extern struct dict_object *ogs_diam_s6b_application; extern struct dict_object *ogs_diam_s6b_mip6_feature_vector; +typedef struct ogs_diam_s6b_message_s { +#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 1 + uint16_t cmd_code; + uint32_t result_code; + uint32_t *err; + uint32_t *exp_err; +} ogs_diam_s6b_message_t; + int ogs_diam_s6b_init(void); #ifdef __cplusplus diff --git a/src/smf/context.h b/src/smf/context.h index a5c2c071f..70a5dddda 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -214,7 +214,13 @@ typedef struct smf_sess_s { bool gx_ccr_init_in_flight; /* Waiting for Gx CCA */ uint32_t gx_cca_init_err; /* Gx CCA RXed error code */ bool gy_ccr_init_in_flight; /* Waiting for Gy CCA */ - uint32_t gy_cca_init_err; /* Gx CCA RXed error code */ + uint32_t gy_cca_init_err; /* Gy CCA RXed error code */ + bool gx_ccr_term_in_flight; /* Waiting for Gx CCA */ + uint32_t gx_cca_term_err; /* Gx CCA RXed error code */ + bool gy_ccr_term_in_flight; /* Waiting for Gy CCA */ + uint32_t gy_cca_term_err; /* Gy CCA RXed error code */ + bool s6b_str_in_flight; /* Waiting for S6B CCA */ + uint32_t s6b_sta_err; /* S6B CCA RXed error code */ } sm_data; ogs_pfcp_sess_t pfcp; /* PFCP session context */ diff --git a/src/smf/event.c b/src/smf/event.c index 181aa0cc3..8dd6dea4f 100644 --- a/src/smf/event.c +++ b/src/smf/event.c @@ -64,6 +64,8 @@ const char *smf_event_get_name(smf_event_t *e) case SMF_EVT_S5C_MESSAGE: return "SMF_EVT_S5C_MESSAGE"; + case SMF_EVT_S6B_MESSAGE: + return "SMF_EVT_S6B_MESSAGE"; case SMF_EVT_GN_MESSAGE: return "SMF_EVT_GN_MESSAGE"; case SMF_EVT_GX_MESSAGE: diff --git a/src/smf/event.h b/src/smf/event.h index 3f8831e30..36c700c7b 100644 --- a/src/smf/event.h +++ b/src/smf/event.h @@ -34,6 +34,7 @@ typedef struct ogs_pfcp_xact_s ogs_pfcp_xact_t; typedef struct ogs_pfcp_message_s ogs_pfcp_message_t; typedef struct ogs_diam_gx_message_s ogs_diam_gx_message_t; typedef struct ogs_diam_gy_message_s ogs_diam_gy_message_t; +typedef struct ogs_diam_s6b_message_s ogs_diam_s6b_message_t; typedef struct smf_sess_s smf_sess_t; typedef struct smf_upf_s smf_upf_t; typedef struct ogs_sbi_request_s ogs_sbi_request_t; @@ -48,6 +49,7 @@ typedef enum { SMF_EVT_BASE = OGS_FSM_USER_SIG, SMF_EVT_S5C_MESSAGE, + SMF_EVT_S6B_MESSAGE, SMF_EVT_GN_MESSAGE, SMF_EVT_GX_MESSAGE, SMF_EVT_GY_MESSAGE, @@ -90,6 +92,7 @@ typedef struct smf_event_s { union { ogs_diam_gx_message_t *gx_message; ogs_diam_gy_message_t *gy_message; + ogs_diam_s6b_message_t *s6b_message; }; struct { diff --git a/src/smf/gn-handler.c b/src/smf/gn-handler.c index 83d6ce2ff..d96cc27f0 100644 --- a/src/smf/gn-handler.c +++ b/src/smf/gn-handler.c @@ -239,39 +239,20 @@ uint8_t smf_gn_handle_create_pdp_context_request( return cause_value; } -void smf_gn_handle_delete_pdp_context_request( +uint8_t smf_gn_handle_delete_pdp_context_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp1_delete_pdp_context_request_t *req) { - uint8_t cause_value = 0; - ogs_debug("Delete PDP Context Request"); - ogs_assert(xact); - ogs_assert(req); - - cause_value = OGS_GTP1_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP1_CAUSE_NON_EXISTENT; - } else { - if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { - ogs_error("No Gx Diameter Peer"); - cause_value = OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE; - } - } - - if (cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp1_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); - return; + if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { + ogs_error("No Gx Diameter Peer"); + return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE; } ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - smf_gx_send_ccr(sess, xact, - OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST); + return OGS_GTP1_CAUSE_REQUEST_ACCEPTED; } void smf_gn_handle_update_pdp_context_request( diff --git a/src/smf/gn-handler.h b/src/smf/gn-handler.h index 8e8f42e63..df1b60e62 100644 --- a/src/smf/gn-handler.h +++ b/src/smf/gn-handler.h @@ -35,7 +35,7 @@ void smf_gn_handle_echo_response( uint8_t smf_gn_handle_create_pdp_context_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp1_create_pdp_context_request_t *req); -void smf_gn_handle_delete_pdp_context_request( +uint8_t smf_gn_handle_delete_pdp_context_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp1_delete_pdp_context_request_t *req); void smf_gn_handle_update_pdp_context_request( diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index b57fdf86e..3af373dfc 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -76,6 +76,16 @@ static void send_gtp_create_err_msg(const smf_sess_t *sess, ogs_gtp_xact_t *gtp_ OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, gtp_cause); } +static void send_gtp_delete_err_msg(const smf_sess_t *sess, ogs_gtp_xact_t *gtp_xact, uint8_t gtp_cause) +{ + if (gtp_xact->gtp_version == 1) + ogs_gtp1_send_error_message(gtp_xact, sess->sgw_s5c_teid, + OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, gtp_cause); + else + ogs_gtp2_send_error_message(gtp_xact, sess->sgw_s5c_teid, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp_cause); +} + static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e) { int use_gy = smf_use_gy_iface(); @@ -103,6 +113,41 @@ static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e) return true; } +static bool send_ccr_termination_req_gx_gy_s6b(smf_sess_t *sess, smf_event_t *e) +{ + /* TODO: we should take into account here whether "sess" has an active Gy + session created, not whether one was supposedly created as per policy */ + int use_gy = smf_use_gy_iface(); + + if (use_gy == -1) { + ogs_error("No Gy Diameter Peer"); + /* TODO: drop Gx connection here, possibly move to another "releasing" state! */ + uint8_t gtp_cause = (e->gtp_xact->gtp_version == 1) ? + OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE : + OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; + send_gtp_delete_err_msg(sess, e->gtp_xact, gtp_cause); + return false; + } + + if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { + sess->sm_data.s6b_str_in_flight = true; + smf_s6b_send_str(sess, e->gtp_xact, + OGS_DIAM_TERMINATION_CAUSE_DIAMETER_LOGOUT); + } + + sess->sm_data.gx_ccr_term_in_flight = true; + smf_gx_send_ccr(sess, e->gtp_xact, + OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST); + + if (use_gy == 1) { + /* Gy is available, set up session for the bearer before accepting it towards the UE */ + sess->sm_data.gy_ccr_term_in_flight = true; + smf_gy_send_ccr(sess, e->gtp_xact, + OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST); + } + return true; +} + void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e) { ogs_assert(s); @@ -110,6 +155,8 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e) smf_sess_t *sess = e->sess; uint8_t gtp1_cause, gtp2_cause; + smf_sm_debug(e); + switch (e->id) { case OGS_FSM_ENTRY_SIG: /* reset state: */ @@ -171,6 +218,8 @@ void smf_gsm_state_initial_wait_auth(ogs_fsm_t *s, smf_event_t *e) smf_sess_t *sess = e->sess; uint32_t diam_err; + smf_sm_debug(e); + switch (e->id) { case SMF_EVT_GX_MESSAGE: switch(e->gx_message->cmd_code) { @@ -235,6 +284,8 @@ void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e) smf_sess_t *sess = e->sess; uint8_t pfcp_cause, gtp_cause; + smf_sm_debug(e); + switch (e->id) { case SMF_EVT_N4_MESSAGE: switch (e->pfcp_message->h.type) { @@ -322,6 +373,8 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) smf_n1_n2_message_transfer_param_t param; uint8_t pfcp_cause; + uint8_t gtp1_cause, gtp2_cause; + bool release; int state = 0; @@ -340,6 +393,44 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) case OGS_FSM_EXIT_SIG: break; + case SMF_EVT_GN_MESSAGE: + switch(e->gtp1_message->h.type) { + case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE: + gtp1_cause = smf_gn_handle_delete_pdp_context_request(sess, + e->gtp_xact, + &e->gtp1_message->delete_pdp_context_request); + if (gtp1_cause != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp1_send_error_message(e->gtp_xact, sess->sgw_s5c_teid, + OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, gtp1_cause); + return; + } + OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_pfcp_deletion); + } + break; + + case SMF_EVT_S5C_MESSAGE: + switch(e->gtp2_message->h.type) { + case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: + gtp2_cause = smf_s5c_handle_delete_session_request(sess, e->gtp_xact, + &e->gtp2_message->delete_session_request); + if (gtp2_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + ogs_gtp2_send_error_message(e->gtp_xact, sess->sgw_s5c_teid, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp2_cause); + return; + } + OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_pfcp_deletion); + break; + case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: + release = smf_s5c_handle_delete_bearer_response( + sess, e->gtp_xact, &e->gtp2_message->delete_bearer_response); + if (release) { + e->gtp_xact = NULL; + OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_pfcp_deletion); + } + break; + } + break; + case SMF_EVT_N4_MESSAGE: switch (e->pfcp_message->h.type) { case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE: @@ -361,6 +452,14 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_assert(param.n2smbuf); smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); break; + case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE: + /* This is left here for 5gc sessions to properly receive messages, + since tear down transitions are not implemented yet for 5gc + sessions. See #if0 in smf_gsm_state_initial_wait_pfcp_deletion() */ + assert(!e->pfcp_xact->epc); + smf_5gc_n4_handle_session_deletion_response(sess, + e->pfcp_xact, &e->pfcp_message->pfcp_session_deletion_response); + break; } break; @@ -743,6 +842,171 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) } } +void smf_gsm_state_release_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e) +{ + smf_sess_t *sess = NULL; + uint8_t pfcp_cause, gtp_cause; + ogs_gtp_xact_t *gtp_xact; + ogs_assert(s); + ogs_assert(e); + + smf_sm_debug(e); + + sess = e->sess; + ogs_assert(sess); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + ogs_assert(OGS_OK == + smf_epc_pfcp_send_session_deletion_request(sess, e->gtp_xact)); + break; + + case OGS_FSM_EXIT_SIG: + break; + + case SMF_EVT_GN_MESSAGE: + case SMF_EVT_S5C_MESSAGE: + break; /* ignore */ + + case SMF_EVT_N4_MESSAGE: + gtp_xact = e->pfcp_xact->assoc_xact; + switch (e->pfcp_message->h.type) { + case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE: + if (e->pfcp_xact->epc) { + gtp_xact = e->pfcp_xact->assoc_xact; + pfcp_cause = smf_epc_n4_handle_session_deletion_response(sess, + e->pfcp_xact, &e->pfcp_message->pfcp_session_deletion_response); + if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { + /* FIXME: tear down Gy and Gx */ + gtp_cause = gtp_cause_from_pfcp(pfcp_cause, gtp_xact->gtp_version); + send_gtp_delete_err_msg(sess, gtp_xact, gtp_cause); + return; + } + e->gtp_xact = gtp_xact; + if (send_ccr_termination_req_gx_gy_s6b(sess, e) == true) + OGS_FSM_TRAN(s, &smf_gsm_state_release_wait_auth); + /* else: free session? */ + } else { +#if 0 + /* This is currently not happening, since 5gc isn't yet properly + integrated and doesn't move to this state */ + smf_5gc_n4_handle_session_deletion_response(sess, + e->pfcp_xact, &message->pfcp_session_deletion_response); + return; /* TODO: implement handling of errors here */ +#endif + } + break; + } + return; + + default: + ogs_error("Unknown event %s", smf_event_get_name(e)); + break; + } +} + +void smf_gsm_state_release_wait_auth(ogs_fsm_t *s, smf_event_t *e) +{ + ogs_assert(e && e->sess); + smf_sess_t *sess = e->sess; + uint32_t diam_err; + + smf_sm_debug(e); + + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + /* reset state: */ + sess->sm_data.gx_cca_term_err = ER_DIAMETER_SUCCESS; + sess->sm_data.gy_cca_term_err = ER_DIAMETER_SUCCESS; + sess->sm_data.s6b_sta_err = ER_DIAMETER_SUCCESS; + break; + + case SMF_EVT_GN_MESSAGE: + case SMF_EVT_S5C_MESSAGE: + case SMF_EVT_N4_MESSAGE: + break; /* ignore */ + + case SMF_EVT_GX_MESSAGE: + switch(e->gx_message->cmd_code) { + case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL: + switch(e->gx_message->cc_request_type) { + case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST: + diam_err = smf_gx_handle_cca_termination_request(sess, + e->gx_message, e->gtp_xact); + sess->sm_data.gx_ccr_term_in_flight = false; + sess->sm_data.gx_cca_term_err = diam_err; + goto test_can_proceed; + } + break; + } + break; + + case SMF_EVT_GY_MESSAGE: + switch(e->gy_message->cmd_code) { + case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL: + switch(e->gy_message->cc_request_type) { + case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST: + ogs_assert(e->gtp_xact); + diam_err = smf_gy_handle_cca_termination_request(sess, + e->gy_message, e->gtp_xact); + sess->sm_data.gy_ccr_term_in_flight = false; + sess->sm_data.gy_cca_term_err = diam_err; + goto test_can_proceed; + } + break; + } + break; + + case SMF_EVT_S6B_MESSAGE: + switch(e->s6b_message->cmd_code) { + case OGS_DIAM_S6B_CMD_SESSION_TERMINATION: + sess->sm_data.s6b_str_in_flight = false; + /* TODO: validate error code from message below: */ + sess->sm_data.s6b_sta_err = ER_DIAMETER_SUCCESS; + goto test_can_proceed; + } + break; + } + return; + +test_can_proceed: + /* First wait for both Gx and Gy requests to be done: */ + if (!sess->sm_data.gx_ccr_term_in_flight && + !sess->sm_data.gy_ccr_term_in_flight && + !sess->sm_data.s6b_str_in_flight) { + diam_err = ER_DIAMETER_SUCCESS; + if (sess->sm_data.gx_cca_term_err != ER_DIAMETER_SUCCESS) + diam_err = sess->sm_data.gx_cca_term_err; + if (sess->sm_data.gy_cca_term_err != ER_DIAMETER_SUCCESS) + diam_err = sess->sm_data.gy_cca_term_err; + if (sess->sm_data.s6b_sta_err != ER_DIAMETER_SUCCESS) + diam_err = sess->sm_data.s6b_sta_err; + + /* Initiated by peer request, let's answer: */ + if (e->gtp_xact) { + if (diam_err == ER_DIAMETER_SUCCESS) { + /* + * 1. MME sends Delete Session Request to SGW/SMF. + * 2. SMF sends Delete Session Response to SGW/MME. + */ + switch (e->gtp_xact->gtp_version) { + case 1: + ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, e->gtp_xact)); + break; + case 2: + ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, e->gtp_xact)); + break; + } + } else { + uint8_t gtp_cause = gtp_cause_from_diameter(e->gtp_xact->gtp_version, + diam_err, NULL); + send_gtp_delete_err_msg(sess, e->gtp_xact, gtp_cause); + } + } + OGS_FSM_TRAN(s, &smf_gsm_state_session_will_release); + } +} + void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e) { smf_sess_t *sess = NULL; @@ -756,6 +1020,7 @@ void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e) switch (e->id) { case OGS_FSM_ENTRY_SIG: + SMF_SESS_CLEAR(sess); break; case OGS_FSM_EXIT_SIG: diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index 27bab4890..90719a4ce 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -243,26 +243,18 @@ uint32_t smf_gx_handle_cca_initial_request( return ER_DIAMETER_SUCCESS; } -void smf_gx_handle_cca_termination_request( +uint32_t smf_gx_handle_cca_termination_request( smf_sess_t *sess, ogs_diam_gx_message_t *gx_message, ogs_gtp_xact_t *gtp_xact) { ogs_assert(sess); ogs_assert(gx_message); - ogs_assert(gtp_xact); ogs_debug("[SMF] Delete Session Response"); ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - /* - * << 'gtp_xact' is NOT NULL >> - * - * 1. MME sends Delete Session Request to SGW/SMF. - * 2. SMF sends Delete Session Response to SGW/MME. - */ - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_deletion_request(sess, gtp_xact)); + return ER_DIAMETER_SUCCESS; } void smf_gx_handle_re_auth_request( diff --git a/src/smf/gx-handler.h b/src/smf/gx-handler.h index 99a0bd921..38066c37d 100644 --- a/src/smf/gx-handler.h +++ b/src/smf/gx-handler.h @@ -29,7 +29,7 @@ extern "C" { uint32_t smf_gx_handle_cca_initial_request( smf_sess_t *sess, ogs_diam_gx_message_t *gx_message, ogs_gtp_xact_t *gtp_xact); -void smf_gx_handle_cca_termination_request( +uint32_t smf_gx_handle_cca_termination_request( smf_sess_t *sess, ogs_diam_gx_message_t *gx_message, ogs_gtp_xact_t *gtp_xact); void smf_gx_handle_re_auth_request( diff --git a/src/smf/gx-path.c b/src/smf/gx-path.c index ed9e1ef72..8f260b518 100644 --- a/src/smf/gx-path.c +++ b/src/smf/gx-path.c @@ -93,7 +93,6 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact, struct sockaddr_in6 sin6; uint32_t charing_id; - ogs_assert(xact); ogs_assert(sess); ogs_assert(sess->ipv4 || sess->ipv6); @@ -742,7 +741,6 @@ static void smf_gx_cca_cb(void *data, struct msg **msg) ogs_debug(" CC-Request-Number[%d]", cc_request_number); xact = sess_data->xact[cc_request_number]; - ogs_assert(xact); sess = sess_data->sess; ogs_assert(sess); diff --git a/src/smf/gy-handler.c b/src/smf/gy-handler.c index a245b0871..4ea88daf3 100644 --- a/src/smf/gy-handler.c +++ b/src/smf/gy-handler.c @@ -182,7 +182,7 @@ void smf_gy_handle_cca_update_request( } } -void smf_gy_handle_cca_termination_request( +uint32_t smf_gy_handle_cca_termination_request( smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, ogs_gtp_xact_t *gtp_xact) { @@ -194,36 +194,7 @@ void smf_gy_handle_cca_termination_request( ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - if (gtp_xact) { - /* - * 1. MME sends Delete Session Request to SGW/SMF. - * 2. SMF sends Delete Session Response to SGW/MME. - */ - switch (gtp_xact->gtp_version) { - case 1: - ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact)); - break; - case 2: - ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact)); - break; - } - } else { - /* - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response to SGW/SMF. - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG. - * 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF. - * - * Note that the following messages are not processed here. - * - Bearer Resource Command - * - Delete Bearer Request/Response with DEDICATED BEARER. - */ - } - SMF_SESS_CLEAR(sess); - return; + return ER_DIAMETER_SUCCESS; } void smf_gy_handle_re_auth_request( diff --git a/src/smf/gy-handler.h b/src/smf/gy-handler.h index bc060b65b..7ad47e467 100644 --- a/src/smf/gy-handler.h +++ b/src/smf/gy-handler.h @@ -33,7 +33,7 @@ uint32_t smf_gy_handle_cca_initial_request( void smf_gy_handle_cca_update_request( smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, ogs_pfcp_xact_t *gtp_xact); -void smf_gy_handle_cca_termination_request( +uint32_t smf_gy_handle_cca_termination_request( smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, ogs_gtp_xact_t *gtp_xact); void smf_gy_handle_re_auth_request( diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 7d5510675..cc885cbf6 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -693,7 +693,7 @@ void smf_5gc_n4_handle_session_deletion_response( ogs_assert(stream); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); - SMF_SESS_CLEAR(sess); + OGS_FSM_TRAN(&sess->sm, smf_gsm_state_session_will_release); } else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) { smf_n1_n2_message_transfer_param_t param; @@ -1045,61 +1045,28 @@ void smf_epc_n4_handle_session_modification_response( } } -void smf_epc_n4_handle_session_deletion_response( +uint8_t smf_epc_n4_handle_session_deletion_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_deletion_response_t *rsp) { - uint8_t cause_value = 0; - uint8_t resp_type = 0; - ogs_gtp_xact_t *gtp_xact = NULL; smf_bearer_t *bearer = NULL; unsigned int i; + ogs_assert(sess); ogs_assert(xact); ogs_assert(rsp); ogs_debug("Session Deletion Response [epc]"); - gtp_xact = xact->assoc_xact; - ogs_pfcp_xact_commit(xact); - /* If !gtp_xact, set it to whatever valid, nothing is sent in the end anyway */ - uint8_t gtp_version = gtp_xact ? gtp_xact->gtp_version : 2; - - if (gtp_version == 1) { - resp_type = OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE; - cause_value = OGS_GTP1_CAUSE_REQUEST_ACCEPTED; - } else { - resp_type = OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE; - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - } - - if (!sess) { - ogs_warn("No Context"); - cause_value = (gtp_version == 1) ? - OGS_GTP1_CAUSE_NON_EXISTENT : - OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - - if (rsp->cause.presence) { - if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { - ogs_warn("PFCP Cause[%d] : Not Accepted", rsp->cause.u8); - cause_value = gtp_cause_from_pfcp(rsp->cause.u8, gtp_version); - } - } else { + if (!rsp->cause.presence) { ogs_error("No Cause"); - cause_value = (gtp_xact->gtp_version == 1) ? - OGS_GTP1_CAUSE_MANDATORY_IE_MISSING : - OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + return OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } - - if (gtp_xact && - ((gtp_version == 1 && cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) || - (gtp_version == 2 && cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED))) { - ogs_gtp_send_error_message(gtp_xact, sess->sgw_s5c_teid, resp_type, - cause_value); - return; + if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { + ogs_warn("PFCP Cause[%d] : Not Accepted", rsp->cause.u8); + return rsp->cause.u8; } ogs_assert(sess); @@ -1124,48 +1091,7 @@ void smf_epc_n4_handle_session_deletion_response( sess->gy.duration += use_rep->duration_measurement.u32; } - switch(smf_use_gy_iface()) { - case 1: - /* Gy is available, terminate the Gy session before terminating it towards the UE */ - smf_gy_send_ccr(sess, gtp_xact, - OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST); - return; - case -1: - ogs_error("No Gy Diameter Peer"); - break; /* continue below */ - /* default: continue below */ - } - - if (gtp_xact) { - /* - * 1. MME sends Delete Session Request to SGW/SMF. - * 2. SMF sends Delete Session Response to SGW/MME. - */ - switch (gtp_version) { - case 1: - ogs_assert(OGS_OK == smf_gtp1_send_delete_pdp_context_response(sess, gtp_xact)); - break; - case 2: - ogs_assert(OGS_OK == smf_gtp_send_delete_session_response(sess, gtp_xact)); - break; - } - } else { - /* - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to SGW/MME. - * 2. MME sends Delete Bearer Response to SGW/SMF. - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEFAULT BEARER) to ePDG. - * 2. ePDG sends Delete Bearer Response(DEFAULT BEARER) to SMF. - * - * Note that the following messages are not processed here. - * - Bearer Resource Command - * - Delete Bearer Request/Response with DEDICATED BEARER. - */ - } - - SMF_SESS_CLEAR(sess); + return OGS_PFCP_CAUSE_REQUEST_ACCEPTED; } void smf_n4_handle_session_report_request( diff --git a/src/smf/n4-handler.h b/src/smf/n4-handler.h index 0d9708d83..0a610e260 100644 --- a/src/smf/n4-handler.h +++ b/src/smf/n4-handler.h @@ -42,7 +42,7 @@ uint8_t smf_epc_n4_handle_session_establishment_response( void smf_epc_n4_handle_session_modification_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_modification_response_t *rsp); -void smf_epc_n4_handle_session_deletion_response( +uint8_t smf_epc_n4_handle_session_deletion_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_deletion_response_t *rsp); diff --git a/src/smf/pfcp-sm.c b/src/smf/pfcp-sm.c index 0f4b54f96..6425c1a97 100644 --- a/src/smf/pfcp-sm.c +++ b/src/smf/pfcp-sm.c @@ -245,17 +245,9 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) break; case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE: - if (!message->h.seid_presence) { + if (!message->h.seid_presence) ogs_error("No SEID"); - break; - } - - if (xact->epc) - smf_epc_n4_handle_session_deletion_response( - sess, xact, &message->pfcp_session_deletion_response); - else - smf_5gc_n4_handle_session_deletion_response( - sess, xact, &message->pfcp_session_deletion_response); + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_PFCP_SESSION_REPORT_REQUEST_TYPE: diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index a6fabf340..2cd2cdd61 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -304,58 +304,31 @@ uint8_t smf_s5c_handle_create_session_request( return OGS_GTP2_CAUSE_REQUEST_ACCEPTED; } -void smf_s5c_handle_delete_session_request( +uint8_t smf_s5c_handle_delete_session_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_delete_session_request_t *req) { - uint8_t cause_value = 0; - ogs_debug("Delete Session Request"); ogs_assert(xact); ogs_assert(req); - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - - if (!sess) { - ogs_warn("No Context"); - cause_value = OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } else { - if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { - ogs_error("No Gx Diameter Peer"); - cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; - } - - if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { - if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) { - ogs_error("No S6b Diameter Peer"); - cause_value = OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; - } - } + if (!ogs_diam_app_connected(OGS_DIAM_GX_APPLICATION_ID)) { + ogs_error("No Gx Diameter Peer"); + return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; } - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value); - return; + if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { + if (!ogs_diam_app_connected(OGS_DIAM_S6B_APPLICATION_ID)) { + ogs_error("No S6b Diameter Peer"); + return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; + } } ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - switch (sess->gtp_rat_type) { - case OGS_GTP2_RAT_TYPE_EUTRAN: - smf_gx_send_ccr(sess, xact, - OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST); - break; - case OGS_GTP2_RAT_TYPE_WLAN: - smf_s6b_send_str(sess, xact, - OGS_DIAM_TERMINATION_CAUSE_DIAMETER_LOGOUT); - break; - default: - ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); - ogs_assert_if_reached(); - } + return OGS_GTP2_CAUSE_REQUEST_ACCEPTED; } void smf_s5c_handle_modify_bearer_request( @@ -664,7 +637,8 @@ void smf_s5c_handle_update_bearer_response( OGS_GTP2_CAUSE_UNDEFINED_VALUE)); } -void smf_s5c_handle_delete_bearer_response( +/* return true if entire session must be released */ +bool smf_s5c_handle_delete_bearer_response( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_delete_bearer_response_t *rsp) { @@ -717,66 +691,64 @@ void smf_s5c_handle_delete_bearer_response( ogs_error("No Cause"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } + /* Release entire session: */ + return true; + } - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_deletion_request( - sess, NULL)); + /* + * 1. MME sends Bearer Resource Command to SGW/SMF. + * 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME + * 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF + * + * OR + * + * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME + * 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF + */ + if (rsp->bearer_contexts.presence == 0) { + ogs_error("No Bearer"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { + ogs_error("No EPS Bearer ID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } - } else { - /* - * 1. MME sends Bearer Resource Command to SGW/SMF. - * 2. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME - * 3. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF - * - * OR - * - * 1. SMF sends Delete Bearer Request(DEDICATED BEARER) to SGW/MME - * 2. MME sends Delete Bearer Response(DEDICATED BEARER) to SGW/SMF - */ - if (rsp->bearer_contexts.presence == 0) { - ogs_error("No Bearer"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (rsp->bearer_contexts.eps_bearer_id.presence == 0) { - ogs_error("No EPS Bearer ID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } + if (rsp->cause.presence) { + ogs_gtp2_cause_t *cause = rsp->cause.data; + ogs_assert(cause); - if (rsp->cause.presence) { - ogs_gtp2_cause_t *cause = rsp->cause.data; - ogs_assert(cause); + cause_value = cause->value; + if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + if (rsp->bearer_contexts.cause.presence) { + cause = rsp->bearer_contexts.cause.data; + ogs_assert(cause); - cause_value = cause->value; - if (cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - if (rsp->bearer_contexts.cause.presence) { - cause = rsp->bearer_contexts.cause.data; - ogs_assert(cause); - - cause_value = cause->value; - } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } + cause_value = cause->value; } else { - ogs_warn("GTP Failed [CAUSE:%d]", cause_value); + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } } else { - ogs_error("No Cause"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + ogs_warn("GTP Failed [CAUSE:%d]", cause_value); } - - ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); - - ogs_debug("Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]", - sess->sgw_s5c_teid, sess->smf_n4_teid); - - ogs_assert(OGS_OK == - smf_epc_pfcp_send_bearer_modification_request( - bearer, NULL, OGS_PFCP_MODIFY_REMOVE, - OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, - OGS_GTP2_CAUSE_UNDEFINED_VALUE)); + } else { + ogs_error("No Cause"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } + + ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); + + ogs_debug("Delete Bearer Response : SGW[0x%x] --> SMF[0x%x]", + sess->sgw_s5c_teid, sess->smf_n4_teid); + + ogs_assert(OGS_OK == + smf_epc_pfcp_send_bearer_modification_request( + bearer, NULL, OGS_PFCP_MODIFY_REMOVE, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_GTP2_CAUSE_UNDEFINED_VALUE)); + return false; } static int reconfigure_packet_filter(smf_pf_t *pf, ogs_gtp2_tft_t *tft, int i) diff --git a/src/smf/s5c-handler.h b/src/smf/s5c-handler.h index 1efe28ea4..b45e70199 100644 --- a/src/smf/s5c-handler.h +++ b/src/smf/s5c-handler.h @@ -34,7 +34,7 @@ void smf_s5c_handle_echo_response( uint8_t smf_s5c_handle_create_session_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_create_session_request_t *req); -void smf_s5c_handle_delete_session_request( +uint8_t smf_s5c_handle_delete_session_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_delete_session_request_t *req); void smf_s5c_handle_modify_bearer_request( @@ -46,7 +46,7 @@ void smf_s5c_handle_create_bearer_response( void smf_s5c_handle_update_bearer_response( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_update_bearer_response_t *req); -void smf_s5c_handle_delete_bearer_response( +bool smf_s5c_handle_delete_bearer_response( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_delete_bearer_response_t *req); void smf_s5c_handle_bearer_resource_command( diff --git a/src/smf/s6b-path.c b/src/smf/s6b-path.c index 280860ed6..141e3bad2 100644 --- a/src/smf/s6b-path.c +++ b/src/smf/s6b-path.c @@ -20,7 +20,7 @@ #include "fd-path.h" static struct session_handler *smf_s6b_reg = NULL; -static struct disp_hdl *hdl_s6b_fb = NULL; +static struct disp_hdl *hdl_s6b_fb = NULL; struct sess_state { smf_sess_t *sess; @@ -62,12 +62,12 @@ static void state_cleanup(struct sess_state *sess_data, os0_t sid, void *opaque) ogs_thread_mutex_unlock(&sess_state_mutex); } -static int smf_s6b_fb_cb(struct msg **msg, struct avp *avp, +static int smf_s6b_fb_cb(struct msg **msg, struct avp *avp, struct session *sess, void *opaque, enum disp_action *act) { /* This CB should never be called */ ogs_warn("Unexpected message received!"); - + return ENOTSUP; } @@ -488,7 +488,7 @@ void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause) smf_ue_t *smf_ue = NULL; char *user_name = NULL; - ogs_assert(xact); + //ogs_assert(xact); ogs_assert(sess); smf_ue = sess->smf_ue; ogs_assert(smf_ue); @@ -603,6 +603,7 @@ void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause) static void smf_s6b_sta_cb(void *data, struct msg **msg) { int ret; + int rv; struct sess_state *sess_data = NULL; struct timespec ts; @@ -612,11 +613,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg) unsigned long dur; int error = 0; int new; - int result_code = 0; - int exp_result_code = 0; + smf_event_t *e = NULL; smf_sess_t *sess = NULL; - ogs_gtp_xact_t *xact = NULL; + ogs_diam_s6b_message_t *s6b_message = NULL; ogs_debug("[Session-Termination-Answer]"); @@ -638,9 +638,11 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg) ogs_debug(" Retrieve its data: [%s]", sess_data->s6b_sid); sess = sess_data->sess; - ogs_assert(sess); - xact = sess_data->xact; - ogs_assert(xact); + + s6b_message = ogs_calloc(1, sizeof(ogs_diam_s6b_message_t)); + ogs_assert(s6b_message); + /* Set Session Termination Command */ + s6b_message->cmd_code = OGS_DIAM_S6B_CMD_SESSION_TERMINATION; /* Value of Result Code */ ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp); @@ -648,9 +650,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg) if (avp) { ret = fd_msg_avp_hdr(avp, &hdr); ogs_assert(ret == 0); - result_code = hdr->avp_value->i32; - if (result_code != ER_DIAMETER_SUCCESS) { - ogs_error("Result Code: %d", result_code); + s6b_message->result_code = hdr->avp_value->i32; + s6b_message->err = &s6b_message->result_code; + if (s6b_message->result_code != ER_DIAMETER_SUCCESS) { + ogs_error("Result Code: %d", s6b_message->result_code); error++; } } else { @@ -665,8 +668,10 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg) if (avpch1) { ret = fd_msg_avp_hdr(avpch1, &hdr); ogs_assert(ret == 0); - exp_result_code = hdr->avp_value->i32; - ogs_error("Experimental Result Code: %d", exp_result_code); + s6b_message->result_code = hdr->avp_value->i32; + s6b_message->exp_err = &s6b_message->result_code; + ogs_error("Experimental Result Code: %d", + s6b_message->result_code); } } else { ogs_error("no Result-Code"); @@ -700,8 +705,21 @@ static void smf_s6b_sta_cb(void *data, struct msg **msg) } if (!error) { - smf_gx_send_ccr(sess, xact, - OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST); + e = smf_event_new(SMF_EVT_S6B_MESSAGE); + ogs_assert(e); + + e->sess = sess; + e->s6b_message = s6b_message; + rv = ogs_queue_push(ogs_app()->queue, e); + if (rv != OGS_OK) { + ogs_warn("ogs_queue_push() failed:%d", (int)rv); + ogs_free(s6b_message); + smf_event_free(e); + } else { + ogs_pollset_notify(ogs_app()->pollset); + } + } else { + ogs_free(s6b_message); } /* Free the message */ diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index c9c71d495..8c4b7f07d 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -62,6 +62,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_diam_gx_message_t *gx_message = NULL; ogs_diam_gy_message_t *gy_message = NULL; + ogs_diam_s6b_message_t *s6b_message = NULL; ogs_pfcp_node_t *pfcp_node = NULL; ogs_pfcp_xact_t *pfcp_xact = NULL; @@ -145,8 +146,14 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: - smf_s5c_handle_delete_session_request( - sess, gtp_xact, >p2_message.delete_session_request); + if (!sess) { + ogs_gtp2_send_error_message(gtp_xact, 0, + OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, + OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); + break; + } + e->sess = sess; + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE: smf_s5c_handle_modify_bearer_request( @@ -161,8 +168,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) sess, gtp_xact, >p2_message.update_bearer_response); break; case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE: - smf_s5c_handle_delete_bearer_response( - sess, gtp_xact, >p2_message.delete_bearer_response); + if (!sess) { + /* TODO: NACK the message */ + break; + } + e->sess = sess; + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE: smf_s5c_handle_bearer_resource_command( @@ -230,8 +241,14 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE: - smf_gn_handle_delete_pdp_context_request( - sess, gtp_xact, >p1_message.delete_pdp_context_request); + if (!sess) { + ogs_gtp1_send_error_message(gtp_xact, 0, + OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, + OGS_GTP1_CAUSE_NON_EXISTENT); + break; + } + e->sess = sess; + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP1_UPDATE_PDP_CONTEXT_REQUEST_TYPE: smf_gn_handle_update_pdp_context_request( @@ -258,16 +275,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) switch(gx_message->cmd_code) { case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL: - gtp_xact = e->gtp_xact; - ogs_assert(gtp_xact); - switch(gx_message->cc_request_type) { case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST: ogs_fsm_dispatch(&sess->sm, e); break; case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST: - smf_gx_handle_cca_termination_request( - sess, gx_message, gtp_xact); + ogs_fsm_dispatch(&sess->sm, e); break; default: ogs_error("Not implemented(%d)", gx_message->cc_request_type); @@ -302,14 +315,12 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_fsm_dispatch(&sess->sm, e); break; case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST: - ogs_assert(e->pfcp_xact); - smf_gy_handle_cca_update_request( - sess, gy_message, e->pfcp_xact); + ogs_assert(e->pfcp_xact); + smf_gy_handle_cca_update_request( + sess, gy_message, e->pfcp_xact); break; case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST: - ogs_assert(e->gtp_xact); - smf_gy_handle_cca_termination_request( - sess, gy_message, e->gtp_xact); + ogs_fsm_dispatch(&sess->sm, e); break; default: ogs_error("Not implemented(%d)", gy_message->cc_request_type); @@ -328,6 +339,25 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_free(gy_message); break; + case SMF_EVT_S6B_MESSAGE: + ogs_assert(e); + s6b_message = e->s6b_message; + ogs_assert(s6b_message); + sess = e->sess; + ogs_assert(sess); + + switch(s6b_message->cmd_code) { + case OGS_DIAM_S6B_CMD_SESSION_TERMINATION: + ogs_fsm_dispatch(&sess->sm, e); + break; + default: + ogs_error("Invalid type(%d)", s6b_message->cmd_code); + break; + } + + ogs_free(s6b_message); + break; + case SMF_EVT_N4_MESSAGE: ogs_assert(e); recvbuf = e->pkbuf; @@ -716,9 +746,6 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) if (OGS_FSM_CHECK(&sess->sm, smf_gsm_state_exception)) { ogs_error("[%s] State machine exception", smf_ue->supi); SMF_SESS_CLEAR(sess); - } else if (OGS_FSM_CHECK( - &sess->sm, smf_gsm_state_session_will_release)) { - SMF_SESS_CLEAR(sess); } break; diff --git a/src/smf/smf-sm.h b/src/smf/smf-sm.h index 72960fe4a..a580bd9c7 100644 --- a/src/smf/smf-sm.h +++ b/src/smf/smf-sm.h @@ -43,13 +43,15 @@ 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_initial_wait_auth(ogs_fsm_t *s, smf_event_t *e); +void smf_gsm_state_initial_wait_pfcp_establishment(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_release_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e); +void smf_gsm_state_release_wait_auth(ogs_fsm_t *s, smf_event_t *e); void smf_gsm_state_session_will_release(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); -void smf_gsm_state_initial_wait_auth(ogs_fsm_t *s, smf_event_t *e); -void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e); void smf_pfcp_state_final(ogs_fsm_t *s, smf_event_t *e); void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e); void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e);