From be84ee854a1476c73592b18ffc51ab22e7924092 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 14 Mar 2018 11:14:44 +0000 Subject: [PATCH] Changing the way that ECM context is stored to keep uplink teids active when the context is release. --- srsepc/hdr/mme/s1ap.h | 32 +- srsepc/hdr/mme/s1ap_common.h | 6 +- srsepc/hdr/mme/s1ap_nas_transport.h | 16 +- srsepc/src/mme/mme_gtpc.cc | 13 +- srsepc/src/mme/s1ap.cc | 339 +++++++++++++++----- srsepc/src/mme/s1ap_ctx_mngmt_proc.cc | 50 +-- srsepc/src/mme/s1ap_nas_transport.cc | 426 ++++++++++++-------------- 7 files changed, 516 insertions(+), 366 deletions(-) diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 311a65784..52d435fbd 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -66,7 +66,7 @@ public: int get_s1_mme(); void delete_enb_ctx(int32_t assoc_id); - void delete_ues_in_enb(uint16_t enb_id); + void release_ues_ecm_ctx_in_enb(uint16_t enb_id); bool handle_s1ap_rx_pdu(srslte::byte_buffer_t *pdu, struct sctp_sndrcvinfo *enb_sri); bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); @@ -81,16 +81,20 @@ public: enb_ctx_t* find_enb_ctx(uint16_t enb_id); void add_new_enb_ctx(const enb_ctx_t &enb_ctx, const struct sctp_sndrcvinfo* enb_sri); - ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id); void add_new_ue_ctx(const ue_ctx_t &ue_ctx); + ue_ctx_t* find_ue_ctx_from_imsi(uint64_t imsi); + ue_ctx_t* find_ue_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); - void add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx); - void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx); - ue_emm_ctx_t* find_ue_emm_ctx_from_imsi(uint64_t imsi); - ue_ecm_ctx_t* find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); - bool delete_ue_emm_ctx(uint64_t imsi); - bool delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id); - void delete_ues_ecm_ctx_in_enb(uint16_t enb_id); + //ue_ctx_t* find_ue_ctx(uint32_t mme_ue_s1ap_id); + //void add_new_ue_ctx(const ue_ctx_t &ue_ctx); + + //void add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx); + //void add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx); + //ue_emm_ctx_t* find_ue_emm_ctx_from_imsi(uint64_t imsi); + //ue_ecm_ctx_t* find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id); + //bool delete_ue_emm_ctx(uint64_t imsi); + //bool delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id); + //void delete_ues_ecm_ctx_in_enb(uint16_t enb_id); void store_tmp_ue_emm_ctx(const ue_emm_ctx_t &ue_ecm_ctx); bool get_tmp_ue_emm_ctx(uint32_t mme_ue_s1ap_id, ue_emm_ctx_t* ue_emm_ptr); @@ -122,9 +126,13 @@ private: std::map m_sctp_to_enb_id; std::map > m_enb_id_to_ue_ids; - std::map m_imsi_to_ue_emm_ctx; - std::map m_mme_ue_s1ap_id_to_ue_ecm_ctx; - std::map m_mme_ue_s1ap_id_to_tmp_ue_emm_ctx; + + std::map m_imsi_to_ue_ctx; + std::map m_mme_ue_s1ap_id_to_ue_ctx; + + //std::map m_imsi_to_ue_emm_ctx; + //std::map m_mme_ue_s1ap_id_to_ue_ecm_ctx; + //std::map m_mme_ue_s1ap_id_to_tmp_ue_emm_ctx; uint32_t m_next_mme_ue_s1ap_id; uint32_t m_next_m_tmsi; diff --git a/srsepc/hdr/mme/s1ap_common.h b/srsepc/hdr/mme/s1ap_common.h index 5bb60e5a6..adb9f68e0 100644 --- a/srsepc/hdr/mme/s1ap_common.h +++ b/srsepc/hdr/mme/s1ap_common.h @@ -122,7 +122,7 @@ typedef struct{ LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT ue_network_cap; bool ms_network_cap_present; LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT ms_network_cap; -} eps_security_ctx_t; +} eps_sec_ctx_t; typedef struct{ enum erab_state state; @@ -135,7 +135,7 @@ typedef struct{ typedef struct{ uint64_t imsi; LIBLTE_MME_EPS_MOBILE_ID_GUTI_STRUCT guti; - eps_security_ctx_t security_ctxt; + eps_sec_ctx_t security_ctxt; uint8_t procedure_transaction_id; emm_state_t state; uint32_t mme_ue_s1ap_id; @@ -156,7 +156,9 @@ typedef struct{ typedef struct{ ue_emm_ctx_t emm_ctx; + eps_sec_ctx_t sec_ctx; ue_ecm_ctx_t ecm_ctx; + erab_ctx_t erabs_ctx[MAX_ERABS_PER_UE]; } ue_ctx_t; }//namespace #endif diff --git a/srsepc/hdr/mme/s1ap_nas_transport.h b/srsepc/hdr/mme/s1ap_nas_transport.h index b107eb010..7ce83f363 100644 --- a/srsepc/hdr/mme/s1ap_nas_transport.h +++ b/srsepc/hdr/mme/s1ap_nas_transport.h @@ -72,14 +72,14 @@ public: srslte::byte_buffer_t *reply_buffer, bool* reply_flag, struct sctp_sndrcvinfo *enb_sri); - bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag); - bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); - bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); - bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); - bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); - bool handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); + bool handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag); + bool handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); + bool handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); + bool handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag); - bool handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); + bool handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag); bool integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu); bool short_integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t *pdu); @@ -94,7 +94,7 @@ public: bool pack_attach_accept(ue_emm_ctx_t *ue_emm_ctx, ue_ecm_ctx_t *ue_ecm_ctx, LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt, struct srslte::gtpc_pdn_address_allocation_ie *paa, srslte::byte_buffer_t *nas_buffer); bool pack_identity_request(srslte::byte_buffer_t *reply_msg, uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id); - bool pack_emm_information(ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg); + bool pack_emm_information(ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg); bool pack_service_reject(srslte::byte_buffer_t *reply_msg, uint8_t emm_cause, uint32_t enb_ue_s1ap_id); void log_unhandled_attach_request_ies(const LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT *attach_req); diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 595166494..53277e89c 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -214,16 +214,13 @@ mme_gtpc::handle_create_session_response(srslte::gtpc_pdu *cs_resp_pdu) } //Save create session response info to E-RAB context - ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(imsi); - if(emm_ctx == NULL){ - m_mme_gtpc_log->error("Could not find UE EMM context\n"); - return; - } - ue_ecm_ctx_t *ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(emm_ctx->mme_ue_s1ap_id); - if(ecm_ctx == NULL){ - m_mme_gtpc_log->error("Could not find UE ECM context\n"); + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(imsi); + if(ue_ctx == NULL){ + m_mme_gtpc_log->error("Could not find UE context\n"); return; } + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; //Save SGW ctrl F-TEID in GTP-C context std::map::iterator it_g = m_imsi_to_gtpc_ctx.find(imsi); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 845675057..e59740299 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -113,18 +113,17 @@ s1ap::stop() { m_s1ap_log->info("Deleting eNB context. eNB Id: 0x%x\n", enb_it->second->enb_id); m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_it->second->enb_id); - delete_ues_ecm_ctx_in_enb(enb_it->second->enb_id); delete enb_it->second; m_active_enbs.erase(enb_it++); } - std::map::iterator ue_it = m_imsi_to_ue_emm_ctx.begin(); - while(ue_it!=m_imsi_to_ue_emm_ctx.end()) + std::map::iterator ue_it = m_imsi_to_ue_ctx.begin(); + while(ue_it!=m_imsi_to_ue_ctx.end()) { m_s1ap_log->info("Deleting UE EMM context. IMSI: %015lu\n", ue_it->first); m_s1ap_log->console("Deleting UE EMM context. IMSI: %015lu\n", ue_it->first); delete ue_it->second; - m_imsi_to_ue_emm_ctx.erase(ue_it++); + m_imsi_to_ue_ctx.erase(ue_it++); } //Cleanup message handlers s1ap_mngmt_proc::cleanup(); @@ -336,7 +335,7 @@ s1ap::delete_enb_ctx(int32_t assoc_id) m_s1ap_log->console("Deleting eNB context. eNB Id: 0x%x\n", enb_id); //Delete connected UEs ctx - delete_ues_ecm_ctx_in_enb(enb_id); + release_ues_ecm_ctx_in_enb(enb_id); //Delete eNB delete it_ctx->second; @@ -348,20 +347,89 @@ s1ap::delete_enb_ctx(int32_t assoc_id) //UE Context Management void -s1ap::add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx) +s1ap::add_new_ue_ctx(const ue_ctx_t &ue_ctx) { - std::map::iterator emm_ctx_it = m_imsi_to_ue_emm_ctx.find(ue_emm_ctx.imsi); - if(emm_ctx_it != m_imsi_to_ue_emm_ctx.end()) + std::map::iterator ctx_it = m_imsi_to_ue_ctx.find(ue_ctx.emm_ctx.imsi); + if(ctx_it != m_imsi_to_ue_ctx.end()) { - m_s1ap_log->warning("EMM Context already exists. Replacing EMM Context\n"); - delete emm_ctx_it->second; - m_imsi_to_ue_emm_ctx.erase(emm_ctx_it); + m_s1ap_log->warning("UE Context already exists. Replacing UE Context\n"); + delete ctx_it->second; + m_imsi_to_ue_ctx.erase(ctx_it); + } + std::map::iterator imsi_it = m_mme_ue_s1ap_id_to_imsi.find(ue_ctx.ecm_ctx.mme_ue_s1ap_id); + if(imsi_it != m_mme_ue_s1ap_id_to_imsi.end()) + { + m_s1ap_log->warning("MME UE S1AP Id already exists, replacing it.\n"); + m_mme_ue_s1ap_id_to_imsi.erase(imsi_it); } - ue_emm_ctx_t *ue_ptr = new ue_emm_ctx_t; - memcpy(ue_ptr,&ue_emm_ctx,sizeof(ue_emm_ctx)); - //This map will store UEs EMM context - m_imsi_to_ue_emm_ctx.insert(std::pair(ue_ptr->imsi,ue_ptr)); + ue_ctx_t *new_ctx = new ue_ctx_t; + memcpy(new_ctx, &ue_ctx,sizeof(ue_ctx)); + + //This map will store UEs context + m_imsi_to_ue_ctx.insert(std::pair(new_ctx->emm_ctx.imsi,new_ctx)); + m_mme_ue_s1ap_id_to_imsi.insert(std::pair(ue_ctx.ecm_ctx.mme_ue_s1ap_id,ue_ctx.emm_ctx.imsi)); + + //Store which enb currently holds the UE + std::map::iterator it_enb = m_sctp_to_enb_id.find(new_ctx->ecm_ctx.enb_sri.sinfo_assoc_id); + uint16_t enb_id = it_enb->second; + std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); + if(it_ue_id==m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find eNB's UEs\n"); + return; + } + it_ue_id->second.insert(new_ctx->ecm_ctx.mme_ue_s1ap_id); + return; +} + +bool +s1ap::add_ue_ctx_to_imsi_map(const ue_ctx_t *ue_ctx) +{ + std::map::iterator ctx_it = m_imsi_to_ue_ctx.find(ue_ctx->emm_ctx.imsi); + if(ctx_it != m_imsi_to_ue_ctx.end()) + { + m_s1ap_log->error("UE Context already exists. IMSI %015lu",ue_ctx->emm_ctx.imsi); + return false; + } + if(ue_ctx->ecm_ctx.mme_ue_s1ap_id != 0) + { + std::map::iterator ctx_it2 = m_mme_ue_s1ap_id_to_ue_ctx.find(ue_ctx.ecm_ctx.mme_ue_s1ap_id); + if(ctx_it2 != m_mme_ue_s1ap_id_to_imsi.end() && ctx_it2->second != ue_ctx) + { + m_s1ap_log->error("Context identified with IMSI does not match context identified by MME UE S1AP Id.\n"); + return false; + } + } + return true; +} + +bool +s1ap::add_ue_ctx_to_mme_ue_s1ap_id_map(const ue_ctx_t *ue_ctx) +{ + if(ue_ctx->ecm_ctx.mme_ue_s1ap_id == 0) + { + m_s1ap_log->error("Could not add UE context to MME UE S1AP map. MME UE S1AP ID 0 is not valid.") + return false; + } + std::map::iterator ctx_it = m_mme_ue_s1ap_id_to_ue_ctx.find(ue_ctx->ecm_ctx.mme_ue_s1ap_id); + if(ctx_it != m_mme_ue_s1ap_id_to_ue_ctx.end()) + { + m_s1ap_log->error("UE Context already exists. MME UE S1AP Id %015lu",ue_ctx->emm_ctx.imsi); + return false; + } + if(ue_ctx->ecm_ctx.imsi != 0) + { + std::map::iterator ctx_it2 = m_mme_ue_s1ap_id_to_ue_ctx.find(ue_ctx.ecm_ctx.mme_ue_s1ap_id); + if(ctx_it2 != m_mme_ue_s1ap_id_to_imsi.end() && ctx_it2->second != ue_ctx) + { + m_s1ap_log->error("Context identified with MME UE S1AP Id does not match context identified by IMSI.\n"); + return false; + } + } + + + return true; } void @@ -389,32 +457,11 @@ s1ap::get_tmp_ue_emm_ctx(uint32_t mme_ue_s1ap_id, ue_emm_ctx_t* ue_emm_ptr) return true; } -void -s1ap::add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx) -{ - ue_ecm_ctx_t *ue_ptr = new ue_ecm_ctx_t; - memcpy(ue_ptr,&ue_ecm_ctx,sizeof(ue_ecm_ctx)); - - //This map will store UE's ECM context. - m_mme_ue_s1ap_id_to_ue_ecm_ctx.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); - //Store which enb currently holds the UE - std::map::iterator it_enb = m_sctp_to_enb_id.find(ue_ptr->enb_sri.sinfo_assoc_id); - uint16_t enb_id = it_enb->second; - std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); - if(it_ue_id==m_enb_id_to_ue_ids.end()) - { - m_s1ap_log->error("Could not find eNB's UEs\n"); - return; - } - it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id); -} - - -ue_emm_ctx_t* -s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi) +ue_ctx_t* +s1ap::find_ue_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) { - std::map::iterator it = m_imsi_to_ue_emm_ctx.find(imsi); - if(it == m_imsi_to_ue_emm_ctx.end()) + std::map::iterator it = m_mme_ue_s1ap_id_to_ue_ctx.find(mme_ue_s1ap_id); + if(it == m_mme_ue_s1ap_id_to_imsi.end()) { return NULL; } @@ -424,11 +471,11 @@ s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi) } } -ue_ecm_ctx_t* -s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) +ue_ctx_t* +s1ap::find_ue_ctx_from_imsi(uint64_t imsi) { - std::map::iterator it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id); - if(it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end()) + std::map::iterator it = m_imsi_to_ue_ctx.find(imsi); + if(it == m_imsi_to_ue_ctx.end()) { return NULL; } @@ -437,39 +484,39 @@ s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) return it->second; } } -bool -s1ap::delete_ue_emm_ctx(uint64_t imsi) + +void +s1ap::release_ues_ecm_ctx_in_enb(uint16_t enb_id) { - std::map::iterator ue_emm_ctx_it = m_imsi_to_ue_emm_ctx.find(imsi); - if(ue_emm_ctx_it == m_imsi_to_ue_emm_ctx.end()) + //delete UEs ctx + std::map >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id); + std::set::iterator ue_id = ues_in_enb->second.begin(); + while(ue_id != ues_in_enb->second.end() ) { - m_s1ap_log->info("Cannot delete UE EMM context, UE not found. IMSI: %d\n", imsi); - return false; + std::map::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ctx.find(*ue_id); + m_s1ap_log->info("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id); + m_s1ap_log->console("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id); + + ue_set->second.erase(mme_ue_s1ap_id); } - - //Delete UE context - m_imsi_to_ue_emm_ctx.erase(ue_emm_ctx_it); - delete ue_emm_ctx_it->second; - m_s1ap_log->info("Deleted UE EMM Context.\n"); - return true; } bool -s1ap::delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) +s1ap::release_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) { - std::map::iterator ue_ecm_ctx_it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id); - if(ue_ecm_ctx_it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end()) + ue_ctx_t *ue_ctx = find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id) + if(ue_ctx == NULL) { - m_s1ap_log->info("Cannot delete UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + m_s1ap_log->error("Cannot release UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); return false; } - ue_ecm_ctx_t* ue_ecm_ctx = ue_ecm_ctx_it->second; + ue_ecm_ctx_t* ecm_ctx = &ue_ctx->ecm_ctx; //Delete UE within eNB UE set - std::map::iterator it = m_sctp_to_enb_id.find(ue_ecm_ctx->enb_sri.sinfo_assoc_id); + std::map::iterator it = m_sctp_to_enb_id.find(ecm_ctx->enb_sri.sinfo_assoc_id); if(it == m_sctp_to_enb_id.end() ) { - m_s1ap_log->error("Could not find eNB for this request.\n"); + m_s1ap_log->error("Could not find eNB for UE release request.\n"); return false; } uint16_t enb_id = it->second; @@ -481,31 +528,42 @@ s1ap::delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) } ue_set->second.erase(mme_ue_s1ap_id); - //Delete UE context - m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ecm_ctx_it); - delete ue_ecm_ctx; - m_s1ap_log->info("Deleted UE ECM Context.\n"); + //Release UE ECM context + m_mme_ue_s1ap_id_to_imsi.erase(mme_ue_s1ap_id); + ecm_ctx->state = ECM_STATE_IDLE; + ecm_ctx->mme_ue_s1ap_id = 0; + ecm_ctx->enb_ue_s1ap_id = 0; + m_s1ap_log->info("Released UE ECM Context.\n"); return true; } -void -s1ap::delete_ues_ecm_ctx_in_enb(uint16_t enb_id) +bool +s1ap::delete_ue_ctx(uint64_t imsi) { - //delete UEs ctx - std::map >::iterator ues_in_enb = m_enb_id_to_ue_ids.find(enb_id); - std::set::iterator ue_id = ues_in_enb->second.begin(); - while(ue_id != ues_in_enb->second.end() ) + ue_ctx_t *ue_ctx = find_ue_ctx_from_imsi(imsi); + if(ue_ctx == NULL) { - std::map::iterator ue_ctx = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(*ue_id); - m_s1ap_log->info("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id); - m_s1ap_log->console("Deleting UE context. UE-MME S1AP Id: %d\n", ue_ctx->second->mme_ue_s1ap_id); - m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ctx); //remove from general MME map - delete ue_ctx->second; //delete UE context - ues_in_enb->second.erase(ue_id++); //erase from the eNB's UE set + m_s1ap_log->info("Cannot delete UE context, UE not found. IMSI: %d\n", imsi); + return false; + } + + //Make sure to release ECM ctx + if(ue_ctx->ecm_ctx.state == ECM_STATE_CONNECTED) + { + release_ue_ecm_ctx(ue_ctx->ecm_state.mme_ue_s1ap_id); } + + //Delete UE context + m_imsi_to_ue_ctx.erase(imsi); + delete ue_ctx; + m_s1ap_log->info("Deleted UE Context.\n"); + return true; } + + + //UE Bearer Managment void s1ap::activate_eps_bearer(uint64_t imsi, uint8_t ebi) @@ -580,3 +638,126 @@ s1ap::print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx) } } //namespace srsepc + + /* +void +s1ap::add_new_ue_emm_ctx(const ue_emm_ctx_t &ue_emm_ctx) +{ + std::map::iterator emm_ctx_it = m_imsi_to_ue_emm_ctx.find(ue_emm_ctx.imsi); + if(emm_ctx_it != m_imsi_to_ue_emm_ctx.end()) + { + m_s1ap_log->warning("EMM Context already exists. Replacing EMM Context\n"); + delete emm_ctx_it->second; + m_imsi_to_ue_emm_ctx.erase(emm_ctx_it); + } + + ue_emm_ctx_t *ue_ptr = new ue_emm_ctx_t; + memcpy(ue_ptr,&ue_emm_ctx,sizeof(ue_emm_ctx)); + //This map will store UEs EMM context + m_imsi_to_ue_emm_ctx.insert(std::pair(ue_ptr->imsi,ue_ptr)); +} + */ + +/* + void + s1ap::add_new_ue_ecm_ctx(const ue_ecm_ctx_t &ue_ecm_ctx) + { + ue_ecm_ctx_t *ue_ptr = new ue_ecm_ctx_t; + memcpy(ue_ptr,&ue_ecm_ctx,sizeof(ue_ecm_ctx)); + + //This map will store UE's ECM context. + m_mme_ue_s1ap_id_to_ue_ecm_ctx.insert(std::pair(ue_ptr->mme_ue_s1ap_id,ue_ptr)); + //Store which enb currently holds the UE + std::map::iterator it_enb = m_sctp_to_enb_id.find(ue_ptr->enb_sri.sinfo_assoc_id); + uint16_t enb_id = it_enb->second; + std::map >::iterator it_ue_id = m_enb_id_to_ue_ids.find(enb_id); + if(it_ue_id==m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find eNB's UEs\n"); + return; + } + it_ue_id->second.insert(ue_ptr->mme_ue_s1ap_id); + } + */ + /* +ue_emm_ctx_t* +s1ap::find_ue_emm_ctx_from_imsi(uint64_t imsi) +{ + std::map::iterator it = m_imsi_to_ue_emm_ctx.find(imsi); + if(it == m_imsi_to_ue_emm_ctx.end()) + { + return NULL; + } + else + { + return it->second; + } +} + +ue_ecm_ctx_t* +s1ap::find_ue_ecm_ctx_from_mme_ue_s1ap_id(uint32_t mme_ue_s1ap_id) +{ + std::map::iterator it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id); + if(it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end()) + { + return NULL; + } + else + { + return it->second; + } +}*/ + /* +bool +s1ap::delete_ue_emm_ctx(uint64_t imsi) +{ + std::map::iterator ue_emm_ctx_it = m_imsi_to_ue_emm_ctx.find(imsi); + if(ue_emm_ctx_it == m_imsi_to_ue_emm_ctx.end()) + { + m_s1ap_log->info("Cannot delete UE EMM context, UE not found. IMSI: %d\n", imsi); + return false; + } + + //Delete UE context + m_imsi_to_ue_emm_ctx.erase(ue_emm_ctx_it); + delete ue_emm_ctx_it->second; + m_s1ap_log->info("Deleted UE EMM Context.\n"); + return true; +} + */ + /* +bool +s1ap::delete_ue_ecm_ctx(uint32_t mme_ue_s1ap_id) +{ + std::map::iterator ue_ecm_ctx_it = m_mme_ue_s1ap_id_to_ue_ecm_ctx.find(mme_ue_s1ap_id); + if(ue_ecm_ctx_it == m_mme_ue_s1ap_id_to_ue_ecm_ctx.end()) + { + m_s1ap_log->info("Cannot delete UE ECM context, UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + return false; + } + ue_ecm_ctx_t* ue_ecm_ctx = ue_ecm_ctx_it->second; + + //Delete UE within eNB UE set + std::map::iterator it = m_sctp_to_enb_id.find(ue_ecm_ctx->enb_sri.sinfo_assoc_id); + if(it == m_sctp_to_enb_id.end() ) + { + m_s1ap_log->error("Could not find eNB for this request.\n"); + return false; + } + uint16_t enb_id = it->second; + std::map >::iterator ue_set = m_enb_id_to_ue_ids.find(enb_id); + if(ue_set == m_enb_id_to_ue_ids.end()) + { + m_s1ap_log->error("Could not find the eNB's UEs.\n"); + return false; + } + ue_set->second.erase(mme_ue_s1ap_id); + + //Delete UE context + m_mme_ue_s1ap_id_to_ue_ecm_ctx.erase(ue_ecm_ctx_it); + delete ue_ecm_ctx; + m_s1ap_log->info("Deleted UE ECM Context.\n"); + + return true; +} + */ diff --git a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc index 34e0c8db3..3485b6e2f 100644 --- a/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc +++ b/srsepc/src/mme/s1ap_ctx_mngmt_proc.cc @@ -205,27 +205,24 @@ bool s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp) { uint32_t mme_ue_s1ap_id = in_ctxt_resp->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - ue_ecm_ctx_t *ue_ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); - if (ue_ecm_ctx == NULL) + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); + if (ue_ctx == NULL) { - m_s1ap_log->error("Could not find UE's ECM context in active UE's map\n"); + m_s1ap_log->error("Could not find UE's context in active UE's map\n"); return false; } - ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if (emm_ctx == NULL) - { - m_s1ap_log->error("Could not find UE's EMM context in active UE's map\n"); - return false; - } + ue_emm_ctx_t * emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t * ecm_ctx = &ue_ctx->ecm_ctx; + m_s1ap_log->console("Received Initial Context Setup Response\n"); //Setup E-RABs for(uint32_t i=0; iE_RABSetupListCtxtSURes.len;i++) { uint8_t erab_id = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].e_RAB_ID.E_RAB_ID; - erab_ctx_t *erab_ctx = &ue_ecm_ctx->erabs_ctx[erab_id]; + erab_ctx_t *erab_ctx = &ecm_ctx->erabs_ctx[erab_id]; if (erab_ctx->state != ERAB_CTX_REQUESTED) { - m_s1ap_log->error("E-RAB requested was not active %d\n",erab_id); + m_s1ap_log->error("E-RAB requested was not previously requested %d\n",erab_id); return false; } //Mark E-RAB with context setup @@ -254,7 +251,7 @@ s1ap_ctx_mngmt_proc::handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_I { m_s1ap_log->console("Initial Context Setup Response triggered from Service Request.\n"); m_s1ap_log->console("Sending Modify Bearer Request.\n"); - m_mme_gtpc->send_modify_bearer_request(ue_ecm_ctx->imsi, &ue_ecm_ctx->erabs_ctx[5]); + m_mme_gtpc->send_modify_bearer_request(emm_ctx->imsi, &ecm_ctx->erabs_ctx[5]); } return true; } @@ -269,13 +266,14 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON m_s1ap_log->info("Received UE Context Release Request. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); m_s1ap_log->console("Received UE Context Release Request. MME-UE S1AP Id %d\n", mme_ue_s1ap_id); - ue_ecm_ctx_t *ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); - if(ecm_ctx == NULL) + ue_ctx_t * ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); + if(ue_ctx == NULL) { - m_s1ap_log->info("No UE ECM context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); - m_s1ap_log->console("No UE ECM context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + m_s1ap_log->info("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); + m_s1ap_log->console("No UE context to release found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); return false; } + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; //Delete user plane context at the SPGW (but keep GTP-C connection). if (ecm_ctx->state == ECM_STATE_CONNECTED) @@ -284,23 +282,27 @@ s1ap_ctx_mngmt_proc::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECON m_s1ap_log->console("There are active E-RABs, send release access mearers request"); m_s1ap_log->info("There are active E-RABs, send release access mearers request"); m_mme_gtpc->send_release_access_bearers_request(ecm_ctx->imsi); + //The handle_releease_access_bearers_response function will make sure to mark E-RABS DEACTIVATED + //It will release the UEs downstream S1-u and keep the upstream S1-U connection active. } else { //No ECM Context to release m_s1ap_log->info("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); m_s1ap_log->console("UE is not ECM connected. No need to release S1-U. MME UE S1AP Id %d\n", mme_ue_s1ap_id); + //Make sure E-RABS are merked as DEACTIVATED. + for(int i=0;ierabs_ctx[i].state = ERAB_DEACTIVATED; + } } - //m_s1ap->delete_ue_ctx(ue_ctx); - for(int i=0;ierabs_ctx[i].state = ERAB_DEACTIVATED; - } + //Delete UE context - ecm_ctx->state = ECM_STATE_DISCONNECTED; + ecm_ctx->state = ECM_STATE_IDLE; + ecm_ctx->enb_ue_s1ap_id = 0; ecm_ctx->mme_ue_s1ap_id = 0; - m_s1ap_log->info("UE ECM Disconnected.\n"); - m_s1ap_log->console("Deleted UE ECM Context.\n"); + m_s1ap_log->info("UE is ECM IDLE.\n"); + m_s1ap_log->console("UE is ECM IDLE.\n"); return true; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 2227cddda..0cde1635d 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -140,14 +140,16 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA bool mac_valid = false; //Get UE ECM context - ue_ecm_ctx_t *ue_ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); - if(ue_ecm_ctx == NULL) + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_mme_ue_s1ap_id(mme_ue_s1ap_id); + if(ue_ctx == NULL) { m_s1ap_log->warning("Received uplink NAS, but could not find UE ECM context. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); return false; } m_s1ap_log->debug("Received uplink NAS and found UE ECM context. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; //Parse NAS message header srslte::byte_buffer_t *nas_msg = m_pool->allocate(); @@ -161,15 +163,13 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA //Find UE EMM context if message is security protected. if(sec_hdr_type != LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS) { - //Get EMM context to do integrity check/de-chiphering - ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if(ue_emm_ctx == NULL) + //Make sure EMM context is set-up, to do integrity check/de-chiphering + if(emm_ctx->imsi == 0) { //No EMM context found. //Perhaps a temporary context is being created? - //This can happen with integrity protected identity reponse and authentication response messages - if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY) && - !(msg_type == LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) + //This can happen with integrity protected identity reponse messages + if( !(msg_type == LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE && sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY)) { m_s1ap_log->warning("Uplink NAS: could not find security context for integrity protected message. MME-UE S1AP id: %lu\n",mme_ue_s1ap_id); m_pool->deallocate(nas_msg); @@ -191,12 +191,12 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA case LIBLTE_MME_MSG_TYPE_IDENTITY_RESPONSE: m_s1ap_log->info("Uplink NAS: Received Identity Response\n"); m_s1ap_log->console("Uplink NAS: Received Identity Response\n"); - handle_identity_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_identity_response(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_RESPONSE: m_s1ap_log->info("Uplink NAS: Received Authentication Response\n"); m_s1ap_log->console("Uplink NAS: Received Authentication Response\n"); - handle_nas_authentication_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_nas_authentication_response(nas_msg, ue_ctx, reply_buffer, reply_flag); break; default: m_s1ap_log->warning("Unhandled Plain NAS message 0x%x\n", msg_type ); @@ -205,14 +205,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA return false; } //Increment UL NAS count. - ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if(ue_emm_ctx == NULL) - { - m_s1ap_log->warning("Could not find UE EMM context in ", msg_type ); - m_pool->deallocate(nas_msg); - return false; - } - ue_emm_ctx->security_ctxt.ul_nas_count++; + emm_ctx->security_ctxt.ul_nas_count++; } else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_WITH_NEW_EPS_SECURITY_CONTEXT || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED_WITH_NEW_EPS_SECURITY_CONTEXT) { @@ -220,11 +213,11 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA case LIBLTE_MME_MSG_TYPE_SECURITY_MODE_COMPLETE: m_s1ap_log->info("Uplink NAS: Received Security Mode Complete\n"); m_s1ap_log->console("Uplink NAS: Received Security Mode Complete\n"); - ue_emm_ctx->security_ctxt.ul_nas_count = 0; - ue_emm_ctx->security_ctxt.dl_nas_count = 0; - mac_valid = integrity_check(ue_emm_ctx,nas_msg); + emm_ctx->security_ctxt.ul_nas_count = 0; + emm_ctx->security_ctxt.dl_nas_count = 0; + mac_valid = integrity_check(emm_ctx,nas_msg); if(mac_valid){ - handle_nas_security_mode_complete(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_nas_security_mode_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); } else { m_s1ap_log->warning("Invalid MAC in Security Mode Command Complete message.\n" ); } @@ -237,7 +230,7 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA else if(sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY || sec_hdr_type == LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED) { //Integrity protected NAS message, possibly chiphered. - ue_emm_ctx->security_ctxt.ul_nas_count++; + emm_ctx->security_ctxt.ul_nas_count++; mac_valid = integrity_check(ue_emm_ctx,nas_msg); if(!mac_valid){ m_s1ap_log->warning("Invalid MAC in NAS message type 0x%x.\n", msg_type); @@ -248,20 +241,20 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA case LIBLTE_MME_MSG_TYPE_ATTACH_COMPLETE: m_s1ap_log->info("Uplink NAS: Received Attach Complete\n"); m_s1ap_log->console("Uplink NAS: Received Attach Complete\n"); - handle_nas_attach_complete(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_nas_attach_complete(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_ESM_INFORMATION_RESPONSE: m_s1ap_log->info("Uplink NAS: Received ESM Information Response\n"); m_s1ap_log->console("Uplink NAS: Received ESM Information Response\n"); - handle_esm_information_response(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_esm_information_response(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_TRACKING_AREA_UPDATE_REQUEST: m_s1ap_log->info("UL NAS: Tracking Area Update Request\n"); - handle_tracking_area_update_request(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_tracking_area_update_request(nas_msg, ue_ctx, reply_buffer, reply_flag); break; case LIBLTE_MME_MSG_TYPE_AUTHENTICATION_FAILURE: m_s1ap_log->info("Uplink NAS: Authentication Failure\n"); - handle_authentication_failure(nas_msg, ue_ecm_ctx, reply_buffer, reply_flag); + handle_authentication_failure(nas_msg, ue_ctx, reply_buffer, reply_flag); break; default: m_s1ap_log->warning("Unhandled NAS integrity protected message 0x%x\n", msg_type ); @@ -281,8 +274,8 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA if(*reply_flag == true) { if(ue_emm_ctx != NULL){ - m_s1ap_log->console("DL NAS: Sent Downlink NAs Message. DL NAS Count=%d, UL NAS count=%d\n",ue_emm_ctx->security_ctxt.dl_nas_count,ue_emm_ctx->security_ctxt.ul_nas_count ); - m_s1ap_log->info("DL NAS: Sent Downlink NAS message. DL NAS Count=%d, UL NAS count=%d\n",ue_emm_ctx->security_ctxt.dl_nas_count, ue_emm_ctx->security_ctxt.ul_nas_count); + m_s1ap_log->console("DL NAS: Sent Downlink NAs Message. DL NAS Count=%d, UL NAS count=%d\n",emm_ctx->security_ctxt.dl_nas_count,emm_ctx->security_ctxt.ul_nas_count ); + m_s1ap_log->info("DL NAS: Sent Downlink NAS message. DL NAS Count=%d, UL NAS count=%d\n",emm_ctx->security_ctxt.dl_nas_count, emm_ctx->security_ctxt.ul_nas_count); } else{ m_s1ap_log->console("DL NAS: Sent Downlink NAS Message\n"); @@ -290,7 +283,6 @@ s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKNASTRA } } m_pool->deallocate(nas_msg); - return true; } @@ -353,54 +345,54 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id, uint8_t rand[16]; uint8_t xres[8]; - - ue_emm_ctx_t ue_emm_ctx; - ue_ecm_ctx_t ue_ecm_ctx; + ue_ctx_t ue_ctx; + ue_emm_ctx_t *emm_ctx = &ue_ctx.emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx.ecm_ctx; //Set UE's EMM context - ue_emm_ctx.imsi = 0; + emm_ctx->imsi = 0; for(int i=0;i<=14;i++){ - ue_emm_ctx.imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + emm_ctx->imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); } - ue_emm_ctx.mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - ue_emm_ctx.state = EMM_STATE_DEREGISTERED; + emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + emm_ctx->state = EMM_STATE_DEREGISTERED; //Save UE network capabilities - memcpy(&ue_emm_ctx.security_ctxt.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); - ue_emm_ctx.security_ctxt.ms_network_cap_present = attach_req.ms_network_cap_present; + memcpy(&emm_ctx->security_ctxt.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); + emm_ctx->security_ctxt.ms_network_cap_present = attach_req.ms_network_cap_present; if(attach_req.ms_network_cap_present) { - memcpy(&ue_emm_ctx.security_ctxt.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); + memcpy(&emm_ctx->security_ctxt.ms_network_cap, &attach_req.ms_network_cap, sizeof(LIBLTE_MME_MS_NETWORK_CAPABILITY_STRUCT)); } uint8_t eps_bearer_id = pdn_con_req.eps_bearer_id; //TODO: Unused - ue_emm_ctx.procedure_transaction_id = pdn_con_req.proc_transaction_id; + emm_ctx->procedure_transaction_id = pdn_con_req.proc_transaction_id; //Initialize NAS count - ue_emm_ctx.security_ctxt.ul_nas_count = 0; - ue_emm_ctx.security_ctxt.dl_nas_count = 0; - + emm_ctx->security_ctxt.ul_nas_count = 0; + emm_ctx->security_ctxt.dl_nas_count = 0; //Set UE ECM context - ue_ecm_ctx.imsi = ue_emm_ctx.imsi; - ue_ecm_ctx.mme_ue_s1ap_id = ue_emm_ctx.mme_ue_s1ap_id; + ecm_ctx->imsi = emm_ctx->imsi; + ecm_ctx->mme_ue_s1ap_id = emm_ctx->mme_ue_s1ap_id; + //Set eNB information - ue_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; - memcpy(&ue_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; + memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); //Save whether secure ESM information transfer is necessary - ue_ecm_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; + ecm_ctx->eit = pdn_con_req.esm_info_transfer_flag_present; //Initialize E-RABs for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) { - ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; - ue_ecm_ctx.erabs_ctx[i].erab_id = i; + ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; + ecm_ctx->erabs_ctx[i].erab_id = i; } //Log Attach Request information - m_s1ap_log->console("Attach request -- IMSI: %015lu\n", ue_emm_ctx.imsi); - m_s1ap_log->info("Attach request -- IMSI: %015lu\n", ue_emm_ctx.imsi); - m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id); - m_s1ap_log->info("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id); + m_s1ap_log->console("Attach request -- IMSI: %015lu\n", emm_ctx->imsi); + m_s1ap_log->info("Attach request -- IMSI: %015lu\n", emm_ctx->imsi); + m_s1ap_log->console("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id); + m_s1ap_log->info("Attach request -- eNB-UE S1AP Id: %d, MME-UE S1AP Id: %d\n", ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id); m_s1ap_log->console("Attach request -- Attach type: %d\n", attach_req.eps_attach_type); m_s1ap_log->info("Attach request -- Attach type: %d\n", attach_req.eps_attach_type); @@ -428,21 +420,20 @@ s1ap_nas_transport::handle_nas_imsi_attach_request(uint32_t enb_ue_s1ap_id, m_s1ap_log->console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); //Save attach request type - ue_emm_ctx.attach_type = attach_req.eps_attach_type; + emm_ctx->attach_type = attach_req.eps_attach_type; //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer(ue_emm_ctx.imsi, ue_emm_ctx.security_ctxt.k_asme, autn, rand, ue_emm_ctx.security_ctxt.xres)) + if(!m_hss->gen_auth_info_answer(emm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres)) { - m_s1ap_log->console("User not found. IMSI %015lu\n",ue_emm_ctx.imsi); - m_s1ap_log->info("User not found. IMSI %015lu\n",ue_emm_ctx.imsi); + m_s1ap_log->console("User not found. IMSI %015lu\n",emm_ctx->imsi); + m_s1ap_log->info("User not found. IMSI %015lu\n",emm_ctx->imsi); return false; } - m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx); - m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx); + m_s1ap->add_new_ue_ctx(ue_ctx); //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_buffer, ue_ecm_ctx.enb_ue_s1ap_id, ue_ecm_ctx.mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); //Send reply to eNB *reply_flag = true; @@ -542,7 +533,7 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, m_s1ap_log->console("Could not find M-TMSI=0x%x. Sending ID request\n",m_tmsi); m_s1ap_log->info("Could not find M-TMSI=0x%x. Sending Id Request\n", m_tmsi); - m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx); + //m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx); //We do not know the IMSI of the UE yet //This will be removed when the identity response is received @@ -558,45 +549,48 @@ s1ap_nas_transport::handle_nas_guti_attach_request( uint32_t enb_ue_s1ap_id, m_s1ap_log->console("Attach Request -- Found M-TMSI: %d\n",m_tmsi); m_s1ap_log->console("Attach Request -- IMSI: %d\n",it->second); //Get UE EMM context - ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(it->second); - if(ue_emm_ctx!=NULL) + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(it->second); + if(ue_ctx!=NULL) { - m_s1ap_log->console("Found UE context. IMSI: %015lu\n",ue_emm_ctx->imsi); + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; + m_s1ap_log->console("Found UE context. IMSI: %015lu\n",emm_ctx->imsi); + //Check NAS integrity bool msg_valid = false; - ue_emm_ctx->security_ctxt.ul_nas_count++; - msg_valid = integrity_check(ue_emm_ctx,nas_msg); + emm_ctx->security_ctxt.ul_nas_count++; + msg_valid = integrity_check(emm_ctx,nas_msg); if(msg_valid == true) { //Create new MME UE S1AP Identity - ue_emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + emm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); //Set EMM as de-registered - ue_emm_ctx->state = EMM_STATE_DEREGISTERED; + emm_ctx->state = EMM_STATE_DEREGISTERED; //Save Attach type - ue_emm_ctx->attach_type = attach_req.eps_attach_type; - //Create UE ECM context - ue_ecm_ctx_t ue_ecm_ctx; + emm_ctx->attach_type = attach_req.eps_attach_type; //Set UE ECM context - ue_ecm_ctx.imsi = ue_emm_ctx->imsi; - ue_ecm_ctx.mme_ue_s1ap_id = ue_emm_ctx->mme_ue_s1ap_id; + ecm_ctx->imsi = ecm_ctx->imsi; + ecm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id; + //Set eNB information - ue_ecm_ctx.enb_ue_s1ap_id = enb_ue_s1ap_id; - memcpy(&ue_ecm_ctx.enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; + memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); //Save whether secure ESM information transfer is necessary - ue_ecm_ctx.eit = pdn_con_req.esm_info_transfer_flag_present; + ecm_ctx->eit = pdn_con_req.esm_info_transfer_flag_present; //Initialize E-RABs for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) { - ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; - ue_ecm_ctx.erabs_ctx[i].erab_id = i; + ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; + ecm_ctx->erabs_ctx[i].erab_id = i; } - m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx); + + //m_s1ap->add_new_ue_ecm_ctx(ue_ecm_ctx); //Create session request m_s1ap_log->console("GUTI Attach -- NAS Integrity OK."); - m_mme_gtpc->send_create_session_request(ue_emm_ctx->imsi); + m_mme_gtpc->send_create_session_request(emm_ctx->imsi); *reply_flag = false; //No reply needed return true; } @@ -649,8 +643,8 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, return true; } - ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(it->second); - if(emm_ctx == NULL || emm_ctx->state != EMM_STATE_REGISTERED) + ue_ctx_t *ue_ctx = m_s1ap->find_ue_ctx_from_imsi(it->second); + if(ue_ctx == NULL || ue_ctx->emm_ctx.state != EMM_STATE_REGISTERED) { m_s1ap_log->console("UE is not EMM-Registered.\n"); m_s1ap_log->error("UE is not EMM-Registered.\n"); @@ -658,80 +652,68 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, *reply_flag = true; return true; } + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; + emm_ctx->security_ctxt.ul_nas_count++; mac_valid = short_integrity_check(emm_ctx,nas_msg); if(mac_valid) { m_s1ap_log->console("Service Request -- Short MAC valid\n"); m_s1ap_log->info("Service Request -- Short MAC valid\n"); - ue_ecm_ctx_t *ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(emm_ctx->mme_ue_s1ap_id); - if(ecm_ctx == NULL) + if(ecm_ctx->state == ECM_STATE_CONNECTED) { - m_s1ap_log->console("UE ECM context is not initialized.\n"); - m_s1ap_log->error("UE ECM context is not initialized.\n"); - pack_service_reject(reply_buffer, LIBLTE_MME_EMM_CAUSE_IMPLICITLY_DETACHED, enb_ue_s1ap_id); - *reply_flag = true; - return true; + m_s1ap_log->error("Service Request -- User is ECM CONNECTED\n"); + + //Service request to Connected UE. + //Set eNB UE S1ap identity + ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; + m_s1ap_log->console("Service Request -- eNB UE S1AP Id %d \n", enb_ue_s1ap_id); + m_s1ap_log->info("Service Request -- eNB UE S1AP Id %d\n ", enb_ue_s1ap_id); + + //Delete eNB context and connect. + m_s1ap_log->console("Service Request -- User has ECM context already\n"); + m_s1ap_log->info("Service Request -- User has ECM context already\n"); + m_s1ap->m_s1ap_ctx_mngmt_proc->send_ue_context_release_command(ecm_ctx,reply_buffer); + //int default_bearer_id = 5; + //m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx, &ecm_ctx->erabs_ctx[default_bearer_id]); + //FIXME Send Modify context request OR send ctx release command and wait for the reply. } - else + else if(ecm_ctx->state == ECM_STATE_IDLE) { - if(ecm_ctx->state == ECM_STATE_CONNECTED) + ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; + + //UE not connect. Connect normally. + m_s1ap_log->console("Service Request -- User is ECM DISCONNECTED\n"); + m_s1ap_log->info("Service Request -- User is ECM DISCONNECTED\n"); + //Create ECM context + ecm_ctx->imsi = emm_ctx->imsi; + ecm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); + emm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id; + //Set eNB information + ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; + memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); + + //Save whether secure ESM information transfer is necessary + ecm_ctx->eit = false; + + //Initialize E-RABs + for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) { - m_s1ap_log->error("Service Request -- User is ECM CONNECTED\n"); - - //Service request to Connected UE. - //Set eNB UE S1ap identity - ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; - m_s1ap_log->console("Service Request -- eNB UE S1AP Id %d \n", enb_ue_s1ap_id); - m_s1ap_log->info("Service Request -- eNB UE S1AP Id %d\n ", enb_ue_s1ap_id); - - //Delete eNB context and connect. - m_s1ap_log->console("Service Request -- User has ECM context already\n"); - m_s1ap_log->info("Service Request -- User has ECM context already\n"); - m_s1ap->m_s1ap_ctx_mngmt_proc->send_ue_context_release_command(ecm_ctx,reply_buffer); - //int default_bearer_id = 5; - //m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx, &ecm_ctx->erabs_ctx[default_bearer_id]); - //FIXME Send Modify context request OR send ctx release command and wait for the reply. - + ecm_ctx->erabs_ctx[i].state = ERAB_DEACTIVATED; + ecm_ctx->erabs_ctx[i].erab_id = i; } - else if(ecm_ctx->state == ECM_STATE_DISCONNECTED) - { - ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; - - //UE not connect. Connect normally. - m_s1ap_log->console("Service Request -- User is ECM DISCONNECTED\n"); - m_s1ap_log->info("Service Request -- User is ECM DISCONNECTED\n"); - //Create ECM context - ecm_ctx->imsi = emm_ctx->imsi; - ecm_ctx->mme_ue_s1ap_id = m_s1ap->get_next_mme_ue_s1ap_id(); - emm_ctx->mme_ue_s1ap_id = ecm_ctx->mme_ue_s1ap_id; - //Set eNB information - ecm_ctx->enb_ue_s1ap_id = enb_ue_s1ap_id; - memcpy(&ecm_ctx->enb_sri, enb_sri, sizeof(struct sctp_sndrcvinfo)); - - //Save whether secure ESM information transfer is necessary - ecm_ctx->eit = false; - //Initialize E-RABs - for(uint i = 0 ; i< MAX_ERABS_PER_UE; i++) - { - ue_ecm_ctx.erabs_ctx[i].state = ERAB_DEACTIVATED; - ue_ecm_ctx.erabs_ctx[i].erab_id = i; - } - ecm_ctx = m_s1ap->find_ue_ecm_ctx_from_mme_ue_s1ap_id(emm_ctx->mme_ue_s1ap_id); - - //Re-generate K_eNB - liblte_security_generate_k_enb(emm_ctx->security_ctxt.k_asme, emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.k_enb); - m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",emm_ctx->security_ctxt.ul_nas_count); - m_s1ap_log->console("UE Ctr TEID %d\n", emm_ctx->sgw_ctrl_fteid.teid); - m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx,&ecm_ctx->erabs_ctx[5]); - - } - else - { - m_s1ap_log->console("ECM context is un-initialized.\n"); - m_s1ap_log->error("ECM context is un-initialized.\n"); - } + //Re-generate K_eNB + liblte_security_generate_k_enb(emm_ctx->security_ctxt.k_asme, emm_ctx->security_ctxt.ul_nas_count, emm_ctx->security_ctxt.k_enb); + m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",emm_ctx->security_ctxt.ul_nas_count); + m_s1ap_log->console("UE Ctr TEID %d\n", emm_ctx->sgw_ctrl_fteid.teid); + m_s1ap->m_s1ap_ctx_mngmt_proc->send_initial_context_setup_request(emm_ctx, ecm_ctx,&ecm_ctx->erabs_ctx[5]); + } + else + { + m_s1ap_log->console("ECM context is un-initialized.\n"); + m_s1ap_log->error("ECM context is un-initialized.\n"); } } else @@ -743,19 +725,15 @@ s1ap_nas_transport::handle_nas_service_request(uint32_t m_tmsi, return true; } bool -s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag) +s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool* reply_flag) { LIBLTE_MME_AUTHENTICATION_RESPONSE_MSG_STRUCT auth_resp; bool ue_valid=true; - ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if(ue_emm_ctx == NULL) - { - m_s1ap_log->error("Authentication Response -- Could not find UE EMM context.\n"); - return false; - } - m_s1ap_log->console("Authentication Response -- IMSI %015lu\n", ue_emm_ctx->imsi); + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; + m_s1ap_log->console("Authentication Response -- IMSI %015lu\n", emm_ctx->imsi); //Get NAS authentication response LIBLTE_ERROR_ENUM err = liblte_mme_unpack_authentication_response_msg((LIBLTE_BYTE_MSG_STRUCT *) nas_msg, &auth_resp); @@ -772,26 +750,19 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na for(int i=0; i<8;i++) { - if(auth_resp.res[i] != ue_emm_ctx->security_ctxt.xres[i]) + if(auth_resp.res[i] != emm_ctx->security_ctxt.xres[i]) { ue_valid = false; } } if(!ue_valid) { - std::cout<security_ctxt.xres[i]; - } - std::cout<info_hex(emm_ctx->security_ctxt.xres,8, "XRES"); m_s1ap_log->console("UE Authentication Rejected.\n"); m_s1ap_log->warning("UE Authentication Rejected.\n"); //Send back Athentication Reject - pack_authentication_reject(reply_buffer, ue_ecm_ctx->enb_ue_s1ap_id, ue_ecm_ctx->mme_ue_s1ap_id); + pack_authentication_reject(reply_buffer, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id); *reply_flag = true; m_s1ap_log->console("Downlink NAS: Sending Authentication Reject.\n"); return false; @@ -801,7 +772,7 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na m_s1ap_log->console("UE Authentication Accepted.\n"); m_s1ap_log->info("UE Authentication Accepted.\n"); //Send Security Mode Command - pack_security_mode_command(reply_buffer, ue_emm_ctx, ue_ecm_ctx); + pack_security_mode_command(reply_buffer, emm_ctx, ecm_ctx); *reply_flag = true; m_s1ap_log->console("Downlink NAS: Sending NAS Security Mode Command.\n"); } @@ -809,15 +780,11 @@ s1ap_nas_transport::handle_nas_authentication_response(srslte::byte_buffer_t *na } bool -s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) +s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_buffer, bool *reply_flag) { - ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if(ue_emm_ctx == NULL) - { - m_s1ap_log->error("Could not find UE's EMM context\n"); - return false; - } + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; LIBLTE_MME_SECURITY_MODE_COMPLETE_MSG_STRUCT sm_comp; @@ -834,11 +801,11 @@ s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas m_s1ap_log->warning("IMEI-SV present but not handled"); } - m_s1ap_log->info("Security Mode Command Complete -- IMSI: %lu\n", ue_ecm_ctx->imsi); - m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", ue_ecm_ctx->imsi); - if(ue_ecm_ctx->eit == true) + m_s1ap_log->info("Security Mode Command Complete -- IMSI: %lu\n", emm_ctx->imsi); + m_s1ap_log->console("Security Mode Command Complete -- IMSI: %lu\n", emm_ctx->imsi); + if(ecm_ctx->eit == true) { - pack_esm_information_request(reply_buffer, ue_emm_ctx, ue_ecm_ctx); + pack_esm_information_request(reply_buffer, emm_ctx, ecm_ctx); m_s1ap_log->console("Sending ESM information request\n"); m_s1ap_log->info("Sending ESM information request\n"); *reply_flag = true; @@ -847,14 +814,14 @@ s1ap_nas_transport::handle_nas_security_mode_complete(srslte::byte_buffer_t *nas { //FIXME The packging of GTP-C messages is not ready. //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - m_mme_gtpc->send_create_session_request(ue_ecm_ctx->imsi); + m_mme_gtpc->send_create_session_request(emm_ctx->imsi); *reply_flag = false; //No reply needed } return true; } bool -s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t *ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) { LIBLTE_MME_ATTACH_COMPLETE_MSG_STRUCT attach_comp; @@ -877,11 +844,8 @@ s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, u return false; } - ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ecm_ctx->imsi); - if(emm_ctx == NULL) - { - m_s1ap_log->error("Received Attach complete, but could not find UE's EMM Context.\n"); - } + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; m_s1ap_log->console("Unpacked Attached Complete Message. IMSI %d\n", emm_ctx->imsi); m_s1ap_log->console("Unpacked Activate Default EPS Bearer message. EPS Bearer id %d\n",act_bearer.eps_bearer_id); @@ -894,10 +858,10 @@ s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, u if(emm_ctx->state == EMM_STATE_DEREGISTERED) { //Attach requested from attach request - m_mme_gtpc->send_modify_bearer_request(ecm_ctx->imsi, &ecm_ctx->erabs_ctx[act_bearer.eps_bearer_id]); + m_mme_gtpc->send_modify_bearer_request(emm_ctx->imsi, &ecm_ctx->erabs_ctx[act_bearer.eps_bearer_id]); //Send reply to eNB m_s1ap_log->console("Packing EMM infromationi\n"); - *reply_flag = pack_emm_information(ecm_ctx, reply_msg); + *reply_flag = pack_emm_information(ue_ctx, reply_msg); m_s1ap_log->console("Sending EMM infromation, bytes %d\n",reply_msg->N_bytes); m_s1ap_log->info("Sending EMM infromation\n"); } @@ -906,7 +870,7 @@ s1ap_nas_transport::handle_nas_attach_complete(srslte::byte_buffer_t *nas_msg, u } bool -s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) { LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp; @@ -930,12 +894,12 @@ s1ap_nas_transport::handle_esm_information_response(srslte::byte_buffer_t *nas_m //FIXME The packging of GTP-C messages is not ready. //This means that GTP-U tunnels are created with function calls, as opposed to GTP-C. - m_mme_gtpc->send_create_session_request(ue_ecm_ctx->imsi); + m_mme_gtpc->send_create_session_request(ue_ctx->emm_ctx.imsi); return true; } bool -s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) { uint8_t autn[16]; uint8_t rand[16]; @@ -953,40 +917,42 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ imsi += id_resp.mobile_id.imsi[i]*std::pow(10,14-i); } + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; //Check if EMM context already exists - ue_emm_ctx_t *ue_tmp_ptr = m_s1ap->find_ue_emm_ctx_from_imsi(imsi); - if(ue_tmp_ptr != NULL) - { - m_s1ap_log->warning("Unkonw GUTI, but UE's EMM context present.\n"); - m_s1ap->delete_ue_emm_ctx(imsi); - } + //ue_ctx_t *ue_tmp_ptr = m_s1ap->find_ue_ctx_from_imsi(imsi); + //if(ue_tmp_ptr != NULL) + //{ + // m_s1ap_log->warning("Unkonw GUTI, but UE's EMM context present.\n"); + // m_s1ap->delete_ue_emm_ctx(imsi); + //} m_s1ap_log->info("Id Response -- IMSI: %015lu\n", imsi); m_s1ap_log->console("Id Response -- IMSI: %015lu\n", imsi); - ue_ecm_ctx->imsi = imsi; + ecm_ctx->imsi = imsi; //Get UE EMM context - ue_emm_ctx_t ue_emm_ctx; - if(m_s1ap->get_tmp_ue_emm_ctx(ue_ecm_ctx->mme_ue_s1ap_id, &ue_emm_ctx) == false) - { - m_s1ap_log->error("Could not find UE's temporary EMM context. MME UE S1AP Id: %d\n",ue_ecm_ctx->mme_ue_s1ap_id); - return false; - } - ue_emm_ctx.imsi=imsi; + //if(m_s1ap->get_tmp_ue_emm_ctx(ue_ecm_ctx->mme_ue_s1ap_id, &ue_emm_ctx) == false) + //{ + // m_s1ap_log->error("Could not find UE's temporary EMM context. MME UE S1AP Id: %d\n",ue_ecm_ctx->mme_ue_s1ap_id); + // return false; + //} + emm_ctx->imsi=imsi; //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer(imsi, ue_emm_ctx.security_ctxt.k_asme, autn, rand, ue_emm_ctx.security_ctxt.xres)) + if(!m_hss->gen_auth_info_answer(imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres)) { m_s1ap_log->console("User not found. IMSI %015lu\n",imsi); m_s1ap_log->info("User not found. IMSI %015lu\n",imsi); return false; } + //Store UE EMM context - m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx); + //m_s1ap->add_new_ue_emm_ctx(ue_emm_ctx); //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_msg, ue_ecm_ctx->enb_ue_s1ap_id, ue_ecm_ctx->mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); //Send reply to eNB *reply_flag = true; @@ -999,7 +965,7 @@ s1ap_nas_transport::handle_identity_response(srslte::byte_buffer_t *nas_msg, ue_ bool -s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) { m_s1ap_log->console("Warning: Tracking Area Update Request messages not handled yet.\n"); @@ -1018,8 +984,8 @@ s1ap_nas_transport::handle_tracking_area_update_request(srslte::byte_buffer_t *n //Setup Dw NAS structure LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; dw_nas->ext=false; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ecm_ctx->mme_ue_s1ap_id; - dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ecm_ctx->enb_ue_s1ap_id; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->ecm_ctx.mme_ue_s1ap_id; + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->ecm_ctx.enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; //m_s1ap_log->console("Tracking area accept to MME-UE S1AP Id %d\n", ue_ctx->mme_ue_s1ap_id); @@ -1197,7 +1163,7 @@ s1ap_nas_transport::integrity_check(ue_emm_ctx_t *emm_ctx, srslte::byte_buffer_t bool -s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ecm_ctx_t* ue_ecm_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) +s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg, ue_ctx_t* ue_ctx, srslte::byte_buffer_t *reply_msg, bool *reply_flag) { uint8_t autn[16]; uint8_t rand[16]; @@ -1210,12 +1176,8 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg return false; } - ue_emm_ctx_t *emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if(emm_ctx == NULL) - { - m_s1ap_log->error("Could not find UE EMM context\n"); - return false; - } + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; switch(auth_fail.emm_cause){ case 20: @@ -1233,22 +1195,22 @@ s1ap_nas_transport::handle_authentication_failure(srslte::byte_buffer_t *nas_msg m_s1ap_log->error("Missing fail parameter\n"); return false; } - if(!m_hss->resync_sqn(ue_ecm_ctx->imsi, auth_fail.auth_fail_param)) + if(!m_hss->resync_sqn(emm_ctx->imsi, auth_fail.auth_fail_param)) { - m_s1ap_log->console("Resynchronization failed. IMSI %015lu\n", ue_ecm_ctx->imsi); - m_s1ap_log->info("Resynchronization failed. IMSI %015lu\n", ue_ecm_ctx->imsi); + m_s1ap_log->console("Resynchronization failed. IMSI %015lu\n", emm_ctx->imsi); + m_s1ap_log->info("Resynchronization failed. IMSI %015lu\n", emm_ctx->imsi); return false; } //Get Authentication Vectors from HSS - if(!m_hss->gen_auth_info_answer(ue_ecm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres)) + if(!m_hss->gen_auth_info_answer(emm_ctx->imsi, emm_ctx->security_ctxt.k_asme, autn, rand, emm_ctx->security_ctxt.xres)) { - m_s1ap_log->console("User not found. IMSI %015lu\n", ue_ecm_ctx->imsi); - m_s1ap_log->info("User not found. IMSI %015lu\n", ue_ecm_ctx->imsi); + m_s1ap_log->console("User not found. IMSI %015lu\n", emm_ctx->imsi); + m_s1ap_log->info("User not found. IMSI %015lu\n", emm_ctx->imsi); return false; } //Pack NAS Authentication Request in Downlink NAS Transport msg - pack_authentication_request(reply_msg, ue_ecm_ctx->enb_ue_s1ap_id, ue_ecm_ctx->mme_ue_s1ap_id, autn, rand); + pack_authentication_request(reply_msg, ecm_ctx->enb_ue_s1ap_id, ecm_ctx->mme_ue_s1ap_id, autn, rand); //Send reply to eNB *reply_flag = true; @@ -1764,10 +1726,12 @@ s1ap_nas_transport::pack_identity_request(srslte::byte_buffer_t *reply_msg, uint } bool -s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte_buffer_t *reply_msg) +s1ap_nas_transport::pack_emm_information( ue_ctx_t *ue_ctx, srslte::byte_buffer_t *reply_msg) { srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); + ue_emm_ctx_t *emm_ctx = &ue_ctx->emm_ctx; + ue_ecm_ctx_t *ecm_ctx = &ue_ctx->ecm_ctx; //Setup initiating message LIBLTE_S1AP_S1AP_PDU_STRUCT tx_pdu; bzero(&tx_pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); @@ -1782,8 +1746,8 @@ s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte //Setup Dw NAS structure LIBLTE_S1AP_MESSAGE_DOWNLINKNASTRANSPORT_STRUCT *dw_nas = &init->choice.DownlinkNASTransport; dw_nas->ext=false; - dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ecm_ctx->mme_ue_s1ap_id;//FIXME Change name - dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ecm_ctx->enb_ue_s1ap_id; + dw_nas->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ecm_ctx->mme_ue_s1ap_id;//FIXME Change name + dw_nas->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ecm_ctx->enb_ue_s1ap_id; dw_nas->HandoverRestrictionList_present=false; dw_nas->SubscriberProfileIDforRFP_present=false; @@ -1799,13 +1763,9 @@ s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte emm_info.utc_and_local_time_zone_present = false; emm_info.net_dst_present = false; - ue_emm_ctx_t *ue_emm_ctx = m_s1ap->find_ue_emm_ctx_from_imsi(ue_ecm_ctx->imsi); - if(ue_emm_ctx ==NULL) - return false; - uint8_t sec_hdr_type =2; - ue_emm_ctx->security_ctxt.dl_nas_count++; - LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, ue_emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); + emm_ctx->security_ctxt.dl_nas_count++; + LIBLTE_ERROR_ENUM err = liblte_mme_pack_emm_information_msg(&emm_info, sec_hdr_type, emm_ctx->security_ctxt.dl_nas_count, (LIBLTE_BYTE_MSG_STRUCT *) nas_buffer); if(err != LIBLTE_SUCCESS) { m_s1ap_log->error("Error packing EMM Information\n"); @@ -1814,8 +1774,8 @@ s1ap_nas_transport::pack_emm_information( ue_ecm_ctx_t *ue_ecm_ctx, srslte::byte } uint8_t mac[4]; - srslte::security_128_eia1 (&ue_emm_ctx->security_ctxt.k_nas_int[16], - ue_emm_ctx->security_ctxt.dl_nas_count, + srslte::security_128_eia1 (&emm_ctx->security_ctxt.k_nas_int[16], + emm_ctx->security_ctxt.dl_nas_count, 0, SECURITY_DIRECTION_DOWNLINK, &nas_buffer->msg[5],