diff --git a/lib/gtp/v2/path.c b/lib/gtp/v2/path.c index 1aa380428..578960590 100644 --- a/lib/gtp/v2/path.c +++ b/lib/gtp/v2/path.c @@ -111,7 +111,7 @@ int ogs_gtp2_send_user_plane( } } - ogs_debug("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]", + ogs_trace("SEND GTP-U[%d] to Peer[%s] : TEID[0x%x]", gtp_hdesc->type, OGS_ADDR(&gnode->addr, buf), gtp_hdesc->teid); rv = ogs_gtp_sendto(gnode, pkbuf); if (rv != OGS_OK) { diff --git a/lib/gtp/xact.h b/lib/gtp/xact.h index 91c840f2c..216cb04f1 100644 --- a/lib/gtp/xact.h +++ b/lib/gtp/xact.h @@ -103,8 +103,7 @@ typedef struct ogs_gtp_xact_s { #define OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE 5 #define OGS_GTP_DELETE_SEND_RELEASE_WITH_S1_REMOVE_AND_UNLINK 6 #define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 7 -#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE_PARTIAL 8 -#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 9 +#define OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST 8 int delete_action; diff --git a/lib/pfcp/rule-match.c b/lib/pfcp/rule-match.c index 3df674897..c1eabab51 100644 --- a/lib/pfcp/rule-match.c +++ b/lib/pfcp/rule-match.c @@ -162,20 +162,20 @@ ogs_pfcp_rule_t *ogs_pfcp_pdr_rule_find_by_packet( continue; } - ogs_debug("PROTO:%d SRC:%08x %08x %08x %08x", + ogs_trace("PROTO:%d SRC:%08x %08x %08x %08x", proto, be32toh(src_addr[0]), be32toh(src_addr[1]), be32toh(src_addr[2]), be32toh(src_addr[3])); - ogs_debug("HLEN:%d DST:%08x %08x %08x %08x", + ogs_trace("HLEN:%d DST:%08x %08x %08x %08x", ip_hlen, be32toh(dst_addr[0]), be32toh(dst_addr[1]), be32toh(dst_addr[2]), be32toh(dst_addr[3])); - ogs_debug("PROTO:%d SRC:%d-%d DST:%d-%d", + ogs_trace("PROTO:%d SRC:%d-%d DST:%d-%d", ipfw->proto, ipfw->port.src.low, ipfw->port.src.high, ipfw->port.dst.low, ipfw->port.dst.high); - ogs_debug("SRC:%08x %08x %08x %08x/%08x %08x %08x %08x", + ogs_trace("SRC:%08x %08x %08x %08x/%08x %08x %08x %08x", be32toh(ipfw->ip.src.addr[0]), be32toh(ipfw->ip.src.addr[1]), be32toh(ipfw->ip.src.addr[2]), @@ -184,7 +184,7 @@ ogs_pfcp_rule_t *ogs_pfcp_pdr_rule_find_by_packet( be32toh(ipfw->ip.src.mask[1]), be32toh(ipfw->ip.src.mask[2]), be32toh(ipfw->ip.src.mask[3])); - ogs_debug("DST:%08x %08x %08x %08x/%08x %08x %08x %08x", + ogs_trace("DST:%08x %08x %08x %08x/%08x %08x %08x %08x", be32toh(ipfw->ip.dst.addr[0]), be32toh(ipfw->ip.dst.addr[1]), be32toh(ipfw->ip.dst.addr[2]), diff --git a/src/amf/gmm-build.h b/src/amf/gmm-build.h index 6cc6d480f..f5bed6000 100644 --- a/src/amf/gmm-build.h +++ b/src/amf/gmm-build.h @@ -59,14 +59,6 @@ ogs_pkbuf_t *gmm_build_dl_nas_transport(amf_sess_t *sess, uint8_t payload_container_type, ogs_pkbuf_t *payload, ogs_nas_5gmm_cause_t cause, uint8_t backoff_time); -ogs_pkbuf_t *gmm_build_tau_accept(amf_ue_t *amf_ue); -ogs_pkbuf_t *gmm_build_tau_reject( - ogs_nas_5gmm_cause_t gmm_cause, amf_ue_t *amf_ue); - -ogs_pkbuf_t *gmm_build_cs_service_notification(amf_ue_t *amf_ue); -ogs_pkbuf_t *gmm_build_downlink_nas_transport( - amf_ue_t *amf_ue, uint8_t *buffer, uint8_t length); - ogs_pkbuf_t *gmm_build_status(amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t cause); #ifdef __cplusplus diff --git a/src/amf/namf-handler.c b/src/amf/namf-handler.c index 231f51a07..844ed669d 100644 --- a/src/amf/namf-handler.c +++ b/src/amf/namf-handler.c @@ -851,11 +851,10 @@ int amf_namf_callback_handle_sdm_data_change_notify( ModificationNotification = recvmsg->ModificationNotification; if (!ModificationNotification) { status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; - ogs_error("[%s] No ModificationNotification", amf_ue->supi); + ogs_error("No ModificationNotification"); goto cleanup; } - OpenAPI_list_for_each(ModificationNotification->notify_items, node) { OpenAPI_notify_item_t *item = node->data; @@ -909,67 +908,65 @@ int amf_namf_callback_handle_sdm_data_change_notify( res_name = NULL; } - if (amf_ue_is_rat_restricted(amf_ue)) { - /* - * - AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED - * 1. UDM_UECM_DeregistrationNotification - * 2. Deregistration request - * 3. UDM_SDM_Unsubscribe - * 4. UDM_UECM_Deregisration - * 5. PDU session release request - * 6. PDUSessionResourceReleaseCommand + - * PDU session release command - * 7. PDUSessionResourceReleaseResponse - * 8. AM_Policy_Association_Termination - * 9. Deregistration accept - * 10. Signalling Connecion Release - */ - if (CM_CONNECTED(amf_ue)) { - r = nas_5gs_send_de_registration_request( - amf_ue, - OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED, - OGS_5GMM_CAUSE_5GS_SERVICES_NOT_ALLOWED); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); + if (amf_ue) { + if (amf_ue_is_rat_restricted(amf_ue)) { + /* + * - AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED + * 1. UDM_UECM_DeregistrationNotification + * 2. Deregistration request + * 3. UDM_SDM_Unsubscribe + * 4. UDM_UECM_Deregisration + * 5. PDU session release request + * 6. PDUSessionResourceReleaseCommand + + * PDU session release command + * 7. PDUSessionResourceReleaseResponse + * 8. AM_Policy_Association_Termination + * 9. Deregistration accept + * 10. Signalling Connecion Release + */ + if (CM_CONNECTED(amf_ue)) { + r = nas_5gs_send_de_registration_request( + amf_ue, + OpenAPI_deregistration_reason_REREGISTRATION_REQUIRED, 0); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); - state = AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED; + state = AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED; - } else if (CM_IDLE(amf_ue)) { - ogs_error("Not implemented : Use Implicit De-registration"); + } else if (CM_IDLE(amf_ue)) { + ogs_error("Not implemented : Use Implicit De-registration"); - state = AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED; + state = AMF_NETWORK_INITIATED_IMPLICIT_DE_REGISTERED; - } else { - ogs_fatal("Invalid State"); - ogs_assert_if_reached(); - } + } else { + ogs_fatal("Invalid State"); + ogs_assert_if_reached(); + } - if (UDM_SDM_SUBSCRIBED(amf_ue)) { - r = amf_ue_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, - amf_nudm_sdm_build_subscription_delete, - amf_ue, state, NULL); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); - } else if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { - r = amf_ue_sbi_discover_and_send( - OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, - NULL, - amf_npcf_am_policy_control_build_delete, - amf_ue, state, NULL); + if (UDM_SDM_SUBSCRIBED(amf_ue)) { + ogs_assert(true == amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NUDM_SDM, NULL, + amf_nudm_sdm_build_subscription_delete, + amf_ue, state, NULL)); + } else if (PCF_AM_POLICY_ASSOCIATED(amf_ue)) { + ogs_assert(true == + amf_ue_sbi_discover_and_send( + OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL, + NULL, + amf_npcf_am_policy_control_build_delete, + amf_ue, state, NULL)); + } + + } else if (ambr_changed) { + ogs_pkbuf_t *ngapbuf; + + ngapbuf = ngap_build_ue_context_modification_request(amf_ue); + ogs_assert(ngapbuf); + + r = nas_5gs_send_to_gnb(amf_ue, ngapbuf); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } - - } else if (ambr_changed) { - ogs_pkbuf_t *ngapbuf; - - ngapbuf = ngap_build_ue_context_modification_request(amf_ue); - ogs_assert(ngapbuf); - - r = nas_5gs_send_to_gnb(amf_ue, ngapbuf); - ogs_expect(r == OGS_OK); - ogs_assert(r != OGS_ERROR); } cleanup: diff --git a/src/amf/nas-path.c b/src/amf/nas-path.c index d799382bb..0714661e5 100644 --- a/src/amf/nas-path.c +++ b/src/amf/nas-path.c @@ -27,8 +27,7 @@ int nas_5gs_send_to_gnb(amf_ue_t *amf_ue, ogs_pkbuf_t *pkbuf) int rv; ogs_assert(pkbuf); - amf_ue = amf_ue_cycle(amf_ue); - if (!amf_ue) { + if (!amf_ue_cycle(amf_ue)) { ogs_error("UE(amf-ue) context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -48,8 +47,7 @@ int nas_5gs_send_to_downlink_nas_transport(amf_ue_t *amf_ue, ogs_pkbuf_t *pkbuf) ogs_assert(pkbuf); - amf_ue = amf_ue_cycle(amf_ue); - if (!amf_ue) { + if (!amf_ue_cycle(amf_ue)) { ogs_error("UE(amf-ue) context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -85,7 +83,11 @@ int nas_5gs_send_registration_accept(amf_ue_t *amf_ue) ogs_pkbuf_t *ngapbuf = NULL; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ran_ue = ran_ue_cycle(amf_ue->ran_ue); if (!ran_ue) { ogs_error("NG context has already been removed"); @@ -187,9 +189,12 @@ int nas_5gs_send_registration_reject( int rv; ogs_pkbuf_t *gmmbuf = NULL; - amf_metrics_inst_by_cause_add(gmm_cause, AMF_METR_CTR_RM_REG_INITFAIL, 1); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } - ogs_assert(amf_ue); + amf_metrics_inst_by_cause_add(gmm_cause, AMF_METR_CTR_RM_REG_INITFAIL, 1); ogs_warn("[%s] Registration reject [%d]", amf_ue->suci, gmm_cause); @@ -214,7 +219,11 @@ int nas_5gs_send_service_accept(amf_ue_t *amf_ue) ogs_pkbuf_t *gmmbuf = NULL; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ran_ue = ran_ue_cycle(amf_ue->ran_ue); if (!ran_ue) { ogs_error("NG context has already been removed"); @@ -288,7 +297,15 @@ int nas_5gs_send_service_reject( int rv; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Service reject", amf_ue->supi); @@ -311,7 +328,11 @@ int nas_5gs_send_de_registration_accept(amf_ue_t *amf_ue) ran_ue_t *ran_ue = NULL; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ran_ue = ran_ue_cycle(amf_ue->ran_ue); if (!ran_ue) { ogs_error("NG context has already been removed"); @@ -354,7 +375,11 @@ int nas_5gs_send_de_registration_request( ran_ue_t *ran_ue = NULL; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ran_ue = ran_ue_cycle(amf_ue->ran_ue); if (!ran_ue) { ogs_error("NG context has already been removed"); @@ -394,7 +419,15 @@ int nas_5gs_send_identity_request(amf_ue_t *amf_ue) int rv; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("Identity request"); @@ -428,7 +461,15 @@ int nas_5gs_send_authentication_request(amf_ue_t *amf_ue) int rv; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Authentication request", amf_ue->suci); @@ -462,9 +503,17 @@ int nas_5gs_send_authentication_reject(amf_ue_t *amf_ue) int rv; ogs_pkbuf_t *gmmbuf = NULL; - amf_metrics_inst_by_cause_add(0, AMF_METR_CTR_RM_REG_INITFAIL, 1); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } - ogs_assert(amf_ue); + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } + + amf_metrics_inst_by_cause_add(0, AMF_METR_CTR_RM_REG_INITFAIL, 1); ogs_warn("[%s] Authentication reject", amf_ue->suci); @@ -485,7 +534,15 @@ int nas_5gs_send_security_mode_command(amf_ue_t *amf_ue) int rv; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Security mode command", amf_ue->supi); @@ -520,7 +577,15 @@ int nas_5gs_send_configuration_update_command( int rv; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_info("[%s] Configuration update command", amf_ue->supi); @@ -767,10 +832,25 @@ int nas_send_pdu_session_release_command(amf_sess_t *sess, rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf); ogs_expect(rv == OGS_OK); } else { - ogs_error("ngap_build_pdu_session_resource_release_command() failed"); - ogs_error(" ACTIVATED[0x%x] SUPI[%s] PSI[%d]", - ran_ue->psimask.activated, amf_ue->supi, sess->psi); - return OGS_ERROR; + /* + * TS23.527 + * 5.3 Restoration Procedures upon Loss of GTP-U contexts + * 5.3.2 Procedure for GTP-U Error Indication received from 5G-AN + * + * 1. gNB sent TP-U Error Indication to the UPF. + * 2. UPF sent PFCP Report to SMF. + * 3. SMF sent N1N2Transfer to AMF to release PDU Session + * 4. In AMF, there is no Activated Session. + * + * Since AMF does not yet have an activated PDU Session, + * it ignores it without requesting PDU release from gNB. + */ + ogs_error("No session and N1 message"); + ogs_error(" ACTIVATED[0x%x] N1[%p], SUPI[%s] PSI[%d]", + ran_ue->psimask.activated, gmmbuf, amf_ue->supi, sess->psi); + + ogs_pkbuf_free(n2smbuf); + rv = OGS_OK; } return rv; @@ -781,7 +861,15 @@ int nas_5gs_send_gmm_status(amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t cause) int rv; ogs_pkbuf_t *gmmbuf = NULL; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] 5GMM status", amf_ue->supi); @@ -801,7 +889,16 @@ int nas_5gs_send_gmm_reject( amf_ue_t *amf_ue, ogs_nas_5gmm_cause_t gmm_cause) { int rv; - ogs_assert(amf_ue); + + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } switch(amf_ue->nas.message_type) { case OGS_NAS_5GS_REGISTRATION_REQUEST: @@ -849,7 +946,16 @@ int nas_5gs_send_gmm_reject_from_sbi(amf_ue_t *amf_ue, int status) { int rv; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } + rv = nas_5gs_send_gmm_reject(amf_ue, gmm_cause_from_sbi(status)); ogs_expect(rv == OGS_OK); @@ -866,8 +972,17 @@ int nas_5gs_send_dl_nas_transport(amf_sess_t *sess, amf_ue_t *amf_ue = NULL; ogs_assert(sess); + amf_ue = sess->amf_ue; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_assert(payload_container_type); ogs_assert(payload_container); @@ -903,8 +1018,21 @@ int nas_5gs_send_gsm_reject(amf_sess_t *sess, uint8_t payload_container_type, ogs_pkbuf_t *payload_container) { int rv; + amf_ue_t *amf_ue = NULL; ogs_assert(sess); + + amf_ue = sess->amf_ue; + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(payload_container_type); ogs_assert(payload_container); @@ -920,8 +1048,21 @@ int nas_5gs_send_back_gsm_message( { int rv; ogs_pkbuf_t *pbuf = NULL; + amf_ue_t *amf_ue = NULL; ogs_assert(sess); + + amf_ue = sess->amf_ue; + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(sess->payload_container_type); ogs_assert(sess->payload_container); diff --git a/src/amf/ngap-path.c b/src/amf/ngap-path.c index 5d0ff6511..42db934aa 100644 --- a/src/amf/ngap-path.c +++ b/src/amf/ngap-path.c @@ -52,8 +52,7 @@ int ngap_send_to_gnb(amf_gnb_t *gnb, ogs_pkbuf_t *pkbuf, uint16_t stream_no) ogs_assert(pkbuf); - gnb = amf_gnb_cycle(gnb); - if (!gnb) { + if (!amf_gnb_cycle(gnb)) { ogs_error("gNB has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -86,8 +85,7 @@ int ngap_send_to_ran_ue(ran_ue_t *ran_ue, ogs_pkbuf_t *pkbuf) int rv; ogs_assert(pkbuf); - ran_ue = ran_ue_cycle(ran_ue); - if (!ran_ue) { + if (!ran_ue_cycle(ran_ue)) { ogs_error("NG context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -260,6 +258,12 @@ int ngap_send_ng_setup_response(amf_gnb_t *gnb) ogs_pkbuf_t *ngap_buffer; ogs_debug("NG-Setup response"); + + if (!amf_gnb_cycle(gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } + ngap_buffer = ngap_build_ng_setup_response(); if (!ngap_buffer) { ogs_error("ngap_build_ng_setup_response() failed"); @@ -279,6 +283,12 @@ int ngap_send_ng_setup_failure( ogs_pkbuf_t *ngap_buffer; ogs_debug("NG-Setup failure"); + + if (!amf_gnb_cycle(gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } + ngap_buffer = ngap_build_ng_setup_failure( group, cause, NGAP_TimeToWait_v10s); if (!ngap_buffer) { @@ -298,6 +308,12 @@ int ngap_send_ran_configuration_update_ack(amf_gnb_t *gnb) ogs_pkbuf_t *ngap_buffer; ogs_debug("RANConfigurationUpdateAcknowledge"); + + if (!amf_gnb_cycle(gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } + ngap_buffer = ngap_build_ran_configuration_update_ack(); if (!ngap_buffer) { ogs_error("ngap_build_ran_configuration_update_ack() failed"); @@ -317,6 +333,12 @@ int ngap_send_ran_configuration_update_failure( ogs_pkbuf_t *ngap_buffer; ogs_debug("RANConfigurationUpdateFailure"); + + if (!amf_gnb_cycle(gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } + ngap_buffer = ngap_build_ran_configuration_update_failure( group, cause, NGAP_TimeToWait_v10s); if (!ngap_buffer) { @@ -337,7 +359,10 @@ int ngap_send_ran_ue_context_release_command( int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(ran_ue); + if (!ran_ue_cycle(ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("UEContextReleaseCommand"); ogs_debug(" RAN_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%lld]", @@ -369,7 +394,11 @@ int ngap_send_amf_ue_context_release_command( uint8_t action, ogs_time_t duration) { int rv; - ogs_assert(amf_ue); + + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } rv = ngap_send_ran_ue_context_release_command( amf_ue->ran_ue, group, cause, action, duration); @@ -386,6 +415,13 @@ int ngap_send_paging(amf_ue_t *amf_ue) int i, j; int rv; + ogs_debug("NG-Paging"); + + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(ogs_timer_running( amf_ue->implicit_deregistration.timer) == false); @@ -436,7 +472,10 @@ int ngap_send_downlink_ran_configuration_transfer( int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(target_gnb); + if (!amf_gnb_cycle(target_gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } ogs_assert(transfer); ngapbuf = ngap_build_downlink_ran_configuration_transfer(transfer); @@ -459,8 +498,17 @@ int ngap_send_path_switch_ack(amf_sess_t *sess) ogs_pkbuf_t *ngapbuf = NULL; ogs_assert(sess); + amf_ue = sess->amf_ue; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!ran_ue_cycle(amf_ue->ran_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ngapbuf = ngap_build_path_switch_ack(amf_ue); if (!ngapbuf) { @@ -481,12 +529,22 @@ int ngap_send_handover_request(amf_ue_t *amf_ue) ran_ue_t *source_ue = NULL, *target_ue = NULL; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(amf_ue); - source_ue = amf_ue->ran_ue; - ogs_assert(source_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } - target_ue = source_ue->target_ue; - ogs_assert(target_ue); + source_ue = ran_ue_cycle(amf_ue->ran_ue); + if (!source_ue) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } + + target_ue = ran_ue_cycle(source_ue->target_ue); + if (!target_ue) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ngapbuf = ngap_build_handover_request(target_ue); if (!ngapbuf) { @@ -506,7 +564,11 @@ int ngap_send_handover_preparation_failure( int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(source_ue); + if (!ran_ue_cycle(source_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(cause); ngapbuf = ngap_build_handover_preparation_failure(source_ue, cause); @@ -528,9 +590,16 @@ int ngap_send_handover_command(amf_ue_t *amf_ue) ran_ue_t *source_ue = NULL; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(amf_ue); - source_ue = amf_ue->ran_ue; - ogs_assert(source_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + source_ue = ran_ue_cycle(amf_ue->ran_ue); + if (!source_ue) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ngapbuf = ngap_build_handover_command(source_ue); if (!ngapbuf) { @@ -549,7 +618,10 @@ int ngap_send_handover_cancel_ack(ran_ue_t *source_ue) int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(source_ue); + if (!ran_ue_cycle(source_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ngapbuf = ngap_build_handover_cancel_ack(source_ue); if (!ngapbuf) { @@ -570,7 +642,10 @@ int ngap_send_downlink_ran_status_transfer( int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(target_ue); + if (!ran_ue_cycle(target_ue)) { + ogs_error("NG context has already been removed"); + return OGS_NOTFOUND; + } ogs_assert(transfer); ngapbuf = ngap_build_downlink_ran_status_transfer(target_ue, transfer); @@ -594,7 +669,10 @@ int ngap_send_error_indication( int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(gnb); + if (!amf_gnb_cycle(gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } ngapbuf = ogs_ngap_build_error_indication( ran_ue_ngap_id, amf_ue_ngap_id, group, cause); @@ -615,7 +693,11 @@ int ngap_send_error_indication2( int rv; ran_ue_t *ran_ue; - ogs_assert(amf_ue); + if (!amf_ue_cycle(amf_ue)) { + ogs_error("UE(amf-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ran_ue = ran_ue_cycle(amf_ue->ran_ue); if (!ran_ue) { ogs_error("NG context has already been removed"); @@ -637,7 +719,10 @@ int ngap_send_ng_reset_ack( int rv; ogs_pkbuf_t *ngapbuf = NULL; - ogs_assert(gnb); + if (!amf_gnb_cycle(gnb)) { + ogs_error("gNB has already been removed"); + return OGS_NOTFOUND; + } ngapbuf = ogs_ngap_build_ng_reset_ack(partOfNG_Interface); if (!ngapbuf) { diff --git a/src/mme/emm-sm.c b/src/mme/emm-sm.c index 7a0749c7f..ed1e30d14 100644 --- a/src/mme/emm-sm.c +++ b/src/mme/emm-sm.c @@ -224,7 +224,7 @@ void emm_state_registered(ogs_fsm_t *s, mme_event_t *e) static void common_register_state(ogs_fsm_t *s, mme_event_t *e) { - int r, rv; + int r, rv, xact_count = 0; mme_ue_t *mme_ue = NULL; enb_ue_t *enb_ue = NULL; @@ -248,6 +248,8 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) h.type = e->nas_type; + xact_count = mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR); + if (message->emm.h.security_header_type == OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { ogs_info("[%s] Service request", mme_ue->imsi_bcd); @@ -325,12 +327,15 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) break; } - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); - } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { mme_s6a_send_air(mme_ue, NULL); } + OGS_FSM_TRAN(s, &emm_state_authentication); break; @@ -353,10 +358,12 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) } if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(mme_ue)) { - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST); - } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { rv = nas_eps_send_emm_to_esm(mme_ue, &mme_ue->pdn_connectivity_request); if (rv != OGS_OK) { @@ -370,15 +377,21 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e) break; } } + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + } else { - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); - } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { mme_s6a_send_air(mme_ue, NULL); } + OGS_FSM_TRAN(s, &emm_state_authentication); + } break; @@ -1174,7 +1187,7 @@ void emm_state_security_mode(ogs_fsm_t *s, mme_event_t *e) void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) { - int r, rv; + int r, rv, xact_count; mme_ue_t *mme_ue = NULL; ogs_nas_eps_message_t *message = NULL; ogs_nas_security_header_type_t h; @@ -1196,6 +1209,8 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) message = e->nas_message; ogs_assert(message); + xact_count = mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR); + if (message->emm.h.security_header_type == OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE) { ogs_debug("Service request"); @@ -1311,8 +1326,16 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { + mme_s6a_send_air(mme_ue, NULL); + } + OGS_FSM_TRAN(s, &emm_state_authentication); break; + case OGS_NAS_EPS_EMM_STATUS: ogs_warn("EMM STATUS : IMSI[%s] Cause[%d]", mme_ue->imsi_bcd, @@ -1412,7 +1435,7 @@ void emm_state_initial_context_setup(ogs_fsm_t *s, mme_event_t *e) void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) { - int r, rv; + int r, rv, xact_count; mme_ue_t *mme_ue = NULL; enb_ue_t *enb_ue = NULL; @@ -1442,6 +1465,8 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) h.type = e->nas_type; + xact_count = mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR); + switch (message->emm.h.message_type) { case OGS_NAS_EPS_ATTACH_REQUEST: ogs_warn("[%s] Attach request", mme_ue->imsi_bcd); @@ -1464,10 +1489,12 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) } if (h.integrity_protected && SECURITY_CONTEXT_IS_VALID(mme_ue)) { - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST); - } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { rv = nas_eps_send_emm_to_esm(mme_ue, &mme_ue->pdn_connectivity_request); if (rv != OGS_OK) { @@ -1481,15 +1508,21 @@ void emm_state_exception(ogs_fsm_t *s, mme_event_t *e) break; } } + OGS_FSM_TRAN(s, &emm_state_initial_context_setup); + } else { - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); - } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_AUTHENTICATION_REQUEST); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { mme_s6a_send_air(mme_ue, NULL); } + OGS_FSM_TRAN(s, &emm_state_authentication); + } break; diff --git a/src/mme/esm-handler.c b/src/mme/esm-handler.c index 242fcbca0..cb5d819b9 100644 --- a/src/mme/esm-handler.c +++ b/src/mme/esm-handler.c @@ -45,7 +45,16 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer, ogs_assert(req); ogs_assert(MME_UE_HAVE_IMSI(mme_ue)); - ogs_assert(SECURITY_CONTEXT_IS_VALID(mme_ue)); + + if (!SECURITY_CONTEXT_IS_VALID(mme_ue)) { + ogs_error("No Security Context : IMSI[%s]", mme_ue->imsi_bcd); + r = nas_eps_send_pdn_connectivity_reject( + sess, OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED, + create_action); + ogs_expect(r == OGS_OK); + ogs_assert(r != OGS_ERROR); + return OGS_ERROR; + } memcpy(&sess->request_type, &req->request_type, sizeof(sess->request_type)); diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index 72dbf9a90..ee92a529a 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -126,8 +126,12 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } + + CLEAR_SGW_S1U_PATH(sess); + OGS_FSM_TRAN(s, esm_state_pdn_will_disconnect); break; + case OGS_NAS_EPS_ESM_INFORMATION_RESPONSE: ogs_debug("ESM information response"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", @@ -316,8 +320,12 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e) ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } + + CLEAR_SGW_S1U_PATH(sess); + OGS_FSM_TRAN(s, esm_state_pdn_will_disconnect); break; + case OGS_NAS_EPS_MODIFY_EPS_BEARER_CONTEXT_ACCEPT: ogs_debug("Modify EPS bearer context accept"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index ac85054b6..9ed1d27eb 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -2460,19 +2460,6 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue) return mme_ue; } -void mme_ue_hash_remove(mme_ue_t *mme_ue) -{ - ogs_assert(mme_ue); - - if (mme_ue->imsi_len != 0) - ogs_hash_set(mme_self()->imsi_ue_hash, - mme_ue->imsi, mme_ue->imsi_len, NULL); - - if (mme_ue->current.m_tmsi) - ogs_hash_set(self.guti_ue_hash, - &mme_ue->current.guti, sizeof(ogs_nas_eps_guti_t), NULL); -} - void mme_ue_remove(mme_ue_t *mme_ue) { ogs_assert(mme_ue); @@ -2484,8 +2471,15 @@ void mme_ue_remove(mme_ue_t *mme_ue) ogs_assert(mme_ue->sgw_ue); sgw_ue_remove(mme_ue->sgw_ue); - if (mme_ue->current.m_tmsi) + if (mme_ue->imsi_len != 0) + ogs_hash_set(mme_self()->imsi_ue_hash, + mme_ue->imsi, mme_ue->imsi_len, NULL); + + if (mme_ue->current.m_tmsi) { + ogs_hash_set(self.guti_ue_hash, + &mme_ue->current.guti, sizeof(ogs_nas_eps_guti_t), NULL); ogs_assert(mme_m_tmsi_free(mme_ue->current.m_tmsi) == OGS_OK); + } if (mme_ue->next.m_tmsi) ogs_assert(mme_m_tmsi_free(mme_ue->next.m_tmsi) == OGS_OK); @@ -2534,7 +2528,6 @@ void mme_ue_remove_all(void) if (enb_ue) enb_ue_remove(enb_ue); - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); } } @@ -2768,6 +2761,8 @@ mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message) int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd) { mme_ue_t *old_mme_ue = NULL; + mme_sess_t *old_sess = NULL; + mme_bearer_t *old_bearer = NULL; ogs_assert(mme_ue && imsi_bcd); ogs_cpystrn(mme_ue->imsi_bcd, imsi_bcd, OGS_MAX_IMSI_BCD_LEN+1); @@ -2792,24 +2787,42 @@ int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd) /* * We should delete the MME-Session Context in the MME-UE Context. - * Otherwise, all unnecessary SESSIONs remain in SMF/SGW-C/SGW-U/UPF. + * Otherwise, all unnecessary SESSIONs remain in SMF/UPF. * - * Hash deletion is separated from mme_ue_remove(). Otherwise, - * hash deletion occurs simultaneously in mme_ue_remove() - * after mme_gtp_send_delete_all_session(). This will delete the Hash - * we added immediately below, so we can't find this IMSI. + * In order to do this, MME-Session Context should be moved + * from OLD MME-UE Context to NEW MME-UE Context. * - * Note that we should not use the session movement method in AMF. - * This is because the MME-S11-TEID in the Delete Session Response - * uses the OLD MME. + * If needed, The Session deletion process in NEW-MME UE context will work. + * + * Note that we should not send Session-Release to the SGW-C at this point. + * Another GTPv2-C Transaction can cause fatal errors. */ - mme_ue_hash_remove(old_mme_ue); + /* Phase-1 : Change MME-UE Context in Session Context */ + ogs_list_for_each(&old_mme_ue->sess_list, old_sess) { + ogs_list_for_each(&old_sess->bearer_list, old_bearer) { + old_bearer->mme_ue = mme_ue; - if (SESSION_CONTEXT_IS_AVAILABLE(old_mme_ue)) { - ogs_warn("[%s] Trigger OLD Session Remove", mme_ue->imsi_bcd); - mme_gtp_send_delete_all_sessions(old_mme_ue, - OGS_GTP_DELETE_UE_CONTEXT_REMOVE_PARTIAL); + if (old_bearer->ebi_node) + ogs_pool_free( + &old_mme_ue->ebi_pool, old_bearer->ebi_node); + old_bearer->ebi_node = NULL; + } + old_sess->mme_ue = mme_ue; } + + /* Phase-2 : Move Session Context from OLD to NEW MME-UE Context */ + memcpy(&mme_ue->sess_list, + &old_mme_ue->sess_list, sizeof(mme_ue->sess_list)); + + /* Phase-3 : Clear Session Context in OLD MME-UE Context */ + memset(&old_mme_ue->sess_list, 0, sizeof(old_mme_ue->sess_list)); + + /* Phase-4 : Move sgw_ue->sgw_s11_teid */ + ogs_assert(old_mme_ue->sgw_ue); + ogs_assert(mme_ue->sgw_ue); + mme_ue->sgw_ue->sgw_s11_teid = old_mme_ue->sgw_ue->sgw_s11_teid; + + mme_ue_remove(old_mme_ue); } } @@ -2860,20 +2873,76 @@ void mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue) bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue) { mme_sess_t *sess = NULL; - mme_bearer_t *bearer = NULL; ogs_assert(mme_ue); ogs_list_for_each(&mme_ue->sess_list, sess) { - ogs_list_for_each(&sess->bearer_list, bearer) { - if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) - return true; - } + if (mme_sess_have_active_eps_bearers(sess) == true) + return true; } return false; } +bool mme_sess_have_active_eps_bearers(mme_sess_t *sess) +{ + mme_bearer_t *bearer = NULL; + ogs_assert(sess); + + ogs_list_for_each(&sess->bearer_list, bearer) { + if (OGS_FSM_CHECK(&bearer->sm, esm_state_active)) + return true; + } + + return false; +} + +bool mme_ue_have_session_release_pending(mme_ue_t *mme_ue) +{ + mme_sess_t *sess = NULL; + + ogs_assert(mme_ue); + + ogs_list_for_each(&mme_ue->sess_list, sess) { + if (mme_sess_have_session_release_pending(sess) == true) + return true; + } + + return false; +} + +bool mme_sess_have_session_release_pending(mme_sess_t *sess) +{ + mme_bearer_t *bearer = NULL; + ogs_assert(sess); + + ogs_list_for_each(&sess->bearer_list, bearer) { + if (OGS_FSM_CHECK(&bearer->sm, esm_state_pdn_will_disconnect)) + return true; + } + + return false; +} + +int mme_ue_xact_count(mme_ue_t *mme_ue, uint8_t org) +{ + sgw_ue_t *sgw_ue = NULL; + ogs_gtp_node_t *gnode = NULL; + + ogs_assert(org == OGS_GTP_LOCAL_ORIGINATOR || + org == OGS_GTP_REMOTE_ORIGINATOR); + + sgw_ue = mme_ue->sgw_ue; + if (!sgw_ue) return 0; + + gnode = sgw_ue->gnode; + if (!gnode) return 0; + + return org == OGS_GTP_LOCAL_ORIGINATOR ? + ogs_list_count(&gnode->local_list) : + ogs_list_count(&gnode->remote_list); +} + void enb_ue_associate_mme_ue(enb_ue_t *enb_ue, mme_ue_t *mme_ue) { ogs_assert(mme_ue); @@ -3112,9 +3181,7 @@ unsigned int mme_sess_count(mme_ue_t *mme_ue) unsigned int count = 0; mme_sess_t *sess = NULL; - sess = mme_sess_first(mme_ue); - while (sess) { - sess = mme_sess_next(sess); + ogs_list_for_each(&mme_ue->sess_list, sess) { count++; } @@ -3179,8 +3246,8 @@ void mme_bearer_remove(mme_bearer_t *bearer) OGS_TLV_CLEAR_DATA(&bearer->tft); - ogs_assert(bearer->ebi_node); - ogs_pool_free(&bearer->mme_ue->ebi_pool, bearer->ebi_node); + if (bearer->ebi_node) + ogs_pool_free(&bearer->mme_ue->ebi_pool, bearer->ebi_node); ogs_pool_free(&mme_bearer_pool, bearer); } diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index c455d513e..f2f214429 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -285,14 +285,6 @@ struct sgw_ue_s { /* UE identity */ uint32_t sgw_s11_teid; /* SGW-S11-TEID is received from SGW */ - /* - * If the MME sends Delete-Session-Request to the SGW for all sessions, - * session_context_will_deleted = 1 - * When the MME receives a Delete-Session-Response for the last session, - * session_context_will_deleted = 0 - */ - int session_context_will_deleted; - /* S11 Holding timer for removing this context */ ogs_timer_t *t_s11_holding; @@ -477,6 +469,7 @@ struct mme_ue_s { #define MME_CLEAR_PAGING_INFO(__mME) \ do { \ ogs_assert(__mME); \ + ogs_debug("[%s] Clear Paging Info", mme_ue->imsi_bcd); \ (__mME)->paging.type = 0; \ } while(0) @@ -484,6 +477,7 @@ struct mme_ue_s { do { \ ogs_assert(__mME); \ ogs_assert(__tYPE); \ + ogs_debug("[%s] Store Paging Info", mme_ue->imsi_bcd); \ (__mME)->paging.type = __tYPE; \ (__mME)->paging.data = __dATA; \ } while(0) @@ -605,19 +599,16 @@ struct mme_ue_s { #define SESSION_CONTEXT_IS_AVAILABLE(__mME) \ ((__mME) && ((__mME)->sgw_ue) && (((__mME)->sgw_ue)->sgw_s11_teid)) -#define SESSION_CONTEXT_WILL_DELETED(__mME) \ - ((__mME) && ((__mME)->sgw_ue) && \ - (((__mME)->sgw_ue)->session_context_will_deleted)) - #define CLEAR_SESSION_CONTEXT(__mME) \ do { \ ogs_assert((__mME)); \ ((__mME)->sgw_ue)->sgw_s11_teid = 0; \ - ((__mME)->sgw_ue)->session_context_will_deleted = 0; \ } while(0) #define ACTIVE_EPS_BEARERS_IS_AVAIABLE(__mME) \ (mme_ue_have_active_eps_bearers(__mME)) +#define MME_SESSION_RELEASE_PENDING(__mME) \ + (mme_ue_have_session_release_pending(__mME)) typedef struct mme_sess_s { ogs_lnode_t lnode; @@ -808,7 +799,6 @@ void mme_ue_new_guti(mme_ue_t *mme_ue); void mme_ue_confirm_guti(mme_ue_t *mme_ue); mme_ue_t *mme_ue_add(enb_ue_t *enb_ue); -void mme_ue_hash_remove(mme_ue_t *mme_ue); void mme_ue_remove(mme_ue_t *mme_ue); void mme_ue_remove_all(void); mme_ue_t *mme_ue_cycle(mme_ue_t *mme_ue); @@ -828,6 +818,11 @@ bool mme_ue_have_indirect_tunnel(mme_ue_t *mme_ue); void mme_ue_clear_indirect_tunnel(mme_ue_t *mme_ue); bool mme_ue_have_active_eps_bearers(mme_ue_t *mme_ue); +bool mme_sess_have_active_eps_bearers(mme_sess_t *sess); +bool mme_ue_have_session_release_pending(mme_ue_t *mme_ue); +bool mme_sess_have_session_release_pending(mme_sess_t *sess); + +int mme_ue_xact_count(mme_ue_t *mme_ue, uint8_t org); /* * o RECV Initial UE-Message : S-TMSI diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index 21f788b6b..580d960ec 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -332,33 +332,12 @@ void mme_gtp_send_delete_all_sessions(mme_ue_t *mme_ue, int action) ogs_assert(sgw_ue); ogs_assert(action); - if (SESSION_CONTEXT_WILL_DELETED(mme_ue)) { - ogs_warn("[%s] Delete-Session-Request has already sent", - mme_ue->imsi_bcd); - return; - } - - sgw_ue->session_context_will_deleted = 1; - - sess = mme_sess_first(mme_ue); - while (sess != NULL) { - next_sess = mme_sess_next(sess); - + ogs_list_for_each_safe(&mme_ue->sess_list, next_sess, sess) { if (MME_HAVE_SGW_S1U_PATH(sess)) { - mme_bearer_t *bearer = mme_default_bearer_in_sess(sess); - ogs_assert(bearer); - - if (bearer && - OGS_FSM_CHECK(&bearer->sm, esm_state_pdn_will_disconnect)) { - ogs_warn("PDN will disconnect[EBI:%d]", bearer->ebi); - } else { - mme_gtp_send_delete_session_request(sgw_ue, sess, action); - } + mme_gtp_send_delete_session_request(sgw_ue, sess, action); } else { mme_sess_remove(sess); } - - sess = next_sess; } } diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index d94295151..5fb6c2d3c 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -27,16 +27,20 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) { - int r; + int r, xact_count; ogs_assert(mme_ue); + xact_count = mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR); + switch (mme_ue->detach_type) { case MME_DETACH_TYPE_REQUEST_FROM_UE: ogs_debug("Detach Request from UE"); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions( - mme_ue, OGS_GTP_DELETE_SEND_DETACH_ACCEPT); - } else { + mme_gtp_send_delete_all_sessions( + mme_ue, OGS_GTP_DELETE_SEND_DETACH_ACCEPT); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { r = nas_eps_send_detach_accept(mme_ue); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); @@ -57,9 +61,7 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) */ case MME_DETACH_TYPE_HSS_EXPLICIT: ogs_debug("Explicit HSS Detach"); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); - } + mme_gtp_send_delete_all_sessions(mme_ue, OGS_GTP_DELETE_NO_ACTION); break; /* MME Implicit Detach, ie: Lost Communication @@ -68,10 +70,12 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) */ case MME_DETACH_TYPE_MME_IMPLICIT: ogs_debug("Implicit MME Detach"); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE); - } else { + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { enb_ue_t *enb_ue = enb_ue_cycle(mme_ue->enb_ue); if (enb_ue) { ogs_assert(OGS_OK == @@ -82,7 +86,6 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) if (mme_ue->location_updated_but_not_canceled_yet == true) { mme_s6a_send_pur(mme_ue); } else { - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); } } @@ -105,10 +108,8 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) */ case MME_DETACH_TYPE_HSS_IMPLICIT: ogs_debug("Implicit HSS Detach"); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE); - } + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE); break; default: @@ -119,13 +120,18 @@ void mme_send_delete_session_or_detach(mme_ue_t *mme_ue) void mme_send_delete_session_or_mme_ue_context_release(mme_ue_t *mme_ue) { - int r; + int r, xact_count = 0; + ogs_assert(mme_ue); - if (SESSION_CONTEXT_IS_AVAILABLE(mme_ue)) { - mme_gtp_send_delete_all_sessions(mme_ue, - OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE); - } else { + xact_count = mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR); + + mme_gtp_send_delete_all_sessions(mme_ue, + OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE); + + if (!MME_SESSION_RELEASE_PENDING(mme_ue) && + mme_ue_xact_count(mme_ue, OGS_GTP_LOCAL_ORIGINATOR) == + xact_count) { enb_ue_t *enb_ue = enb_ue_cycle(mme_ue->enb_ue); if (enb_ue) { r = s1ap_send_ue_context_release_command(enb_ue, diff --git a/src/mme/mme-s11-handler.c b/src/mme/mme-s11-handler.c index 5879a699b..6bef8937f 100644 --- a/src/mme/mme-s11-handler.c +++ b/src/mme/mme-s11-handler.c @@ -111,8 +111,18 @@ void mme_s11_handle_create_session_response( create_action = xact->create_action; sess = xact->data; ogs_assert(sess); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); + mme_ue = mme_ue_cycle(sess->mme_ue); + + rv = ogs_gtp_xact_commit(xact); + if (rv != OGS_OK) { + ogs_error("ogs_gtp_xact_commit() failed"); + return; + } + + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } source_ue = sgw_ue_cycle(mme_ue->sgw_ue); ogs_assert(source_ue); @@ -124,12 +134,6 @@ void mme_s11_handle_create_session_response( ogs_assert(target_ue); } - rv = ogs_gtp_xact_commit(xact); - if (rv != OGS_OK) { - ogs_error("ogs_gtp_xact_commit() failed"); - return; - } - /************************ * Getting Cause Value ************************/ @@ -458,10 +462,7 @@ void mme_s11_handle_modify_bearer_response( ********************/ ogs_assert(xact); modify_action = xact->modify_action; - mme_ue = xact->data; - ogs_assert(mme_ue); - sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); - ogs_assert(sgw_ue); + mme_ue = mme_ue_cycle(xact->data); rv = ogs_gtp_xact_commit(xact); if (rv != OGS_OK) { @@ -469,6 +470,13 @@ void mme_s11_handle_modify_bearer_response( return; } + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } + sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(sgw_ue); + /************************ * Getting Cause Value ************************/ @@ -568,8 +576,18 @@ void mme_s11_handle_delete_session_response( ogs_assert(action); sess = xact->data; ogs_assert(sess); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); + mme_ue = mme_ue_cycle(sess->mme_ue); + + rv = ogs_gtp_xact_commit(xact); + if (rv != OGS_OK) { + ogs_error("ogs_gtp_xact_commit() failed"); + return; + } + + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } target_ue = sgw_ue_cycle(mme_ue->sgw_ue); ogs_assert(target_ue); @@ -581,17 +599,24 @@ void mme_s11_handle_delete_session_response( ogs_assert(source_ue); } - rv = ogs_gtp_xact_commit(xact); - if (rv != OGS_OK) { - ogs_error("ogs_gtp_xact_commit() failed"); - return; - } - /************************ * Check MME-UE Context ************************/ if (!mme_ue_from_teid) { - ogs_error("No Context in TEID"); + /* + * In mme_ue_set_imsi(), + * OLD MME-UE Context could be switched to NEW MME-UE Context + * + * OLD/NEW MME-UE Contexts have different MME-S11-TEID. + * Since MME has NEW MME-S11-TEID and SGW-C has OLD MME-S11-TEID. + * + * At this time, if the MME receives OLD MME-S11-TEID from SGW-C + * in the Delete Session Response, MME cannot find MME-UE Context. + * + * Since there is such a case, + * Delete Session Response treats this as a WARNING. + */ + ogs_warn("No Context in TEID"); } /******************** @@ -645,12 +670,7 @@ void mme_s11_handle_delete_session_response( ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); - /* - * mme_sess_remove() should not be called here. - * - * if Deactivate bearer context accept is received, - * Session will be removed */ - CLEAR_SGW_S1U_PATH(sess); + /* mme_sess_remove() should not be called here. */ return; } else if (action == OGS_GTP_DELETE_SEND_RELEASE_WITH_UE_CONTEXT_REMOVE) { @@ -659,7 +679,6 @@ void mme_s11_handle_delete_session_response( if (mme_ue->location_updated_but_not_canceled_yet == true) { mme_s6a_send_pur(mme_ue); } else { - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); } } else { @@ -702,12 +721,6 @@ void mme_s11_handle_delete_session_response( } } - } else if (action == OGS_GTP_DELETE_UE_CONTEXT_REMOVE_PARTIAL) { - - /* Remove MME-UE Context with Session Context since IMSI duplicated */ - mme_ue_remove(mme_ue); - return; - } else if (action == OGS_GTP_DELETE_IN_PATH_SWITCH_REQUEST) { /* Don't have to remove Session in X2 Handover with SGW relocation */ @@ -918,6 +931,7 @@ void mme_s11_handle_create_bearer_request( ogs_assert(OGS_OK == mme_gtp_send_create_bearer_response( bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + MME_CLEAR_PAGING_INFO(mme_ue); } else { MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_CREATE_BEARER, bearer); @@ -926,11 +940,13 @@ void mme_s11_handle_create_bearer_request( ogs_assert(r != OGS_ERROR); } } else { + MME_CLEAR_PAGING_INFO(mme_ue); r = nas_eps_send_activate_dedicated_bearer_context_request(bearer); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); } } else { + MME_CLEAR_PAGING_INFO(mme_ue); /* * After received Activate EPS default bearer context accept * Invoke nas_eps_send_activate_all_dedicated_bearers() @@ -1066,6 +1082,7 @@ void mme_s11_handle_update_bearer_request( ogs_assert(OGS_OK == mme_gtp_send_update_bearer_response( bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + MME_CLEAR_PAGING_INFO(mme_ue); } else { MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_UPDATE_BEARER, bearer); @@ -1074,6 +1091,7 @@ void mme_s11_handle_update_bearer_request( ogs_assert(r != OGS_ERROR); } } else { + MME_CLEAR_PAGING_INFO(mme_ue); r = nas_eps_send_modify_bearer_context_request(bearer, req->bearer_contexts.bearer_level_qos.presence, req->bearer_contexts.tft.presence); @@ -1081,6 +1099,7 @@ void mme_s11_handle_update_bearer_request( ogs_assert(r != OGS_ERROR); } } else { + MME_CLEAR_PAGING_INFO(mme_ue); ogs_error("[IGNORE] Update Bearer Request : " "Both QoS and TFT is NULL"); @@ -1221,6 +1240,7 @@ void mme_s11_handle_delete_bearer_request( ogs_assert(OGS_OK == mme_gtp_send_delete_bearer_response( bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + MME_CLEAR_PAGING_INFO(mme_ue); } else { MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DELETE_BEARER, bearer); @@ -1229,6 +1249,7 @@ void mme_s11_handle_delete_bearer_request( ogs_assert(r != OGS_ERROR); } } else { + MME_CLEAR_PAGING_INFO(mme_ue); r = nas_eps_send_deactivate_bearer_context_request(bearer); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); @@ -1259,10 +1280,7 @@ void mme_s11_handle_release_access_bearers_response( ogs_assert(xact); action = xact->release_action; ogs_assert(action); - mme_ue = xact->data; - ogs_assert(mme_ue); - sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); - ogs_assert(sgw_ue); + mme_ue = mme_ue_cycle(xact->data); rv = ogs_gtp_xact_commit(xact); if (rv != OGS_OK) { @@ -1270,6 +1288,13 @@ void mme_s11_handle_release_access_bearers_response( return; } + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } + sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(sgw_ue); + /*********************** * Check MME-UE Context ***********************/ @@ -1497,6 +1522,7 @@ void mme_s11_handle_downlink_data_notification( ogs_assert(OGS_OK == mme_gtp_send_downlink_data_notification_ack( bearer, OGS_GTP2_CAUSE_UNABLE_TO_PAGE_UE)); + MME_CLEAR_PAGING_INFO(mme_ue); } else { MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DOWNLINK_DATA_NOTIFICATION, bearer); @@ -1505,6 +1531,7 @@ void mme_s11_handle_downlink_data_notification( ogs_assert(r != OGS_ERROR); } } else if (ECM_CONNECTED(mme_ue)) { + MME_CLEAR_PAGING_INFO(mme_ue); if (cause_value == OGS_GTP2_CAUSE_ERROR_INDICATION_RECEIVED) { /* @@ -1573,10 +1600,7 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( * Check Transaction ********************/ ogs_assert(xact); - mme_ue = xact->data; - ogs_assert(mme_ue); - sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); - ogs_assert(sgw_ue); + mme_ue = mme_ue_cycle(xact->data); rv = ogs_gtp_xact_commit(xact); if (rv != OGS_OK) { @@ -1584,6 +1608,13 @@ void mme_s11_handle_create_indirect_data_forwarding_tunnel_response( return; } + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } + sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(sgw_ue); + /************************ * Getting Cause Value ************************/ @@ -1704,10 +1735,7 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( ogs_assert(xact); action = xact->delete_indirect_action; ogs_assert(action); - mme_ue = xact->data; - ogs_assert(mme_ue); - sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); - ogs_assert(sgw_ue); + mme_ue = mme_ue_cycle(xact->data); rv = ogs_gtp_xact_commit(xact); if (rv != OGS_OK) { @@ -1715,6 +1743,13 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response( return; } + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } + sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(sgw_ue); + /************************ * Getting Cause Value ************************/ @@ -1811,10 +1846,7 @@ void mme_s11_handle_bearer_resource_failure_indication( ogs_assert(ind); sess = bearer->sess; ogs_assert(sess); - mme_ue = sess->mme_ue; - ogs_assert(mme_ue); - sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); - ogs_assert(sgw_ue); + mme_ue = mme_ue_cycle(sess->mme_ue); rv = ogs_gtp_xact_commit(xact); if (rv != OGS_OK) { @@ -1822,6 +1854,13 @@ void mme_s11_handle_bearer_resource_failure_indication( return; } + if (!mme_ue) { + ogs_error("MME-UE Context has already been removed"); + return; + } + sgw_ue = sgw_ue_cycle(mme_ue->sgw_ue); + ogs_assert(sgw_ue); + if (!mme_ue_from_teid) ogs_error("No Context in TEID"); diff --git a/src/mme/mme-s6a-handler.c b/src/mme/mme-s6a-handler.c index 4f298f8bd..a38cebd64 100644 --- a/src/mme/mme-s6a-handler.c +++ b/src/mme/mme-s6a-handler.c @@ -143,7 +143,6 @@ uint8_t mme_s6a_handle_pua( if (s6a_message->result_code != ER_DIAMETER_SUCCESS) { ogs_error("Purge UE failed for IMSI[%s] [%d]", mme_ue->imsi_bcd, s6a_message->result_code); - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); return OGS_ERROR; } @@ -151,7 +150,6 @@ uint8_t mme_s6a_handle_pua( if (pua_message->pua_flags & OGS_DIAM_S6A_PUA_FLAGS_FREEZE_MTMSI) ogs_debug("Freeze M-TMSI requested but not implemented."); - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); return OGS_OK; @@ -226,7 +224,6 @@ void mme_s6a_handle_clr(mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message) */ if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_de_registered)) { ogs_warn("UE has already been de-registered"); - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); return; } @@ -279,6 +276,7 @@ void mme_s6a_handle_clr(mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message) } else { mme_send_delete_session_or_detach(mme_ue); } + MME_CLEAR_PAGING_INFO(mme_ue); } else { MME_STORE_PAGING_INFO(mme_ue, MME_PAGING_TYPE_DETACH_TO_UE, NULL); @@ -287,6 +285,7 @@ void mme_s6a_handle_clr(mme_ue_t *mme_ue, ogs_diam_s6a_message_t *s6a_message) ogs_assert(r != OGS_ERROR); } } else { + MME_CLEAR_PAGING_INFO(mme_ue); r = nas_eps_send_detach_request(mme_ue); ogs_expect(r == OGS_OK); ogs_assert(r != OGS_ERROR); diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index dad39c294..36836e0e4 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -32,8 +32,7 @@ int nas_eps_send_to_enb(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf) ogs_assert(pkbuf); - mme_ue = mme_ue_cycle(mme_ue); - if (!mme_ue) { + if (!mme_ue_cycle(mme_ue)) { ogs_error("UE(mme-ue) context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -51,7 +50,11 @@ int nas_eps_send_emm_to_esm(mme_ue_t *mme_ue, int rv; ogs_pkbuf_t *esmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(esm_message_container); ogs_assert(esm_message_container->length); @@ -74,25 +77,22 @@ int nas_eps_send_to_downlink_nas_transport(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf) { int rv; ogs_pkbuf_t *s1apbuf = NULL; - enb_ue_t *enb_ue = NULL; ogs_assert(pkbuf); - mme_ue = mme_ue_cycle(mme_ue); - if (!mme_ue) { + if (!mme_ue_cycle(mme_ue)) { ogs_error("UE(mme-ue) context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; } - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (!enb_ue) { + if (!enb_ue_cycle(mme_ue->enb_ue)) { ogs_error("S1 context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; } - s1apbuf = s1ap_build_downlink_nas_transport(enb_ue, pkbuf); + s1apbuf = s1ap_build_downlink_nas_transport(mme_ue->enb_ue, pkbuf); if (!s1apbuf) { ogs_error("s1ap_build_downlink_nas_transport() failed"); return OGS_ERROR; @@ -112,7 +112,16 @@ int nas_eps_send_attach_accept(mme_ue_t *mme_ue) ogs_pkbuf_t *s1apbuf = NULL; ogs_pkbuf_t *esmbuf = NULL, *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + sess = mme_sess_first(mme_ue); ogs_assert(sess); ogs_assert(mme_sess_next(sess) == NULL); @@ -178,12 +187,16 @@ int nas_eps_send_attach_reject(mme_ue_t *mme_ue, mme_sess_t *sess = NULL; ogs_pkbuf_t *esmbuf = NULL, *emmbuf = NULL; - mme_ue = mme_ue_cycle(mme_ue); - if (!mme_ue) { + if (!mme_ue_cycle(mme_ue)) { ogs_error("UE(mme-ue) context has already been removed"); return OGS_NOTFOUND; } + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_debug("[%s] Attach reject", mme_ue->imsi_bcd); ogs_debug(" Cause[%d]", emm_cause); @@ -213,7 +226,15 @@ int nas_eps_send_identity_request(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("Identity request"); @@ -247,7 +268,15 @@ int nas_eps_send_authentication_request(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Authentication request", mme_ue->imsi_bcd); @@ -281,7 +310,15 @@ int nas_eps_send_security_mode_command(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Security mode command", mme_ue->imsi_bcd); @@ -315,7 +352,15 @@ int nas_eps_send_authentication_reject(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Authentication reject", mme_ue->imsi_bcd); @@ -336,6 +381,16 @@ int nas_eps_send_detach_request(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *emmbuf = NULL; + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_debug("[%s] Detach request to UE", mme_ue->imsi_bcd); if (mme_ue->t3422.pkbuf) { @@ -367,12 +422,14 @@ int nas_eps_send_detach_accept(mme_ue_t *mme_ue) { int rv; - enb_ue_t *enb_ue = NULL; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (!enb_ue) { + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { ogs_error("S1 context has already been removed"); return OGS_NOTFOUND; } @@ -394,7 +451,7 @@ int nas_eps_send_detach_accept(mme_ue_t *mme_ue) } } - rv = s1ap_send_ue_context_release_command(enb_ue, + rv = s1ap_send_ue_context_release_command(mme_ue->enb_ue, S1AP_Cause_PR_nas, S1AP_CauseNas_detach, S1AP_UE_CTX_REL_S1_REMOVE_AND_UNLINK, 0); ogs_expect(rv == OGS_OK); @@ -410,8 +467,17 @@ int nas_eps_send_pdn_connectivity_reject( ogs_pkbuf_t *esmbuf = NULL; ogs_assert(sess); + mme_ue = sess->mme_ue; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } if (create_action == OGS_GTP_CREATE_IN_ATTACH_REQUEST) { /* During the UE-attach process, we'll send Attach-Reject @@ -449,8 +515,17 @@ int nas_eps_send_esm_information_request(mme_bearer_t *bearer) ogs_pkbuf_t *esmbuf = NULL; ogs_assert(bearer); + mme_ue = bearer->mme_ue; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } if (bearer->t3489.pkbuf) { esmbuf = bearer->t3489.pkbuf; @@ -489,8 +564,17 @@ int nas_eps_send_activate_default_bearer_context_request( ogs_assert(bearer); sess = bearer->sess; ogs_assert(sess); + mme_ue = bearer->mme_ue; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } esmbuf = esm_build_activate_default_bearer_context_request( sess, create_action); @@ -520,8 +604,17 @@ int nas_eps_send_activate_dedicated_bearer_context_request( mme_ue_t *mme_ue = NULL; ogs_assert(bearer); + mme_ue = bearer->mme_ue; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } esmbuf = esm_build_activate_dedicated_bearer_context_request(bearer); if (!esmbuf) { @@ -566,8 +659,17 @@ int nas_eps_send_modify_bearer_context_request( mme_ue_t *mme_ue = NULL; ogs_assert(bearer); + mme_ue = bearer->mme_ue; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } esmbuf = esm_build_modify_bearer_context_request( bearer, qos_presence, tft_presence); @@ -601,8 +703,17 @@ int nas_eps_send_deactivate_bearer_context_request(mme_bearer_t *bearer) mme_ue_t *mme_ue = NULL; ogs_assert(bearer); + mme_ue = bearer->mme_ue; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } esmbuf = esm_build_deactivate_bearer_context_request( bearer, OGS_NAS_ESM_CAUSE_REGULAR_DEACTIVATION); @@ -630,7 +741,16 @@ int nas_eps_send_bearer_resource_allocation_reject( int rv; ogs_pkbuf_t *esmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(pti != OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED); esmbuf = esm_build_bearer_resource_allocation_reject( @@ -652,7 +772,16 @@ int nas_eps_send_bearer_resource_modification_reject( int rv; ogs_pkbuf_t *esmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(pti != OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED); esmbuf = esm_build_bearer_resource_modification_reject( @@ -674,7 +803,15 @@ int nas_eps_send_tau_accept( int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Tracking area update accept", mme_ue->imsi_bcd); @@ -720,7 +857,15 @@ int nas_eps_send_tau_reject(mme_ue_t *mme_ue, ogs_nas_emm_cause_t emm_cause) int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Tracking area update reject", mme_ue->imsi_bcd); @@ -743,7 +888,15 @@ int nas_eps_send_service_reject(mme_ue_t *mme_ue, int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] Service reject", mme_ue->imsi_bcd); @@ -765,7 +918,15 @@ int nas_eps_send_cs_service_notification(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } ogs_debug("[%s] CS Service Notification", mme_ue->imsi_bcd); @@ -787,7 +948,16 @@ int nas_eps_send_downlink_nas_transport( int rv; ogs_pkbuf_t *emmbuf = NULL; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(buffer); ogs_assert(length); diff --git a/src/mme/s1ap-build.c b/src/mme/s1ap-build.c index 01f2eccad..618c2e7aa 100644 --- a/src/mme/s1ap-build.c +++ b/src/mme/s1ap-build.c @@ -201,6 +201,7 @@ ogs_pkbuf_t *s1ap_build_downlink_nas_transport( S1AP_NAS_PDU_t *NAS_PDU = NULL; ogs_assert(emmbuf); + enb_ue = enb_ue_cycle(enb_ue); ogs_assert(enb_ue); ogs_debug("DownlinkNASTransport"); @@ -283,16 +284,10 @@ ogs_pkbuf_t *s1ap_build_initial_context_setup_request( mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + mme_ue = mme_ue_cycle(mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); - if (!enb_ue) { - ogs_error("S1 context has already been removed"); - if (emmbuf && emmbuf->len) { - ogs_error("NAS message is forcibly removed"); - ogs_pkbuf_free(emmbuf); - } - return NULL; - } + ogs_assert(enb_ue); ogs_debug("InitialContextSetupRequest"); @@ -706,6 +701,7 @@ ogs_pkbuf_t *s1ap_build_ue_context_modification_request(mme_ue_t *mme_ue) enb_ue_t *enb_ue = NULL; + mme_ue = mme_ue_cycle(mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(enb_ue); @@ -841,6 +837,7 @@ ogs_pkbuf_t *s1ap_build_ue_context_release_command( S1AP_UE_S1AP_IDs_t *UE_S1AP_IDs = NULL; S1AP_Cause_t *Cause = NULL; + enb_ue = enb_ue_cycle(enb_ue); ogs_assert(enb_ue); if (enb_ue->mme_ue_s1ap_id == 0) { @@ -926,7 +923,7 @@ ogs_pkbuf_t *s1ap_build_e_rab_setup_request( ogs_assert(esmbuf); ogs_assert(bearer); - mme_ue = bearer->mme_ue; + mme_ue = mme_ue_cycle(bearer->mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(enb_ue); @@ -1059,7 +1056,7 @@ ogs_pkbuf_t *s1ap_build_e_rab_modify_request( ogs_assert(esmbuf); ogs_assert(bearer); - mme_ue = bearer->mme_ue; + mme_ue = mme_ue_cycle(bearer->mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(enb_ue); @@ -1187,7 +1184,7 @@ ogs_pkbuf_t *s1ap_build_e_rab_release_command( ogs_assert(esmbuf); ogs_assert(bearer); - mme_ue = bearer->mme_ue; + mme_ue = mme_ue_cycle(bearer->mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(enb_ue); @@ -1308,6 +1305,7 @@ ogs_pkbuf_t *s1ap_build_e_rab_modification_confirm(mme_ue_t *mme_ue) mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + mme_ue = mme_ue_cycle(mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(enb_ue); @@ -1409,6 +1407,7 @@ ogs_pkbuf_t *s1ap_build_paging( uint64_t ue_imsi_value = 0; int i = 0; + mme_ue = mme_ue_cycle(mme_ue); ogs_assert(mme_ue); ogs_debug("Paging"); @@ -1577,6 +1576,7 @@ ogs_pkbuf_t *s1ap_build_path_switch_ack( mme_bearer_t *bearer = NULL; enb_ue_t *enb_ue = NULL; + mme_ue = mme_ue_cycle(mme_ue); ogs_assert(mme_ue); enb_ue = enb_ue_cycle(mme_ue->enb_ue); ogs_assert(enb_ue); @@ -1773,8 +1773,10 @@ ogs_pkbuf_t *s1ap_build_handover_command(enb_ue_t *source_ue) mme_sess_t *sess = NULL; mme_bearer_t *bearer = NULL; + source_ue = enb_ue_cycle(source_ue); ogs_assert(source_ue); - mme_ue = source_ue->mme_ue; + mme_ue = mme_ue_cycle(source_ue->mme_ue); + ogs_assert(mme_ue); ogs_debug("HandoverCommand"); @@ -1930,6 +1932,7 @@ ogs_pkbuf_t *s1ap_build_handover_preparation_failure( S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; S1AP_Cause_t *Cause = NULL; + source_ue = enb_ue_cycle(source_ue); ogs_assert(source_ue); ogs_assert(group); @@ -2022,8 +2025,9 @@ ogs_pkbuf_t *s1ap_build_handover_request( ogs_assert(cause); ogs_assert(source_totarget_transparentContainer); + target_ue = enb_ue_cycle(target_ue); ogs_assert(target_ue); - mme_ue = target_ue->mme_ue; + mme_ue = mme_ue_cycle(target_ue->mme_ue); ogs_assert(mme_ue); ogs_debug("HandoverRequest"); @@ -2256,6 +2260,7 @@ ogs_pkbuf_t *s1ap_build_handover_cancel_ack(enb_ue_t *source_ue) S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL; S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL; + source_ue = enb_ue_cycle(source_ue); ogs_assert(source_ue); ogs_debug("HandoverCancelAcknowledge"); @@ -2319,6 +2324,7 @@ ogs_pkbuf_t *s1ap_build_mme_status_transfer( S1AP_ENB_StatusTransfer_TransparentContainer_t *ENB_StatusTransfer_TransparentContainer = NULL; + target_ue = enb_ue_cycle(target_ue); ogs_assert(target_ue); ogs_assert(enb_statustransfer_transparentContainer); diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c index cbc6a831d..5c3f75613 100644 --- a/src/mme/s1ap-handler.c +++ b/src/mme/s1ap-handler.c @@ -1572,7 +1572,6 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue) if (mme_ue->location_updated_but_not_canceled_yet == true) { mme_s6a_send_pur(mme_ue); } else { - mme_ue_hash_remove(mme_ue); mme_ue_remove(mme_ue); } break; @@ -1973,7 +1972,7 @@ void s1ap_handle_path_switch_request( return; } - mme_ue = enb_ue->mme_ue; + mme_ue = mme_ue_cycle(enb_ue->mme_ue); if (!mme_ue) { ogs_error("No UE(mme-ue) context"); return; diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index 59fe0f1f3..57398583b 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -53,8 +53,7 @@ int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no) ogs_assert(pkbuf); - enb = mme_enb_cycle(enb); - if (!enb) { + if (!mme_enb_cycle(enb)) { ogs_error("eNB has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -87,8 +86,7 @@ int s1ap_send_to_enb_ue(enb_ue_t *enb_ue, ogs_pkbuf_t *pkbuf) int rv; ogs_assert(pkbuf); - enb_ue = enb_ue_cycle(enb_ue); - if (!enb_ue) { + if (!enb_ue_cycle(enb_ue)) { ogs_error("S1 context has already been removed"); ogs_pkbuf_free(pkbuf); return OGS_NOTFOUND; @@ -268,6 +266,12 @@ int s1ap_send_s1_setup_response(mme_enb_t *enb) ogs_pkbuf_t *s1ap_buffer; ogs_debug("S1-Setup response"); + + if (!mme_enb_cycle(enb)) { + ogs_error("eNB has already been removed"); + return OGS_NOTFOUND; + } + s1ap_buffer = s1ap_build_setup_rsp(); if (!s1ap_buffer) { ogs_error("s1ap_build_setup_rsp() failed"); @@ -287,6 +291,12 @@ int s1ap_send_s1_setup_failure( ogs_pkbuf_t *s1ap_buffer; ogs_debug("S1-Setup failure"); + + if (!mme_enb_cycle(enb)) { + ogs_error("eNB has already been removed"); + return OGS_NOTFOUND; + } + s1ap_buffer = s1ap_build_setup_failure(group, cause, S1AP_TimeToWait_v10s); if (!s1ap_buffer) { ogs_error("s1ap_build_setup_failure() failed"); @@ -304,9 +314,18 @@ int s1ap_send_initial_context_setup_request(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(mme_ue); - ogs_debug("InitialContextSetupRequest"); + + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_initial_context_setup_request(mme_ue, NULL); if (!s1apbuf) { ogs_error("s1ap_build_initial_context_setup_request() failed"); @@ -324,9 +343,18 @@ int s1ap_send_ue_context_modification_request(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(mme_ue); - ogs_debug("UEContextModificationRequest"); + + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_ue_context_modification_request(mme_ue); if (!s1apbuf) { ogs_error("s1ap_build_ue_context_modification_request() failed"); @@ -346,9 +374,13 @@ int s1ap_send_ue_context_release_command( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(enb_ue); - ogs_debug("UEContextReleaseCommand"); + + if (!enb_ue_cycle(enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_debug(" ENB_UE_S1AP_ID[%d] MME_UE_S1AP_ID[%d]", enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id); @@ -380,6 +412,13 @@ int s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain) int i; int rv; + ogs_debug("S1-Paging"); + + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(ogs_timer_running(mme_ue->t_implicit_detach.timer) == false); /* Find enB with matched TAI */ @@ -429,10 +468,15 @@ int s1ap_send_mme_configuration_transfer( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(target_enb); + ogs_debug("MMEConfigurationTransfer"); + + if (!mme_enb_cycle(target_enb)) { + ogs_error("eNB has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(SONConfigurationTransfer); - ogs_debug("MMEConfigurationTransfer"); s1apbuf = s1ap_build_mme_configuration_transfer(SONConfigurationTransfer); if (!s1apbuf) { ogs_error("s1ap_build_mme_configuration_transfer() failed"); @@ -450,9 +494,18 @@ int s1ap_send_e_rab_modification_confirm(mme_ue_t *mme_ue) int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(mme_ue); - ogs_debug("E-RABModificationConfirm"); + + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_e_rab_modification_confirm(mme_ue); if (!s1apbuf) { ogs_error("s1ap_build_e_rab_modification_confirm() failed"); @@ -471,9 +524,18 @@ int s1ap_send_path_switch_ack( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(mme_ue); - ogs_debug("PathSwitchAcknowledge"); + + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!enb_ue_cycle(mme_ue->enb_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_path_switch_ack( mme_ue, e_rab_to_switched_in_uplink_list); if (!s1apbuf) { @@ -492,9 +554,18 @@ int s1ap_send_handover_command(enb_ue_t *source_ue) int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(source_ue); - ogs_debug("HandoverCommand"); + + if (!enb_ue_cycle(source_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + + if (!mme_ue_cycle(source_ue->mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_handover_command(source_ue); if (!s1apbuf) { ogs_error("s1ap_build_handover_command() failed"); @@ -513,10 +584,15 @@ int s1ap_send_handover_preparation_failure( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(source_ue); + ogs_debug("HandoverPreparationFailure"); + + if (!enb_ue_cycle(source_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(group); - ogs_debug("HandoverPreparationFailure"); s1apbuf = s1ap_build_handover_preparation_failure(source_ue, group, cause); if (!s1apbuf) { ogs_error("s1ap_build_handover_preparation_failure() failed"); @@ -534,9 +610,13 @@ int s1ap_send_handover_cancel_ack(enb_ue_t *source_ue) int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(source_ue); - ogs_debug("HandoverCancelAcknowledge"); + + if (!enb_ue_cycle(source_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_handover_cancel_ack(source_ue); if (!s1apbuf) { ogs_error("s1ap_build_handover_cancel_ack() failed"); @@ -562,9 +642,23 @@ int s1ap_send_handover_request( enb_ue_t *target_ue = NULL; ogs_info("HandoverRequest"); - ogs_assert(source_ue); + + if (!enb_ue_cycle(source_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + + if (!mme_ue_cycle(source_ue->mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + + if (!mme_enb_cycle(target_enb)) { + ogs_error("eNB has already been removed"); + return OGS_NOTFOUND; + } + ogs_assert(source_ue->target_ue == NULL); - ogs_assert(target_enb); target_ue = enb_ue_add(target_enb, INVALID_UE_S1AP_ID); if (target_ue == NULL) { @@ -605,9 +699,13 @@ int s1ap_send_mme_status_transfer( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(target_ue); - ogs_info("MMEStatusTransfer"); + + if (!enb_ue_cycle(target_ue)) { + ogs_error("S1 context has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = s1ap_build_mme_status_transfer(target_ue, enb_statustransfer_transparentContainer); if (!s1apbuf) { @@ -630,9 +728,13 @@ int s1ap_send_error_indication( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(enb); - ogs_info("ErrorIndication"); + + if (!mme_enb_cycle(enb)) { + ogs_error("eNB has already been removed"); + return OGS_NOTFOUND; + } + s1apbuf = ogs_s1ap_build_error_indication( mme_ue_s1ap_id, enb_ue_s1ap_id, group, cause); if (!s1apbuf) { @@ -656,12 +758,17 @@ int s1ap_send_error_indication2( S1AP_MME_UE_S1AP_ID_t mme_ue_s1ap_id; S1AP_ENB_UE_S1AP_ID_t enb_ue_s1ap_id; - ogs_assert(mme_ue); + if (!mme_ue_cycle(mme_ue)) { + ogs_error("UE(mme-ue) context has already been removed"); + return OGS_NOTFOUND; + } + enb_ue = enb_ue_cycle(mme_ue->enb_ue); if (!enb_ue) { ogs_error("S1 context has already been removed"); return OGS_NOTFOUND; } + enb = mme_enb_cycle(enb_ue->enb); if (!enb) { ogs_error("eNB has already been removed"); @@ -685,7 +792,10 @@ int s1ap_send_s1_reset_ack( int rv; ogs_pkbuf_t *s1apbuf = NULL; - ogs_assert(enb); + if (!mme_enb_cycle(enb)) { + ogs_error("eNB has already been removed"); + return OGS_NOTFOUND; + } ogs_info("S1-Reset Acknowledge"); s1apbuf = ogs_s1ap_build_s1_reset_ack(partOfS1_Interface); diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 2032ed6af..e227f72b2 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -402,6 +402,7 @@ void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_assert(OGS_OK == sgsap_send_paging_reject( mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE)); + MME_CLEAR_PAGING_INFO(mme_ue); } else { /* UE will respond Extended Service Request in PS CNDomain*/ MME_STORE_PAGING_INFO(mme_ue, @@ -426,6 +427,7 @@ void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_assert(OGS_OK == sgsap_send_paging_reject( mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE)); + MME_CLEAR_PAGING_INFO(mme_ue); } else { /* UE will respond Service Request in PS CNDomain*/ MME_STORE_PAGING_INFO(mme_ue, @@ -438,6 +440,7 @@ void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) goto paging_reject; } else { + MME_CLEAR_PAGING_INFO(mme_ue); if (CS_CALL_SERVICE_INDICATOR(mme_ue)) { r = nas_eps_send_cs_service_notification(mme_ue); ogs_expect(r == OGS_OK); diff --git a/src/sgwu/gtp-path.c b/src/sgwu/gtp-path.c index f572ef5ef..91484bef9 100644 --- a/src/sgwu/gtp-path.c +++ b/src/sgwu/gtp-path.c @@ -90,7 +90,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data) teid = be32toh(gtp_h->teid); - ogs_debug("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]", + ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]", gtp_h->type, OGS_ADDR(&from, buf), teid); qfi = 0; @@ -110,7 +110,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data) OGS_GTP2_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER) { if (extension_header->pdu_type == OGS_GTP2_EXTENSION_HEADER_PDU_TYPE_UL_PDU_SESSION_INFORMATION) { - ogs_debug(" QFI [0x%x]", + ogs_trace(" QFI [0x%x]", extension_header->qos_flow_identifier); qfi = extension_header->qos_flow_identifier; } diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index 80ec3cf42..6178d335f 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -230,10 +230,11 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data) ogs_assert(strerror); ogs_error("%s", strerror); - ogs_assert(stream); - smf_sbi_send_sm_context_update_error(stream, - OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, - strerror, NULL, NULL, NULL); + if (stream) { + smf_sbi_send_sm_context_update_error(stream, + OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, + strerror, NULL, NULL, NULL); + } ogs_free(strerror); break; case OGS_PFCP_SESSION_DELETION_REQUEST_TYPE: diff --git a/src/upf/gtp-path.c b/src/upf/gtp-path.c index cd99cad01..4a6b8f4c2 100644 --- a/src/upf/gtp-path.c +++ b/src/upf/gtp-path.c @@ -312,7 +312,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data) teid = be32toh(gtp_h->teid); - ogs_debug("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]", + ogs_trace("[RECV] GPU-U Type [%d] from [%s] : TEID[0x%x]", gtp_h->type, OGS_ADDR(&from, buf), teid); qfi = 0; @@ -332,7 +332,7 @@ static void _gtpv1_u_recv_cb(short when, ogs_socket_t fd, void *data) OGS_GTP2_EXTENSION_HEADER_TYPE_PDU_SESSION_CONTAINER) { if (extension_header->pdu_type == OGS_GTP2_EXTENSION_HEADER_PDU_TYPE_UL_PDU_SESSION_INFORMATION) { - ogs_debug(" QFI [0x%x]", + ogs_trace(" QFI [0x%x]", extension_header->qos_flow_identifier); qfi = extension_header->qos_flow_identifier; } diff --git a/src/upf/rule-match.c b/src/upf/rule-match.c index dd4980646..9ff8bc10b 100644 --- a/src/upf/rule-match.c +++ b/src/upf/rule-match.c @@ -58,9 +58,9 @@ upf_sess_t *upf_sess_find_by_ue_ip_address(ogs_pkbuf_t *pkbuf) if (sess) { if (ip_h && sess->ipv4) - ogs_debug("PAA IPv4:%s", OGS_INET_NTOP(&sess->ipv4->addr, buf)); + ogs_trace("PAA IPv4:%s", OGS_INET_NTOP(&sess->ipv4->addr, buf)); if (ip6_h && sess->ipv6) - ogs_debug("PAA IPv6:%s", OGS_INET6_NTOP(&sess->ipv6->addr, buf)); + ogs_trace("PAA IPv6:%s", OGS_INET6_NTOP(&sess->ipv6->addr, buf)); } return sess;