diff --git a/src/smf/event.h b/src/smf/event.h index 8b6cfca30..3f8831e30 100644 --- a/src/smf/event.h +++ b/src/smf/event.h @@ -21,6 +21,7 @@ #define SMF_EVENT_H #include "ogs-core.h" +#include "ogs-gtp.h" #ifdef __cplusplus extern "C" { @@ -81,6 +82,11 @@ typedef struct smf_event_s { ogs_pfcp_xact_t *pfcp_xact; ogs_pfcp_message_t *pfcp_message; + union { + ogs_gtp1_message_t *gtp1_message; + ogs_gtp2_message_t *gtp2_message; + }; + union { ogs_diam_gx_message_t *gx_message; ogs_diam_gy_message_t *gy_message; diff --git a/src/smf/gn-handler.c b/src/smf/gn-handler.c index e0fdc3bac..83d6ce2ff 100644 --- a/src/smf/gn-handler.c +++ b/src/smf/gn-handler.c @@ -46,7 +46,7 @@ void smf_gn_handle_echo_response( /* Not Implemented */ } -void smf_gn_handle_create_pdp_context_request( +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) { @@ -65,6 +65,7 @@ void smf_gn_handle_create_pdp_context_request( ogs_gtp1_qos_profile_decoded_t qos_pdec; uint8_t qci = 9; + ogs_assert(sess); ogs_assert(xact); ogs_assert(req); @@ -101,23 +102,14 @@ void smf_gn_handle_create_pdp_context_request( cause_value = OGS_GTP1_CAUSE_MANDATORY_IE_MISSING; } - if (!sess) { - ogs_error("No Context"); - cause_value = OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND; - } 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 (!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_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); - return; - } + if (cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) + return cause_value; - ogs_assert(sess); smf_ue = sess->smf_ue; ogs_assert(smf_ue); @@ -133,12 +125,9 @@ void smf_gn_handle_create_pdp_context_request( ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - if (ogs_gtp1_parse_uli(&uli, &req->user_location_information) == 0) { - ogs_gtp1_send_error_message(xact, sess->sgw_s5c_teid, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, - OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT); - return; - } + if (ogs_gtp1_parse_uli(&uli, &req->user_location_information) == 0) + return OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT; + /* TODO: Copy uli->cgi/sai/rai into sess-> */ switch (uli.geo_loc_type) { case OGS_GTP1_GEO_LOC_TYPE_CGI: @@ -155,12 +144,8 @@ void smf_gn_handle_create_pdp_context_request( /* Set Bearer QoS */ rv = ogs_gtp1_parse_qos_profile(&qos_pdec, &req->quality_of_service_profile); - if(rv < 0) { - ogs_gtp1_send_error_message(xact, sess->sgw_s5c_teid, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, - OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT); - return; - } + if(rv < 0) + return OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT; /* 3GPP TS 23.060 section 9.2.1A: "The QoS profiles of the PDP context and EPS bearer are mapped as specified in TS 23.401" * 3GPP TS 23.401 Annex E: "Mapping between EPS and Release 99 QoS parameters" @@ -205,12 +190,9 @@ void smf_gn_handle_create_pdp_context_request( ogs_assert(eua); rv = ogs_gtp1_eua_to_ip(eua, req->end_user_address.len, &sess->session.ue_ip, &sess->ue_session_type); - if(rv != OGS_OK) { - ogs_gtp1_send_error_message(xact, sess->sgw_s5c_teid, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, - OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT); - return; - } + if(rv != OGS_OK) + return OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT; + /* Initially Set Session Type from UE */ sess->session.session_type = sess->ue_session_type; @@ -240,19 +222,12 @@ void smf_gn_handle_create_pdp_context_request( /* Check if selected PGW is associated with SMF */ ogs_assert(sess->pfcp_node); - if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated)) { - ogs_gtp1_send_error_message(xact, sess->sgw_s5c_teid, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, - OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE); - return; - } + if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated)) + return OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE; if ((pfcp_cause = smf_sess_set_ue_ip(sess)) != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { cause_value = gtp_cause_from_pfcp(pfcp_cause, 1); - ogs_gtp1_send_error_message(xact, sess->sgw_s5c_teid, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, - cause_value); - return; + return cause_value; } ogs_info("UE IMSI[%s] APN[%s] IPv4[%s] IPv6[%s]", @@ -261,8 +236,7 @@ void smf_gn_handle_create_pdp_context_request( sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "", sess->ipv6 ? OGS_INET6_NTOP(&sess->ipv6->addr, buf2) : ""); - smf_gx_send_ccr(sess, xact, - OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST); + return cause_value; } void smf_gn_handle_delete_pdp_context_request( diff --git a/src/smf/gn-handler.h b/src/smf/gn-handler.h index cdb234393..8e8f42e63 100644 --- a/src/smf/gn-handler.h +++ b/src/smf/gn-handler.h @@ -32,7 +32,7 @@ void smf_gn_handle_echo_request( void smf_gn_handle_echo_response( ogs_gtp_xact_t *xact, ogs_gtp1_echo_response_t *req); -void smf_gn_handle_create_pdp_context_request( +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( diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 68f20cf45..18c293922 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -17,7 +17,13 @@ * along with this program. If not, see . */ +#include "binding.h" #include "sbi-path.h" +#include "gn-handler.h" +#include "gx-handler.h" +#include "gy-handler.h" +#include "n4-handler.h" +#include "s5c-handler.h" #include "nnrf-handler.h" #include "nsmf-handler.h" #include "nudm-handler.h" @@ -25,18 +31,262 @@ #include "namf-handler.h" #include "gsm-handler.h" #include "ngap-handler.h" +#include "gtp-path.h" #include "pfcp-path.h" #include "ngap-path.h" +#include "fd-path.h" + +static uint8_t gtp_cause_from_diameter(uint8_t gtp_version, + const uint32_t dia_err, const uint32_t *dia_exp_err) +{ + switch (gtp_version) { + case 1: + switch (dia_err) { + case OGS_DIAM_UNKNOWN_SESSION_ID: + return OGS_GTP1_CAUSE_APN_ACCESS_DENIED; + } + break; + case 2: + switch (dia_err) { + case OGS_DIAM_UNKNOWN_SESSION_ID: + return OGS_GTP2_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION; + } + break; + } + + ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe " + "network failure", + dia_err, dia_exp_err ? *dia_exp_err : -1); + switch (gtp_version) { + case 1: + return OGS_GTP1_CAUSE_USER_AUTHENTICATION_FAILED; + case 2: + default: + return OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; + } +} + +static void send_gtp_create_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_CREATE_PDP_CONTEXT_RESPONSE_TYPE, gtp_cause); + else + ogs_gtp2_send_error_message(gtp_xact, sess->sgw_s5c_teid, + OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, gtp_cause); +} void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e) { ogs_assert(s); + ogs_assert(e && e->sess); + smf_sess_t *sess = e->sess; + uint8_t gtp1_cause, gtp2_cause; - OGS_FSM_TRAN(s, &smf_gsm_state_operational); + switch (e->id) { + case OGS_FSM_ENTRY_SIG: + if (!sess->gtp_rat_type) /* 5gc */ + OGS_FSM_TRAN(s, &smf_gsm_state_operational); + break; + + case SMF_EVT_GN_MESSAGE: + switch(e->gtp1_message->h.type) { + case OGS_GTP1_CREATE_PDP_CONTEXT_REQUEST_TYPE: + gtp1_cause = smf_gn_handle_create_pdp_context_request(sess, + e->gtp_xact, + &e->gtp1_message->create_pdp_context_request); + if (gtp1_cause != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) { + send_gtp_create_err_msg(sess, e->gtp_xact, gtp1_cause); + return; + } + OGS_FSM_TRAN(s, &smf_gsm_state_initial_wait_auth); + smf_gx_send_ccr(sess, e->gtp_xact, + OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST); + } + break; + + case SMF_EVT_S5C_MESSAGE: + switch(e->gtp2_message->h.type) { + case OGS_GTP2_CREATE_SESSION_REQUEST_TYPE: + gtp2_cause = smf_s5c_handle_create_session_request(sess, + e->gtp_xact, + &e->gtp2_message->create_session_request); + if (gtp2_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { + send_gtp_create_err_msg(sess, e->gtp_xact, gtp2_cause); + return; + } + OGS_FSM_TRAN(s, &smf_gsm_state_initial_wait_auth); + switch (sess->gtp_rat_type) { + case OGS_GTP2_RAT_TYPE_EUTRAN: + smf_gx_send_ccr(sess, e->gtp_xact, + OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST); + break; + case OGS_GTP2_RAT_TYPE_WLAN: + smf_s6b_send_aar(sess, e->gtp_xact); + break; + default: + ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type); + ogs_assert_if_reached(); + } + break; + } + break; + } } -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) { + ogs_assert(e && e->sess); + smf_sess_t *sess = e->sess; + uint32_t diam_err; + uint8_t gtp_cause; + + switch (e->id) { + 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_INITIAL_REQUEST: + ogs_assert(e->gtp_xact); + diam_err = smf_gx_handle_cca_initial_request(sess, + e->gx_message, e->gtp_xact); + if (diam_err != ER_DIAMETER_SUCCESS) { + uint8_t gtp_cause = gtp_cause_from_diameter( + e->gtp_xact->gtp_version, + diam_err, e->gx_message->exp_err); + send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause); + return; + } + switch(smf_use_gy_iface()) { + case 1: + /* Gy is available, set up session for the bearer before accepting it towards the UE */ + /* OGS_FSM_TRAN: keep current state, we handle Gy here. */ + smf_gy_send_ccr(sess, e->gtp_xact, + OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST); + return; + case 0: + /* Not using Gy, jump directly to PFCP Session Establishment Request */ + OGS_FSM_TRAN(s, &smf_gsm_state_initial_wait_pfcp_establishment); + ogs_assert(OGS_OK == + smf_epc_pfcp_send_session_establishment_request(sess, e->gtp_xact)); + return; + case -1: + ogs_error("No Gy Diameter Peer"); + /* TODO: drop Gx connection here, possibly move to another "releasing" state! */ + 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_create_err_msg(sess, e->gtp_xact, gtp_cause); + return; + } + break; + } + 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_INITIAL_REQUEST: + ogs_assert(e->gtp_xact); + diam_err = smf_gy_handle_cca_initial_request(sess, + e->gy_message, e->gtp_xact); + if (diam_err != ER_DIAMETER_SUCCESS) { + /* FIXME: tear down Gx session */ + gtp_cause = gtp_cause_from_diameter(e->gtp_xact->gtp_version, + diam_err, e->gy_message->exp_err); + send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause); + return; + } + OGS_FSM_TRAN(s, &smf_gsm_state_initial_wait_pfcp_establishment); + ogs_assert(OGS_OK == + smf_epc_pfcp_send_session_establishment_request(sess, e->gtp_xact)); + return; + } + break; + } + break; + } +} + +void smf_gsm_state_initial_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e) +{ + ogs_assert(e && e->sess); + smf_sess_t *sess = e->sess; + uint8_t pfcp_cause, gtp_cause; + + switch (e->id) { + case SMF_EVT_N4_MESSAGE: + switch (e->pfcp_message->h.type) { + case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE: + if (e->pfcp_xact->epc) { + ogs_gtp_xact_t *gtp_xact = e->pfcp_xact->assoc_xact; + pfcp_cause = smf_epc_n4_handle_session_establishment_response( + sess, e->pfcp_xact, + &e->pfcp_message->pfcp_session_establishment_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_create_err_msg(sess, e->gtp_xact, gtp_cause); + return; + } + switch (gtp_xact->gtp_version) { + case 1: + ogs_assert(OGS_OK == smf_gtp1_send_create_pdp_context_response(sess, gtp_xact)); + break; + case 2: + ogs_assert(OGS_OK == smf_gtp_send_create_session_response(sess, gtp_xact)); + break; + } + if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { + /* + * TS23.214 + * 6.3.1.7 Procedures with modification of bearer + * p50 + * 2. ... + * For "PGW/MME initiated bearer deactivation procedure", + * PGW-C shall indicate PGW-U to stop counting and stop + * forwarding downlink packets for the affected bearer(s). + */ + ogs_assert(sess->smf_ue); + smf_sess_t *eutran_sess = smf_sess_find_by_apn( + sess->smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_EUTRAN); + if (eutran_sess) { + ogs_assert(OGS_OK == + smf_epc_pfcp_send_session_modification_request( + eutran_sess, NULL, + OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP)); + } + } + smf_bearer_binding(sess); + } else { +#if 0 + /* This is currently not happening, since 5gc isn't yet properly integrated and moves directly to operational state */ + smf_n1_n2_message_transfer_param_t param; + pfcp_cause = smf_5gc_n4_handle_session_establishment_response( + sess, e->pfcp_xact, + &e->pfcp_message->pfcp_session_establishment_response); + if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) + return; + memset(¶m, 0, sizeof(param)); + param.state = SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT; + param.n1smbuf = gsm_build_pdu_session_establishment_accept(sess); + ogs_assert(param.n1smbuf); + param.n2smbuf = ngap_build_pdu_session_resource_setup_request_transfer( + sess); + ogs_assert(param.n2smbuf); + smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); +#endif + } + OGS_FSM_TRAN(s, &smf_gsm_state_operational); + break; + } + break; + } } void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) @@ -52,6 +302,9 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_sbi_stream_t *stream = NULL; ogs_sbi_message_t *sbi_message = NULL; + smf_n1_n2_message_transfer_param_t param; + uint8_t pfcp_cause; + int state = 0; ogs_assert(s); @@ -69,6 +322,30 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) case OGS_FSM_EXIT_SIG: break; + case SMF_EVT_N4_MESSAGE: + switch (e->pfcp_message->h.type) { + case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE: + /* This is left here for 5gc sessions to properly receive messages, + since startup transitions are not implemented yet for 5gc + sessions. See #if0 in smf_gsm_state_initial_wait_pfcp_establishment() */ + assert(!e->pfcp_xact->epc); + pfcp_cause = smf_5gc_n4_handle_session_establishment_response( + sess, e->pfcp_xact, + &e->pfcp_message->pfcp_session_establishment_response); + if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) + return; + memset(¶m, 0, sizeof(param)); + param.state = SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT; + param.n1smbuf = gsm_build_pdu_session_establishment_accept(sess); + ogs_assert(param.n1smbuf); + param.n2smbuf = ngap_build_pdu_session_resource_setup_request_transfer( + sess); + ogs_assert(param.n2smbuf); + smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); + break; + } + break; + case SMF_EVT_SBI_SERVER: sbi_message = e->sbi.message; ogs_assert(sbi_message); @@ -495,3 +772,7 @@ void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e) break; } } + +void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e) +{ +} diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index 3d3edde1e..ea36dc2b4 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -25,25 +25,8 @@ #include "gx-handler.h" #include "binding.h" -static uint8_t gtp_cause_from_diameter( - const uint32_t *dia_err, const uint32_t *dia_exp_err) -{ - if (dia_exp_err) { - } - if (dia_err) { - switch (*dia_err) { - case OGS_DIAM_UNKNOWN_SESSION_ID: - return OGS_GTP2_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION; - } - } - - ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe " - "network failure", - dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1); - return OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; -} - -void smf_gx_handle_cca_initial_request( +/* Returns ER_DIAMETER_SUCCESS on success, Diameter error code on failue. */ +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) { @@ -68,18 +51,10 @@ void smf_gx_handle_cca_initial_request( ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - if (gx_message->result_code != ER_DIAMETER_SUCCESS) { - uint8_t cause_value = gtp_cause_from_diameter( - gx_message->err, gx_message->exp_err); + if (gx_message->result_code != ER_DIAMETER_SUCCESS) + return gx_message->err ? *gx_message->err : + ER_DIAMETER_AUTHENTICATION_REJECTED; - if (gtp_xact->gtp_version == 1) - ogs_gtp1_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); - else - ogs_gtp2_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); - return; - } sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule; for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++) @@ -272,30 +247,7 @@ void smf_gx_handle_cca_initial_request( ogs_pfcp_pdr_associate_qer(dl_pdr, qer); ogs_pfcp_pdr_associate_qer(ul_pdr, qer); } - - switch(smf_use_gy_iface()) { - case 1: - /* Gy is available, set up session for the bearer before accepting it towards the UE */ - smf_gy_send_ccr(sess, gtp_xact, - OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST); - return; - case 0: - /* Not using Gy, jump directly to PFCP Session Establishment Request */ - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_establishment_request(sess, gtp_xact)); - return; - case -1: - ogs_error("No Gy Diameter Peer"); - if (gtp_xact->gtp_version == 1) - ogs_gtp1_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, - OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE); - else - ogs_gtp2_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER); - return; - } + return ER_DIAMETER_SUCCESS; } void smf_gx_handle_cca_termination_request( diff --git a/src/smf/gx-handler.h b/src/smf/gx-handler.h index 30b165da0..99a0bd921 100644 --- a/src/smf/gx-handler.h +++ b/src/smf/gx-handler.h @@ -26,7 +26,7 @@ extern "C" { #endif -void smf_gx_handle_cca_initial_request( +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( diff --git a/src/smf/gy-handler.c b/src/smf/gy-handler.c index 2ddb2f793..a245b0871 100644 --- a/src/smf/gy-handler.c +++ b/src/smf/gy-handler.c @@ -24,24 +24,6 @@ #include "gy-handler.h" #include "binding.h" -static uint8_t gtp_cause_from_diameter( - const uint32_t *dia_err, const uint32_t *dia_exp_err) -{ - if (dia_exp_err) { - } - if (dia_err) { - switch (*dia_err) { - case OGS_DIAM_UNKNOWN_SESSION_ID: - return OGS_GTP2_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION; - } - } - - ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe " - "network failure", - dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1); - return OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER; -} - static void urr_enable_total_volume_threshold(smf_sess_t *sess, ogs_pfcp_urr_t *urr, uint64_t total_volume_threshold) { @@ -96,7 +78,8 @@ static void urr_update_time_threshold(ogs_pfcp_urr_t *urr, ogs_diam_gy_message_t } } -void smf_gy_handle_cca_initial_request( +/* Returns ER_DIAMETER_SUCCESS on success, Diameter error code on failue. */ +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) { @@ -110,18 +93,9 @@ void smf_gy_handle_cca_initial_request( 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) { - uint8_t cause_value = gtp_cause_from_diameter( - gy_message->err, gy_message->exp_err); - - if (gtp_xact->gtp_version == 1) - ogs_gtp1_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, cause_value); - else - ogs_gtp2_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); - return; - } + if (gy_message->result_code != ER_DIAMETER_SUCCESS) + return gy_message->err ? *gy_message->err : + ER_DIAMETER_AUTHENTICATION_REJECTED; bearer = smf_default_bearer_in_sess(sess); ogs_assert(bearer); @@ -137,9 +111,7 @@ void smf_gy_handle_cca_initial_request( /* Associate acconting URR each direction PDR: */ ogs_pfcp_pdr_associate_urr(bearer->ul_pdr, bearer->urr); ogs_pfcp_pdr_associate_urr(bearer->dl_pdr, bearer->urr); - - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_establishment_request(sess, gtp_xact)); + return ER_DIAMETER_SUCCESS; } void smf_gy_handle_cca_update_request( diff --git a/src/smf/gy-handler.h b/src/smf/gy-handler.h index 6dde724eb..bc060b65b 100644 --- a/src/smf/gy-handler.h +++ b/src/smf/gy-handler.h @@ -27,7 +27,7 @@ extern "C" { #endif -void smf_gy_handle_cca_initial_request( +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); void smf_gy_handle_cca_update_request( diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 7181fd53a..9c9fddac2 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -141,20 +141,21 @@ static int sbi_status_from_pfcp(uint8_t pfcp_cause) return OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR; } -void smf_5gc_n4_handle_session_establishment_response( +/* Returns OGS_PFCP_CAUSE_REQUEST_ACCEPTED on success, other cause value on failure */ +uint8_t smf_5gc_n4_handle_session_establishment_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_establishment_response_t *rsp) { int i; - smf_n1_n2_message_transfer_param_t param; ogs_sbi_stream_t *stream = NULL; - uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; + uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; uint8_t offending_ie_value = 0; ogs_pfcp_f_seid_t *up_f_seid = NULL; + ogs_assert(sess); ogs_assert(xact); ogs_assert(rsp); @@ -165,41 +166,36 @@ void smf_5gc_n4_handle_session_establishment_response( ogs_pfcp_xact_commit(xact); - if (!sess) { - ogs_warn("No Context"); - return; - } - if (rsp->up_f_seid.presence == 0) { ogs_error("No UP F-SEID"); - return; + cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->created_pdr[0].presence == 0) { ogs_error("No Created PDR"); - return; + cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->cause.presence) { if (rsp->cause.u8 != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { ogs_error("PFCP Cause [%d] : Not Accepted", rsp->cause.u8); - return; + cause_value = rsp->cause.u8; } } else { ogs_error("No Cause"); - return; + cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } - ogs_assert(sess); + if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) + return cause_value; - pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) { ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_far_t *far = NULL; pdr = ogs_pfcp_handle_created_pdr( &sess->pfcp, &rsp->created_pdr[i], - &pfcp_cause_value, &offending_ie_value); + &cause_value, &offending_ie_value); if (!pdr) break; @@ -230,14 +226,14 @@ void smf_5gc_n4_handle_session_establishment_response( } } - if (pfcp_cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { - ogs_error("PFCP Cause [%d] : Not Accepted", pfcp_cause_value); - return; + if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { + ogs_error("PFCP Cause [%d] : Not Accepted", cause_value); + return cause_value; } if (sess->upf_n3_addr == NULL && sess->upf_n3_addr6 == NULL) { ogs_error("No UP F-TEID"); - return; + return OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND; } /* UP F-SEID */ @@ -245,15 +241,7 @@ void smf_5gc_n4_handle_session_establishment_response( ogs_assert(up_f_seid); sess->upf_n4_seid = be64toh(up_f_seid->seid); - memset(¶m, 0, sizeof(param)); - param.state = SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT; - param.n1smbuf = gsm_build_pdu_session_establishment_accept(sess); - ogs_assert(param.n1smbuf); - param.n2smbuf = ngap_build_pdu_session_resource_setup_request_transfer( - sess); - ogs_assert(param.n2smbuf); - - smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); + return OGS_PFCP_CAUSE_REQUEST_ACCEPTED; } void smf_5gc_n4_handle_session_modification_response( @@ -723,18 +711,19 @@ void smf_5gc_n4_handle_session_deletion_response( } } -void smf_epc_n4_handle_session_establishment_response( +/* Returns OGS_PFCP_CAUSE_REQUEST_ACCEPTED on success, other cause value on failure */ +uint8_t smf_epc_n4_handle_session_establishment_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_establishment_response_t *rsp) { - uint8_t cause_value = 0; - uint8_t resp_type = 0; + uint8_t cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; smf_bearer_t *bearer = NULL; ogs_gtp_xact_t *gtp_xact = NULL; ogs_pfcp_f_seid_t *up_f_seid = NULL; + ogs_assert(sess); ogs_assert(xact); ogs_assert(rsp); @@ -745,62 +734,37 @@ void smf_epc_n4_handle_session_establishment_response( ogs_pfcp_xact_commit(xact); - if (gtp_xact->gtp_version == 1) { - cause_value = OGS_GTP1_CAUSE_REQUEST_ACCEPTED; - resp_type = OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE; - } else { - cause_value = OGS_GTP2_CAUSE_REQUEST_ACCEPTED; - resp_type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE; - } - - if (!sess) { - ogs_warn("No Context"); - cause_value = (gtp_xact->gtp_version == 1) ? - OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND : - OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND; - } - if (rsp->up_f_seid.presence == 0) { ogs_error("No UP F-SEID"); - cause_value = (gtp_xact->gtp_version == 1) ? - OGS_GTP1_CAUSE_MANDATORY_IE_MISSING : - OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } if (rsp->created_pdr[0].presence == 0) { ogs_error("No Created PDR"); - cause_value = (gtp_xact->gtp_version == 1) ? - OGS_GTP1_CAUSE_MANDATORY_IE_MISSING : - OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } 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_xact->gtp_version); + cause_value = rsp->cause.u8; } } else { ogs_error("No Cause"); - cause_value = (gtp_xact->gtp_version == 1) ? - OGS_GTP1_CAUSE_MANDATORY_IE_MISSING : - OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + cause_value = OGS_PFCP_CAUSE_MANDATORY_IE_MISSING; } - if ((gtp_xact->gtp_version == 1 && cause_value == OGS_GTP1_CAUSE_REQUEST_ACCEPTED) || - (gtp_xact->gtp_version == 2 && cause_value == OGS_GTP2_CAUSE_REQUEST_ACCEPTED)) { + if (cause_value == OGS_PFCP_CAUSE_REQUEST_ACCEPTED) { int i; - - uint8_t pfcp_cause_value = OGS_PFCP_CAUSE_REQUEST_ACCEPTED; uint8_t offending_ie_value = 0; - ogs_assert(sess); for (i = 0; i < OGS_MAX_NUM_OF_PDR; i++) { ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_far_t *far = NULL; pdr = ogs_pfcp_handle_created_pdr( &sess->pfcp, &rsp->created_pdr[i], - &pfcp_cause_value, &offending_ie_value); + &cause_value, &offending_ie_value); if (!pdr) break; @@ -836,74 +800,25 @@ void smf_epc_n4_handle_session_establishment_response( ogs_assert(OGS_ERROR != ogs_pfcp_setup_pdr_gtpu_node(pdr)); } } - - cause_value = gtp_cause_from_pfcp(pfcp_cause_value, gtp_xact->gtp_version); } - if ((gtp_xact->gtp_version == 1 && cause_value != OGS_GTP1_CAUSE_REQUEST_ACCEPTED) || - (gtp_xact->gtp_version == 2 && cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED)) { - ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - resp_type, cause_value); - return; - } + if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) + return cause_value; - ogs_assert(sess); bearer = smf_default_bearer_in_sess(sess); ogs_assert(bearer); if (bearer->pgw_s5u_addr == NULL && bearer->pgw_s5u_addr6 == NULL) { ogs_error("No UP F-TEID"); - ogs_gtp_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0, - resp_type, - (gtp_xact->gtp_version == 1) ? - OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND : OGS_GTP2_CAUSE_GRE_KEY_NOT_FOUND); - return; + return OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND; } /* UP F-SEID */ up_f_seid = rsp->up_f_seid.data; ogs_assert(up_f_seid); sess->upf_n4_seid = be64toh(up_f_seid->seid); - - switch (gtp_xact->gtp_version) { - case 1: - ogs_assert(OGS_OK == smf_gtp1_send_create_pdp_context_response(sess, gtp_xact)); - break; - case 2: - ogs_assert(OGS_OK == smf_gtp_send_create_session_response(sess, gtp_xact)); - break; - } - - if (sess->gtp_rat_type == OGS_GTP2_RAT_TYPE_WLAN) { - /* - * TS23.214 - * 6.3.1.7 Procedures with modification of bearer - * p50 - * 2. ... - * For "PGW/MME initiated bearer deactivation procedure", - * PGW-C shall indicate PGW-U to stop counting and stop - * forwarding downlink packets for the affected bearer(s). - */ - smf_ue_t *smf_ue = NULL; - smf_sess_t *eutran_sess = NULL; - - smf_ue = sess->smf_ue; - ogs_assert(smf_ue); - - eutran_sess = smf_sess_find_by_apn( - smf_ue, sess->session.name, OGS_GTP2_RAT_TYPE_EUTRAN); - if (eutran_sess) { - ogs_assert(OGS_OK == - smf_epc_pfcp_send_session_modification_request( - eutran_sess, NULL, - OGS_PFCP_MODIFY_DL_ONLY|OGS_PFCP_MODIFY_DEACTIVATE, - OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, - OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP)); - } - } - - smf_bearer_binding(sess); + return OGS_PFCP_CAUSE_REQUEST_ACCEPTED; } void smf_epc_n4_handle_session_modification_response( diff --git a/src/smf/n4-handler.h b/src/smf/n4-handler.h index 57e1a9eff..0d9708d83 100644 --- a/src/smf/n4-handler.h +++ b/src/smf/n4-handler.h @@ -26,7 +26,7 @@ extern "C" { #endif -void smf_5gc_n4_handle_session_establishment_response( +uint8_t smf_5gc_n4_handle_session_establishment_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_establishment_response_t *rsp); void smf_5gc_n4_handle_session_modification_response( @@ -36,7 +36,7 @@ void smf_5gc_n4_handle_session_deletion_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_deletion_response_t *rsp); -void smf_epc_n4_handle_session_establishment_response( +uint8_t smf_epc_n4_handle_session_establishment_response( smf_sess_t *sess, ogs_pfcp_xact_t *xact, ogs_pfcp_session_establishment_response_t *rsp); void smf_epc_n4_handle_session_modification_response( diff --git a/src/smf/pfcp-sm.c b/src/smf/pfcp-sm.c index 266575549..0f4b54f96 100644 --- a/src/smf/pfcp-sm.c +++ b/src/smf/pfcp-sm.c @@ -187,6 +187,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) if (message->h.seid_presence && message->h.seid != 0) sess = smf_sess_find_by_seid(message->h.seid); + if (sess) + e->sess = sess; switch (message->h.type) { case OGS_PFCP_HEARTBEAT_REQUEST_TYPE: @@ -210,17 +212,22 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e) &message->pfcp_association_setup_response); break; case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE: - if (!message->h.seid_presence) { + if (!message->h.seid_presence) ogs_error("No SEID"); - break; + if (!sess) { + ogs_gtp_xact_t *gtp_xact = xact->assoc_xact; + ogs_assert(gtp_xact); + if (gtp_xact->gtp_version == 1) + ogs_gtp1_send_error_message(gtp_xact, 0, + OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, + OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND); + else + ogs_gtp2_send_error_message(gtp_xact, 0, + OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, + OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); + return; } - - if (xact->epc) - smf_epc_n4_handle_session_establishment_response( - sess, xact, &message->pfcp_session_establishment_response); - else - smf_5gc_n4_handle_session_establishment_response( - sess, xact, &message->pfcp_session_establishment_response); + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE: diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index bf709495e..cd2793777 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -45,7 +45,7 @@ void smf_s5c_handle_echo_response( /* Not Implemented */ } -void smf_s5c_handle_create_session_request( +uint8_t smf_s5c_handle_create_session_request( smf_sess_t *sess, ogs_gtp_xact_t *xact, ogs_gtp2_create_session_request_t *req) { @@ -66,6 +66,7 @@ void smf_s5c_handle_create_session_request( ogs_gtp2_ambr_t *ambr = NULL; uint16_t decoded = 0; + ogs_assert(sess); ogs_assert(xact); ogs_assert(req); @@ -111,50 +112,41 @@ void smf_s5c_handle_create_session_request( cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - if (!sess) { - ogs_error("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; - } - switch (sess->gtp_rat_type) { - case OGS_GTP2_RAT_TYPE_EUTRAN: - if (req->bearer_contexts_to_be_created. - s5_s8_u_sgw_f_teid.presence == 0) { - ogs_error("No S5/S8 SGW GTP-U TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - if (req->user_location_information.presence == 0) { - ogs_error("No UE Location Information"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - break; - case 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 (req->bearer_contexts_to_be_created. - s2b_u_epdg_f_teid_5.presence == 0) { - ogs_error("No S2b ePDG GTP-U TEID"); - cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; - } - break; - default: - ogs_error("Unknown RAT Type [%d]", req->rat_type.u8); + 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; + } + switch (sess->gtp_rat_type) { + case OGS_GTP2_RAT_TYPE_EUTRAN: + if (req->bearer_contexts_to_be_created. + s5_s8_u_sgw_f_teid.presence == 0) { + ogs_error("No S5/S8 SGW GTP-U TEID"); cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } + if (req->user_location_information.presence == 0) { + ogs_error("No UE Location Information"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + break; + case 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 (req->bearer_contexts_to_be_created. + s2b_u_epdg_f_teid_5.presence == 0) { + ogs_error("No S2b ePDG GTP-U TEID"); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; + } + break; + default: + ogs_error("Unknown RAT Type [%d]", req->rat_type.u8); + cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING; } - if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) { - ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value); - return; - } + if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) + return cause_value; - ogs_assert(sess); smf_ue = sess->smf_ue; ogs_assert(smf_ue); @@ -184,10 +176,7 @@ void smf_s5c_handle_create_session_request( if (eutran_session_count < 1) { ogs_error("Cannot handover to WLAN"); - ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP2_CAUSE_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED); - return; + return OGS_GTP2_CAUSE_MULTIPLE_ACCESSES_TO_A_PDN_CONNECTION_NOT_ALLOWED; } } } @@ -200,12 +189,8 @@ void smf_s5c_handle_create_session_request( /* Check if selected PGW is associated with SMF */ ogs_assert(sess->pfcp_node); - if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated)) { - ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, - OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, - OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING); - return; - } + if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated)) + return OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING; /* UE IP Address */ paa = req->pdn_address_allocation.data; @@ -316,18 +301,7 @@ void smf_s5c_handle_create_session_request( OGS_TLV_STORE_DATA(&sess->gtp.ue_timezone, &req->ue_time_zone); } - switch (sess->gtp_rat_type) { - case OGS_GTP2_RAT_TYPE_EUTRAN: - smf_gx_send_ccr(sess, xact, - OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST); - break; - case OGS_GTP2_RAT_TYPE_WLAN: - smf_s6b_send_aar(sess, xact); - 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_delete_session_request( diff --git a/src/smf/s5c-handler.h b/src/smf/s5c-handler.h index 7f9c7ebe1..1efe28ea4 100644 --- a/src/smf/s5c-handler.h +++ b/src/smf/s5c-handler.h @@ -31,7 +31,7 @@ void smf_s5c_handle_echo_request( void smf_s5c_handle_echo_response( ogs_gtp_xact_t *xact, ogs_gtp2_echo_response_t *req); -void smf_s5c_handle_create_session_request( +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( diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 9866edb5f..d4733365e 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -100,6 +100,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_pkbuf_free(recvbuf); break; } + e->gtp2_message = >p_message; if (gtp_message.h.teid != 0) { sess = smf_sess_find_by_teid(gtp_message.h.teid); @@ -118,6 +119,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_pkbuf_free(recvbuf); break; } + e->gtp_xact = gtp_xact; switch(gtp_message.h.type) { case OGS_GTP2_ECHO_REQUEST_TYPE: @@ -133,8 +135,14 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) if (sess) OGS_SETUP_GTP_NODE(sess, gnode); } - smf_s5c_handle_create_session_request( - sess, gtp_xact, >p_message.create_session_request); + if (!sess) { + ogs_gtp1_send_error_message(gtp_xact, 0, + OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, + OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND); + break; + } + e->sess = sess; + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE: smf_s5c_handle_delete_session_request( @@ -177,6 +185,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_pkbuf_free(recvbuf); break; } + e->gtp1_message = >p1_message; if (gtp1_message.h.teid != 0) { sess = smf_sess_find_by_teid(gtp1_message.h.teid); @@ -195,6 +204,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_pkbuf_free(recvbuf); break; } + e->gtp_xact = gtp_xact; switch(gtp1_message.h.type) { case OGS_GTP1_ECHO_REQUEST_TYPE: @@ -210,8 +220,14 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) if (sess) OGS_SETUP_GTP_NODE(sess, gnode); } - smf_gn_handle_create_pdp_context_request( - sess, gtp_xact, >p1_message.create_pdp_context_request); + if (!sess) { + ogs_gtp1_send_error_message(gtp_xact, 0, + OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, + OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND); + break; + } + e->sess = sess; + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE: smf_gn_handle_delete_pdp_context_request( @@ -247,8 +263,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) switch(gx_message->cc_request_type) { case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST: - smf_gx_handle_cca_initial_request( - sess, gx_message, gtp_xact); + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST: smf_gx_handle_cca_termination_request( @@ -284,9 +299,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL: switch(gy_message->cc_request_type) { case OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST: - ogs_assert(e->gtp_xact); - smf_gy_handle_cca_initial_request( - sess, gy_message, e->gtp_xact); + ogs_fsm_dispatch(&sess->sm, e); break; case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST: ogs_assert(e->pfcp_xact); diff --git a/src/smf/smf-sm.h b/src/smf/smf-sm.h index 2a7914b5b..72960fe4a 100644 --- a/src/smf/smf-sm.h +++ b/src/smf/smf-sm.h @@ -48,6 +48,8 @@ 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);