forked from acouzens/open5gs
[SMF] On sess. est. fail, don't reply to AMF twice on the same stream
This commit is contained in:
parent
bae6444262
commit
9cef0f14e3
212
src/smf/gsm-sm.c
212
src/smf/gsm-sm.c
|
@ -545,74 +545,54 @@ void smf_gsm_state_wait_5gc_sm_policy_association(ogs_fsm_t *s, smf_event_t *e)
|
|||
break;
|
||||
|
||||
CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL)
|
||||
stream = e->h.sbi.data;
|
||||
/*
|
||||
* 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 ...
|
||||
*/
|
||||
state = e->h.sbi.state;
|
||||
|
||||
SWITCH(sbi_message->h.resource.component[0])
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SM_POLICIES)
|
||||
if (sbi_message->h.resource.component[1]) {
|
||||
strerror = ogs_msprintf("[%s:%d] "
|
||||
"Unknown resource name [%s]",
|
||||
ogs_error("[%s:%d] Unknown resource name [%s]",
|
||||
smf_ue->supi, sess->psi,
|
||||
sbi_message->h.resource.component[1]);
|
||||
ogs_assert(strerror);
|
||||
|
||||
ogs_error("%s", strerror);
|
||||
if (stream)
|
||||
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);
|
||||
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);
|
||||
} else {
|
||||
ogs_assert(stream);
|
||||
if (sbi_message->res_status !=
|
||||
OGS_SBI_HTTP_STATUS_CREATED) {
|
||||
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_npcf_smpolicycontrol_handle_create(
|
||||
sess, stream, state, sbi_message) == true) {
|
||||
OGS_FSM_TRAN(s,
|
||||
&smf_gsm_state_wait_pfcp_establishment);
|
||||
} else {
|
||||
ogs_error(
|
||||
"smf_npcf_smpolicycontrol_handle_create() failed");
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_exception);
|
||||
}
|
||||
ogs_error(
|
||||
"smf_npcf_smpolicycontrol_handle_create() failed");
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
||||
}
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
strerror = ogs_msprintf("[%s:%d] Invalid resource name [%s]",
|
||||
ogs_error("[%s:%d] Invalid resource name [%s]",
|
||||
smf_ue->supi, sess->psi,
|
||||
sbi_message->h.resource.component[0]);
|
||||
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);
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
||||
END
|
||||
break;
|
||||
|
||||
|
@ -714,8 +694,10 @@ void smf_gsm_state_wait_pfcp_establishment(ogs_fsm_t *s, smf_event_t *e)
|
|||
pfcp_cause = smf_5gc_n4_handle_session_establishment_response(
|
||||
sess, pfcp_xact,
|
||||
&pfcp_message->pfcp_session_establishment_response);
|
||||
if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED)
|
||||
if (pfcp_cause != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_5gc_n1_n2_reject);
|
||||
return;
|
||||
}
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.state = SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT;
|
||||
param.n1smbuf =
|
||||
|
@ -1648,6 +1630,126 @@ void smf_gsm_state_wait_5gc_n1_n2_release(ogs_fsm_t *s, smf_event_t *e)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
sess = e->sess;
|
||||
ogs_assert(sess);
|
||||
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)
|
||||
OGS_FSM_TRAN(s, smf_gsm_state_session_will_release);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e)
|
||||
{
|
||||
smf_sess_t *sess = NULL;
|
||||
|
|
|
@ -269,16 +269,13 @@ static void update_authorized_pcc_rule_and_qos(
|
|||
}
|
||||
|
||||
bool smf_npcf_smpolicycontrol_handle_create(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, int state,
|
||||
ogs_sbi_message_t *recvmsg)
|
||||
smf_sess_t *sess, int state, ogs_sbi_message_t *recvmsg)
|
||||
{
|
||||
int rv;
|
||||
char buf1[OGS_ADDRSTRLEN];
|
||||
char buf2[OGS_ADDRSTRLEN];
|
||||
|
||||
char *strerror = NULL;
|
||||
smf_ue_t *smf_ue = NULL;
|
||||
|
||||
smf_bearer_t *qos_flow = NULL;
|
||||
ogs_pfcp_pdr_t *dl_pdr = NULL;
|
||||
ogs_pfcp_pdr_t *ul_pdr = NULL;
|
||||
|
@ -297,23 +294,20 @@ bool smf_npcf_smpolicycontrol_handle_create(
|
|||
ogs_sbi_header_t header;
|
||||
|
||||
ogs_assert(sess);
|
||||
ogs_assert(stream);
|
||||
smf_ue = sess->smf_ue;
|
||||
ogs_assert(smf_ue);
|
||||
|
||||
ogs_assert(recvmsg);
|
||||
|
||||
if (!recvmsg->http.location) {
|
||||
strerror = ogs_msprintf("[%s:%d] No http.location",
|
||||
smf_ue->supi, sess->psi);
|
||||
goto cleanup;
|
||||
ogs_error("[%s:%d] No http.location", smf_ue->supi, sess->psi);
|
||||
return false;
|
||||
}
|
||||
|
||||
SmPolicyDecision = recvmsg->SmPolicyDecision;
|
||||
if (!SmPolicyDecision) {
|
||||
strerror = ogs_msprintf("[%s:%d] No SmPolicyDecision",
|
||||
smf_ue->supi, sess->psi);
|
||||
goto cleanup;
|
||||
ogs_error("[%s:%d] No SmPolicyDecision", smf_ue->supi, sess->psi);
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
|
@ -321,17 +315,17 @@ bool smf_npcf_smpolicycontrol_handle_create(
|
|||
|
||||
rv = ogs_sbi_parse_header(&message, &header);
|
||||
if (rv != OGS_OK) {
|
||||
strerror = ogs_msprintf("[%s:%d] Cannot parse http.location [%s]",
|
||||
ogs_error("[%s:%d] Cannot parse http.location [%s]",
|
||||
smf_ue->supi, sess->psi, recvmsg->http.location);
|
||||
goto cleanup;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!message.h.resource.component[1]) {
|
||||
strerror = ogs_msprintf("[%s:%d] No Assocication ID [%s]",
|
||||
ogs_error("[%s:%d] No Assocication ID [%s]",
|
||||
smf_ue->supi, sess->psi, recvmsg->http.location);
|
||||
|
||||
ogs_sbi_header_free(&header);
|
||||
goto cleanup;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sess->policy_association_id)
|
||||
|
@ -445,9 +439,8 @@ bool smf_npcf_smpolicycontrol_handle_create(
|
|||
/* Check if selected UPF is associated with SMF */
|
||||
ogs_assert(sess->pfcp_node);
|
||||
if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated)) {
|
||||
strerror = ogs_msprintf("[%s:%d] No associated UPF",
|
||||
smf_ue->supi, sess->psi);
|
||||
goto cleanup;
|
||||
ogs_error("[%s:%d] No associated UPF", smf_ue->supi, sess->psi);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Remove all previous QoS flow */
|
||||
|
@ -651,17 +644,6 @@ bool smf_npcf_smpolicycontrol_handle_create(
|
|||
smf_5gc_pfcp_send_session_establishment_request(sess, 0));
|
||||
|
||||
return true;
|
||||
|
||||
cleanup:
|
||||
ogs_assert(strerror);
|
||||
|
||||
ogs_error("%s", strerror);
|
||||
ogs_assert(true ==
|
||||
ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
recvmsg, strerror, NULL));
|
||||
ogs_free(strerror);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool smf_npcf_smpolicycontrol_handle_update_notify(
|
||||
|
|
|
@ -27,8 +27,7 @@ extern "C" {
|
|||
#include "context.h"
|
||||
|
||||
bool smf_npcf_smpolicycontrol_handle_create(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, int state,
|
||||
ogs_sbi_message_t *recvmsg);
|
||||
smf_sess_t *sess, int state, ogs_sbi_message_t *recvmsg);
|
||||
bool smf_npcf_smpolicycontrol_handle_update_notify(
|
||||
smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
|
||||
bool smf_npcf_smpolicycontrol_handle_terminate_notify(
|
||||
|
|
|
@ -175,6 +175,20 @@ void smf_namf_comm_send_n1_n2_message_transfer(
|
|||
}
|
||||
}
|
||||
|
||||
void smf_namf_comm_send_n1_n2_pdu_establishment_reject(
|
||||
smf_sess_t *sess)
|
||||
{
|
||||
smf_n1_n2_message_transfer_param_t param;
|
||||
|
||||
memset(¶m, 0, sizeof(param));
|
||||
param.state = SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE;
|
||||
param.n1smbuf = gsm_build_pdu_session_establishment_reject(sess,
|
||||
OGS_5GSM_CAUSE_NETWORK_FAILURE);
|
||||
ogs_assert(param.n1smbuf);
|
||||
|
||||
smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m);
|
||||
}
|
||||
|
||||
void smf_sbi_send_sm_context_create_error(
|
||||
ogs_sbi_stream_t *stream,
|
||||
int status, const char *title, const char *detail,
|
||||
|
|
|
@ -43,6 +43,8 @@ int smf_sbi_discover_and_send(
|
|||
|
||||
void smf_namf_comm_send_n1_n2_message_transfer(
|
||||
smf_sess_t *sess, smf_n1_n2_message_transfer_param_t *param);
|
||||
void smf_namf_comm_send_n1_n2_pdu_establishment_reject(
|
||||
smf_sess_t *sess);
|
||||
|
||||
void smf_sbi_send_sm_context_create_error(
|
||||
ogs_sbi_stream_t *stream,
|
||||
|
|
|
@ -40,6 +40,7 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e);
|
|||
void smf_gsm_state_wait_pfcp_deletion(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_wait_epc_auth_release(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_wait_5gc_n1_n2_release(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_5gc_n1_n2_reject(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_session_will_release(ogs_fsm_t *s, smf_event_t *e);
|
||||
void smf_gsm_state_exception(ogs_fsm_t *s, smf_event_t *e);
|
||||
|
||||
|
|
Loading…
Reference in New Issue