[ALL] Fix the memory leak (#1282)

This commit is contained in:
Sukchan Lee 2022-01-31 22:58:52 +09:00
parent 340b23af94
commit 83d56fe40d
9 changed files with 94 additions and 15 deletions

View File

@ -92,6 +92,7 @@ typedef struct ogs_gtp_xact_s {
#define OGS_GTP_DELETE_SEND_DEACTIVATE_BEARER_CONTEXT_REQUEST 3
#define OGS_GTP_DELETE_SEND_UE_CONTEXT_RELEASE_COMMAND 4
#define OGS_GTP_DELETE_HANDLE_PDN_CONNECTIVITY_REQUEST 5
#define OGS_GTP_DELETE_UE_CONTEXT_REMOVE 6
int delete_action;
#define OGS_GTP_RELEASE_SEND_UE_CONTEXT_RELEASE_COMMAND 1

View File

@ -1210,6 +1210,10 @@ void ogs_pfcp_far_remove(ogs_pfcp_far_t *far)
ogs_list_remove(&sess->far_list, far);
if (far->hash.teid.len)
ogs_hash_set(self.far_teid_hash,
&far->hash.teid.key, far->hash.teid.len, NULL);
if (far->hash.f_teid.len)
ogs_hash_set(self.far_f_teid_hash,
&far->hash.f_teid.key, far->hash.f_teid.len, NULL);

View File

@ -924,6 +924,8 @@ int amf_gnb_set_gnb_id(amf_gnb_t *gnb, uint32_t gnb_id)
{
ogs_assert(gnb);
ogs_hash_set(self.gnb_id_hash, &gnb_id, sizeof(gnb_id), NULL);
gnb->gnb_id = gnb_id;
ogs_hash_set(self.gnb_id_hash, &gnb->gnb_id, sizeof(gnb->gnb_id), gnb);
@ -1508,6 +1510,7 @@ void amf_ue_set_suci(amf_ue_t *amf_ue,
ogs_nas_5gs_mobile_identity_t *mobile_identity)
{
amf_ue_t *old_amf_ue = NULL;
amf_sess_t *old_sess = NULL;
char *suci = NULL;
ogs_assert(amf_ue);
@ -1531,6 +1534,31 @@ void amf_ue_set_suci(amf_ue_t *amf_ue,
(long long)old_amf_ue->ran_ue->amf_ue_ngap_id);
ran_ue_remove(old_amf_ue->ran_ue);
}
/*
* We should delete the AMF-Session Context in the AMF-UE Context.
* Otherwise, all unnecessary SESSIONs remain in SMF/UPF.
*
* In order to do this, AMF-Session Context should be moved
* from OLD AMF-UE Context to NEW AMF-UE Context.
*
* If needed, The Session deletion process in NEW-AMF UE context will work.
*
* Note that we should not send Session-Release to the SMF at this point.
* Another SBI Transaction can cause fatal errors.
*/
/* Phase-1 : Change AMF-UE Context in Session Context */
ogs_list_for_each(&old_amf_ue->sess_list, old_sess)
old_sess->amf_ue = amf_ue;
/* Phase-2 : Move Session Context from OLD to NEW AMF-UE Context */
memcpy(&amf_ue->sess_list,
&old_amf_ue->sess_list, sizeof(amf_ue->sess_list));
/* Phase-3 : Clear Session Context in OLD AMF-UE Context */
memset(&old_amf_ue->sess_list, 0, sizeof(old_amf_ue->sess_list));
amf_ue_remove(old_amf_ue);
}
}

View File

@ -413,7 +413,7 @@ int gmm_handle_registration_update(amf_ue_t *amf_ue,
if ((psimask & (1 << sess->psi)) == 0) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_release_session(
sess, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT);
sess, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT);
}
}
}
@ -622,7 +622,7 @@ int gmm_handle_service_update(amf_ue_t *amf_ue,
if ((psimask & (1 << sess->psi)) == 0) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_release_session(
sess, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT);
sess, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT);
}
}
}
@ -694,7 +694,8 @@ int gmm_handle_deregistration_request(amf_ue_t *amf_ue,
ogs_info("[%s] SUCI", amf_ue->suci);
amf_sbi_send_release_all_sessions(amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (ogs_list_count(&amf_ue->sess_list) == 0)
ogs_assert(OGS_OK ==

View File

@ -261,7 +261,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e)
}
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (amf_sess_xact_count(amf_ue) == xact_count) {
ogs_assert(true ==
amf_ue_sbi_discover_and_send(
@ -1135,7 +1135,7 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e)
}
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (amf_sess_xact_count(amf_ue) == xact_count) {
ogs_assert(true ==
amf_ue_sbi_discover_and_send(

View File

@ -26,6 +26,7 @@
#include "s1ap-path.h"
#include "s1ap-handler.h"
#include "mme-sm.h"
#include "mme-gtp-path.h"
#define MAX_CELL_PER_ENB 8
@ -1870,6 +1871,8 @@ int mme_enb_set_enb_id(mme_enb_t *enb, uint32_t enb_id)
{
ogs_assert(enb);
ogs_hash_set(self.enb_id_hash, &enb_id, sizeof(enb_id), NULL);
enb->enb_id = enb_id;
ogs_hash_set(self.enb_id_hash, &enb->enb_id, sizeof(enb->enb_id), enb);
@ -2151,6 +2154,19 @@ 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);
@ -2159,17 +2175,12 @@ void mme_ue_remove(mme_ue_t *mme_ue)
mme_ue_fsm_fini(mme_ue);
if (mme_ue->current.m_tmsi) {
ogs_hash_set(self.guti_ue_hash,
&mme_ue->current.guti, sizeof(ogs_nas_eps_guti_t), NULL);
if (mme_ue->current.m_tmsi)
ogs_assert(mme_m_tmsi_free(mme_ue->current.m_tmsi) == OGS_OK);
}
if (mme_ue->next.m_tmsi) {
if (mme_ue->next.m_tmsi)
ogs_assert(mme_m_tmsi_free(mme_ue->next.m_tmsi) == OGS_OK);
}
if (mme_ue->imsi_len != 0)
ogs_hash_set(self.imsi_ue_hash, mme_ue->imsi, mme_ue->imsi_len, NULL);
/* Clear the saved PDN Connectivity Request */
OGS_NAS_CLEAR_DATA(&mme_ue->pdn_connectivity_request);
@ -2212,6 +2223,7 @@ 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);
}
}
@ -2463,10 +2475,34 @@ int mme_ue_set_imsi(mme_ue_t *mme_ue, char *imsi_bcd)
old_mme_ue->enb_ue->mme_ue_s1ap_id);
enb_ue_remove(old_mme_ue->enb_ue);
}
mme_ue_remove(old_mme_ue);
/*
* We should delete the MME-Session Context in the MME-UE Context.
* Otherwise, all unnecessary SESSIONs remain in SMF/SGW-C/SGW-U/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.
*
* 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.
*/
mme_ue_hash_remove(old_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);
}
}
}
if (mme_ue->imsi_len != 0)
ogs_hash_set(mme_self()->imsi_ue_hash,
mme_ue->imsi, mme_ue->imsi_len, NULL);
ogs_hash_set(self.imsi_ue_hash, mme_ue->imsi, mme_ue->imsi_len, mme_ue);
return OGS_OK;

View File

@ -704,6 +704,7 @@ 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);

View File

@ -406,6 +406,12 @@ void mme_s11_handle_delete_session_response(
}
}
} else if (action == OGS_GTP_DELETE_UE_CONTEXT_REMOVE) {
/* Remove MME-UE Context with Session Context since IMSI duplicated */
mme_ue_remove(mme_ue);
return;
} else {
ogs_fatal("Invalid action = %d", action);
ogs_assert_if_reached();

View File

@ -1477,6 +1477,8 @@ void s1ap_handle_ue_context_release_action(enb_ue_t *enb_ue)
ogs_debug(" Action: UE context remove");
enb_ue_remove(enb_ue);
ogs_expect_or_return(mme_ue);
mme_ue_hash_remove(mme_ue);
mme_ue_remove(mme_ue);
break;
case S1AP_UE_CTX_REL_S1_HANDOVER_COMPLETE: