From b116f077a5305cce3b067f5b1f96527a0d7517e6 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 25 Jul 2023 22:38:38 +0900 Subject: [PATCH] UPF HA - release/establish new PDU session in CM_IDLE (#2471) See also #2396, #2418 --- lib/sbi/types.c | 79 +++++++++++++++++++++++- lib/sbi/types.h | 110 +++++++++++++++++++++++++++++++++ src/amf/namf-handler.c | 49 ++++++++++++--- src/amf/ngap-handler.c | 16 +++++ src/amf/nsmf-handler.c | 54 +++++++++++++++-- src/smf/gsm-handler.c | 15 ++--- src/smf/gsm-sm.c | 36 ++++++++++- src/smf/n4-handler.c | 12 ++-- src/smf/namf-handler.c | 33 +++++++++- src/smf/ngap-handler.c | 134 ++++++++++++++++++++--------------------- src/smf/nsmf-handler.c | 105 +++++++++++++++++--------------- src/smf/nudm-handler.c | 6 +- src/smf/pfcp-path.c | 5 +- src/smf/sbi-path.c | 17 +++++- src/smf/sbi-path.h | 28 ++++++++- src/smf/smf-sm.c | 13 ++-- 16 files changed, 546 insertions(+), 166 deletions(-) diff --git a/lib/sbi/types.c b/lib/sbi/types.c index e09eae56c..0095313aa 100644 --- a/lib/sbi/types.c +++ b/lib/sbi/types.c @@ -85,8 +85,6 @@ static struct service_desc_s service_desc[] = { { OpenAPI_nf_type_NSSAAF, OGS_SBI_SERVICE_NAME_NNSSAAF_NSSAA }, }; - - OpenAPI_nf_type_e ogs_sbi_service_type_to_nf_type(ogs_sbi_service_type_e type) { ogs_assert(type > OGS_SBI_SERVICE_TYPE_NULL && @@ -116,3 +114,80 @@ ogs_sbi_service_type_e ogs_sbi_service_type_from_name(const char *name) return OGS_SBI_SERVICE_TYPE_NULL; } + +struct app_error_desc_s { + const char *app_strerror; +}; + +static struct app_error_desc_s app_error_desc[] = { + { NULL }, + { OGS_SBI_APP_STRERROR_N1_SM_ERROR }, + { OGS_SBI_APP_STRERROR_N2_SM_ERROR }, + { OGS_SBI_APP_STRERROR_SNSSAI_DENIED }, + { OGS_SBI_APP_STRERROR_DNN_DENIED }, + { OGS_SBI_APP_STRERROR_PDUTYPE_DENIED }, + { OGS_SBI_APP_STRERROR_SSC_DENIED }, + { OGS_SBI_APP_STRERROR_SUBSCRIPTION_DENIED }, + { OGS_SBI_APP_STRERROR_DNN_NOT_SUPPORTED }, + { OGS_SBI_APP_STRERROR_PDUTYPE_NOT_SUPPORTED }, + { OGS_SBI_APP_STRERROR_SSC_NOT_SUPPORTED }, + { OGS_SBI_APP_STRERROR_HOME_ROUTED_ROAMING_REQUIRED }, + { OGS_SBI_APP_STRERROR_OUT_OF_LADN_SERVICE_AREA }, + { OGS_SBI_APP_STRERROR_PRIORITIZED_SERVICES_ONLY }, + { OGS_SBI_APP_STRERROR_PDU_SESSION_ANCHOR_CHANGE }, + { OGS_SBI_APP_STRERROR_TARGET_MME_CAPABILITY }, + { OGS_SBI_APP_STRERROR_NO_EPS_5GS_CONTINUITY }, + { OGS_SBI_APP_STRERROR_UNABLE_TO_PAGE_UE }, + { OGS_SBI_APP_STRERROR_UE_NOT_RESPONDING }, + { OGS_SBI_APP_STRERROR_REJECTED_BY_UE }, + { OGS_SBI_APP_STRERROR_REJECTED_DUE_VPLMN_POLICY }, + { OGS_SBI_APP_STRERROR_HO_TAU_IN_PROGRESS }, + { OGS_SBI_APP_STRERROR_INTEGRITY_PROTECTED_MDR_NOT_ACCEPTABLE }, + { OGS_SBI_APP_STRERROR_EBI_EXHAUSTED }, + { OGS_SBI_APP_STRERROR_EBI_REJECTED_LOCAL_POLICY }, + { OGS_SBI_APP_STRERROR_EBI_REJECTED_NO_N26 }, + { OGS_SBI_APP_STRERROR_DEFAULT_EPS_BEARER_INACTIVE }, + { OGS_SBI_APP_STRERROR_HANDOVER_RESOURCE_ALLOCATION_FAILURE }, + { OGS_SBI_APP_STRERROR_LATE_OVERLAPPING_REQUEST }, + { OGS_SBI_APP_STRERROR_DEFAULT_EBI_NOT_TRANSFERRED }, + { OGS_SBI_APP_STRERROR_NOT_SUPPORTED_WITH_ISMF }, + { OGS_SBI_APP_STRERROR_SERVICE_NOT_AUTHORIZED_BY_NEXT_HOP }, + { OGS_SBI_APP_STRERROR_NO_DATA_FORWARDING }, + { OGS_SBI_APP_STRERROR_S_NSSAI_UNAVAILABLE_DUE_TO_NSAC }, + { OGS_SBI_APP_STRERROR_EXCEEDED_UE_SLICE_DATA_RATE }, + { OGS_SBI_APP_STRERROR_EXCEEDED_SLICE_DATA_RATE }, + { OGS_SBI_APP_STRERROR_CONTEXT_NOT_FOUND }, + { OGS_SBI_APP_STRERROR_HIGHER_PRIORITY_REQUEST_ONGOING }, + { OGS_SBI_APP_STRERROR_UE_IN_CM_IDLE_STATE }, + { OGS_SBI_APP_STRERROR_INSUFFICIENT_RESOURCES_SLICE }, + { OGS_SBI_APP_STRERROR_INSUFFICIENT_RESOURCES_SLICE_DNN }, + { OGS_SBI_APP_STRERROR_DNN_CONGESTION }, + { OGS_SBI_APP_STRERROR_S_NSSAI_CONGESTION }, + { OGS_SBI_APP_STRERROR_PEER_NOT_RESPONDING }, + { OGS_SBI_APP_STRERROR_NETWORK_FAILURE }, + { OGS_SBI_APP_STRERROR_UPF_NOT_RESPONDING }, + { OGS_SBI_APP_STRERROR_UE_NOT_REACHABLE }, +}; + +const char *ogs_sbi_app_strerror(ogs_sbi_app_errno_e err) +{ + ogs_assert(err > OGS_SBI_APP_ERRNO_NULL && + err < OGS_SBI_MAX_NUM_OF_APP_ERRNO); + ogs_assert(app_error_desc[err].app_strerror); + return app_error_desc[err].app_strerror; +} + +ogs_sbi_app_errno_e ogs_sbi_app_errno(const char *str) +{ + int i; + + ogs_assert(str); + + for (i = 0; i < OGS_SBI_MAX_NUM_OF_APP_ERRNO; i++) { + if (app_error_desc[i].app_strerror && + strcmp(str, app_error_desc[i].app_strerror) == 0) + return (ogs_sbi_app_errno_e)i; + } + + return OGS_SBI_APP_ERRNO_NULL; +} diff --git a/lib/sbi/types.h b/lib/sbi/types.h index fcd95597c..e7c40f069 100644 --- a/lib/sbi/types.h +++ b/lib/sbi/types.h @@ -161,6 +161,116 @@ OpenAPI_nf_type_e ogs_sbi_service_type_to_nf_type( const char *ogs_sbi_service_type_to_name(ogs_sbi_service_type_e service_type); ogs_sbi_service_type_e ogs_sbi_service_type_from_name(const char *service_name); +typedef enum { + OGS_SBI_APP_ERRNO_NULL = 0, + + /* + * Nsmf_PDUService + * + * TS29.502 + * 6.1.7 Error Handling + * 6.1.7.3 Application Errors + */ + OGS_SBI_APP_ERRNO_N1_SM_ERRNO, + OGS_SBI_APP_ERRNO_N2_SM_ERRNO, + OGS_SBI_APP_ERRNO_SNSSAI_DENIED, + OGS_SBI_APP_ERRNO_DNN_DENIED, + OGS_SBI_APP_ERRNO_PDUTYPE_DENIED, + OGS_SBI_APP_ERRNO_SSC_DENIED, + OGS_SBI_APP_ERRNO_SUBSCRIPTION_DENIED, + OGS_SBI_APP_ERRNO_DNN_NOT_SUPPORTED, + OGS_SBI_APP_ERRNO_PDUTYPE_NOT_SUPPORTED, + OGS_SBI_APP_ERRNO_SSC_NOT_SUPPORTED, + OGS_SBI_APP_ERRNO_HOME_ROUTED_ROAMING_REQUIRED, + OGS_SBI_APP_ERRNO_OUT_OF_LADN_SERVICE_AREA, + OGS_SBI_APP_ERRNO_PRIORITIZED_SERVICES_ONLY, + OGS_SBI_APP_ERRNO_PDU_SESSION_ANCHOR_CHANGE, + OGS_SBI_APP_ERRNO_TARGET_MME_CAPABILITY, + OGS_SBI_APP_ERRNO_NO_EPS_5GS_CONTINUITY, + OGS_SBI_APP_ERRNO_UNABLE_TO_PAGE_UE, + OGS_SBI_APP_ERRNO_UE_NOT_RESPONDING, + OGS_SBI_APP_ERRNO_REJECTED_BY_UE, + OGS_SBI_APP_ERRNO_REJECTED_DUE_VPLMN_POLICY, + OGS_SBI_APP_ERRNO_HO_TAU_IN_PROGRESS, + OGS_SBI_APP_ERRNO_INTEGRITY_PROTECTED_MDR_NOT_ACCEPTABLE, + OGS_SBI_APP_ERRNO_EBI_EXHAUSTED, + OGS_SBI_APP_ERRNO_EBI_REJECTED_LOCAL_POLICY, + OGS_SBI_APP_ERRNO_EBI_REJECTED_NO_N26, + OGS_SBI_APP_ERRNO_DEFAULT_EPS_BEARER_INACTIVE, + OGS_SBI_APP_ERRNO_HANDOVER_RESOURCE_ALLOCATION_FAILURE, + OGS_SBI_APP_ERRNO_LATE_OVERLAPPING_REQUEST, + OGS_SBI_APP_ERRNO_DEFAULT_EBI_NOT_TRANSFERRED, + OGS_SBI_APP_ERRNO_NOT_SUPPORTED_WITH_ISMF, + OGS_SBI_APP_ERRNO_SERVICE_NOT_AUTHORIZED_BY_NEXT_HOP, + OGS_SBI_APP_ERRNO_NO_DATA_FORWARDING, + OGS_SBI_APP_ERRNO_S_NSSAI_UNAVAILABLE_DUE_TO_NSAC, + OGS_SBI_APP_ERRNO_EXCEEDED_UE_SLICE_DATA_RATE, + OGS_SBI_APP_ERRNO_EXCEEDED_SLICE_DATA_RATE, + OGS_SBI_APP_ERRNO_CONTEXT_NOT_FOUND, + OGS_SBI_APP_ERRNO_HIGHER_PRIORITY_REQUEST_ONGOING, + OGS_SBI_APP_ERRNO_UE_IN_CM_IDLE_STATE, + OGS_SBI_APP_ERRNO_INSUFFICIENT_RESOURCES_SLICE, + OGS_SBI_APP_ERRNO_INSUFFICIENT_RESOURCES_SLICE_DNN, + OGS_SBI_APP_ERRNO_DNN_CONGESTION, + OGS_SBI_APP_ERRNO_S_NSSAI_CONGESTION, + OGS_SBI_APP_ERRNO_PEER_NOT_RESPONDING, + OGS_SBI_APP_ERRNO_NETWORK_FAILURE, + OGS_SBI_APP_ERRNO_UPF_NOT_RESPONDING, + OGS_SBI_APP_ERRNO_UE_NOT_REACHABLE, + + OGS_SBI_MAX_NUM_OF_APP_ERRNO, +} ogs_sbi_app_errno_e; + +#define OGS_SBI_APP_STRERROR_N1_SM_ERROR "N1_SM_ERROR" +#define OGS_SBI_APP_STRERROR_N2_SM_ERROR "N2_SM_ERROR" +#define OGS_SBI_APP_STRERROR_SNSSAI_DENIED "SNSSAI_DENIED" +#define OGS_SBI_APP_STRERROR_DNN_DENIED "DNN_DENIED" +#define OGS_SBI_APP_STRERROR_PDUTYPE_DENIED "PDUTYPE_DENIED" +#define OGS_SBI_APP_STRERROR_SSC_DENIED "SSC_DENIED" +#define OGS_SBI_APP_STRERROR_SUBSCRIPTION_DENIED "SUBSCRIPTION_DENIED" +#define OGS_SBI_APP_STRERROR_DNN_NOT_SUPPORTED "DNN_NOT_SUPPORTED" +#define OGS_SBI_APP_STRERROR_PDUTYPE_NOT_SUPPORTED "PDUTYPE_NOT_SUPPORTED" +#define OGS_SBI_APP_STRERROR_SSC_NOT_SUPPORTED "SSC_NOT_SUPPORTED" +#define OGS_SBI_APP_STRERROR_HOME_ROUTED_ROAMING_REQUIRED "HOME_ROUTED_ROAMING_REQUIRED" +#define OGS_SBI_APP_STRERROR_OUT_OF_LADN_SERVICE_AREA "OUT_OF_LADN_SERVICE_AREA" +#define OGS_SBI_APP_STRERROR_PRIORITIZED_SERVICES_ONLY "PRIORITIZED_SERVICES_ONLY" +#define OGS_SBI_APP_STRERROR_PDU_SESSION_ANCHOR_CHANGE "PDU_SESSION_ANCHOR_CHANGE" +#define OGS_SBI_APP_STRERROR_TARGET_MME_CAPABILITY "TARGET_MME_CAPABILITY" +#define OGS_SBI_APP_STRERROR_NO_EPS_5GS_CONTINUITY "NO_EPS_5GS_CONTINUITY" +#define OGS_SBI_APP_STRERROR_UNABLE_TO_PAGE_UE "UNABLE_TO_PAGE_UE" +#define OGS_SBI_APP_STRERROR_UE_NOT_RESPONDING "UE_NOT_RESPONDING" +#define OGS_SBI_APP_STRERROR_REJECTED_BY_UE "REJECTED_BY_UE" +#define OGS_SBI_APP_STRERROR_REJECTED_DUE_VPLMN_POLICY "REJECTED_DUE_VPLMN_POLICY" +#define OGS_SBI_APP_STRERROR_HO_TAU_IN_PROGRESS "HO_TAU_IN_PROGRESS" +#define OGS_SBI_APP_STRERROR_INTEGRITY_PROTECTED_MDR_NOT_ACCEPTABLE "INTEGRITY_PROTECTED_MDR_NOT_ACCEPTABLE" +#define OGS_SBI_APP_STRERROR_EBI_EXHAUSTED "EBI_EXHAUSTED" +#define OGS_SBI_APP_STRERROR_EBI_REJECTED_LOCAL_POLICY "EBI_REJECTED_LOCAL_POLICY" +#define OGS_SBI_APP_STRERROR_EBI_REJECTED_NO_N26 "EBI_REJECTED_NO_N26" +#define OGS_SBI_APP_STRERROR_DEFAULT_EPS_BEARER_INACTIVE "DEFAULT_EPS_BEARER_INACTIVE" +#define OGS_SBI_APP_STRERROR_HANDOVER_RESOURCE_ALLOCATION_FAILURE "HANDOVER_RESOURCE_ALLOCATION_FAILURE" +#define OGS_SBI_APP_STRERROR_LATE_OVERLAPPING_REQUEST "LATE_OVERLAPPING_REQUEST" +#define OGS_SBI_APP_STRERROR_DEFAULT_EBI_NOT_TRANSFERRED "DEFAULT_EBI_NOT_TRANSFERRED" +#define OGS_SBI_APP_STRERROR_NOT_SUPPORTED_WITH_ISMF "NOT_SUPPORTED_WITH_ISMF" +#define OGS_SBI_APP_STRERROR_SERVICE_NOT_AUTHORIZED_BY_NEXT_HOP "SERVICE_NOT_AUTHORIZED_BY_NEXT_HOP" +#define OGS_SBI_APP_STRERROR_NO_DATA_FORWARDING "NO_DATA_FORWARDING" +#define OGS_SBI_APP_STRERROR_S_NSSAI_UNAVAILABLE_DUE_TO_NSAC "S_NSSAI_UNAVAILABLE_DUE_TO_NSAC" +#define OGS_SBI_APP_STRERROR_EXCEEDED_UE_SLICE_DATA_RATE "EXCEEDED_UE_SLICE_DATA_RATE" +#define OGS_SBI_APP_STRERROR_EXCEEDED_SLICE_DATA_RATE "EXCEEDED_SLICE_DATA_RATE" +#define OGS_SBI_APP_STRERROR_CONTEXT_NOT_FOUND "CONTEXT_NOT_FOUND" +#define OGS_SBI_APP_STRERROR_HIGHER_PRIORITY_REQUEST_ONGOING "HIGHER_PRIORITY_REQUEST_ONGOING" +#define OGS_SBI_APP_STRERROR_UE_IN_CM_IDLE_STATE "UE_IN_CM_IDLE_STATE" +#define OGS_SBI_APP_STRERROR_INSUFFICIENT_RESOURCES_SLICE "INSUFFICIENT_RESOURCES_SLICE" +#define OGS_SBI_APP_STRERROR_INSUFFICIENT_RESOURCES_SLICE_DNN "INSUFFICIENT_RESOURCES_SLICE_DNN" +#define OGS_SBI_APP_STRERROR_DNN_CONGESTION "DNN_CONGESTION" +#define OGS_SBI_APP_STRERROR_S_NSSAI_CONGESTION "S_NSSAI_CONGESTION" +#define OGS_SBI_APP_STRERROR_PEER_NOT_RESPONDING "PEER_NOT_RESPONDING" +#define OGS_SBI_APP_STRERROR_NETWORK_FAILURE "NETWORK_FAILURE" +#define OGS_SBI_APP_STRERROR_UPF_NOT_RESPONDING "UPF_NOT_RESPONDING" +#define OGS_SBI_APP_STRERROR_UE_NOT_REACHABLE "UE_NOT_REACHABLE" + +const char *ogs_sbi_app_strerror(ogs_sbi_app_errno_e e); +ogs_sbi_app_errno_e ogs_sbi_app_errno(const char *str); + #ifdef __cplusplus } #endif diff --git a/src/amf/namf-handler.c b/src/amf/namf-handler.c index 764fa7201..7eb3bda75 100644 --- a/src/amf/namf-handler.c +++ b/src/amf/namf-handler.c @@ -368,18 +368,53 @@ int amf_namf_comm_handle_n1_n2_message_transfer( } if (CM_IDLE(amf_ue)) { - if (n1buf) - ogs_pkbuf_free(n1buf); - if (n2buf) - ogs_pkbuf_free(n2buf); - if (N1N2MessageTransferReqData->is_skip_ind == true && N1N2MessageTransferReqData->skip_ind == true) { + + if (n1buf) + ogs_pkbuf_free(n1buf); + if (n2buf) + ogs_pkbuf_free(n2buf); + N1N2MessageTransferRspData.cause = OpenAPI_n1_n2_message_transfer_cause_N1_MSG_NOT_TRANSFERRED; + } else { - ogs_fatal("[%s] No skipInd", amf_ue->supi); - ogs_assert_if_reached(); + ogs_sbi_server_t *server = NULL; + ogs_sbi_header_t header; + + status = OGS_SBI_HTTP_STATUS_ACCEPTED; + N1N2MessageTransferRspData.cause = + OpenAPI_n1_n2_message_transfer_cause_ATTEMPTING_TO_REACH_UE; + + /* Location */ + server = ogs_sbi_server_from_stream(stream); + ogs_assert(server); + + memset(&header, 0, sizeof(header)); + header.service.name = (char *)OGS_SBI_SERVICE_NAME_NAMF_COMM; + header.api.version = (char *)OGS_SBI_API_V1; + header.resource.component[0] = + (char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS; + header.resource.component[1] = amf_ue->supi; + header.resource.component[2] = + (char *)OGS_SBI_RESOURCE_NAME_N1_N2_MESSAGES; + header.resource.component[3] = sess->sm_context_ref; + + sendmsg.http.location = ogs_sbi_server_uri(server, &header); + + /* Store Paging Info */ + AMF_SESS_STORE_PAGING_INFO( + sess, sendmsg.http.location, NULL); + + /* Store 5GSM Message */ + AMF_SESS_STORE_5GSM_MESSAGE(sess, + OGS_NAS_5GS_PDU_SESSION_RELEASE_COMMAND, + n1buf, n2buf); + + r = ngap_send_paging(amf_ue); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); } } else if (CM_CONNECTED(amf_ue)) { diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index 82ee5e54e..d809566e1 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -1018,6 +1018,22 @@ void ngap_handle_initial_context_setup_response( AMF_SESS_CLEAR_5GSM_MESSAGE(sess); + break; + case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMMAND: + r = nas_send_pdu_session_release_command(sess, + sess->gsm_message.n1buf, sess->gsm_message.n2buf); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + + /* n1buf is de-allocated + * in gmm_build_dl_nas_transport() */ + sess->gsm_message.n1buf = NULL; + /* n2buf is de-allocated + * in ngap_build_pdu_session_resource_modify_request() */ + sess->gsm_message.n2buf = NULL; + + AMF_SESS_CLEAR_5GSM_MESSAGE(sess); + break; default: ogs_fatal("Unknown GSM Message Type[%d]", diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index f1b5e520c..21e1f9d85 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -849,6 +849,7 @@ int amf_nsmf_pdusession_handle_update_sm_context( } } else { OpenAPI_sm_context_update_error_t *SmContextUpdateError = NULL; + OpenAPI_ext_problem_details_t *ProblemDetails = NULL; OpenAPI_ref_to_binary_data_t *n1SmMsg = NULL; ogs_pkbuf_t *n1smbuf = NULL; @@ -871,8 +872,10 @@ int amf_nsmf_pdusession_handle_update_sm_context( return OGS_ERROR; } - if (!SmContextUpdateError->error) { - ogs_error("[%d:%d] No Error [%d]", + + ProblemDetails = SmContextUpdateError->error; + if (!ProblemDetails) { + ogs_error("[%d:%d] No ProblemDetails [%d]", sess->psi, sess->pti, recvmsg->res_status); r = ngap_send_error_indication2(amf_ue, NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error); @@ -882,6 +885,46 @@ int amf_nsmf_pdusession_handle_update_sm_context( return OGS_ERROR; } + if (state == AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST) { + /* + * In a situation where the UPF is changed through High Availability + * it is implemented to send the Service-Accept to the UE + * even if reactivation for user-resource fails. + * + * This is because it cannot be predicted whether a UE will + * retransmit or leave it as it is, depending on the manufacturer, + * in case of including reactivation error IE + * such as Insufficient Resource. + * + * TS24.501 + * 5.6 5GMM connection management procedures + * 5.6.1 Service request procedure + * 5.6.1.4 Service request procedure accepted by the network + * 5.6.1.4.1 UE is not using 5GS services + * with control plane CIoT 5GS optimization + * + * NOTE 1: It is up to UE implementation when to re-send a request + * for user-plane re-establishment for the associated PDU session + * after receiving a PDU session reactivation result error cause IE + * with a 5GMM cause set to #92 "insufficient user-plane resources + * for the PDU session". + */ + ogs_error("Service-Request: ACTIVATING FAILED [%d:%s:%s]", + recvmsg->res_status, + OpenAPI_up_cnx_state_ToString( + SmContextUpdateError->up_cnx_state), + ProblemDetails->cause ? ProblemDetails->cause : "Unknown"); + + if (AMF_SESSION_SYNC_DONE(amf_ue, + AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST)) { + r = nas_5gs_send_service_accept(amf_ue); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + } + + return OGS_OK; + } + n1SmMsg = SmContextUpdateError->n1_sm_msg; if (n1SmMsg && n1SmMsg->content_id) { n1smbuf = ogs_sbi_find_part_by_content_id( @@ -891,8 +934,8 @@ int amf_nsmf_pdusession_handle_update_sm_context( * NOTE : The pkbuf created in the SBI message will be removed * from ogs_sbi_message_free(), so it must be copied. */ - ogs_error("[%d:%d] PDU session establishment reject", - sess->psi, sess->pti); + ogs_error("[%d:%d] PDU session establishment reject [state:%d]", + sess->psi, sess->pti, state); n1smbuf = ogs_pkbuf_copy(n1smbuf); ogs_assert(n1smbuf); @@ -931,7 +974,8 @@ int amf_nsmf_pdusession_handle_update_sm_context( } #endif - ogs_error("[%d:%d] Error Indication", sess->psi, sess->pti); + ogs_error("[%d:%d] Error Indication [state:%d]", + sess->psi, sess->pti, state); r = ngap_send_error_indication2(amf_ue, NGAP_Cause_PR_protocol, NGAP_CauseProtocol_semantic_error); diff --git a/src/smf/gsm-handler.c b/src/smf/gsm-handler.c index 4bdca9b1b..058de3260 100644 --- a/src/smf/gsm-handler.c +++ b/src/smf/gsm-handler.c @@ -192,8 +192,6 @@ int gsm_handle_pdu_session_modification_request( ogs_nas_5gs_pdu_session_modification_request_t * pdu_session_modification_request) { - char *strerror = NULL; - int i, j; uint64_t pfcp_flags = 0; @@ -477,20 +475,17 @@ int gsm_handle_pdu_session_modification_request( } if (ogs_list_count(&sess->qos_flow_to_modify_list) != 1) { - strerror = ogs_msprintf("[%s:%d] Invalid modification request " - "[modify:%d]", smf_ue->supi, sess->psi, + ogs_error("[%s:%d] Invalid modification request [modify:%d]", + smf_ue->supi, sess->psi, ogs_list_count(&sess->qos_flow_to_modify_list)); - ogs_assert(strerror); - ogs_error("%s", strerror); n1smbuf = gsm_build_pdu_session_modification_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); ogs_assert(n1smbuf); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - strerror, smf_ue->supi, n1smbuf, NULL); - ogs_free(strerror); + 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); return OGS_ERROR; } diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 2063b6371..df1ce18cb 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -970,7 +970,26 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release); ogs_assert(param.n2smbuf); - param.skip_ind = true; + /* + * 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 + */ smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); } else { @@ -1588,6 +1607,21 @@ void smf_gsm_state_wait_5gc_n1_n2_release(ogs_fsm_t *s, smf_event_t *e) ogs_assert(e->ngap.type); switch (e->ngap.type) { + 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; + case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP: ngap_state = sess->ngap_state.pdu_session_resource_release; diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 639a22a0a..467229ed8 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -358,8 +358,8 @@ void smf_5gc_n4_handle_session_modification_response( char *strerror = ogs_msprintf( "PFCP Cause [%d] : Not Accepted", rsp->cause.u8); if (stream) - smf_sbi_send_sm_context_update_error( - stream, status, strerror, NULL, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, status, strerror, NULL); ogs_error("%s", strerror); ogs_free(strerror); return; @@ -369,8 +369,8 @@ void smf_5gc_n4_handle_session_modification_response( if (sess->upf_n3_addr == NULL && sess->upf_n3_addr6 == NULL) { if (stream) - smf_sbi_send_sm_context_update_error( - stream, status, "No UP F_TEID", NULL, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, status, "No UP F_TEID", NULL); return; } @@ -694,8 +694,8 @@ int smf_5gc_n4_handle_session_deletion_response( } else if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || trigger == OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT) { ogs_assert(stream); - smf_sbi_send_sm_context_update_error( - stream, status, strerror, NULL, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, status, strerror, NULL); } else if (trigger == OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) { ogs_assert(stream); ogs_assert(true == diff --git a/src/smf/namf-handler.c b/src/smf/namf-handler.c index 0443ec72a..0656bf884 100644 --- a/src/smf/namf-handler.c +++ b/src/smf/namf-handler.c @@ -106,6 +106,7 @@ bool smf_namf_comm_handle_n1_n2_message_transfer( case SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE: case SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN: + N1N2MessageTransferRspData = recvmsg->N1N2MessageTransferRspData; if (!N1N2MessageTransferRspData) { ogs_error("No N1N2MessageTransferRspData [status:%d]", @@ -113,7 +114,37 @@ bool smf_namf_comm_handle_n1_n2_message_transfer( break; } - if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) { + if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_ACCEPTED) { + /* + * OpenAPI_n1_n2_message_transfer_cause_ATTEMPTING_TO_REACH_UE and + * HTTP_STATUS_ACCEPTED should be handled here when removing PDU session + * due to the change of PDU Session Anchor. + * + * 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 + */ + if (N1N2MessageTransferRspData->cause == + OpenAPI_n1_n2_message_transfer_cause_ATTEMPTING_TO_REACH_UE) { + /* Nothing */ + } else { + ogs_error("Not implemented [cause:%d]", + N1N2MessageTransferRspData->cause); + ogs_assert_if_reached(); + } + } else if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) { if (N1N2MessageTransferRspData->cause == OpenAPI_n1_n2_message_transfer_cause_N1_MSG_NOT_TRANSFERRED) { smf_n1_n2_message_transfer_param_t param; diff --git a/src/smf/ngap-handler.c b/src/smf/ngap-handler.c index 396adf10c..d5d2febb3 100644 --- a/src/smf/ngap-handler.c +++ b/src/smf/ngap-handler.c @@ -57,9 +57,9 @@ int ngap_handle_pdu_session_resource_setup_response_transfer( if (rv != OGS_OK) { ogs_error("[%s:%d] Cannot decode NGAP message", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Info Type", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Info Type", smf_ue->supi); goto cleanup; } @@ -75,19 +75,19 @@ int ngap_handle_pdu_session_resource_setup_response_transfer( "[%s:%d] Unknown NGAP_UPTransportLayerInformation.present [%d]", smf_ue->supi, sess->psi, uPTransportLayerInformation->present); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, "Unknown NGAP_UPTransportLayerInformation.present", - smf_ue->supi, NULL, NULL); + smf_ue->supi); goto cleanup; } gTPTunnel = uPTransportLayerInformation->choice.gTPTunnel; if (!gTPTunnel) { ogs_error("[%s:%d] No GTPTunnel", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No GTPTunnel", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No GTPTunnel", smf_ue->supi); goto cleanup; } @@ -95,9 +95,9 @@ int ngap_handle_pdu_session_resource_setup_response_transfer( &gTPTunnel->transportLayerAddress, &gnb_n3_ip); if (rv != OGS_OK) { ogs_error("[%s:%d] No transportLayerAddress", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No transportLayerAddress", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No transportLayerAddress", smf_ue->supi); goto cleanup; } ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID, &gnb_n3_teid); @@ -137,9 +137,9 @@ int ngap_handle_pdu_session_resource_setup_response_transfer( dl_far->outer_header_creation.teid = sess->gnb_n3_teid; } else { ogs_error("[%s:%d] No QoS flow", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No QoS flow", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No QoS flow", smf_ue->supi); goto cleanup; } } @@ -196,9 +196,9 @@ int ngap_handle_pdu_session_resource_setup_unsuccessful_transfer( if (rv != OGS_OK) { ogs_error("[%s:%d] Cannot decode NGAP message", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Info Type", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Info Type", smf_ue->supi); goto cleanup; } @@ -296,9 +296,9 @@ int ngap_handle_pdu_session_resource_modify_response_transfer( if (rv != OGS_OK) { ogs_error("[%s:%d] Cannot decode NGAP message", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Info Type", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Info Type", smf_ue->supi); goto cleanup; } @@ -348,9 +348,9 @@ int ngap_handle_pdu_session_resource_modify_response_transfer( if (ogs_list_count(&sess->qos_flow_to_modify_list) == 0) { ogs_error("[%s:%d] No QoS flow", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No QoS flow", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No QoS flow", smf_ue->supi); goto cleanup; } @@ -400,9 +400,9 @@ int ngap_handle_path_switch_request_transfer( if (rv != OGS_OK) { ogs_error("[%s:%d] Cannot decode NGAP message", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Info Type", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Info Type", smf_ue->supi); goto cleanup; } @@ -414,19 +414,18 @@ int ngap_handle_path_switch_request_transfer( ogs_error( "[%s:%d] Unknown dL_NGU_UP_TNLInformation->present [%d]", smf_ue->supi, sess->psi, dL_NGU_UP_TNLInformation->present); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "Unknown dL_NGU_UP_TNLInformation->present", - smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "Unknown dL_NGU_UP_TNLInformation->present", smf_ue->supi); goto cleanup; } gTPTunnel = dL_NGU_UP_TNLInformation->choice.gTPTunnel; if (!gTPTunnel) { ogs_error("[%s:%d] No GTPTunnel", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No GTPTunnel", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No GTPTunnel", smf_ue->supi); goto cleanup; } @@ -434,9 +433,9 @@ int ngap_handle_path_switch_request_transfer( &gTPTunnel->transportLayerAddress, &gnb_n3_ip); if (rv != OGS_OK) { ogs_error("[%s:%d] No transportLayerAddress", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No transportLayerAddress", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No transportLayerAddress", smf_ue->supi); goto cleanup; } ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID, &gnb_n3_teid); @@ -474,9 +473,9 @@ int ngap_handle_path_switch_request_transfer( dl_far->outer_header_creation.teid = sess->gnb_n3_teid; } else { ogs_error("[%s:%d] No QoS flow", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No QoS flow", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No QoS flow", smf_ue->supi); goto cleanup; } } @@ -528,9 +527,9 @@ int ngap_handle_handover_required_transfer( if (rv != OGS_OK) { ogs_error("[%s:%d] Cannot decode NGAP message", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Info Type", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Info Type", smf_ue->supi); goto cleanup; } @@ -580,9 +579,9 @@ int ngap_handle_handover_request_ack( if (rv != OGS_OK) { ogs_error("[%s:%d] Cannot decode NGAP message", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Info Type", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Info Type", smf_ue->supi); goto cleanup; } @@ -594,19 +593,18 @@ int ngap_handle_handover_request_ack( ogs_error( "[%s:%d] Unknown dL_NGU_UP_TNLInformation->present [%d]", smf_ue->supi, sess->psi, dL_NGU_UP_TNLInformation->present); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "Unknown dL_NGU_UP_TNLInformation->present", - smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "Unknown dL_NGU_UP_TNLInformation->present", smf_ue->supi); goto cleanup; } gTPTunnel = dL_NGU_UP_TNLInformation->choice.gTPTunnel; if (!gTPTunnel) { ogs_error("[%s:%d] No GTPTunnel", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No GTPTunnel", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No GTPTunnel", smf_ue->supi); goto cleanup; } @@ -614,9 +612,9 @@ int ngap_handle_handover_request_ack( &sess->handover.gnb_n3_ip); if (rv != OGS_OK) { ogs_error("[%s:%d] No transportLayerAddress", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No transportLayerAddress", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No transportLayerAddress", smf_ue->supi); goto cleanup; } ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID, @@ -638,9 +636,9 @@ int ngap_handle_handover_request_ack( } else { ogs_error("[%s:%d] No QoS flow", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No QoS flow", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No QoS flow", smf_ue->supi); goto cleanup; } } @@ -653,19 +651,19 @@ int ngap_handle_handover_request_ack( ogs_error( "[%s:%d] Unknown dLForwardingUP_TNLInformation->present [%d]", smf_ue->supi, sess->psi, dL_NGU_UP_TNLInformation->present); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, "Unknown dLForwardingUP_TNLInformation->present", - smf_ue->supi, NULL, NULL); + smf_ue->supi); goto cleanup; } gTPTunnel = dLForwardingUP_TNLInformation->choice.gTPTunnel; if (!gTPTunnel) { ogs_error("[%s:%d] No GTPTunnel", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No GTPTunnel", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No GTPTunnel", smf_ue->supi); goto cleanup; } @@ -674,9 +672,9 @@ int ngap_handle_handover_request_ack( if (rv != OGS_OK) { ogs_error("[%s:%d] No transportLayerAddress", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No transportLayerAddress", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No transportLayerAddress", smf_ue->supi); goto cleanup; } ogs_asn_OCTET_STRING_to_uint32(&gTPTunnel->gTP_TEID, diff --git a/src/smf/nsmf-handler.c b/src/smf/nsmf-handler.c index 36dc57875..4533458dd 100644 --- a/src/smf/nsmf-handler.c +++ b/src/smf/nsmf-handler.c @@ -55,7 +55,7 @@ bool smf_nsmf_handle_create_sm_context( ogs_error("[%s:%d] No SmContextCreateData", smf_ue->supi, sess->psi); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No SmContextCreateData", smf_ue->supi, NULL); return false; } @@ -64,7 +64,7 @@ bool smf_nsmf_handle_create_sm_context( if (!n1SmMsg || !n1SmMsg->content_id) { ogs_error("[%s:%d] No n1SmMsg", smf_ue->supi, sess->psi); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No n1SmMsg", smf_ue->supi, NULL); return false; } @@ -74,7 +74,7 @@ bool smf_nsmf_handle_create_sm_context( ogs_error("[%s:%d] No N1 SM Content [%s]", smf_ue->supi, sess->psi, n1SmMsg->content_id); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No N1 SM Content", smf_ue->supi, NULL); return false; } @@ -86,7 +86,7 @@ bool smf_nsmf_handle_create_sm_context( if (sess->pti == OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) { ogs_error("[%s:%d] No PTI", smf_ue->supi, sess->psi); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No PTI", smf_ue->supi, NULL); return false; @@ -98,7 +98,7 @@ bool smf_nsmf_handle_create_sm_context( n1smbuf = gsm_build_pdu_session_establishment_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No sNssai", smf_ue->supi, n1smbuf); return false; } @@ -110,7 +110,7 @@ bool smf_nsmf_handle_create_sm_context( n1smbuf = gsm_build_pdu_session_establishment_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No servingNetwork", smf_ue->supi, n1smbuf); return false; } @@ -121,7 +121,7 @@ bool smf_nsmf_handle_create_sm_context( n1smbuf = gsm_build_pdu_session_establishment_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No UeLocation", smf_ue->supi, n1smbuf); return false; } @@ -135,7 +135,7 @@ bool smf_nsmf_handle_create_sm_context( n1smbuf = gsm_build_pdu_session_establishment_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No UeLocation", smf_ue->supi, n1smbuf); return false; } @@ -146,7 +146,7 @@ bool smf_nsmf_handle_create_sm_context( n1smbuf = gsm_build_pdu_session_establishment_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, "No SmContextStatusNotification", smf_ue->supi, n1smbuf); return false; } @@ -160,7 +160,8 @@ bool smf_nsmf_handle_create_sm_context( n1smbuf = gsm_build_pdu_session_establishment_reject(sess, OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, "Invalid URI", + OGS_SBI_HTTP_STATUS_BAD_REQUEST, OGS_SBI_APP_ERRNO_NULL, + "Invalid URI", SmContextCreateData->sm_context_status_uri, n1smbuf); return false; } @@ -314,9 +315,9 @@ bool smf_nsmf_handle_update_sm_context( if (!SmContextUpdateData) { ogs_error("[%s:%d] No SmContextUpdateData", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No SmContextUpdateData", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No SmContextUpdateData", smf_ue->supi); return false; } @@ -346,9 +347,9 @@ bool smf_nsmf_handle_update_sm_context( n1SmMsg = SmContextUpdateData->n1_sm_msg; if (!n1SmMsg || !n1SmMsg->content_id) { ogs_error("[%s:%d] No n1SmMsg", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No n1SmMsg", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No n1SmMsg", smf_ue->supi); return false; } @@ -356,9 +357,9 @@ bool smf_nsmf_handle_update_sm_context( if (!n1smbuf) { ogs_error("[%s:%d] No N1 SM Content [%s]", smf_ue->supi, sess->psi, n1SmMsg->content_id); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N1 SM Content", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N1 SM Content", smf_ue->supi); return false; } @@ -385,9 +386,9 @@ bool smf_nsmf_handle_update_sm_context( if (!SmContextUpdateData->n2_sm_info_type) { ogs_error("[%s:%d] No n2SmInfoType", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No n2SmInfoType", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No n2SmInfoType", smf_ue->supi); return false; } @@ -395,18 +396,18 @@ bool smf_nsmf_handle_update_sm_context( if (!n2SmMsg || !n2SmMsg->content_id) { ogs_error("[%s:%d] No N2SmInfo.content_id", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No n2SmInfo.content_id", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No n2SmInfo.content_id", smf_ue->supi); return false; } n2smbuf = ogs_sbi_find_part_by_content_id(message, n2SmMsg->content_id); if (!n2smbuf) { ogs_error("[%s:%d] No N2 SM Content", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No N2 SM Content", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No N2 SM Content", smf_ue->supi); return false; } @@ -464,9 +465,8 @@ bool smf_nsmf_handle_update_sm_context( OpenAPI_sm_context_updated_data_t SmContextUpdatedData; OpenAPI_ref_to_binary_data_t n2SmInfo; + if (!OGS_FSM_CHECK(&sess->sm, smf_gsm_state_operational)) { /* - * TODO : - * * TS29.502 5.2.2.3.2.2 * Activation of User Plane connectivity of PDU session * @@ -492,14 +492,23 @@ bool smf_nsmf_handle_update_sm_context( * TS23.502 4.2.3 * Service Request Procedures * - * 8a. If the SMF find the PDU Session is activated - * when receiving the Nsmf_PDUSession_UpdateSMContext Request - * in step 4 with Operation Type set to "UP activate" - * to indicate establishment of User Plane resources - * for the PDU Session(s), it deletes the AN Tunnel Info - * and initiates an N4 Session Modification procedure - * to remove Tunnel Info of AN in the UPF. + * 11. ... + * If the SMF decided to change the PSA UPF for the requested + * PDU Session as described in step 5b. In this case, after sending + * Nsmf_PDUSession_UpdateSMContext Response, the SMF triggers + * another procedure to instruct UE to re-establish the PDU Session + * as described in clause 4.3.5.1 for SSC mode 2. */ + ogs_error("[%s:%d] Service-Request: ACTIVATING FAILED", + smf_ue->supi, sess->psi); + + smf_sbi_send_sm_context_update_app_error( + stream, OGS_SBI_HTTP_STATUS_FORBIDDEN, + OGS_SBI_APP_ERRNO_PDU_SESSION_ANCHOR_CHANGE, + OpenAPI_up_cnx_state_DEACTIVATED); + + return false; + } memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.SmContextUpdatedData = &SmContextUpdatedData; @@ -539,8 +548,8 @@ bool smf_nsmf_handle_update_sm_context( ogs_assert(strerror); ogs_error("%s", strerror); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL); ogs_free(strerror); return false; @@ -597,9 +606,9 @@ bool smf_nsmf_handle_update_sm_context( ogs_assert(strerror); ogs_error("%s", strerror); - smf_sbi_send_sm_context_update_error( + smf_sbi_send_sm_context_update_error_log( stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, - strerror, NULL, NULL, NULL); + strerror, NULL); ogs_free(strerror); return false; @@ -635,8 +644,8 @@ bool smf_nsmf_handle_update_sm_context( ogs_assert(strerror); ogs_error("%s", strerror); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, strerror, NULL); ogs_free(strerror); return false; @@ -674,9 +683,9 @@ bool smf_nsmf_handle_update_sm_context( ogs_assert(r != OGS_ERROR); } else { ogs_error("No PolicyAssociationId"); - smf_sbi_send_sm_context_update_error( + smf_sbi_send_sm_context_update_error_log( stream, OGS_SBI_HTTP_STATUS_NOT_FOUND, - "No PolicyAssociationId", NULL, NULL, NULL); + "No PolicyAssociationId", NULL); } } else if (SmContextUpdateData->serving_nf_id) { ogs_debug("Old serving_nf_id: %s, new serving_nf_id: %s", @@ -694,9 +703,9 @@ bool smf_nsmf_handle_update_sm_context( ogs_assert(true == ogs_sbi_server_send_response(stream, response)); } else { ogs_error("[%s:%d] No UpdateData", smf_ue->supi, sess->psi); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - "No UpdateData", smf_ue->supi, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + "No UpdateData", smf_ue->supi); return false; } diff --git a/src/smf/nudm-handler.c b/src/smf/nudm-handler.c index e74078948..f4c60fd16 100644 --- a/src/smf/nudm-handler.c +++ b/src/smf/nudm-handler.c @@ -96,7 +96,8 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_warn("%s", strerror); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_NOT_FOUND, strerror, NULL, n1smbuf); + OGS_SBI_HTTP_STATUS_NOT_FOUND, OGS_SBI_APP_ERRNO_NULL, + strerror, NULL, n1smbuf); ogs_free(strerror); return false; @@ -320,7 +321,8 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_warn("%s", strerror); smf_sbi_send_sm_context_create_error(stream, - OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, strerror, NULL, n1smbuf); + OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR, + OGS_SBI_APP_ERRNO_NULL, strerror, NULL, n1smbuf); ogs_free(strerror); return false; diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index ff00025b6..4a1ed2b6b 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -248,9 +248,8 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) ogs_error("%s", strerror); if (stream) { - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, - strerror, NULL, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, strerror, NULL); } ogs_free(strerror); break; diff --git a/src/smf/sbi-path.c b/src/smf/sbi-path.c index 09b82cfe7..f3785fd74 100644 --- a/src/smf/sbi-path.c +++ b/src/smf/sbi-path.c @@ -191,7 +191,8 @@ void smf_namf_comm_send_n1_n2_pdu_establishment_reject( void smf_sbi_send_sm_context_create_error( ogs_sbi_stream_t *stream, - int status, const char *title, const char *detail, + int status, ogs_sbi_app_errno_e err, + const char *title, const char *detail, ogs_pkbuf_t *n1smbuf) { ogs_sbi_message_t sendmsg; @@ -210,6 +211,8 @@ void smf_sbi_send_sm_context_create_error( } problem.title = (char*)title; problem.detail = (char*)detail; + if (err > OGS_SBI_APP_ERRNO_NULL && err < OGS_SBI_MAX_NUM_OF_APP_ERRNO) + problem.cause = (char*)ogs_sbi_app_strerror(err); memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.SmContextCreateError = &SmContextCreateError; @@ -311,8 +314,11 @@ void smf_sbi_send_sm_context_updated_data( void smf_sbi_send_sm_context_update_error( ogs_sbi_stream_t *stream, - int status, const char *title, const char *detail, - ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf) + int status, ogs_sbi_app_errno_e err, + const char *title, const char *detail, + ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf, + OpenAPI_n2_sm_info_type_e n2_sm_info_type, + OpenAPI_up_cnx_state_e up_cnx_state) { ogs_sbi_message_t sendmsg; ogs_sbi_response_t *response = NULL; @@ -331,6 +337,8 @@ void smf_sbi_send_sm_context_update_error( } problem.title = (char*)title; problem.detail = (char*)detail; + if (err > OGS_SBI_APP_ERRNO_NULL && err < OGS_SBI_MAX_NUM_OF_APP_ERRNO) + problem.cause = (char*)ogs_sbi_app_strerror(err); memset(&sendmsg, 0, sizeof(sendmsg)); sendmsg.SmContextUpdateError = &SmContextUpdateError; @@ -360,6 +368,9 @@ void smf_sbi_send_sm_context_update_error( sendmsg.num_of_part++; } + SmContextUpdateError.n2_sm_info_type = n2_sm_info_type; + SmContextUpdateError.up_cnx_state = up_cnx_state; + response = ogs_sbi_build_response(&sendmsg, problem.status); ogs_assert(response); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); diff --git a/src/smf/sbi-path.h b/src/smf/sbi-path.h index 8be5920e9..0e0cbea01 100644 --- a/src/smf/sbi-path.h +++ b/src/smf/sbi-path.h @@ -48,7 +48,8 @@ void smf_namf_comm_send_n1_n2_pdu_establishment_reject( void smf_sbi_send_sm_context_create_error( ogs_sbi_stream_t *stream, - int status, const char *title, const char *detail, + int status, ogs_sbi_app_errno_e err, + const char *title, const char *detail, ogs_pkbuf_t *n1smbuf); #define smf_sbi_send_sm_context_updated_data_up_cnx_state( \ @@ -74,10 +75,31 @@ void smf_sbi_send_sm_context_updated_data( ogs_pkbuf_t *n1smbuf, OpenAPI_n2_sm_info_type_e n2type, ogs_pkbuf_t *n2smbuf); +#define smf_sbi_send_sm_context_update_error_log( \ + __sTREAM, __sTATUS, __tITLE, __dETAIL) \ + smf_sbi_send_sm_context_update_error( \ + __sTREAM, __sTATUS, OGS_SBI_APP_ERRNO_NULL, \ + __tITLE, __dETAIL, NULL, NULL, \ + OpenAPI_n2_sm_info_type_NULL, OpenAPI_up_cnx_state_NULL) +#define smf_sbi_send_sm_context_update_error_n1_n2_message( \ + __sTREAM, __sTATUS, __n1SmBuf, __n2Type, __n2SmBuf) \ + smf_sbi_send_sm_context_update_error( \ + __sTREAM, __sTATUS, OGS_SBI_APP_ERRNO_NULL, \ + NULL, NULL, __n1SmBuf, __n2SmBuf, __n2Type, \ + OpenAPI_up_cnx_state_NULL) +#define smf_sbi_send_sm_context_update_app_error( \ + __sTREAM, __sTATUS, __aPPError, __uPCnxState) \ + smf_sbi_send_sm_context_update_error( \ + __sTREAM, __sTATUS, __aPPError, \ + NULL, NULL, NULL, NULL, \ + OpenAPI_n2_sm_info_type_NULL, __uPCnxState); void smf_sbi_send_sm_context_update_error( ogs_sbi_stream_t *stream, - int status, const char *title, const char *detail, - ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf); + int status, ogs_sbi_app_errno_e err, + const char *title, const char *detail, + ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf, + OpenAPI_n2_sm_info_type_e n2_sm_info_type, + OpenAPI_up_cnx_state_e up_cnx_state); bool smf_sbi_send_sm_context_status_notify(smf_sess_t *sess); diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index ab30fe5fe..e1067a256 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -508,11 +508,10 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) if (!sbi_message.h.resource.component[1]) { ogs_error("No smContextRef [%s]", sbi_message.h.resource.component[1]); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, "No smContextRef", - sbi_message.h.resource.component[1], - NULL, NULL); + sbi_message.h.resource.component[1]); break; } @@ -521,9 +520,9 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) if (!sess) { ogs_warn("Not found [%s]", sbi_message.h.uri); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_NOT_FOUND, "Not found", - sbi_message.h.uri, NULL, NULL); + smf_sbi_send_sm_context_update_error_log( + stream, OGS_SBI_HTTP_STATUS_NOT_FOUND, + "Not found", sbi_message.h.uri); } break;