2020-06-17 05:22:28 +00:00
|
|
|
/*
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
|
2020-06-17 05:22:28 +00:00
|
|
|
*
|
|
|
|
* This file is part of Open5GS.
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
#include "binding.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
#include "sbi-path.h"
|
2022-04-14 01:30:58 +00:00
|
|
|
#include "gn-handler.h"
|
|
|
|
#include "gx-handler.h"
|
|
|
|
#include "gy-handler.h"
|
|
|
|
#include "n4-handler.h"
|
|
|
|
#include "s5c-handler.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
#include "nnrf-handler.h"
|
|
|
|
#include "nsmf-handler.h"
|
|
|
|
#include "nudm-handler.h"
|
2020-12-11 19:03:20 +00:00
|
|
|
#include "npcf-handler.h"
|
2021-01-01 02:07:08 +00:00
|
|
|
#include "namf-handler.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
#include "gsm-handler.h"
|
|
|
|
#include "ngap-handler.h"
|
2022-04-14 01:30:58 +00:00
|
|
|
#include "gtp-path.h"
|
2020-06-17 05:22:28 +00:00
|
|
|
#include "pfcp-path.h"
|
2021-01-18 16:48:35 +00:00
|
|
|
#include "ngap-path.h"
|
2022-04-14 01:30:58 +00:00
|
|
|
#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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
static void send_gtp_create_err_msg(const smf_sess_t *sess,
|
|
|
|
ogs_gtp_xact_t *gtp_xact, uint8_t gtp_cause)
|
2022-04-14 01:30:58 +00:00
|
|
|
{
|
|
|
|
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
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
ogs_gtp2_send_error_message(gtp_xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess->sgw_s5c_teid,
|
2022-04-14 01:30:58 +00:00
|
|
|
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, gtp_cause);
|
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
static void send_gtp_delete_err_msg(const smf_sess_t *sess,
|
|
|
|
ogs_gtp_xact_t *gtp_xact, uint8_t gtp_cause)
|
2022-04-20 12:42:18 +00:00
|
|
|
{
|
|
|
|
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
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
ogs_gtp2_send_error_message(gtp_xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess->sgw_s5c_teid,
|
2022-04-20 12:42:18 +00:00
|
|
|
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp_cause);
|
|
|
|
}
|
|
|
|
|
2022-04-14 22:00:32 +00:00
|
|
|
static bool send_ccr_init_req_gx_gy(smf_sess_t *sess, smf_event_t *e)
|
|
|
|
{
|
|
|
|
int use_gy = smf_use_gy_iface();
|
|
|
|
|
|
|
|
if (use_gy == -1) {
|
|
|
|
ogs_error("No Gy Diameter Peer");
|
2022-05-14 21:27:54 +00:00
|
|
|
/* TODO: drop Gx connection here,
|
|
|
|
* possibly move to another "releasing" state! */
|
2022-04-14 22:00:32 +00:00
|
|
|
uint8_t gtp_cause = (e->gtp_xact->gtp_version == 1) ?
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE :
|
|
|
|
OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER;
|
2022-04-14 22:00:32 +00:00
|
|
|
send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sess->sm_data.gx_ccr_init_in_flight = true;
|
|
|
|
smf_gx_send_ccr(sess, e->gtp_xact,
|
|
|
|
OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
|
|
|
|
|
|
|
|
if (use_gy == 1) {
|
2022-05-14 21:27:54 +00:00
|
|
|
/* Gy is available,
|
|
|
|
* set up session for the bearer before accepting it towards the UE */
|
2022-04-14 22:00:32 +00:00
|
|
|
sess->sm_data.gy_ccr_init_in_flight = true;
|
|
|
|
smf_gy_send_ccr(sess, e->gtp_xact,
|
|
|
|
OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
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");
|
2022-05-14 21:27:54 +00:00
|
|
|
/* TODO: drop Gx connection here,
|
|
|
|
* possibly move to another "releasing" state! */
|
2022-04-20 12:42:18 +00:00
|
|
|
uint8_t gtp_cause = (e->gtp_xact->gtp_version == 1) ?
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_GTP1_CAUSE_NO_RESOURCES_AVAILABLE :
|
|
|
|
OGS_GTP2_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER;
|
2022-04-20 12:42:18 +00:00
|
|
|
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) {
|
2022-05-14 21:27:54 +00:00
|
|
|
/* Gy is available,
|
|
|
|
* set up session for the bearer before accepting it towards the UE */
|
2022-04-20 12:42:18 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
2022-05-14 21:27:54 +00:00
|
|
|
int rv;
|
|
|
|
char *strerror = NULL;
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
|
|
|
|
ogs_gtp1_message_t *gtp1_message = NULL;
|
|
|
|
ogs_gtp2_message_t *gtp2_message = NULL;
|
2022-04-14 01:30:58 +00:00
|
|
|
uint8_t gtp1_cause, gtp2_cause;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_nas_5gs_message_t *nas_message = NULL;
|
|
|
|
|
|
|
|
ogs_sbi_stream_t *stream = NULL;
|
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
|
|
|
|
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
smf_sm_debug(e);
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2022-04-14 01:30:58 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
2022-04-14 22:00:32 +00:00
|
|
|
/* reset state: */
|
2024-02-26 11:21:59 +00:00
|
|
|
sess->sm_data.s6b_aar_in_flight = false;
|
2022-04-14 22:00:32 +00:00
|
|
|
sess->sm_data.gx_ccr_init_in_flight = false;
|
|
|
|
sess->sm_data.gy_ccr_init_in_flight = false;
|
2024-02-26 11:21:59 +00:00
|
|
|
sess->sm_data.s6b_aaa_err = ER_DIAMETER_SUCCESS;
|
2022-04-14 22:00:32 +00:00
|
|
|
sess->sm_data.gx_cca_init_err = ER_DIAMETER_SUCCESS;
|
|
|
|
sess->sm_data.gy_cca_init_err = ER_DIAMETER_SUCCESS;
|
2022-05-14 21:27:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
2022-04-14 01:30:58 +00:00
|
|
|
break;
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
case SMF_EVT_GN_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gtp1_message = e->gtp1_message;
|
|
|
|
ogs_assert(gtp1_message);
|
|
|
|
|
|
|
|
switch(gtp1_message->h.type) {
|
2022-04-14 01:30:58 +00:00
|
|
|
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;
|
|
|
|
}
|
2022-04-14 22:00:32 +00:00
|
|
|
if (send_ccr_init_req_gx_gy(sess, e) == true)
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_S5C_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gtp2_message = e->gtp2_message;
|
|
|
|
ogs_assert(gtp2_message);
|
|
|
|
|
|
|
|
switch(gtp2_message->h.type) {
|
2022-04-14 01:30:58 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
switch (sess->gtp_rat_type) {
|
|
|
|
case OGS_GTP2_RAT_TYPE_EUTRAN:
|
2022-04-14 22:00:32 +00:00
|
|
|
if (send_ccr_init_req_gx_gy(sess, e) == true)
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
|
2022-04-14 01:30:58 +00:00
|
|
|
break;
|
|
|
|
case OGS_GTP2_RAT_TYPE_WLAN:
|
|
|
|
smf_s6b_send_aar(sess, e->gtp_xact);
|
2024-02-26 11:21:59 +00:00
|
|
|
sess->sm_data.s6b_aar_in_flight = true;
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
|
2024-02-26 11:21:59 +00:00
|
|
|
/* Gx/Gy Init Req is done after s6b AAR + AAA */
|
2022-04-14 01:30:58 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
|
|
|
break;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
default:
|
2022-08-24 12:02:28 +00:00
|
|
|
ogs_error("Not implemented(type:%d)", gtp2_message->h.type);
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
break;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
case OGS_EVENT_SBI_SERVER:
|
|
|
|
sbi_message = e->h.sbi.message;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(sbi_message);
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NSMF_PDUSESSION)
|
|
|
|
SWITCH(sbi_message->h.resource.component[2])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_RELEASE)
|
|
|
|
ogs_error("Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
break;
|
|
|
|
DEFAULT
|
|
|
|
if (smf_nsmf_handle_create_sm_context(
|
|
|
|
sess, stream, sbi_message) == false) {
|
|
|
|
ogs_error("smf_nsmf_handle_create_sm_context() failed");
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("Invalid API name [%s]", sbi_message->h.service.name);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid API name", sbi_message->h.service.name));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_5GSM_MESSAGE:
|
|
|
|
nas_message = e->nas.message;
|
|
|
|
ogs_assert(nas_message);
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
|
|
|
switch (nas_message->gsm.h.message_type) {
|
|
|
|
case OGS_NAS_5GS_PDU_SESSION_ESTABLISHMENT_REQUEST:
|
|
|
|
rv = gsm_handle_pdu_session_establishment_request(sess, stream,
|
|
|
|
&nas_message->gsm.pdu_session_establishment_request);
|
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NAS message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_5gc_sm_policy_association);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
strerror = ogs_msprintf("Unknown message [%d]",
|
|
|
|
nas_message->gsm.h.message_type);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("No handler for event %s", smf_event_get_name(e));
|
|
|
|
break;
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
|
2022-04-14 01:30:58 +00:00
|
|
|
{
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
|
2024-02-26 11:21:59 +00:00
|
|
|
ogs_diam_s6b_message_t *s6b_message = NULL;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_diam_gy_message_t *gy_message = NULL;
|
|
|
|
ogs_diam_gx_message_t *gx_message = NULL;
|
2022-04-14 01:30:58 +00:00
|
|
|
uint32_t diam_err;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
smf_sm_debug(e);
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2024-02-26 11:21:59 +00:00
|
|
|
case SMF_EVT_S6B_MESSAGE:
|
|
|
|
s6b_message = e->s6b_message;
|
|
|
|
ogs_assert(s6b_message);
|
|
|
|
|
|
|
|
switch(s6b_message->cmd_code) {
|
|
|
|
case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION:
|
|
|
|
sess->sm_data.s6b_aar_in_flight = false;
|
|
|
|
sess->sm_data.s6b_aaa_err = s6b_message->result_code;
|
|
|
|
if (s6b_message->result_code == ER_DIAMETER_SUCCESS) {
|
|
|
|
send_ccr_init_req_gx_gy(sess, e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
goto test_can_proceed;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
case SMF_EVT_GX_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gx_message = e->gx_message;
|
|
|
|
ogs_assert(gx_message);
|
|
|
|
|
|
|
|
switch(gx_message->cmd_code) {
|
2022-04-14 01:30:58 +00:00
|
|
|
case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL:
|
2022-05-14 21:27:54 +00:00
|
|
|
switch(gx_message->cc_request_type) {
|
2022-04-14 01:30:58 +00:00
|
|
|
case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
|
|
|
|
ogs_assert(e->gtp_xact);
|
|
|
|
diam_err = smf_gx_handle_cca_initial_request(sess,
|
2022-05-14 21:27:54 +00:00
|
|
|
gx_message, e->gtp_xact);
|
2022-04-14 22:00:32 +00:00
|
|
|
sess->sm_data.gx_ccr_init_in_flight = false;
|
|
|
|
sess->sm_data.gx_cca_init_err = diam_err;
|
|
|
|
goto test_can_proceed;
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_GY_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gy_message = e->gy_message;
|
|
|
|
ogs_assert(gy_message);
|
|
|
|
|
|
|
|
switch(gy_message->cmd_code) {
|
2022-04-14 01:30:58 +00:00
|
|
|
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
|
2022-05-14 21:27:54 +00:00
|
|
|
switch(gy_message->cc_request_type) {
|
2022-04-14 01:30:58 +00:00
|
|
|
case OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST:
|
|
|
|
ogs_assert(e->gtp_xact);
|
|
|
|
diam_err = smf_gy_handle_cca_initial_request(sess,
|
2022-05-14 21:27:54 +00:00
|
|
|
gy_message, e->gtp_xact);
|
2022-04-14 22:00:32 +00:00
|
|
|
sess->sm_data.gy_ccr_init_in_flight = false;
|
|
|
|
sess->sm_data.gy_cca_init_err = diam_err;
|
|
|
|
goto test_can_proceed;
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-04-14 22:00:32 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
test_can_proceed:
|
|
|
|
/* First wait for both Gx and Gy requests to be done: */
|
2024-02-26 11:21:59 +00:00
|
|
|
if (!sess->sm_data.s6b_aar_in_flight &&
|
|
|
|
!sess->sm_data.gx_ccr_init_in_flight &&
|
2022-04-14 22:00:32 +00:00
|
|
|
!sess->sm_data.gy_ccr_init_in_flight) {
|
|
|
|
diam_err = ER_DIAMETER_SUCCESS;
|
2024-02-26 11:21:59 +00:00
|
|
|
if (sess->sm_data.s6b_aaa_err != ER_DIAMETER_SUCCESS)
|
|
|
|
diam_err = sess->sm_data.s6b_aaa_err;
|
2022-04-14 22:00:32 +00:00
|
|
|
if (sess->sm_data.gx_cca_init_err != ER_DIAMETER_SUCCESS)
|
|
|
|
diam_err = sess->sm_data.gx_cca_init_err;
|
|
|
|
if (sess->sm_data.gy_cca_init_err != ER_DIAMETER_SUCCESS)
|
|
|
|
diam_err = sess->sm_data.gy_cca_init_err;
|
|
|
|
|
|
|
|
if (diam_err == ER_DIAMETER_SUCCESS) {
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_establishment);
|
2022-04-14 22:00:32 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_epc_pfcp_send_session_establishment_request(
|
2023-04-15 09:54:03 +00:00
|
|
|
sess, e->gtp_xact, 0));
|
2022-04-14 22:00:32 +00:00
|
|
|
} else {
|
2022-05-14 21:27:54 +00:00
|
|
|
/* FIXME: tear down Gx/Gy session
|
|
|
|
* if its sm_data.*init_err == ER_DIAMETER_SUCCESS */
|
|
|
|
uint8_t gtp_cause = gtp_cause_from_diameter(
|
|
|
|
e->gtp_xact->gtp_version, diam_err, NULL);
|
2022-04-14 22:00:32 +00:00
|
|
|
send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause);
|
|
|
|
}
|
|
|
|
}
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
void smf_gsm_state_wait_5gc_sm_policy_association(ogs_fsm_t *s, smf_event_t *e)
|
2020-06-17 05:22:28 +00:00
|
|
|
{
|
2022-05-14 21:27:54 +00:00
|
|
|
char *strerror = NULL;
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
|
|
|
|
ogs_sbi_stream_t *stream = NULL;
|
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
|
|
|
|
|
|
|
int state = 0;
|
|
|
|
|
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2022-05-14 21:27:54 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
|
|
|
break;
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
case OGS_EVENT_SBI_CLIENT:
|
|
|
|
sbi_message = e->h.sbi.message;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(sbi_message);
|
|
|
|
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NUDM_SDM)
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.resource.component[1])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_SM_DATA)
|
|
|
|
if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_OK) {
|
|
|
|
strerror = ogs_msprintf("[%s:%d] HTTP response error [%d]",
|
|
|
|
smf_ue->supi, sess->psi, sbi_message->res_status);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(
|
|
|
|
stream, sbi_message->res_status,
|
|
|
|
sbi_message, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (smf_nudm_sdm_handle_get(
|
|
|
|
sess, stream, sbi_message) == false) {
|
|
|
|
ogs_error("smf_nudm_sdm_handle_get() failed");
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
strerror = ogs_msprintf("[%s:%d] Invalid resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[1]);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
|
|
|
sbi_message, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL)
|
2023-07-10 07:29:17 +00:00
|
|
|
/*
|
|
|
|
* By here, SMF has already sent a response to AMF in
|
|
|
|
* smf_nudm_sdm_handle_get. Therefore, 'stream = e->h.sbi.data'
|
|
|
|
* should not be used here. Instead of sending additional error
|
|
|
|
* replies to AMF over 'stream', SMF should send a
|
|
|
|
* Namf_Communication_N1N2MessageTransfer request by transitioning
|
|
|
|
* into smf_gsm_state_5gc_n1_n2_reject. This is according to
|
|
|
|
*
|
|
|
|
* TS23.502
|
|
|
|
* 6.3.1.7 4.3.2.2 UE Requested PDU Session Establishment
|
|
|
|
* p100
|
|
|
|
* 11. ...
|
|
|
|
* If the PDU session establishment failed anywhere between step 5
|
|
|
|
* and step 11, then the Namf_Communication_N1N2MessageTransfer
|
|
|
|
* request shall include the N1 SM container with a PDU Session
|
|
|
|
* Establishment Reject message ...
|
|
|
|
*/
|
2022-08-12 05:03:53 +00:00
|
|
|
state = e->h.sbi.state;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
SWITCH(sbi_message->h.resource.component[0])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_SM_POLICIES)
|
|
|
|
if (sbi_message->h.resource.component[1]) {
|
2023-07-10 07:29:17 +00:00
|
|
|
ogs_error("[%s:%d] Unknown resource name [%s]",
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[1]);
|
2023-07-10 07:29:17 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
|
|
|
} else if (sbi_message->res_status !=
|
|
|
|
OGS_SBI_HTTP_STATUS_CREATED) {
|
|
|
|
ogs_error("[%s:%d] HTTP response error [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->res_status);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
|
|
|
} else if (smf_npcf_smpolicycontrol_handle_create(
|
|
|
|
sess, state, sbi_message) == true) {
|
|
|
|
OGS_FSM_TRAN(s,
|
|
|
|
&smf_gsm_state_wait_pfcp_establishment);
|
2022-05-14 21:27:54 +00:00
|
|
|
} else {
|
2023-07-10 07:29:17 +00:00
|
|
|
ogs_error(
|
|
|
|
"smf_npcf_smpolicycontrol_handle_create() failed");
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
2022-05-14 21:27:54 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
2023-07-10 07:29:17 +00:00
|
|
|
ogs_error("[%s:%d] Invalid resource name [%s]",
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[0]);
|
2023-07-10 07:29:17 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
2022-05-14 21:27:54 +00:00
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid API name [%s]",
|
|
|
|
smf_ue->supi, sess->psi, sbi_message->h.service.name);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("No handler for event %s", smf_event_get_name(e));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void smf_gsm_state_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
|
|
|
smf_sess_t *sess = NULL;
|
2022-04-14 01:30:58 +00:00
|
|
|
uint8_t pfcp_cause, gtp_cause;
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_n1_n2_message_transfer_param_t param;
|
|
|
|
|
|
|
|
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
|
|
|
ogs_pfcp_message_t *pfcp_message = NULL;
|
2022-05-31 12:27:42 +00:00
|
|
|
int rv;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
2022-04-14 01:30:58 +00:00
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
smf_sm_debug(e);
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2023-07-10 12:13:28 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
|
|
|
break;
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
case SMF_EVT_N4_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
pfcp_xact = e->pfcp_xact;
|
|
|
|
ogs_assert(pfcp_xact);
|
|
|
|
pfcp_message = e->pfcp_message;
|
|
|
|
ogs_assert(pfcp_message);
|
|
|
|
|
|
|
|
switch (pfcp_message->h.type) {
|
2022-04-14 01:30:58 +00:00
|
|
|
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
|
2022-05-14 21:27:54 +00:00
|
|
|
if (pfcp_xact->epc) {
|
|
|
|
ogs_gtp_xact_t *gtp_xact = pfcp_xact->assoc_xact;
|
|
|
|
ogs_assert(gtp_xact);
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
pfcp_cause = smf_epc_n4_handle_session_establishment_response(
|
2022-05-14 21:27:54 +00:00
|
|
|
sess, pfcp_xact,
|
|
|
|
&pfcp_message->pfcp_session_establishment_response);
|
2022-04-14 01:30:58 +00:00
|
|
|
if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
/* FIXME: tear down Gy and Gx */
|
2022-05-14 21:27:54 +00:00
|
|
|
gtp_cause = gtp_cause_from_pfcp(
|
|
|
|
pfcp_cause, gtp_xact->gtp_version);
|
2022-04-14 01:30:58 +00:00
|
|
|
send_gtp_create_err_msg(sess, e->gtp_xact, gtp_cause);
|
|
|
|
return;
|
|
|
|
}
|
2023-04-15 09:54:03 +00:00
|
|
|
|
|
|
|
gtp_xact = pfcp_xact->assoc_xact;
|
|
|
|
if (gtp_xact) {
|
|
|
|
switch (gtp_xact->gtp_version) {
|
|
|
|
case 1:
|
|
|
|
rv = smf_gtp1_send_create_pdp_context_response(
|
|
|
|
sess, gtp_xact);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
rv = smf_gtp2_send_create_session_response(
|
|
|
|
sess, gtp_xact);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
rv = OGS_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* If no CreatePDPCtxResp can be sent,
|
|
|
|
* then tear down the session: */
|
|
|
|
if (rv != OGS_OK) {
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
2023-04-15 09:54:03 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-05-31 12:27:42 +00:00
|
|
|
}
|
|
|
|
|
2022-04-14 01:30:58 +00:00
|
|
|
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).
|
|
|
|
*/
|
2022-05-12 13:52:36 +00:00
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
smf_epc_pfcp_send_deactivation(sess,
|
|
|
|
OGS_GTP2_CAUSE_RAT_CHANGED_FROM_3GPP_TO_NON_3GPP));
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
smf_bearer_binding(sess);
|
|
|
|
} else {
|
|
|
|
pfcp_cause = smf_5gc_n4_handle_session_establishment_response(
|
2022-05-14 21:27:54 +00:00
|
|
|
sess, pfcp_xact,
|
|
|
|
&pfcp_message->pfcp_session_establishment_response);
|
2023-07-10 07:29:17 +00:00
|
|
|
if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
2022-04-14 01:30:58 +00:00
|
|
|
return;
|
2023-07-10 07:29:17 +00:00
|
|
|
}
|
2022-04-14 01:30:58 +00:00
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.state = SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT;
|
2022-05-14 21:27:54 +00:00
|
|
|
param.n1smbuf =
|
|
|
|
gsm_build_pdu_session_establishment_accept(sess);
|
2022-04-14 01:30:58 +00:00
|
|
|
ogs_assert(param.n1smbuf);
|
2022-05-14 21:27:54 +00:00
|
|
|
param.n2smbuf =
|
|
|
|
ngap_build_pdu_session_resource_setup_request_transfer(
|
|
|
|
sess);
|
2022-04-14 01:30:58 +00:00
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
|
|
|
}
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_operational);
|
2022-04-14 01:30:58 +00:00
|
|
|
break;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("cannot handle PFCP message type[%d]",
|
|
|
|
pfcp_message->h.type);
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
2023-07-10 12:13:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_N4_TIMER:
|
|
|
|
switch (e->h.timer_id) {
|
|
|
|
case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE:
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown timer[%s:%d]",
|
|
|
|
ogs_timer_get_name(e->h.timer_id), e->h.timer_id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown event [%s]", smf_event_get_name(e));
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
2021-01-18 16:48:35 +00:00
|
|
|
int rv, ngap_state;
|
2020-07-02 05:50:23 +00:00
|
|
|
char *strerror = NULL;
|
2020-06-18 01:43:16 +00:00
|
|
|
smf_ue_t *smf_ue = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
|
2023-04-15 09:54:03 +00:00
|
|
|
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
|
|
|
ogs_pfcp_message_t *pfcp_message = NULL;
|
|
|
|
|
2024-03-19 15:00:47 +00:00
|
|
|
ogs_diam_gy_message_t *gy_message = NULL;
|
|
|
|
uint32_t diam_err;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_nas_5gs_message_t *nas_message = NULL;
|
|
|
|
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_sbi_stream_t *stream = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_gtp1_message_t *gtp1_message = NULL;
|
|
|
|
ogs_gtp2_message_t *gtp2_message = NULL;
|
2022-04-20 12:42:18 +00:00
|
|
|
uint8_t gtp1_cause, gtp2_cause;
|
|
|
|
bool release;
|
2023-01-31 10:38:17 +00:00
|
|
|
int r;
|
2022-04-14 01:30:58 +00:00
|
|
|
|
2023-02-01 08:28:57 +00:00
|
|
|
int state = 0;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2020-06-17 05:22:28 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
case SMF_EVT_GN_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gtp1_message = e->gtp1_message;
|
|
|
|
ogs_assert(gtp1_message);
|
|
|
|
|
|
|
|
switch(gtp1_message->h.type) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_GTP1_DELETE_PDP_CONTEXT_REQUEST_TYPE:
|
|
|
|
gtp1_cause = smf_gn_handle_delete_pdp_context_request(sess,
|
|
|
|
e->gtp_xact,
|
2022-05-14 21:27:54 +00:00
|
|
|
>p1_message->delete_pdp_context_request);
|
2022-04-20 12:42:18 +00:00
|
|
|
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;
|
|
|
|
}
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
2022-04-20 12:42:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_S5C_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gtp2_message = e->gtp2_message;
|
|
|
|
ogs_assert(gtp2_message);
|
|
|
|
|
|
|
|
switch(gtp2_message->h.type) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_GTP2_DELETE_SESSION_REQUEST_TYPE:
|
2022-05-14 21:27:54 +00:00
|
|
|
gtp2_cause = smf_s5c_handle_delete_session_request(
|
|
|
|
sess, e->gtp_xact,
|
|
|
|
>p2_message->delete_session_request);
|
2022-04-20 12:42:18 +00:00
|
|
|
if (gtp2_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
|
[GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.
As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.
This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 01:00:08 +00:00
|
|
|
ogs_gtp2_send_error_message(e->gtp_xact,
|
|
|
|
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
|
|
|
|
sess->sgw_s5c_teid,
|
|
|
|
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp2_cause);
|
2022-04-20 12:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
2022-04-20 12:42:18 +00:00
|
|
|
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;
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
2022-04-20 12:42:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
default:
|
2022-08-24 12:02:28 +00:00
|
|
|
ogs_error("Not implemented(type:%d)", gtp2_message->h.type);
|
2022-04-14 01:30:58 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-04-15 09:54:03 +00:00
|
|
|
case SMF_EVT_N4_MESSAGE:
|
|
|
|
pfcp_xact = e->pfcp_xact;
|
|
|
|
ogs_assert(pfcp_xact);
|
|
|
|
pfcp_message = e->pfcp_message;
|
|
|
|
ogs_assert(pfcp_message);
|
|
|
|
|
|
|
|
switch (pfcp_message->h.type) {
|
|
|
|
case OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE:
|
|
|
|
if ((pfcp_xact->create_flags &
|
|
|
|
OGS_PFCP_CREATE_RESTORATION_INDICATION)) {
|
|
|
|
ogs_pfcp_session_establishment_response_t *rsp = NULL;
|
|
|
|
ogs_pfcp_f_seid_t *up_f_seid = NULL;
|
|
|
|
|
|
|
|
rsp = &pfcp_message->pfcp_session_establishment_response;
|
|
|
|
if (rsp->up_f_seid.presence == 0) {
|
|
|
|
ogs_error("No UP F-SEID");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
up_f_seid = rsp->up_f_seid.data;
|
|
|
|
ogs_assert(up_f_seid);
|
|
|
|
sess->upf_n4_seid = be64toh(up_f_seid->seid);
|
|
|
|
} else {
|
|
|
|
ogs_error("cannot handle PFCP Session Establishment Response");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-04-16 02:50:31 +00:00
|
|
|
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
2023-08-18 11:14:33 +00:00
|
|
|
ogs_error("EPC Session Released by Error Indication");
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_epc_session_will_release);
|
2023-04-16 02:50:31 +00:00
|
|
|
break;
|
|
|
|
|
2023-04-15 09:54:03 +00:00
|
|
|
default:
|
|
|
|
ogs_error("cannot handle PFCP message type[%d]",
|
|
|
|
pfcp_message->h.type);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2024-03-19 15:00:47 +00:00
|
|
|
case SMF_EVT_GY_MESSAGE:
|
|
|
|
gy_message = e->gy_message;
|
|
|
|
ogs_assert(gy_message);
|
|
|
|
|
|
|
|
switch(gy_message->cmd_code) {
|
|
|
|
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
|
|
|
|
switch (gy_message->cc_request_type) {
|
|
|
|
case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST:
|
|
|
|
ogs_assert(e->pfcp_xact);
|
|
|
|
diam_err = smf_gy_handle_cca_update_request(sess, gy_message, e->pfcp_xact);
|
|
|
|
if (diam_err != ER_DIAMETER_SUCCESS)
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
case OGS_EVENT_SBI_SERVER:
|
|
|
|
sbi_message = e->h.sbi.message;
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_assert(sbi_message);
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_assert(stream);
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NSMF_PDUSESSION)
|
|
|
|
SWITCH(sbi_message->h.resource.component[2])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
2020-11-27 02:44:37 +00:00
|
|
|
smf_nsmf_handle_update_sm_context(sess, stream, sbi_message);
|
2020-06-17 05:22:28 +00:00
|
|
|
break;
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_RELEASE)
|
2020-11-27 02:44:37 +00:00
|
|
|
smf_nsmf_handle_release_sm_context(sess, stream, sbi_message);
|
2020-06-17 05:22:28 +00:00
|
|
|
break;
|
|
|
|
DEFAULT
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_error("Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
2020-06-17 05:22:28 +00:00
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("Invalid API name [%s]", sbi_message->h.service.name);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
2020-06-17 05:22:28 +00:00
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
2021-06-06 13:35:46 +00:00
|
|
|
"Invalid API name", sbi_message->h.service.name));
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
2020-06-17 05:22:28 +00:00
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
case OGS_EVENT_SBI_CLIENT:
|
|
|
|
sbi_message = e->h.sbi.message;
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_assert(sbi_message);
|
2020-08-03 03:22:41 +00:00
|
|
|
|
2020-06-18 01:43:16 +00:00
|
|
|
smf_ue = sess->smf_ue;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(smf_ue);
|
2020-12-11 19:03:20 +00:00
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
SWITCH(sbi_message->h.service.name)
|
2020-12-11 19:03:20 +00:00
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL)
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2023-02-01 08:28:57 +00:00
|
|
|
state = e->h.sbi.state;
|
2021-05-29 06:56:12 +00:00
|
|
|
|
2020-12-11 19:03:20 +00:00
|
|
|
SWITCH(sbi_message->h.resource.component[0])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_SM_POLICIES)
|
2021-05-29 06:56:12 +00:00
|
|
|
if (!sbi_message->h.resource.component[1]) {
|
2021-11-14 12:07:56 +00:00
|
|
|
ogs_assert(stream);
|
2022-05-14 21:27:54 +00:00
|
|
|
strerror = ogs_msprintf(
|
|
|
|
"[%s:%d] HTTP response error [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->res_status);
|
|
|
|
ogs_assert(strerror);
|
2021-05-29 06:56:12 +00:00
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(
|
|
|
|
stream, sbi_message->res_status,
|
|
|
|
sbi_message, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
2021-05-29 06:56:12 +00:00
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
break;
|
2021-05-29 06:56:12 +00:00
|
|
|
} else {
|
|
|
|
SWITCH(sbi_message->h.resource.component[2])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_DELETE)
|
2023-07-15 14:30:32 +00:00
|
|
|
if (sess->policy_association_id)
|
|
|
|
ogs_free(sess->policy_association_id);
|
|
|
|
sess->policy_association_id = NULL;
|
|
|
|
|
2021-05-29 06:56:12 +00:00
|
|
|
if (sbi_message->res_status !=
|
|
|
|
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
2023-07-11 06:46:55 +00:00
|
|
|
ogs_error("[%s:%d] HTTP response error [%d]",
|
2021-05-29 06:56:12 +00:00
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->res_status);
|
2023-07-11 06:46:55 +00:00
|
|
|
/* In spite of error from PCF, continue with
|
|
|
|
session teardown, so as to not leave stale
|
|
|
|
sessions. */
|
2021-05-29 06:56:12 +00:00
|
|
|
}
|
|
|
|
|
2023-02-01 08:28:57 +00:00
|
|
|
if (state == OGS_PFCP_DELETE_TRIGGER_SMF_INITIATED) {
|
|
|
|
OGS_FSM_TRAN(&sess->sm, smf_gsm_state_wait_5gc_n1_n2_release);
|
|
|
|
|
|
|
|
smf_n1_n2_message_transfer_param_t param;
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.state = SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE;
|
|
|
|
sess->pti = OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED;
|
|
|
|
param.n1smbuf = gsm_build_pdu_session_release_command(
|
|
|
|
sess, OGS_5GSM_CAUSE_REACTIVATION_REQUESTED);
|
|
|
|
ogs_assert(param.n1smbuf);
|
|
|
|
|
|
|
|
param.n2smbuf =
|
|
|
|
ngap_build_pdu_session_resource_release_command_transfer(
|
|
|
|
sess, SMF_NGAP_STATE_DELETE_TRIGGER_SMF_INITIATED,
|
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
|
2023-07-25 13:38:38 +00:00
|
|
|
/*
|
|
|
|
* Skip_ind is not used when changing the PDU Session Anchor.
|
|
|
|
* param.skip_ind = false;
|
|
|
|
*
|
|
|
|
* TS23.502
|
|
|
|
* 4.3.4 PDU Session Release
|
|
|
|
* 4.3.4.2 UE or network requested PDU Session Release for Non-Roaming
|
|
|
|
* and Roaming with Local Breakout
|
|
|
|
*
|
|
|
|
* 3b. ...
|
|
|
|
*
|
|
|
|
* The "skip indicator" tells the AMF whether it may skip sending
|
|
|
|
* the N1 SM container to the UE (e.g. when the UE is in CM-IDLE state).
|
|
|
|
* SMF includes the "skip indicator"
|
|
|
|
* in the Namf_Communication_N1N2MessageTransfer
|
|
|
|
* except when the procedure is triggered to change PDU Session Anchor
|
|
|
|
* of a PDU Session with SSC mode 2.
|
|
|
|
*
|
|
|
|
* Related Issue #2396
|
|
|
|
*/
|
2023-02-01 08:28:57 +00:00
|
|
|
|
|
|
|
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
|
|
|
} else {
|
|
|
|
OGS_FSM_TRAN(&sess->sm,
|
|
|
|
&smf_gsm_state_wait_pfcp_deletion);
|
|
|
|
}
|
2021-05-29 06:56:12 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
strerror = ogs_msprintf("[%s:%d] "
|
|
|
|
"Unknown resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[2]);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
2021-11-14 12:07:56 +00:00
|
|
|
if (stream)
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
|
|
|
sbi_message, strerror, NULL));
|
2021-05-29 06:56:12 +00:00
|
|
|
ogs_free(strerror);
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
2021-05-29 06:56:12 +00:00
|
|
|
END
|
2020-12-11 19:03:20 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
strerror = ogs_msprintf("[%s:%d] Invalid resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[0]);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
2020-12-11 19:03:20 +00:00
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
2021-06-06 13:35:46 +00:00
|
|
|
sbi_message, strerror, NULL));
|
2020-12-11 19:03:20 +00:00
|
|
|
ogs_free(strerror);
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
2020-06-17 05:22:28 +00:00
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
|
|
|
|
SWITCH(sbi_message->h.resource.component[0])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS)
|
2021-11-14 12:07:56 +00:00
|
|
|
smf_namf_comm_handle_n1_n2_message_transfer(
|
2022-08-12 05:03:53 +00:00
|
|
|
sess, e->h.sbi.state, sbi_message);
|
2020-06-17 05:22:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
2020-12-11 19:03:20 +00:00
|
|
|
ogs_error("[%s:%d] Invalid resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
2020-06-17 05:22:28 +00:00
|
|
|
sbi_message->h.resource.component[0]);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
2020-12-11 19:03:20 +00:00
|
|
|
ogs_error("[%s:%d] Invalid API name [%s]",
|
|
|
|
smf_ue->supi, sess->psi, sbi_message->h.service.name);
|
2021-01-18 16:48:35 +00:00
|
|
|
ogs_assert_if_reached();
|
2020-06-17 05:22:28 +00:00
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_5GSM_MESSAGE:
|
|
|
|
nas_message = e->nas.message;
|
|
|
|
ogs_assert(nas_message);
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_assert(stream);
|
2020-06-18 01:43:16 +00:00
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
2020-06-17 05:22:28 +00:00
|
|
|
|
|
|
|
switch (nas_message->gsm.h.message_type) {
|
2021-11-14 12:07:56 +00:00
|
|
|
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST:
|
|
|
|
rv = gsm_handle_pdu_session_modification_request(sess, stream,
|
|
|
|
&nas_message->gsm.pdu_session_modification_request);
|
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NAS message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE:
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
2021-01-01 02:07:08 +00:00
|
|
|
break;
|
|
|
|
|
2020-07-02 05:50:23 +00:00
|
|
|
case OGS_NAS_5GS_PDU_SESSION_RELEASE_REQUEST:
|
2021-08-28 15:02:39 +00:00
|
|
|
if (sess->policy_association_id) {
|
2021-05-29 06:56:12 +00:00
|
|
|
smf_npcf_smpolicycontrol_param_t param;
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
|
|
|
|
param.ran_nas_release.gsm_cause =
|
|
|
|
OGS_5GSM_CAUSE_REGULAR_DEACTIVATION;
|
|
|
|
param.ran_nas_release.ngap_cause.group = NGAP_Cause_PR_nas;
|
|
|
|
param.ran_nas_release.ngap_cause.value =
|
|
|
|
NGAP_CauseNas_normal_release;
|
|
|
|
|
2023-01-31 10:38:17 +00:00
|
|
|
r = smf_sbi_discover_and_send(
|
2022-08-26 15:12:22 +00:00
|
|
|
OGS_SBI_SERVICE_TYPE_NPCF_SMPOLICYCONTROL, NULL,
|
2022-07-24 06:10:09 +00:00
|
|
|
smf_npcf_smpolicycontrol_build_delete,
|
|
|
|
sess, stream,
|
2023-01-31 10:38:17 +00:00
|
|
|
OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-08-28 15:02:39 +00:00
|
|
|
} else {
|
2023-08-24 12:20:25 +00:00
|
|
|
ogs_warn("[%s:%d] No PolicyAssociationId. "
|
|
|
|
"Forcibly remove SESSION", smf_ue->supi, sess->psi);
|
|
|
|
r = smf_sbi_discover_and_send(
|
|
|
|
OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL,
|
|
|
|
smf_nudm_uecm_build_deregistration, sess, stream,
|
|
|
|
SMF_UECM_STATE_DEREGISTERED_BY_AMF, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2021-05-29 06:56:12 +00:00
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
break;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
default:
|
2020-07-02 05:50:23 +00:00
|
|
|
strerror = ogs_msprintf("Unknown message [%d]",
|
|
|
|
nas_message->gsm.h.message_type);
|
|
|
|
ogs_assert(strerror);
|
2020-12-11 19:03:20 +00:00
|
|
|
|
2020-07-02 05:50:23 +00:00
|
|
|
ogs_error("%s", strerror);
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL));
|
2020-07-02 05:50:23 +00:00
|
|
|
ogs_free(strerror);
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_NGAP_MESSAGE:
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2020-11-27 02:44:37 +00:00
|
|
|
ogs_assert(stream);
|
2020-06-18 01:43:16 +00:00
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
2020-06-17 05:22:28 +00:00
|
|
|
pkbuf = e->pkbuf;
|
|
|
|
ogs_assert(pkbuf);
|
|
|
|
ogs_assert(e->ngap.type);
|
|
|
|
|
|
|
|
switch (e->ngap.type) {
|
|
|
|
case OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP:
|
|
|
|
rv = ngap_handle_pdu_session_resource_setup_response_transfer(
|
2020-11-27 02:44:37 +00:00
|
|
|
sess, stream, pkbuf);
|
2021-01-01 02:07:08 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NGAP message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-11-28 11:54:51 +00:00
|
|
|
case OpenAPI_n2_sm_info_type_PDU_RES_SETUP_FAIL:
|
|
|
|
rv = ngap_handle_pdu_session_resource_setup_unsuccessful_transfer(
|
|
|
|
sess, stream, pkbuf);
|
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NGAP message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2021-01-01 02:07:08 +00:00
|
|
|
case OpenAPI_n2_sm_info_type_PDU_RES_MOD_RSP:
|
|
|
|
rv = ngap_handle_pdu_session_resource_modify_response_transfer(
|
|
|
|
sess, stream, pkbuf);
|
2020-06-17 05:22:28 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NGAP message",
|
2020-06-18 01:43:16 +00:00
|
|
|
smf_ue->supi, sess->psi);
|
2020-06-17 05:22:28 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-07-02 05:50:23 +00:00
|
|
|
case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP:
|
2021-01-18 16:48:35 +00:00
|
|
|
ngap_state = sess->ngap_state.pdu_session_resource_release;
|
|
|
|
|
2021-12-11 11:35:16 +00:00
|
|
|
if (ngap_state == SMF_NGAP_STATE_NONE) {
|
|
|
|
strerror = ogs_msprintf(
|
|
|
|
"[%s:%d] No PDUSessionResourceReleaseRequest",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
|
2021-01-18 16:48:35 +00:00
|
|
|
} else if (ngap_state ==
|
|
|
|
SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN) {
|
|
|
|
smf_n1_n2_message_transfer_param_t param;
|
|
|
|
|
2021-06-06 13:35:46 +00:00
|
|
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
2021-01-18 16:48:35 +00:00
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.state = SMF_NETWORK_TRIGGERED_SERVICE_REQUEST;
|
|
|
|
param.n2smbuf =
|
|
|
|
ngap_build_pdu_session_resource_setup_request_transfer(
|
|
|
|
sess);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
|
|
|
|
param.n1n2_failure_txf_notif_uri = true;
|
|
|
|
|
|
|
|
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
|
|
|
} else {
|
|
|
|
ogs_fatal("Invalid state [%d]", ngap_state);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
2020-07-02 05:50:23 +00:00
|
|
|
break;
|
|
|
|
|
2021-01-03 05:50:59 +00:00
|
|
|
case OpenAPI_n2_sm_info_type_PATH_SWITCH_REQ:
|
2021-01-28 19:23:54 +00:00
|
|
|
rv = ngap_handle_path_switch_request_transfer(sess, stream, pkbuf);
|
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NGAP message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OpenAPI_n2_sm_info_type_HANDOVER_REQUIRED:
|
|
|
|
rv = ngap_handle_handover_required_transfer(sess, stream, pkbuf);
|
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NGAP message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OpenAPI_n2_sm_info_type_HANDOVER_REQ_ACK:
|
|
|
|
rv = ngap_handle_handover_request_ack(sess, stream, pkbuf);
|
2021-01-03 05:50:59 +00:00
|
|
|
if (rv != OGS_OK) {
|
|
|
|
ogs_error("[%s:%d] Cannot handle NGAP message",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
default:
|
|
|
|
ogs_error("Unknown message[%d]", e->ngap.type);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-07-10 12:13:28 +00:00
|
|
|
case SMF_EVT_N4_TIMER:
|
|
|
|
switch (e->h.timer_id) {
|
|
|
|
case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE:
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown timer[%s:%d]",
|
|
|
|
ogs_timer_get_name(e->h.timer_id), e->h.timer_id);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
default:
|
2020-06-18 01:43:16 +00:00
|
|
|
ogs_error("Unknown event [%s]", smf_event_get_name(e));
|
2020-06-17 05:22:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
void smf_gsm_state_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e)
|
2022-04-20 12:42:18 +00:00
|
|
|
{
|
2022-05-14 21:27:54 +00:00
|
|
|
int status;
|
|
|
|
|
2024-01-05 12:09:17 +00:00
|
|
|
smf_ue_t *smf_ue = NULL;
|
2022-04-20 12:42:18 +00:00
|
|
|
smf_sess_t *sess = NULL;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
ogs_sbi_stream_t *stream = NULL;
|
2024-01-05 12:09:17 +00:00
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
ogs_pfcp_xact_t *pfcp_xact = NULL;
|
|
|
|
ogs_pfcp_message_t *pfcp_message = NULL;
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
uint8_t pfcp_cause, gtp_cause;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_gtp_xact_t *gtp_xact = NULL;
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
2023-11-19 10:34:51 +00:00
|
|
|
/* Since `pfcp_xact->epc` is not available,
|
2022-05-14 21:27:54 +00:00
|
|
|
* we'll use `sess->epc` */
|
|
|
|
if (sess->epc) {
|
|
|
|
/* EPC */
|
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
smf_epc_pfcp_send_session_deletion_request(sess, e->gtp_xact));
|
|
|
|
} else {
|
|
|
|
/* 5GC */
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
ogs_assert(OGS_OK ==
|
|
|
|
smf_5gc_pfcp_send_session_deletion_request(
|
2022-08-12 05:03:53 +00:00
|
|
|
sess, stream, e->h.sbi.state));
|
2022-05-14 21:27:54 +00:00
|
|
|
}
|
2022-04-20 12:42:18 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_GN_MESSAGE:
|
|
|
|
case SMF_EVT_S5C_MESSAGE:
|
|
|
|
break; /* ignore */
|
|
|
|
|
|
|
|
case SMF_EVT_N4_MESSAGE:
|
2022-05-14 21:27:54 +00:00
|
|
|
pfcp_xact = e->pfcp_xact;
|
|
|
|
ogs_assert(pfcp_xact);
|
|
|
|
pfcp_message = e->pfcp_message;
|
|
|
|
ogs_assert(pfcp_message);
|
|
|
|
|
|
|
|
switch (pfcp_message->h.type) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE:
|
2022-05-14 21:27:54 +00:00
|
|
|
if (pfcp_xact->epc) {
|
|
|
|
gtp_xact = pfcp_xact->assoc_xact;
|
|
|
|
|
|
|
|
pfcp_cause = smf_epc_n4_handle_session_deletion_response(
|
|
|
|
sess, pfcp_xact,
|
|
|
|
&pfcp_message->pfcp_session_deletion_response);
|
2022-04-20 12:42:18 +00:00
|
|
|
if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
|
|
|
/* FIXME: tear down Gy and Gx */
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(gtp_xact);
|
|
|
|
gtp_cause = gtp_cause_from_pfcp(
|
|
|
|
pfcp_cause, gtp_xact->gtp_version);
|
2022-04-20 12:42:18 +00:00
|
|
|
send_gtp_delete_err_msg(sess, gtp_xact, gtp_cause);
|
2022-05-14 21:27:54 +00:00
|
|
|
break;
|
2022-04-20 12:42:18 +00:00
|
|
|
}
|
|
|
|
e->gtp_xact = gtp_xact;
|
|
|
|
if (send_ccr_termination_req_gx_gy_s6b(sess, e) == true)
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_release);
|
2022-04-20 12:42:18 +00:00
|
|
|
/* else: free session? */
|
|
|
|
} else {
|
2022-05-14 21:27:54 +00:00
|
|
|
int trigger;
|
|
|
|
|
|
|
|
stream = pfcp_xact->assoc_stream;
|
|
|
|
trigger = pfcp_xact->delete_trigger;
|
|
|
|
ogs_assert(trigger);
|
|
|
|
|
|
|
|
ogs_pfcp_xact_commit(pfcp_xact);
|
|
|
|
|
|
|
|
status = smf_5gc_n4_handle_session_deletion_response(
|
|
|
|
sess, stream, trigger,
|
|
|
|
&pfcp_message->pfcp_session_deletion_response);
|
|
|
|
if (status != OGS_SBI_HTTP_STATUS_OK) {
|
|
|
|
ogs_error(
|
2022-05-17 12:44:52 +00:00
|
|
|
"[%d] smf_5gc_n4_handle_session_deletion_response() "
|
|
|
|
"failed", trigger);
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
2022-05-14 21:27:54 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
if (trigger == OGS_PFCP_DELETE_TRIGGER_LOCAL_INITIATED) {
|
|
|
|
|
|
|
|
ogs_error("OLD Session Released");
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
|
|
|
|
|
|
|
} else if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) {
|
|
|
|
ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
n1smbuf = gsm_build_pdu_session_release_command(
|
|
|
|
sess, OGS_5GSM_CAUSE_REGULAR_DEACTIVATION);
|
|
|
|
ogs_assert(n1smbuf);
|
2022-05-17 12:44:52 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
n2smbuf = ngap_build_pdu_session_resource_release_command_transfer(
|
|
|
|
sess, SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED,
|
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
|
|
|
|
ogs_assert(n2smbuf);
|
2022-05-17 12:44:52 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
smf_sbi_send_sm_context_updated_data_n1_n2_message(
|
|
|
|
sess, stream,
|
|
|
|
n1smbuf, OpenAPI_n2_sm_info_type_PDU_RES_REL_CMD,
|
|
|
|
n2smbuf);
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_5gc_n1_n2_release);
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
} else if (trigger ==
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT ||
|
2023-08-18 11:14:33 +00:00
|
|
|
trigger ==
|
2022-05-14 21:27:54 +00:00
|
|
|
OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) {
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
int r = smf_sbi_discover_and_send(
|
|
|
|
OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL,
|
|
|
|
smf_nudm_uecm_build_deregistration, sess, stream,
|
|
|
|
SMF_UECM_STATE_DEREGISTERED_BY_AMF, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
|
|
|
|
|
|
|
} else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) {
|
|
|
|
smf_n1_n2_message_transfer_param_t param;
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
param.state = SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE;
|
|
|
|
param.n2smbuf = ngap_build_pdu_session_resource_release_command_transfer(
|
|
|
|
sess, SMF_NGAP_STATE_DELETE_TRIGGER_PCF_INITIATED,
|
|
|
|
NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release);
|
|
|
|
ogs_assert(param.n2smbuf);
|
|
|
|
|
|
|
|
param.skip_ind = true;
|
|
|
|
|
|
|
|
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_wait_5gc_n1_n2_release);
|
|
|
|
} else {
|
|
|
|
ogs_fatal("Unknown trigger [%d]", trigger);
|
|
|
|
ogs_assert_if_reached();
|
2022-05-14 21:27:54 +00:00
|
|
|
}
|
2022-04-20 12:42:18 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
default:
|
|
|
|
ogs_error("cannot handle PFCP message type[%d]",
|
|
|
|
pfcp_message->h.type);
|
|
|
|
}
|
2024-01-05 12:09:17 +00:00
|
|
|
break;
|
|
|
|
case OGS_EVENT_SBI_CLIENT:
|
|
|
|
sbi_message = e->h.sbi.message;
|
|
|
|
ogs_assert(sbi_message);
|
|
|
|
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL)
|
|
|
|
ogs_pkbuf_t *n1smbuf = NULL;
|
|
|
|
|
|
|
|
stream = e->h.sbi.data;
|
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
ogs_error("[%s:%d] state [%d] res_status [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
e->h.sbi.state, sbi_message->res_status);
|
|
|
|
|
|
|
|
n1smbuf = gsm_build_pdu_session_release_reject(sess,
|
|
|
|
OGS_5GSM_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE);
|
|
|
|
ogs_assert(n1smbuf);
|
|
|
|
|
|
|
|
smf_sbi_send_sm_context_update_error_n1_n2_message(
|
|
|
|
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
|
|
|
n1smbuf, OpenAPI_n2_sm_info_type_NULL, NULL);
|
|
|
|
break;
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid API name [%s]",
|
|
|
|
smf_ue->supi, sess->psi, sbi_message->h.service.name);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
END
|
|
|
|
break;
|
2022-04-20 12:42:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
void smf_gsm_state_wait_epc_auth_release(ogs_fsm_t *s, smf_event_t *e)
|
2022-04-20 12:42:18 +00:00
|
|
|
{
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
|
|
|
|
ogs_diam_gx_message_t *gx_message = NULL;
|
|
|
|
ogs_diam_gy_message_t *gy_message = NULL;
|
|
|
|
ogs_diam_s6b_message_t *s6b_message = NULL;
|
2022-04-20 12:42:18 +00:00
|
|
|
uint32_t diam_err;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
2022-04-20 12:42:18 +00:00
|
|
|
smf_sm_debug(e);
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2022-04-20 12:42:18 +00:00
|
|
|
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:
|
2022-05-14 21:27:54 +00:00
|
|
|
gx_message = e->gx_message;
|
|
|
|
ogs_assert(gx_message);
|
|
|
|
|
|
|
|
switch(gx_message->cmd_code) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_DIAM_GX_CMD_CODE_CREDIT_CONTROL:
|
2022-05-14 21:27:54 +00:00
|
|
|
switch(gx_message->cc_request_type) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
|
|
|
diam_err = smf_gx_handle_cca_termination_request(sess,
|
2022-05-14 21:27:54 +00:00
|
|
|
gx_message, e->gtp_xact);
|
2022-04-20 12:42:18 +00:00
|
|
|
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:
|
2022-05-14 21:27:54 +00:00
|
|
|
gy_message = e->gy_message;
|
|
|
|
ogs_assert(gy_message);
|
|
|
|
|
|
|
|
switch(gy_message->cmd_code) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
|
2022-05-14 21:27:54 +00:00
|
|
|
switch(gy_message->cc_request_type) {
|
2022-04-20 12:42:18 +00:00
|
|
|
case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
|
|
|
diam_err = smf_gy_handle_cca_termination_request(sess,
|
2022-05-14 21:27:54 +00:00
|
|
|
gy_message, e->gtp_xact);
|
2022-04-20 12:42:18 +00:00
|
|
|
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:
|
2022-05-14 21:27:54 +00:00
|
|
|
s6b_message = e->s6b_message;
|
|
|
|
ogs_assert(s6b_message);
|
|
|
|
|
|
|
|
switch(s6b_message->cmd_code) {
|
2022-04-20 12:42:18 +00:00
|
|
|
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:
|
2022-05-31 12:27:42 +00:00
|
|
|
smf_gtp1_send_delete_pdp_context_response(
|
|
|
|
sess, e->gtp_xact);
|
2022-04-20 12:42:18 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2022-05-31 12:27:42 +00:00
|
|
|
smf_gtp2_send_delete_session_response(
|
|
|
|
sess, e->gtp_xact);
|
2022-04-20 12:42:18 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
2022-05-14 21:27:54 +00:00
|
|
|
uint8_t gtp_cause = gtp_cause_from_diameter(
|
|
|
|
e->gtp_xact->gtp_version, diam_err, NULL);
|
2022-04-20 12:42:18 +00:00
|
|
|
send_gtp_delete_err_msg(sess, e->gtp_xact, gtp_cause);
|
|
|
|
}
|
|
|
|
}
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_epc_session_will_release);
|
2022-04-20 12:42:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
void smf_gsm_state_wait_5gc_n1_n2_release(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
|
|
|
int ngap_state;
|
|
|
|
char *strerror = NULL;
|
|
|
|
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
ogs_pkbuf_t *pkbuf = NULL;
|
|
|
|
|
|
|
|
ogs_nas_5gs_message_t *nas_message = NULL;
|
|
|
|
|
|
|
|
ogs_sbi_stream_t *stream = NULL;
|
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
|
|
|
|
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2022-05-14 21:27:54 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
|
|
|
break;
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
case OGS_EVENT_SBI_SERVER:
|
|
|
|
sbi_message = e->h.sbi.message;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(sbi_message);
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NSMF_PDUSESSION)
|
|
|
|
SWITCH(sbi_message->h.resource.component[2])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_MODIFY)
|
|
|
|
smf_nsmf_handle_update_sm_context(sess, stream, sbi_message);
|
|
|
|
break;
|
2023-08-24 12:20:25 +00:00
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_RELEASE)
|
|
|
|
smf_nsmf_handle_release_sm_context(sess, stream, sbi_message);
|
|
|
|
break;
|
2022-05-14 21:27:54 +00:00
|
|
|
DEFAULT
|
|
|
|
ogs_error("Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("Invalid API name [%s]", sbi_message->h.service.name);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid API name", sbi_message->h.service.name));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
case OGS_EVENT_SBI_CLIENT:
|
|
|
|
sbi_message = e->h.sbi.message;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(sbi_message);
|
|
|
|
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
|
|
|
|
SWITCH(sbi_message->h.resource.component[0])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS)
|
2023-08-18 11:14:33 +00:00
|
|
|
ogs_warn("[%s:%d] state [%d] res_status [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
e->h.sbi.state, sbi_message->res_status);
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_namf_comm_handle_n1_n2_message_transfer(
|
2022-08-12 05:03:53 +00:00
|
|
|
sess, e->h.sbi.state, sbi_message);
|
2022-05-14 21:27:54 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[0]);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
2024-01-05 12:09:17 +00:00
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL)
|
|
|
|
ogs_pkbuf_t *n1smbuf = NULL;
|
|
|
|
|
|
|
|
stream = e->h.sbi.data;
|
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
ogs_error("[%s:%d] state [%d] res_status [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
e->h.sbi.state, sbi_message->res_status);
|
|
|
|
|
|
|
|
n1smbuf = gsm_build_pdu_session_release_reject(sess,
|
|
|
|
OGS_5GSM_CAUSE_MESSAGE_NOT_COMPATIBLE_WITH_THE_PROTOCOL_STATE);
|
|
|
|
ogs_assert(n1smbuf);
|
|
|
|
|
|
|
|
smf_sbi_send_sm_context_update_error_n1_n2_message(
|
|
|
|
stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
|
|
|
n1smbuf, OpenAPI_n2_sm_info_type_NULL, NULL);
|
|
|
|
break;
|
2022-05-14 21:27:54 +00:00
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid API name [%s]",
|
|
|
|
smf_ue->supi, sess->psi, sbi_message->h.service.name);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_NGAP_MESSAGE:
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
pkbuf = e->pkbuf;
|
|
|
|
ogs_assert(pkbuf);
|
|
|
|
ogs_assert(e->ngap.type);
|
|
|
|
|
|
|
|
switch (e->ngap.type) {
|
2023-07-25 13:38:38 +00:00
|
|
|
case OpenAPI_n2_sm_info_type_PDU_RES_SETUP_RSP:
|
|
|
|
/*
|
|
|
|
* In case of PDU Session Anchor change, when removing the session,
|
|
|
|
* it cannot be activated because there is no UPF.
|
|
|
|
*
|
|
|
|
* 1. InitialContextSetupResponse
|
|
|
|
* 2. /nsmf-pdusession/v1/sm-contexts/{smContextRef}/modify
|
|
|
|
* 3. PFCP Session Modifcation Request (Apply: FORWARD)
|
|
|
|
* 4. No UPF, so we cannot do PFCP Session Modifcation Response
|
|
|
|
*
|
|
|
|
* At this point, we just reply HTTP_STATUS_NO_CONTENT to the AMF.
|
|
|
|
*/
|
|
|
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
|
|
|
break;
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP:
|
|
|
|
ngap_state = sess->ngap_state.pdu_session_resource_release;
|
|
|
|
|
|
|
|
if (ngap_state == SMF_NGAP_STATE_NONE) {
|
|
|
|
strerror = ogs_msprintf(
|
|
|
|
"[%s:%d] No PDUSessionResourceReleaseRequest",
|
|
|
|
smf_ue->supi, sess->psi);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
|
|
|
|
} else if (
|
|
|
|
ngap_state == SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED ||
|
2023-02-01 08:28:57 +00:00
|
|
|
ngap_state == SMF_NGAP_STATE_DELETE_TRIGGER_PCF_INITIATED ||
|
|
|
|
ngap_state == SMF_NGAP_STATE_DELETE_TRIGGER_SMF_INITIATED) {
|
2022-05-14 21:27:54 +00:00
|
|
|
|
|
|
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
|
|
|
|
2022-09-12 11:07:51 +00:00
|
|
|
sess->n2_released = true;
|
|
|
|
if ((sess->n1_released) && (sess->n2_released)) {
|
2023-08-18 11:14:33 +00:00
|
|
|
int r = smf_sbi_discover_and_send(
|
|
|
|
OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL,
|
|
|
|
smf_nudm_uecm_build_deregistration, sess, NULL,
|
|
|
|
SMF_UECM_STATE_DEREGISTERED_BY_N1_N2_RELEASE, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
2022-09-12 11:07:51 +00:00
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
} else {
|
|
|
|
ogs_fatal("Invalid state [%d]", ngap_state);
|
|
|
|
ogs_assert_if_reached();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown message[%d]", e->ngap.type);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SMF_EVT_5GSM_MESSAGE:
|
|
|
|
nas_message = e->nas.message;
|
|
|
|
ogs_assert(nas_message);
|
2022-08-12 05:03:53 +00:00
|
|
|
stream = e->h.sbi.data;
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_assert(stream);
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
|
|
|
switch (nas_message->gsm.h.message_type) {
|
|
|
|
case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE:
|
|
|
|
ogs_assert(true == ogs_sbi_send_http_status_no_content(stream));
|
2022-09-12 11:07:51 +00:00
|
|
|
|
|
|
|
sess->n1_released = true;
|
|
|
|
if ((sess->n1_released) && (sess->n2_released)) {
|
2023-08-18 11:14:33 +00:00
|
|
|
int r = smf_sbi_discover_and_send(
|
|
|
|
OGS_SBI_SERVICE_TYPE_NUDM_UECM, NULL,
|
|
|
|
smf_nudm_uecm_build_deregistration, sess, NULL,
|
|
|
|
SMF_UECM_STATE_DEREGISTERED_BY_N1_N2_RELEASE, NULL);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
ogs_assert(r != OGS_ERROR);
|
|
|
|
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_5gc_session_will_deregister);
|
2022-09-12 11:07:51 +00:00
|
|
|
}
|
|
|
|
|
2022-05-14 21:27:54 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
strerror = ogs_msprintf("Unknown message [%d]",
|
|
|
|
nas_message->gsm.h.message_type);
|
|
|
|
ogs_assert(strerror);
|
|
|
|
|
|
|
|
ogs_error("%s", strerror);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, NULL, strerror, NULL));
|
|
|
|
ogs_free(strerror);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-10 07:29:17 +00:00
|
|
|
void smf_gsm_state_5gc_n1_n2_reject(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
|
|
|
smf_ue_t *smf_ue = NULL;
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
|
|
|
|
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
|
|
|
switch (e->h.id) {
|
|
|
|
case OGS_FSM_ENTRY_SIG:
|
|
|
|
if (sess->policy_association_id) {
|
|
|
|
smf_npcf_smpolicycontrol_param_t param;
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
memset(¶m, 0, sizeof(param));
|
|
|
|
|
|
|
|
param.ue_location = true;
|
|
|
|
param.ue_timezone = true;
|
|
|
|
|
|
|
|
r = smf_sbi_discover_and_send(
|
|
|
|
OGS_SBI_SERVICE_TYPE_NPCF_SMPOLICYCONTROL, NULL,
|
|
|
|
smf_npcf_smpolicycontrol_build_delete,
|
|
|
|
sess, NULL,
|
|
|
|
OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT, ¶m);
|
|
|
|
ogs_expect(r == OGS_OK);
|
|
|
|
} else {
|
|
|
|
smf_namf_comm_send_n1_n2_pdu_establishment_reject(sess);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_EVENT_SBI_CLIENT:
|
|
|
|
sbi_message = e->h.sbi.message;
|
|
|
|
ogs_assert(sbi_message);
|
|
|
|
|
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL)
|
|
|
|
SWITCH(sbi_message->h.resource.component[0])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_SM_POLICIES)
|
|
|
|
if (!sbi_message->h.resource.component[1]) {
|
|
|
|
ogs_error("[%s:%d] HTTP response error [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->res_status);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
SWITCH(sbi_message->h.resource.component[2])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_DELETE)
|
|
|
|
if (sess->policy_association_id)
|
|
|
|
ogs_free(sess->policy_association_id);
|
|
|
|
sess->policy_association_id = NULL;
|
|
|
|
|
|
|
|
if (sbi_message->res_status !=
|
|
|
|
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
|
|
|
ogs_error("[%s:%d] HTTP response error [%d]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->res_status);
|
|
|
|
/* In spite of error from PCF, continue with
|
|
|
|
session teardown, so as to not leave stale
|
|
|
|
sessions. */
|
|
|
|
}
|
|
|
|
|
|
|
|
smf_namf_comm_send_n1_n2_pdu_establishment_reject(sess);
|
|
|
|
break;
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Unknown resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[2]);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[0]);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
|
|
|
|
SWITCH(sbi_message->h.resource.component[0])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS)
|
2023-08-18 11:14:33 +00:00
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_epc_session_will_release);
|
2023-07-10 07:29:17 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid resource name [%s]",
|
|
|
|
smf_ue->supi, sess->psi,
|
|
|
|
sbi_message->h.resource.component[0]);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("[%s:%d] Invalid API name [%s]",
|
|
|
|
smf_ue->supi, sess->psi, sbi_message->h.service.name);
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown event [%s]", smf_event_get_name(e));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
void smf_gsm_state_5gc_session_will_deregister(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
2024-02-03 00:41:12 +00:00
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
|
|
|
|
ogs_sbi_stream_t *stream = NULL;
|
|
|
|
ogs_sbi_message_t *sbi_message = NULL;
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
2024-02-03 00:41:12 +00:00
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
switch (e->h.id) {
|
|
|
|
case OGS_FSM_ENTRY_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
2024-02-03 00:41:12 +00:00
|
|
|
case OGS_EVENT_SBI_SERVER:
|
|
|
|
sbi_message = e->h.sbi.message;
|
|
|
|
ogs_assert(sbi_message);
|
|
|
|
stream = e->h.sbi.data;
|
|
|
|
ogs_assert(stream);
|
|
|
|
|
|
|
|
SWITCH(sbi_message->h.service.name)
|
|
|
|
CASE(OGS_SBI_SERVICE_NAME_NSMF_PDUSESSION)
|
|
|
|
SWITCH(sbi_message->h.resource.component[2])
|
|
|
|
CASE(OGS_SBI_RESOURCE_NAME_RELEASE)
|
|
|
|
ogs_assert(true == ogs_sbi_send_response(
|
|
|
|
stream, OGS_SBI_HTTP_STATUS_TOO_MANY_REQUESTS));
|
|
|
|
break;
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid resource name [%s]",
|
|
|
|
sbi_message->h.resource.component[2]));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
ogs_error("Invalid API name [%s]", sbi_message->h.service.name);
|
|
|
|
ogs_assert(true ==
|
|
|
|
ogs_sbi_server_send_error(stream,
|
|
|
|
OGS_SBI_HTTP_STATUS_BAD_REQUEST, sbi_message,
|
|
|
|
"Invalid API name", sbi_message->h.service.name));
|
|
|
|
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
|
|
|
END
|
|
|
|
break;
|
|
|
|
|
2023-08-18 11:14:33 +00:00
|
|
|
default:
|
|
|
|
ogs_error("Unknown event %s", smf_event_get_name(e));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void smf_gsm_state_epc_session_will_release(ogs_fsm_t *s, smf_event_t *e)
|
2021-02-04 04:49:16 +00:00
|
|
|
{
|
|
|
|
smf_sess_t *sess = NULL;
|
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2021-02-04 04:49:16 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
2022-04-20 12:42:18 +00:00
|
|
|
SMF_SESS_CLEAR(sess);
|
2021-02-04 04:49:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ogs_error("Unknown event %s", smf_event_get_name(e));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_ue_t *smf_ue = NULL;
|
2020-06-17 05:22:28 +00:00
|
|
|
smf_sess_t *sess = NULL;
|
2022-05-14 21:27:54 +00:00
|
|
|
|
2020-06-17 05:22:28 +00:00
|
|
|
ogs_assert(s);
|
|
|
|
ogs_assert(e);
|
|
|
|
|
|
|
|
smf_sm_debug(e);
|
|
|
|
|
|
|
|
sess = e->sess;
|
|
|
|
ogs_assert(sess);
|
2022-05-14 21:27:54 +00:00
|
|
|
smf_ue = sess->smf_ue;
|
|
|
|
ogs_assert(smf_ue);
|
2020-06-17 05:22:28 +00:00
|
|
|
|
2022-08-12 05:03:53 +00:00
|
|
|
switch (e->h.id) {
|
2020-06-17 05:22:28 +00:00
|
|
|
case OGS_FSM_ENTRY_SIG:
|
2022-05-14 21:27:54 +00:00
|
|
|
ogs_error("[%s:%d] State machine exception", smf_ue->supi, sess->psi);
|
|
|
|
SMF_SESS_CLEAR(sess);
|
2020-06-17 05:22:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OGS_FSM_EXIT_SIG:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2020-07-20 01:42:58 +00:00
|
|
|
ogs_error("Unknown event %s", smf_event_get_name(e));
|
2020-06-17 05:22:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-04-14 01:30:58 +00:00
|
|
|
|
|
|
|
void smf_gsm_state_final(ogs_fsm_t *s, smf_event_t *e)
|
|
|
|
{
|
|
|
|
}
|