From b4358fe70308a7cd146837bed8b4c529b207cc4d Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Fri, 8 Jan 2021 15:09:02 -0500 Subject: [PATCH] fix: Add dedicated bearer activation reject (#755) --- src/mme/esm-sm.c | 39 +++++++++++++++++++++++++++++++++++---- src/sgwc/context.c | 10 ++++++++++ src/sgwc/context.h | 2 ++ src/sgwc/s11-handler.c | 5 +++++ src/sgwc/s5c-handler.c | 4 ++++ src/sgwc/sxa-handler.c | 9 +++++++++ src/smf/binding.c | 8 ++++++++ src/smf/context.c | 30 ++++++++++++++++++++---------- src/smf/context.h | 8 +++++--- tests/common/esm-build.c | 34 ++++++++++++++++++++++++++++++++++ tests/common/esm-build.h | 2 ++ 11 files changed, 134 insertions(+), 17 deletions(-) diff --git a/src/mme/esm-sm.c b/src/mme/esm-sm.c index ed99d9f46..8138f4261 100644 --- a/src/mme/esm-sm.c +++ b/src/mme/esm-sm.c @@ -32,6 +32,24 @@ #undef OGS_LOG_DOMAIN #define OGS_LOG_DOMAIN __esm_log_domain +static uint8_t gtp_cause_from_esm(uint8_t esm_cause) +{ + switch (esm_cause) { + case ESM_CAUSE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION: + return OGS_GTP_CAUSE_SEMANTIC_ERROR_IN_THE_TFT_OPERATION; + case ESM_CAUSE_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION: + return OGS_GTP_CAUSE_SYNTACTIC_ERROR_IN_THE_TFT_OPERATION; + case ESM_CAUSE_SYNTACTICAL_ERROR_IN_PACKET_FILTERS: + return OGS_GTP_CAUSE_SYNTACTIC_ERRORS_IN_PACKET_FILTER; + case ESM_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTERS: + return OGS_GTP_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER; + default: + return OGS_GTP_CAUSE_SYSTEM_FAILURE; + } + + return OGS_GTP_CAUSE_SYSTEM_FAILURE; +} + void esm_state_initial(ogs_fsm_t *s, mme_event_t *e) { ogs_assert(s); @@ -57,6 +75,9 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) ogs_nas_eps_message_t *message = NULL; ogs_nas_security_header_type_t h; + ogs_nas_eps_activate_dedicated_eps_bearer_context_reject_t + *activate_dedicated_eps_bearer_context_reject = NULL; + ogs_assert(s); ogs_assert(e); @@ -145,8 +166,7 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) } break; case OGS_NAS_EPS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT: - ogs_debug("Activate default EPS bearer " - "context accept"); + ogs_debug("Activate default EPS bearer context accept"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", mme_ue->imsi_bcd, sess->pti, bearer->ebi); /* Check if Initial Context Setup Response or @@ -159,8 +179,7 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) OGS_FSM_TRAN(s, esm_state_active); break; case OGS_NAS_EPS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT: - ogs_debug("Activate dedicated EPS bearer " - "context accept"); + ogs_debug("Activate dedicated EPS bearer context accept"); ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]", mme_ue->imsi_bcd, sess->pti, bearer->ebi); /* Check if Initial Context Setup Response or @@ -172,6 +191,18 @@ void esm_state_inactive(ogs_fsm_t *s, mme_event_t *e) OGS_FSM_TRAN(s, esm_state_active); break; + case OGS_NAS_EPS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT: + ogs_error("Activate dedicated EPS bearer context reject"); + ogs_error(" IMSI[%s] PTI[%d] EBI[%d]", + mme_ue->imsi_bcd, sess->pti, bearer->ebi); + activate_dedicated_eps_bearer_context_reject = + &message->esm.activate_dedicated_eps_bearer_context_reject; + ogs_assert(activate_dedicated_eps_bearer_context_reject); + mme_gtp_send_create_bearer_response(bearer, + gtp_cause_from_esm( + activate_dedicated_eps_bearer_context_reject->esm_cause)); + OGS_FSM_TRAN(s, esm_state_bearer_deactivated); + break; default: ogs_error("Unknown message(type:%d)", message->esm.h.message_type); break; diff --git a/src/sgwc/context.c b/src/sgwc/context.c index 605c6b6c1..8374c4941 100644 --- a/src/sgwc/context.c +++ b/src/sgwc/context.c @@ -599,6 +599,11 @@ sgwc_sess_t *sgwc_sess_find_by_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi) return NULL; } +sgwc_sess_t *sgwc_sess_cycle(sgwc_sess_t *sess) +{ + return ogs_pool_cycle(&sgwc_sess_pool, sess); +} + sgwc_bearer_t *sgwc_bearer_add(sgwc_sess_t *sess) { sgwc_bearer_t *bearer = NULL; @@ -749,6 +754,11 @@ sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess) return ogs_list_first(&sess->bearer_list); } +sgwc_bearer_t *sgwc_bearer_cycle(sgwc_bearer_t *bearer) +{ + return ogs_pool_cycle(&sgwc_bearer_pool, bearer); +} + sgwc_tunnel_t *sgwc_tunnel_add( sgwc_bearer_t *bearer, uint8_t interface_type) { diff --git a/src/sgwc/context.h b/src/sgwc/context.h index a29b04fc8..ea8e0f8cd 100644 --- a/src/sgwc/context.h +++ b/src/sgwc/context.h @@ -175,6 +175,7 @@ sgwc_sess_t *sgwc_sess_find_by_seid(uint64_t seid); sgwc_sess_t *sgwc_sess_find_by_apn(sgwc_ue_t *sgwc_ue, char *apn); sgwc_sess_t *sgwc_sess_find_by_ebi(sgwc_ue_t *sgwc_ue, uint8_t ebi); +sgwc_sess_t *sgwc_sess_cycle(sgwc_sess_t *sess); sgwc_bearer_t *sgwc_bearer_add(sgwc_sess_t *sess); int sgwc_bearer_remove(sgwc_bearer_t *bearer); @@ -187,6 +188,7 @@ sgwc_bearer_t *sgwc_bearer_find_by_error_indication_report( sgwc_sess_t *sess, ogs_pfcp_tlv_error_indication_report_t *error_indication_report); sgwc_bearer_t *sgwc_default_bearer_in_sess(sgwc_sess_t *sess); +sgwc_bearer_t *sgwc_bearer_cycle(sgwc_bearer_t *bearer); sgwc_tunnel_t *sgwc_tunnel_add( sgwc_bearer_t *bearer, uint8_t interface_type); diff --git a/src/sgwc/s11-handler.c b/src/sgwc/s11-handler.c index 52ba6fbb7..0c56f608f 100644 --- a/src/sgwc/s11-handler.c +++ b/src/sgwc/s11-handler.c @@ -38,6 +38,11 @@ static void sess_timeout(ogs_gtp_xact_t *xact, void *data) switch (type) { case OGS_GTP_DELETE_SESSION_REQUEST_TYPE: ogs_error("[%s] No Delete Session Response", sgwc_ue->imsi_bcd); + if (!sgwc_sess_cycle(sess)) { + ogs_warn("[%s] Session has already been removed", + sgwc_ue->imsi_bcd); + break; + } sgwc_pfcp_send_session_deletion_request(sess, NULL, NULL); break; default: diff --git a/src/sgwc/s5c-handler.c b/src/sgwc/s5c-handler.c index 135dda9f9..131efd758 100644 --- a/src/sgwc/s5c-handler.c +++ b/src/sgwc/s5c-handler.c @@ -44,6 +44,10 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) break; case OGS_GTP_DELETE_BEARER_REQUEST_TYPE: ogs_error("[%s] No Delete Bearer Response", sgwc_ue->imsi_bcd); + if (!sgwc_bearer_cycle(bearer)) { + ogs_warn("[%s] Bearer has already been removed", sgwc_ue->imsi_bcd); + break; + } sgwc_pfcp_send_bearer_modification_request( bearer, NULL, NULL, OGS_PFCP_MODIFY_REMOVE); break; diff --git a/src/sgwc/sxa-handler.c b/src/sgwc/sxa-handler.c index e744b9fd9..8a53375e9 100644 --- a/src/sgwc/sxa-handler.c +++ b/src/sgwc/sxa-handler.c @@ -76,6 +76,11 @@ static void sess_timeout(ogs_gtp_xact_t *xact, void *data) switch (type) { case OGS_GTP_CREATE_SESSION_REQUEST_TYPE: ogs_error("[%s] No Create Session Response", sgwc_ue->imsi_bcd); + if (!sgwc_sess_cycle(sess)) { + ogs_warn("[%s] Session has already been removed", + sgwc_ue->imsi_bcd); + break; + } sgwc_pfcp_send_session_deletion_request(sess, NULL, NULL); break; default: @@ -103,6 +108,10 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) switch (type) { case OGS_GTP_CREATE_BEARER_REQUEST_TYPE: ogs_error("[%s] No Create Bearer Response", sgwc_ue->imsi_bcd); + if (!sgwc_bearer_cycle(bearer)) { + ogs_warn("[%s] Bearer has already been removed", sgwc_ue->imsi_bcd); + break; + } sgwc_pfcp_send_bearer_modification_request( bearer, NULL, NULL, OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE); diff --git a/src/smf/binding.c b/src/smf/binding.c index e6761bb80..1b55e1eda 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -41,6 +41,10 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) switch (type) { case OGS_GTP_CREATE_BEARER_REQUEST_TYPE: ogs_error("[%s] No Create Bearer Response", smf_ue->imsi_bcd); + if (!smf_bearer_cycle(bearer)) { + ogs_warn("[%s] Bearer has already been removed", smf_ue->imsi_bcd); + break; + } smf_epc_pfcp_send_bearer_modification_request( bearer, OGS_PFCP_MODIFY_REMOVE); break; @@ -49,6 +53,10 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) break; case OGS_GTP_DELETE_BEARER_REQUEST_TYPE: ogs_error("[%s] No Delete Bearer Response", smf_ue->imsi_bcd); + if (!smf_bearer_cycle(bearer)) { + ogs_warn("[%s] Bearer has already been removed", smf_ue->imsi_bcd); + break; + } smf_epc_pfcp_send_bearer_modification_request( bearer, OGS_PFCP_MODIFY_REMOVE); break; diff --git a/src/smf/context.c b/src/smf/context.c index 95c3a7b12..a80f193b7 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1171,16 +1171,6 @@ smf_sess_t *smf_sess_find_by_ipv6(uint32_t *addr6) return (smf_sess_t *)ogs_hash_get(self.ipv6_hash, addr6, OGS_IPV6_LEN); } -smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue) -{ - return ogs_pool_cycle(&smf_ue_pool, smf_ue); -} - -smf_sess_t *smf_sess_cycle(smf_sess_t *sess) -{ - return ogs_pool_cycle(&smf_sess_pool, sess); -} - smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess) { smf_bearer_t *qos_flow = NULL; @@ -1610,6 +1600,26 @@ smf_bearer_t *smf_bearer_next(smf_bearer_t *bearer) return ogs_list_next(bearer); } +smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue) +{ + return ogs_pool_cycle(&smf_ue_pool, smf_ue); +} + +smf_sess_t *smf_sess_cycle(smf_sess_t *sess) +{ + return ogs_pool_cycle(&smf_sess_pool, sess); +} + +smf_bearer_t *smf_bearer_cycle(smf_bearer_t *bearer) +{ + return ogs_pool_cycle(&smf_bearer_pool, bearer); +} + +smf_bearer_t *smf_qos_flow_cycle(smf_bearer_t *qos_flow) +{ + return ogs_pool_cycle(&smf_bearer_pool, qos_flow); +} + smf_pf_t *smf_pf_add(smf_bearer_t *bearer) { smf_pf_t *pf = NULL; diff --git a/src/smf/context.h b/src/smf/context.h index 349884d45..6a6e90f01 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -332,9 +332,6 @@ smf_sess_t *smf_sess_find_by_sm_context_ref(char *sm_context_ref); smf_sess_t *smf_sess_find_by_ipv4(uint32_t addr); smf_sess_t *smf_sess_find_by_ipv6(uint32_t *addr6); -smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue); -smf_sess_t *smf_sess_cycle(smf_sess_t *sess); - smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess); smf_bearer_t *smf_qos_flow_find_by_qfi(smf_sess_t *sess, uint8_t qfi); smf_bearer_t *smf_qos_flow_find_by_pcc_rule_id( @@ -361,6 +358,11 @@ bool smf_bearer_is_default(smf_bearer_t *bearer); smf_bearer_t *smf_bearer_first(smf_sess_t *sess); smf_bearer_t *smf_bearer_next(smf_bearer_t *bearer); +smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue); +smf_sess_t *smf_sess_cycle(smf_sess_t *sess); +smf_bearer_t *smf_qos_flow_cycle(smf_bearer_t *qos_flow); +smf_bearer_t *smf_bearer_cycle(smf_bearer_t *bearer); + smf_pf_t *smf_pf_add(smf_bearer_t *bearer); int smf_pf_remove(smf_pf_t *pf); void smf_pf_remove_all(smf_bearer_t *bearer); diff --git a/tests/common/esm-build.c b/tests/common/esm-build.c index 45b8f432d..7e74ca89a 100644 --- a/tests/common/esm-build.c +++ b/tests/common/esm-build.c @@ -256,6 +256,40 @@ ogs_pkbuf_t *testesm_build_activate_dedicated_eps_bearer_context_accept( return test_nas_eps_security_encode(test_ue, &message); } +ogs_pkbuf_t *testesm_build_activate_dedicated_eps_bearer_context_reject( + test_bearer_t *bearer, uint8_t esm_cause) +{ + ogs_nas_eps_message_t message; + ogs_nas_eps_activate_dedicated_eps_bearer_context_reject_t + *activate_dedicated_eps_bearer_context_reject = + &message.esm.activate_dedicated_eps_bearer_context_reject; + + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + ogs_pkbuf_t *pkbuf = NULL; + + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + test_ue = sess->test_ue; + ogs_assert(test_ue); + + memset(&message, 0, sizeof(message)); + + message.h.security_header_type = + OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED; + message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM; + + message.esm.h.eps_bearer_identity = bearer->ebi; + message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM; + message.esm.h.message_type = + OGS_NAS_EPS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT; + + activate_dedicated_eps_bearer_context_reject->esm_cause = esm_cause; + + return test_nas_eps_security_encode(test_ue, &message); +} + ogs_pkbuf_t *testesm_build_modify_eps_bearer_context_accept( test_bearer_t *bearer) { diff --git a/tests/common/esm-build.h b/tests/common/esm-build.h index 2b27e6567..eecd35946 100644 --- a/tests/common/esm-build.h +++ b/tests/common/esm-build.h @@ -31,6 +31,8 @@ ogs_pkbuf_t *testesm_build_activate_default_eps_bearer_context_accept( test_bearer_t *bearer, bool integrity_protected_and_ciphered); ogs_pkbuf_t *testesm_build_activate_dedicated_eps_bearer_context_accept( test_bearer_t *bearer); +ogs_pkbuf_t *testesm_build_activate_dedicated_eps_bearer_context_reject( + test_bearer_t *bearer, uint8_t esm_cause); ogs_pkbuf_t *testesm_build_modify_eps_bearer_context_accept( test_bearer_t *bearer); ogs_pkbuf_t *testesm_build_deactivate_eps_bearer_context_accept(