diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 281e9f9ad..2b65f257c 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -47,6 +47,7 @@ static OGS_POOL(mme_csmap_pool, mme_csmap_t); static OGS_POOL(mme_enb_pool, mme_enb_t); static OGS_POOL(mme_ue_pool, mme_ue_t); static OGS_POOL(mme_s11_teid_pool, ogs_pool_id_t); +static OGS_POOL(mme_gn_teid_pool, ogs_pool_id_t); static OGS_POOL(enb_ue_pool, enb_ue_t); static OGS_POOL(sgw_ue_pool, sgw_ue_t); static OGS_POOL(mme_sess_pool, mme_sess_t); @@ -110,6 +111,8 @@ void mme_context_init(void) ogs_pool_init(&mme_ue_pool, ogs_global_conf()->max.ue); ogs_pool_init(&mme_s11_teid_pool, ogs_global_conf()->max.ue); ogs_pool_random_id_generate(&mme_s11_teid_pool); + ogs_pool_init(&mme_gn_teid_pool, ogs_global_conf()->max.ue); + ogs_pool_random_id_generate(&mme_gn_teid_pool); ogs_pool_init(&enb_ue_pool, ogs_global_conf()->max.ue); ogs_pool_init(&sgw_ue_pool, ogs_global_conf()->max.ue); @@ -128,6 +131,8 @@ void mme_context_init(void) ogs_assert(self.guti_ue_hash); self.mme_s11_teid_hash = ogs_hash_make(); ogs_assert(self.mme_s11_teid_hash); + self.mme_gn_teid_hash = ogs_hash_make(); + ogs_assert(self.mme_gn_teid_hash); ogs_list_init(&self.mme_ue_list); @@ -158,12 +163,15 @@ void mme_context_final(void) ogs_hash_destroy(self.guti_ue_hash); ogs_assert(self.mme_s11_teid_hash); ogs_hash_destroy(self.mme_s11_teid_hash); + ogs_assert(self.mme_gn_teid_hash); + ogs_hash_destroy(self.mme_gn_teid_hash); ogs_pool_final(&m_tmsi_pool); ogs_pool_final(&mme_bearer_pool); ogs_pool_final(&mme_sess_pool); ogs_pool_final(&mme_ue_pool); ogs_pool_final(&mme_s11_teid_pool); + ogs_pool_final(&mme_gn_teid_pool); ogs_pool_final(&enb_ue_pool); ogs_pool_final(&sgw_ue_pool); @@ -3301,15 +3309,20 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue) ogs_list_init(&mme_ue->sess_list); - /* Set MME-S11_TEID */ + /* Set MME-S11-TEID */ ogs_pool_alloc(&mme_s11_teid_pool, &mme_ue->mme_s11_teid_node); ogs_assert(mme_ue->mme_s11_teid_node); - mme_ue->mme_s11_teid = *(mme_ue->mme_s11_teid_node); - ogs_hash_set(self.mme_s11_teid_hash, &mme_ue->mme_s11_teid, sizeof(mme_ue->mme_s11_teid), mme_ue); + /* Set MME-Gn-TEID */ + ogs_pool_alloc(&mme_gn_teid_pool, &mme_ue->gn.mme_gn_teid_node); + ogs_assert(mme_ue->gn.mme_gn_teid_node); + mme_ue->gn.mme_gn_teid = *(mme_ue->gn.mme_gn_teid_node); + ogs_hash_set(self.mme_gn_teid_hash, + &mme_ue->gn.mme_gn_teid, sizeof(mme_ue->gn.mme_gn_teid), mme_ue); + /* * When used for the first time, if last node is set, * the search is performed from the first SGW in a round-robin manner. @@ -3353,6 +3366,8 @@ void mme_ue_remove(mme_ue_t *mme_ue) ogs_hash_set(self.mme_s11_teid_hash, &mme_ue->mme_s11_teid, sizeof(mme_ue->mme_s11_teid), NULL); + ogs_hash_set(self.mme_gn_teid_hash, + &mme_ue->gn.mme_gn_teid, sizeof(mme_ue->gn.mme_gn_teid), NULL); ogs_assert(mme_ue->sgw_ue); sgw_ue_remove(mme_ue->sgw_ue); @@ -3400,6 +3415,7 @@ void mme_ue_remove(mme_ue_t *mme_ue) mme_ebi_pool_final(mme_ue); ogs_pool_free(&mme_s11_teid_pool, mme_ue->mme_s11_teid_node); + ogs_pool_free(&mme_gn_teid_pool, mme_ue->gn.mme_gn_teid_node); ogs_pool_free(&mme_ue_pool, mme_ue); ogs_info("[Removed] Number of MME-UEs is now %d", @@ -3473,11 +3489,16 @@ mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *guti) self.guti_ue_hash, guti, sizeof(ogs_nas_eps_guti_t)); } -mme_ue_t *mme_ue_find_by_teid(uint32_t teid) +mme_ue_t *mme_ue_find_by_s11_local_teid(uint32_t teid) { return ogs_hash_get(self.mme_s11_teid_hash, &teid, sizeof(teid)); } +mme_ue_t *mme_ue_find_by_gn_local_teid(uint32_t teid) +{ + return ogs_hash_get(self.mme_gn_teid_hash, &teid, sizeof(teid)); +} + mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message) { mme_ue_t *mme_ue = NULL; diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 749a48c5e..7efddfe35 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -192,6 +192,7 @@ typedef struct mme_context_s { ogs_hash_t *guti_ue_hash; /* hash table (GUTI : MME_UE) */ ogs_hash_t *mme_s11_teid_hash; /* hash table (MME-S11-TEID : MME_UE) */ + ogs_hash_t *mme_gn_teid_hash; /* hash table (MME-GN-TEID : MME_UE) */ struct { struct { @@ -421,6 +422,10 @@ struct mme_ue_s { char a_msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1]; mme_p_tmsi_t p_tmsi; + struct { + ogs_pool_id_t *mme_gn_teid_node; /* A node of MME-Gn-TEID */ + uint32_t mme_gn_teid; /* MME-Gn-TEID is derived from NODE */ + } gn; struct { mme_m_tmsi_t *m_tmsi; @@ -943,7 +948,8 @@ void mme_ue_fsm_fini(mme_ue_t *mme_ue); mme_ue_t *mme_ue_find_by_imsi(uint8_t *imsi, int imsi_len); mme_ue_t *mme_ue_find_by_imsi_bcd(char *imsi_bcd); mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *nas_guti); -mme_ue_t *mme_ue_find_by_teid(uint32_t teid); +mme_ue_t *mme_ue_find_by_s11_local_teid(uint32_t teid); +mme_ue_t *mme_ue_find_by_gn_local_teid(uint32_t teid); 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); diff --git a/src/mme/mme-gtp-path.c b/src/mme/mme-gtp-path.c index cce8a714e..423d9829e 100644 --- a/src/mme/mme-gtp-path.c +++ b/src/mme/mme-gtp-path.c @@ -268,7 +268,7 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action) return OGS_ERROR; } xact->create_action = create_action; - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -307,7 +307,7 @@ int mme_gtp_send_modify_bearer_request( return OGS_ERROR; } xact->modify_action = modify_action; - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -346,7 +346,7 @@ int mme_gtp_send_delete_session_request( return OGS_ERROR; } xact->delete_action = action; - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -537,7 +537,7 @@ int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue, int action) return OGS_ERROR; } xact->release_action = action; - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -670,7 +670,7 @@ int mme_gtp_send_create_indirect_data_forwarding_tunnel_request( ogs_error("ogs_gtp_xact_local_create() failed"); return OGS_ERROR; } - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -709,7 +709,7 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request( return OGS_ERROR; } xact->delete_indirect_action = action; - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); @@ -750,7 +750,7 @@ int mme_gtp_send_bearer_resource_command( return OGS_ERROR; } xact->xid |= OGS_GTP_CMD_XACT_ID; - xact->local_teid = mme_ue->mme_s11_teid; + xact->local_teid = mme_ue->gn.mme_gn_teid; rv = ogs_gtp_xact_commit(xact); ogs_expect(rv == OGS_OK); diff --git a/src/mme/mme-sm.c b/src/mme/mme-sm.c index 1a437a5d5..de43aeb97 100644 --- a/src/mme/mme-sm.c +++ b/src/mme/mme-sm.c @@ -528,14 +528,14 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) */ if (gtp_message.h.teid_presence && gtp_message.h.teid != 0) { /* Cause is not "Context not found" */ - mme_ue = mme_ue_find_by_teid(gtp_message.h.teid); + mme_ue = mme_ue_find_by_s11_local_teid(gtp_message.h.teid); } else if (xact->local_teid) { /* rx no TEID or TEID=0 */ /* 3GPP TS 29.274 5.5.2: we receive TEID=0 under some * conditions, such as cause "Session context not found". In those * cases, we still want to identify the local session which * originated the message, so try harder by using the TEID we * locally stored in xact when sending the original request: */ - mme_ue = mme_ue_find_by_teid(xact->local_teid); + mme_ue = mme_ue_find_by_s11_local_teid(xact->local_teid); } switch (gtp_message.h.type) { @@ -655,6 +655,15 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e) break; } + if (gtp1_message.h.teid != 0) { + /* Cause is not "Context not found" */ + mme_ue = mme_ue_find_by_gn_local_teid(gtp1_message.h.teid); + } else if (xact->local_teid) { /* rx no TEID or TEID=0 */ + /* Try harder by using the TEID we locally stored in xact when + *sending the original request: */ + mme_ue = mme_ue_find_by_gn_local_teid(xact->local_teid); + } + switch (gtp1_message.h.type) { case OGS_GTP1_ECHO_REQUEST_TYPE: mme_gn_handle_echo_request(xact, >p1_message.echo_request);