From 321c8d4cf9466a017250ae25750d6cea5f83985b Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 19 Aug 2022 18:58:55 +0900 Subject: [PATCH] [SGsAP] Changed message if Paging failed (#1701) The problem occurred in the following scenario: 1. VLR sent PAGING-REQUEST to the MME 2. MME sent S1-Paging to the UE 3. Paging failed 4. MME responded SERVICE-REQUEST to the VLR 5. VLR sent DOWNLINK-UNITDATA to the MME 6. Even though there is no S1 Context, MME try to sent DownlinkNASTransport message to the UE. 7. So, the problem occurred. I've changed the number 4 PAGING-REJECT instead of SERVICE-REQUEST. --- src/mme/mme-context.c | 10 ++++++++++ src/mme/mme-context.h | 2 ++ src/mme/mme-path.c | 8 +++----- src/mme/nas-path.c | 41 +++++++++++++++++++++++++---------------- src/mme/s1ap-path.c | 22 ++++++++++++++++------ src/mme/sgsap-build.c | 1 - src/mme/sgsap-handler.c | 12 ++++++------ src/mme/sgsap-path.c | 19 +++++++++++++++++++ src/mme/sgsap-path.h | 1 + 9 files changed, 82 insertions(+), 34 deletions(-) diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index a564d0802..851730260 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -1927,6 +1927,11 @@ int mme_enb_sock_type(ogs_sock_t *sock) return SOCK_STREAM; } +mme_enb_t *mme_enb_cycle(mme_enb_t *enb) +{ + return ogs_pool_cycle(&mme_enb_pool, enb); +} + /** enb_ue_context handling function */ enb_ue_t *enb_ue_add(mme_enb_t *enb, uint32_t enb_ue_s1ap_id) { @@ -2389,6 +2394,11 @@ void mme_ue_remove_all(void) } } +mme_ue_t *mme_ue_cycle(mme_ue_t *mme_ue) +{ + return ogs_pool_cycle(&mme_ue_pool, mme_ue); +} + void mme_ue_fsm_init(mme_ue_t *mme_ue) { mme_event_t e; diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 11405b71b..c8fa72430 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -764,6 +764,7 @@ mme_enb_t *mme_enb_find_by_addr(ogs_sockaddr_t *addr); mme_enb_t *mme_enb_find_by_enb_id(uint32_t enb_id); int mme_enb_set_enb_id(mme_enb_t *enb, uint32_t enb_id); int mme_enb_sock_type(ogs_sock_t *sock); +mme_enb_t *mme_enb_cycle(mme_enb_t *enb); enb_ue_t *enb_ue_add(mme_enb_t *enb, uint32_t enb_ue_s1ap_id); void enb_ue_remove(enb_ue_t *enb_ue); @@ -794,6 +795,7 @@ 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); void mme_ue_fsm_init(mme_ue_t *mme_ue); void mme_ue_fsm_fini(mme_ue_t *mme_ue); diff --git a/src/mme/mme-path.c b/src/mme/mme-path.c index 03c261cdf..32b439376 100644 --- a/src/mme/mme-path.c +++ b/src/mme/mme-path.c @@ -173,7 +173,7 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) case MME_PAGING_TYPE_CS_CALL_SERVICE: if (failed == true) { ogs_assert(OGS_OK == - sgsap_send_service_request( + sgsap_send_paging_reject( mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE)); } else { /* Nothing */ @@ -182,7 +182,7 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) case MME_PAGING_TYPE_SMS_SERVICE: if (failed == true) { ogs_assert(OGS_OK == - sgsap_send_service_request( + sgsap_send_paging_reject( mme_ue, SGSAP_SGS_CAUSE_UE_UNREACHABLE)); } else { ogs_assert(OGS_OK == @@ -193,9 +193,7 @@ void mme_send_after_paging(mme_ue_t *mme_ue, bool failed) case MME_PAGING_TYPE_DETACH_TO_UE: if (failed == true) { /* Nothing */ - ogs_fatal("MME-initiated Detach should not be invoked " - "if Paging failed"); - ogs_assert_if_reached(); + ogs_warn("MME-initiated Detach cannot be invoked"); } else { ogs_assert(OGS_OK == nas_eps_send_detach_request(mme_ue)); if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) { diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index a14a817fc..0b5128c33 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -28,13 +28,16 @@ int nas_eps_send_to_enb(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf) { - enb_ue_t *enb_ue = NULL; + ogs_assert(pkbuf); - ogs_assert(mme_ue); - enb_ue = enb_ue_cycle(mme_ue->enb_ue); - ogs_expect_or_return_val(enb_ue, OGS_ERROR); + mme_ue = mme_ue_cycle(mme_ue); + if (!mme_ue) { + ogs_warn("UE(mme-ue) context has already been removed"); + ogs_pkbuf_free(pkbuf); + return OGS_ERROR; + } - return s1ap_send_to_enb_ue(enb_ue, pkbuf); + return s1ap_send_to_enb_ue(mme_ue->enb_ue, pkbuf); } int nas_eps_send_emm_to_esm(mme_ue_t *mme_ue, @@ -69,22 +72,28 @@ int nas_eps_send_to_downlink_nas_transport(mme_ue_t *mme_ue, ogs_pkbuf_t *pkbuf) enb_ue_t *enb_ue = NULL; ogs_assert(pkbuf); - ogs_assert(mme_ue); + + mme_ue = mme_ue_cycle(mme_ue); + if (!mme_ue) { + ogs_warn("UE(mme-ue) context has already been removed"); + ogs_pkbuf_free(pkbuf); + return OGS_ERROR; + } + enb_ue = enb_ue_cycle(mme_ue->enb_ue); if (!enb_ue) { - ogs_error("S1 context has already been removed"); + ogs_warn("S1 context has already been removed"); ogs_pkbuf_free(pkbuf); - return OGS_ERROR; - } else { - s1apbuf = s1ap_build_downlink_nas_transport(enb_ue, pkbuf); - ogs_expect_or_return_val(s1apbuf, OGS_ERROR); - - rv = nas_eps_send_to_enb(mme_ue, s1apbuf); - ogs_expect(rv == OGS_OK); - - return rv; } + + s1apbuf = s1ap_build_downlink_nas_transport(enb_ue, pkbuf); + ogs_expect_or_return_val(s1apbuf, OGS_ERROR); + + rv = nas_eps_send_to_enb(mme_ue, s1apbuf); + ogs_expect(rv == OGS_OK); + + return rv; } int nas_eps_send_attach_accept(mme_ue_t *mme_ue) diff --git a/src/mme/s1ap-path.c b/src/mme/s1ap-path.c index 219d37fb5..1681ae8fb 100644 --- a/src/mme/s1ap-path.c +++ b/src/mme/s1ap-path.c @@ -51,8 +51,15 @@ int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no) { char buf[OGS_ADDRSTRLEN]; - ogs_assert(enb); ogs_assert(pkbuf); + + enb = mme_enb_cycle(enb); + if (!enb) { + ogs_warn("eNB has already been removed"); + ogs_pkbuf_free(pkbuf); + return OGS_ERROR; + } + ogs_assert(enb->sctp.sock); if (enb->sctp.sock->fd == INVALID_SOCKET) { ogs_fatal("eNB SCTP socket has already been destroyed"); @@ -77,13 +84,16 @@ int s1ap_send_to_enb(mme_enb_t *enb, ogs_pkbuf_t *pkbuf, uint16_t stream_no) int s1ap_send_to_enb_ue(enb_ue_t *enb_ue, ogs_pkbuf_t *pkbuf) { - mme_enb_t *enb = NULL; + ogs_assert(pkbuf); - ogs_assert(enb_ue); - enb = enb_ue->enb; - ogs_assert(enb); + enb_ue = enb_ue_cycle(enb_ue); + if (!enb_ue) { + ogs_warn("S1 context has already been removed"); + ogs_pkbuf_free(pkbuf); + return OGS_ERROR; + } - return s1ap_send_to_enb(enb, pkbuf, enb_ue->enb_ostream_id); + return s1ap_send_to_enb(enb_ue->enb, pkbuf, enb_ue->enb_ostream_id); } int s1ap_delayed_send_to_enb_ue( diff --git a/src/mme/sgsap-build.c b/src/mme/sgsap-build.c index c14967759..7bc8fa136 100644 --- a/src/mme/sgsap-build.c +++ b/src/mme/sgsap-build.c @@ -237,7 +237,6 @@ ogs_pkbuf_t *sgsap_build_paging_reject( root = ogs_tlv_add(NULL, OGS_TLV_MODE_T1_L1, SGSAP_IE_IMSI_TYPE, SGSAP_IE_IMSI_LEN, 0, nas_mobile_identity_imsi); - sgs_cause = SGSAP_SGS_CAUSE_IMSI_UNKNOWN; ogs_tlv_add(root, OGS_TLV_MODE_T1_L1, SGSAP_IE_SGS_CAUSE_TYPE, SGSAP_IE_SGS_CAUSE_LEN, 0, &sgs_cause); diff --git a/src/mme/sgsap-handler.c b/src/mme/sgsap-handler.c index 7d2a1b8ca..de3fd25c9 100644 --- a/src/mme/sgsap-handler.c +++ b/src/mme/sgsap-handler.c @@ -209,7 +209,7 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) mme_send_delete_session_or_mme_ue_context_release(mme_ue); return; - + error: ogs_error("Error processing SGsAP LU REJECT"); return; @@ -333,7 +333,7 @@ void sgsap_handle_paging_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_nas_eps_imsi_to_bcd(nas_mobile_identity_imsi, nas_mobile_identity_imsi_len, imsi_bcd); mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); - } else + } else ogs_expect_or_return(0); if (mme_ue) { @@ -386,7 +386,7 @@ paging_reject: ogs_debug(" IMSI[%s]", imsi_bcd); sgsap_send_to_vlr_with_sid( - vlr, + vlr, sgsap_build_paging_reject( nas_mobile_identity_imsi, nas_mobile_identity_imsi_len, SGSAP_SGS_CAUSE_IMSI_UNKNOWN), @@ -445,7 +445,7 @@ void sgsap_handle_downlink_unitdata(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_nas_eps_imsi_to_bcd(nas_mobile_identity_imsi, nas_mobile_identity_imsi_len, imsi_bcd); mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); - } else + } else ogs_assert_if_reached(); ogs_expect_or_return(mme_ue); @@ -514,7 +514,7 @@ void sgsap_handle_release_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_nas_eps_imsi_to_bcd(nas_mobile_identity_imsi, nas_mobile_identity_imsi_len, imsi_bcd); mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); - } else + } else ogs_expect_or_return(0); if (mme_ue) @@ -571,7 +571,7 @@ void sgsap_handle_mm_information_request(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf) ogs_nas_eps_imsi_to_bcd(nas_mobile_identity_imsi, nas_mobile_identity_imsi_len, imsi_bcd); mme_ue = mme_ue_find_by_imsi_bcd(imsi_bcd); - } else + } else ogs_expect_or_return(0); if (mme_ue) diff --git a/src/mme/sgsap-path.c b/src/mme/sgsap-path.c index dde72e706..ed08aca16 100644 --- a/src/mme/sgsap-path.c +++ b/src/mme/sgsap-path.c @@ -175,6 +175,25 @@ int sgsap_send_mo_csfb_indication(mme_ue_t *mme_ue) return rv; } +int sgsap_send_paging_reject(mme_ue_t *mme_ue, uint8_t sgs_cause) +{ + int rv; + ogs_pkbuf_t *pkbuf = NULL; + ogs_assert(mme_ue); + + ogs_debug("[SGSAP] PAGING-REJECT"); + ogs_debug(" IMSI[%s]", mme_ue->imsi_bcd); + + pkbuf = sgsap_build_paging_reject( + &mme_ue->nas_mobile_identity_imsi, + SGSAP_IE_IMSI_LEN, sgs_cause); + ogs_expect_or_return_val(pkbuf, OGS_ERROR); + rv = sgsap_send_to_vlr(mme_ue, pkbuf); + ogs_expect(rv == OGS_OK); + + return rv; +} + int sgsap_send_service_request(mme_ue_t *mme_ue, uint8_t emm_mode) { int rv; diff --git a/src/mme/sgsap-path.h b/src/mme/sgsap-path.h index a1a9b35be..0c22996a8 100644 --- a/src/mme/sgsap-path.h +++ b/src/mme/sgsap-path.h @@ -47,6 +47,7 @@ int sgsap_send_location_update_request(mme_ue_t *mme_ue); int sgsap_send_tmsi_reallocation_complete(mme_ue_t *mme_ue); int sgsap_send_detach_indication(mme_ue_t *mme_ue); int sgsap_send_mo_csfb_indication(mme_ue_t *mme_ue); +int sgsap_send_paging_reject(mme_ue_t *mme_ue, uint8_t sgs_cause); int sgsap_send_service_request(mme_ue_t *mme_ue, uint8_t emm_mode); int sgsap_send_reset_ack(mme_vlr_t *vlr); int sgsap_send_uplink_unitdata(mme_ue_t *mme_ue,