diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 32da155f2..7ec051e6f 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -337,6 +337,7 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e) ogs_diam_gy_message_t *gy_message = NULL; ogs_diam_gx_message_t *gx_message = NULL; uint32_t diam_err; + bool need_gy_terminate = false; ogs_assert(s); ogs_assert(e); @@ -392,7 +393,7 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e) case OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST: ogs_assert(e->gtp_xact); diam_err = smf_gy_handle_cca_initial_request(sess, - gy_message, e->gtp_xact); + gy_message, e->gtp_xact, &need_gy_terminate); sess->sm_data.gy_ccr_init_in_flight = false; sess->sm_data.gy_cca_init_err = diam_err; goto test_can_proceed; @@ -422,8 +423,16 @@ test_can_proceed: smf_epc_pfcp_send_session_establishment_request( sess, e->gtp_xact, 0)); } else { - /* FIXME: tear down Gx/Gy session - * if its sm_data.*init_err == ER_DIAMETER_SUCCESS */ + /* Tear down Gx/Gy session if its sm_data.*init_err == ER_DIAMETER_SUCCESS */ + if (sess->sm_data.gx_cca_init_err == ER_DIAMETER_SUCCESS) { + 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 (smf_use_gy_iface() == 1 && + (sess->sm_data.gy_cca_init_err == ER_DIAMETER_SUCCESS || need_gy_terminate)) { + 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); + } uint8_t gtp_cause = gtp_cause_from_diameter( e->gtp_xact->gtp_version, diam_err, NULL); send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause); diff --git a/src/smf/gy-handler.c b/src/smf/gy-handler.c index 78dfa2e01..63b780a50 100644 --- a/src/smf/gy-handler.c +++ b/src/smf/gy-handler.c @@ -113,24 +113,41 @@ static void urr_update_time(smf_sess_t *sess, ogs_pfcp_urr_t *urr, ogs_diam_gy_m } } -/* Returns ER_DIAMETER_SUCCESS on success, Diameter error code on failue. */ +/* Returns ER_DIAMETER_SUCCESS on success, Diameter error code on failue. + * Upon failure, CCR-Terminate is needed based on "need_termination" value (this + * may happen eg. if messaged RC is successful but MSCC RC is rejected). */ uint32_t smf_gy_handle_cca_initial_request( smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_gtp_xact_t *gtp_xact) + ogs_gtp_xact_t *gtp_xact, + bool *need_termination) { smf_bearer_t *bearer; ogs_assert(sess); ogs_assert(gy_message); ogs_assert(gtp_xact); + ogs_assert(need_termination); ogs_debug("[Gy CCA Initial]"); ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - if (gy_message->result_code != ER_DIAMETER_SUCCESS) + *need_termination = false; + if (gy_message->result_code != ER_DIAMETER_SUCCESS) { + ogs_warn("Gy CCA Initial Diameter failure: res=%u", + gy_message->result_code); return gy_message->err ? *gy_message->err : ER_DIAMETER_AUTHENTICATION_REJECTED; + } + if (gy_message->cca.result_code != ER_DIAMETER_SUCCESS) { + ogs_warn("Gy CCA Initial Diameter Multiple-Services-Credit-Control Result-Code=%u", + gy_message->cca.result_code); + /* Message RC was successful but MSCC was rejected. The session needs to + * be tear down through CCR-T: */ + *need_termination = true; + return gy_message->cca.err ? *gy_message->cca.err : + ER_DIAMETER_AUTHENTICATION_REJECTED; + } bearer = smf_default_bearer_in_sess(sess); ogs_assert(bearer); @@ -173,8 +190,8 @@ uint32_t smf_gy_handle_cca_update_request( sess->sgw_s5c_teid, sess->smf_n4_teid); if (gy_message->result_code != ER_DIAMETER_SUCCESS) { - ogs_warn("Gy CCA Update Diameter failure: res=%u err=%u", - gy_message->result_code, *gy_message->err); + ogs_warn("Gy CCA Update Diameter failure: Result-Code=%u", + gy_message->result_code); return gy_message->err ? *gy_message->err : ER_DIAMETER_AUTHENTICATION_REJECTED; } diff --git a/src/smf/gy-handler.h b/src/smf/gy-handler.h index 019d9b29d..ad8a089c0 100644 --- a/src/smf/gy-handler.h +++ b/src/smf/gy-handler.h @@ -29,7 +29,8 @@ extern "C" { uint32_t smf_gy_handle_cca_initial_request( smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, - ogs_gtp_xact_t *gtp_xact); + ogs_gtp_xact_t *gtp_xact, + bool *need_termination); uint32_t smf_gy_handle_cca_update_request( smf_sess_t *sess, ogs_diam_gy_message_t *gy_message, ogs_pfcp_xact_t *pfcp_xact);