From e61b469489690465319acaf98382f50bf693d9fa Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 14 Apr 2022 03:30:58 +0200 Subject: [PATCH] [SMF] Inegrate session setup cycle into sess->sm (#1489) It allows for much better control on the lifecycle of the session, and already shows some missing tear down paths in case of errors. It also clarifies the existence of "sess" pointer in several paths. The code also becomes clearer overall, since all the transitions and logic to send next messages are put together. Tear down of the session will be integrated into gsm-sm in a follow-up patch. The 5gc session setup is only partially moved to gsm-sm, and left as an exercise for users wishin to improve 5gc support. --- src/smf/event.h | 6 + src/smf/gn-handler.c | 64 +++------- src/smf/gn-handler.h | 2 +- src/smf/gsm-sm.c | 285 +++++++++++++++++++++++++++++++++++++++++- src/smf/gx-handler.c | 60 +-------- src/smf/gx-handler.h | 2 +- src/smf/gy-handler.c | 40 +----- src/smf/gy-handler.h | 2 +- src/smf/n4-handler.c | 145 +++++---------------- src/smf/n4-handler.h | 4 +- src/smf/pfcp-sm.c | 25 ++-- src/smf/s5c-handler.c | 98 ++++++--------- src/smf/s5c-handler.h | 2 +- src/smf/smf-sm.c | 31 +++-- src/smf/smf-sm.h | 2 + 15 files changed, 432 insertions(+), 336 deletions(-) diff --git a/src/smf/event.h b/src/smf/event.h index 8b6cfca307..3f8831e308 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 e0fdc3bacb..83d6ce2ffb 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 cdb2343936..8e8f42e638 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 68f20cf459..18c2939226 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 3d3edde1e2..ea36dc2b45 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 30b165da07..99a0bd921c 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 2ddb2f7939..a245b08715 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 6dde724eb5..bc060b65b0 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 7181fd53a7..9c9fddac21 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 57e1a9eff3..0d9708d83b 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 2665755495..0f4b54f969 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 bf709495e0..cd2793777a 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 7f9c7ebe1e..1efe28ea44 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 9866edb5ff..d4733365ed 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 2a7914b5b7..72960fe4a1 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);