diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index ba4a982eb..509a887ee 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -71,10 +71,6 @@ public: bool handle_initiating_message(LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *msg, struct sctp_sndrcvinfo *enb_sri); bool handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg); - //bool handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri); - //bool send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid); - //bool handle_initial_context_setup_response(LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPRESPONSE_STRUCT *in_ctxt_resp); - void activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi); void print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx); @@ -87,6 +83,8 @@ public: void add_new_ue_ctx(const ue_ctx_t &ue_ctx); bool delete_ue_ctx(ue_ctx_t *ue_ctx); + uint32_t allocate_m_tmsi(); + s1ap_args_t m_s1ap_args; srslte::log_filter *m_s1ap_log; @@ -94,6 +92,8 @@ public: s1ap_nas_transport* m_s1ap_nas_transport; s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; + std::map m_tmsi_to_s1ap_id; + private: s1ap(); virtual ~s1ap(); @@ -110,8 +110,8 @@ private: std::map m_active_ues; std::map > m_enb_id_to_ue_ids; uint32_t m_next_mme_ue_s1ap_id; + uint32_t m_next_m_tmsi; - //FIXME the GTP-C should be moved to the MME class, the the packaging of GTP-C messages is done. mme_gtpc *m_mme_gtpc; }; diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index e0887c44d..03eaadd35 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -73,7 +73,7 @@ s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter *s1ap_log) m_s1ap_args = s1ap_args; srslte::s1ap_mccmnc_to_plmn(s1ap_args.mcc, s1ap_args.mnc, &m_plmn); - + m_next_m_tmsi = rand(); //Init log m_s1ap_log = s1ap_log; @@ -307,243 +307,7 @@ s1ap::handle_successful_outcome(LIBLTE_S1AP_SUCCESSFULOUTCOME_STRUCT *msg) return true; } - /* -bool -s1ap::send_initial_context_setup_request(uint32_t mme_ue_s1ap_id, struct srslte::gtpc_create_session_response *cs_resp, struct srslte::gtpc_f_teid_ie sgw_ctrl_fteid) -{ - ue_ctx_t *ue_ctx; - - //Prepare reply PDU - LIBLTE_S1AP_S1AP_PDU_STRUCT pdu; - bzero(&pdu, sizeof(LIBLTE_S1AP_S1AP_PDU_STRUCT)); - pdu.choice_type = LIBLTE_S1AP_S1AP_PDU_CHOICE_INITIATINGMESSAGE; - - LIBLTE_S1AP_INITIATINGMESSAGE_STRUCT *init = &pdu.choice.initiatingMessage; - init->procedureCode = LIBLTE_S1AP_PROC_ID_INITIALCONTEXTSETUP; - init->choice_type = LIBLTE_S1AP_INITIATINGMESSAGE_CHOICE_INITIALCONTEXTSETUPREQUEST; - - LIBLTE_S1AP_MESSAGE_INITIALCONTEXTSETUPREQUEST_STRUCT *in_ctxt_req = &init->choice.InitialContextSetupRequest; - - LIBLTE_S1AP_E_RABTOBESETUPITEMCTXTSUREQ_STRUCT *erab_ctxt = &in_ctxt_req->E_RABToBeSetupListCtxtSUReq.buffer[0]; //FIXME support more than one erab - srslte::byte_buffer_t *reply_buffer = m_pool->allocate(); - - m_s1ap_log->info("Preparing to send Initial Context Setup request\n"); - - //Find UE Context - std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); - if(ue_ctx_it == m_active_ues.end()) - { - m_s1ap_log->error("Could not find UE to send Setup Context Request. MME S1AP Id: %d", mme_ue_s1ap_id); - return false; - } - ue_ctx = ue_ctx_it->second; - - //Add MME and eNB S1AP Ids - in_ctxt_req->MME_UE_S1AP_ID.MME_UE_S1AP_ID = ue_ctx->mme_ue_s1ap_id; - in_ctxt_req->eNB_UE_S1AP_ID.ENB_UE_S1AP_ID = ue_ctx->enb_ue_s1ap_id; - - //Set UE-AMBR - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateDL.BitRate=1000000000;//2^32-1 - in_ctxt_req->uEaggregateMaximumBitrate.uEaggregateMaximumBitRateUL.BitRate=1000000000;//FIXME Get UE-AMBR from HSS - - //Setup eRAB context - in_ctxt_req->E_RABToBeSetupListCtxtSUReq.len = 1; - erab_ctxt->e_RAB_ID.E_RAB_ID = cs_resp->eps_bearer_context_created.ebi; - //Setup E-RAB QoS parameters - erab_ctxt->e_RABlevelQoSParameters.qCI.QCI = 9; - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.priorityLevel.PriorityLevel = 15 ;//Lowest - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionCapability = LIBLTE_S1AP_PRE_EMPTIONCAPABILITY_SHALL_NOT_TRIGGER_PRE_EMPTION; - erab_ctxt->e_RABlevelQoSParameters.allocationRetentionPriority.pre_emptionVulnerability = LIBLTE_S1AP_PRE_EMPTIONVULNERABILITY_PRE_EMPTABLE; - - erab_ctxt->e_RABlevelQoSParameters.gbrQosInformation_present=false; - - //Set E-RAB S-GW F-TEID - if (cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present == false){ - m_s1ap_log->error("Did not receive S1-U TEID in create session response\n"); - return false; - } - erab_ctxt->transportLayerAddress.n_bits = 32; //IPv4 - uint32_t sgw_s1u_ip = htonl(cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4); - //uint32_t sgw_s1u_ip = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.ipv4; - uint8_t *tmp_ptr = erab_ctxt->transportLayerAddress.buffer; - liblte_value_2_bits(sgw_s1u_ip, &tmp_ptr, 32);//FIXME consider ipv6 - - uint32_t tmp_teid = cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid; - memcpy(erab_ctxt->gTP_TEID.buffer, &tmp_teid, sizeof(uint32_t)); - - //Set UE security capabilities and k_enb - bzero(in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer,sizeof(uint8_t)*16); - bzero(in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer,sizeof(uint8_t)*16); - for(int i = 0; i<3; i++) - { - if(ue_ctx->ue_network_cap.eea[i+1] == true) - { - in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 1; //EEA supported - } - else - { - in_ctxt_req->UESecurityCapabilities.encryptionAlgorithms.buffer[i] = 0; //EEA not supported - } - if(ue_ctx->ue_network_cap.eia[i+1] == true) - { - in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 1; //EEA supported - } - else - { - in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[i] = 0; //EEA not supported - } - // in_ctxt_req->UESecurityCapabilities.integrityProtectionAlgorithms.buffer[0] = 1; //EIA1 - } - uint8_t key_enb[32]; - liblte_security_generate_k_enb(ue_ctx->security_ctxt.k_asme, ue_ctx->security_ctxt.ul_nas_count, key_enb); - liblte_unpack(key_enb, 32, in_ctxt_req->SecurityKey.buffer); - m_s1ap_log->info("Generating KeNB with UL NAS COUNT: %d\n",ue_ctx->security_ctxt.ul_nas_count); - //Set Attach accepted and activat default bearer NAS messages - if(cs_resp->paa_present != true) - { - m_s1ap_log->error("PAA not present\n"); - return false; - } - if(cs_resp->paa.pdn_type != srslte::GTPC_PDN_TYPE_IPV4) - { - m_s1ap_log->error("IPv6 not supported yet\n"); - return false; - } - srslte::byte_buffer_t *nas_buffer = m_pool->allocate(); - m_s1ap_nas_transport->pack_attach_accept(ue_ctx, erab_ctxt, &cs_resp->paa, nas_buffer); - - - LIBLTE_ERROR_ENUM err = liblte_s1ap_pack_s1ap_pdu(&pdu, (LIBLTE_BYTE_MSG_STRUCT*)reply_buffer); - if(err != LIBLTE_SUCCESS) - { - m_s1ap_log->error("Could not pack Initial Context Setup Request Message\n"); - return false; - } - //Send Reply to eNB - ssize_t n_sent = sctp_send(m_s1mme,reply_buffer->msg, reply_buffer->N_bytes, &ue_ctx->enb_sri, 0); - if(n_sent == -1) - { - m_s1ap_log->error("Failed to send Initial Context Setup Request\n"); - return false; - } - - //Change E-RAB state to Context Setup Requested and save S-GW control F-TEID - ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].state = ERAB_CTX_REQUESTED; - ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.teid = sgw_ctrl_fteid.teid; - ue_ctx->erabs_ctx[erab_ctxt->e_RAB_ID.E_RAB_ID].sgw_ctrl_fteid.ipv4 = sgw_ctrl_fteid.ipv4; - - struct in_addr addr; - addr.s_addr = sgw_s1u_ip; - m_s1ap_log->info("Sent Intial Context Setup Request. E-RAB id %d \n",erab_ctxt->e_RAB_ID.E_RAB_ID); - m_s1ap_log->info("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); - m_s1ap_log->console("Sent Intial Context Setup Request, E-RAB id %d\n",erab_ctxt->e_RAB_ID.E_RAB_ID); - m_s1ap_log->console("Initial Context -- S1-U TEID 0x%x. IP %s \n", tmp_teid,inet_ntoa(addr)); - - m_pool->deallocate(reply_buffer); - m_pool->deallocate(nas_buffer); - return true; -} - - -bool -s1ap::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; - std::map::iterator ue_ctx_it = m_active_ues.find(mme_ue_s1ap_id); - if (ue_ctx_it == m_active_ues.end()) - { - m_s1ap_log->error("Could not find UE's context in active UE's map\n"); - return false; - } - 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_ctx_it->second->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); - return false; - } - //Mark E-RAB with context setup - erab_ctx->state = ERAB_CTX_SETUP; - - //Set the GTP information - uint8_t *bit_ptr = in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].transportLayerAddress.buffer; - erab_ctx->enb_fteid.ipv4 = htonl(liblte_bits_2_value(&bit_ptr,32)); - memcpy(&erab_ctx->enb_fteid.teid, in_ctxt_resp->E_RABSetupListCtxtSURes.buffer[i].gTP_TEID.buffer, 4); - erab_ctx->enb_fteid.teid = ntohl(erab_ctx->enb_fteid.teid); - - char enb_addr_str[INET_ADDRSTRLEN+1]; - const char *err = inet_ntop(AF_INET, &erab_ctx->enb_fteid.ipv4,enb_addr_str,sizeof(enb_addr_str)); - if(err == NULL) - { - m_s1ap_log->error("Error converting IP to string\n"); - } - - m_s1ap_log->info("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); - m_s1ap_log->info("E-RAB Context -- eNB TEID 0x%x, eNB Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); - m_s1ap_log->console("E-RAB Context Setup. E-RAB id %d\n",erab_ctx->erab_id); - m_s1ap_log->console("E-RAB Context -- eNB TEID 0x%x; eNB GTP-U Address %s\n", erab_ctx->enb_fteid.teid, enb_addr_str); - - } - return true; -} - -bool -s1ap::handle_ue_context_release_request(LIBLTE_S1AP_MESSAGE_UECONTEXTRELEASEREQUEST_STRUCT *ue_rel, struct sctp_sndrcvinfo *enb_sri) -{ - - uint32_t mme_ue_s1ap_id = ue_rel->MME_UE_S1AP_ID.MME_UE_S1AP_ID; - 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); - std::map::iterator ue_ctx = m_active_ues.find(mme_ue_s1ap_id); - if(ue_ctx == m_active_ues.end() ) - { - m_s1ap_log->info("UE not found. MME-UE S1AP Id: %d\n", mme_ue_s1ap_id); - return false; - } - - //Delete UE within eNB UE set - std::map::iterator it = m_sctp_to_enb_id.find(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 any context at the SPGW - bool active = false; - for(int i=0;isecond->erabs_ctx[i].state != ERAB_DEACTIVATED) - { - active = true; - break; - } - } - if(active == true) - { - //There are active E-RABs, send delete session request - m_mme_gtpc->send_delete_session_request(ue_ctx->second); - } - - //Delete UE context - delete ue_ctx->second; - m_active_ues.erase(ue_ctx); - m_s1ap_log->info("Deleted UE Context.\n"); - return true; -} - */ bool s1ap::delete_ue_ctx(ue_ctx_t *ue_ctx) { @@ -668,6 +432,12 @@ s1ap::activate_eps_bearer(uint32_t mme_s1ap_id, uint8_t ebi) return; } +uint32_t +s1ap::allocate_m_tmsi() +{ + return m_next_m_tmsi++; +} + void s1ap::print_enb_ctx_info(const std::string &prefix, const enb_ctx_t &enb_ctx) { diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 3a8425f91..6746b7e00 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -81,7 +81,7 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA LIBLTE_MME_ATTACH_REQUEST_MSG_STRUCT attach_req; LIBLTE_MME_PDN_CONNECTIVITY_REQUEST_MSG_STRUCT pdn_con_req; - uint64_t imsi; + uint64_t imsi = 0; uint8_t k_asme[32]; uint8_t autn[16]; uint8_t rand[6]; @@ -106,13 +106,31 @@ s1ap_nas_transport::handle_initial_ue_message(LIBLTE_S1AP_MESSAGE_INITIALUEMESSA return false; } - //Get IMSI - imsi = 0; - for(int i=0;i<=14;i++){ - imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + //Get Mobile ID + if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_IMSI) + { + //IMSI style attach + imsi = 0; + for(int i=0;i<=14;i++){ + imsi += attach_req.eps_mobile_id.imsi[i]*std::pow(10,14-i); + } + } + else if(attach_req.eps_mobile_id.type_of_id == LIBLTE_MME_EPS_MOBILE_ID_TYPE_GUTI) + { + //GUTI style attach + uint32_t m_tmsi = attach_req.eps_mobile_id.guti.m_tmsi; + std::map::iterator it = m_s1ap->m_tmsi_to_s1ap_id.find(m_tmsi); + if(it == m_s1ap->m_tmsi_to_s1ap_id.end()) + { + //FIXME Send Id request + m_s1ap_log->info("Could not find M-TMSI in attach request\n"); + return false; + } + ue_ctx_t *tmp = m_s1ap->find_ue_ctx(it->second); + imsi = tmp->imsi; } m_s1ap_log->console("Attach request from IMSI: %015lu\n", imsi); - m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); + m_s1ap_log->info("Attach request from IMSI: %015lu\n", imsi); //Get UE network capabilities memcpy(&ue_ctx.ue_network_cap, &attach_req.ue_network_cap, sizeof(LIBLTE_MME_UE_NETWORK_CAPABILITY_STRUCT)); @@ -745,18 +763,18 @@ s1ap_nas_transport::pack_attach_accept(ue_ctx_t *ue_ctx, LIBLTE_S1AP_E_RABTOBESE attach_accept.t3412.value = 30; // 30 minute periodic timer //FIXME: Set tai_list from config attach_accept.tai_list.N_tais = 1; - attach_accept.tai_list.tai[0].mcc = 1; - attach_accept.tai_list.tai[0].mnc = 1; - attach_accept.tai_list.tai[0].tac = 7; + attach_accept.tai_list.tai[0].mcc = m_s1ap->m_s1ap_args.mcc; + attach_accept.tai_list.tai[0].mnc = m_s1ap->m_s1ap_args.mnc; + attach_accept.tai_list.tai[0].tac = m_s1ap->m_s1ap_args.tac; //Allocate a GUTI ot the UE attach_accept.guti_present=true; attach_accept.guti.type_of_id = 6; //110 -> GUTI - attach_accept.guti.guti.mcc = 1; - attach_accept.guti.guti.mnc = 1; + attach_accept.guti.guti.mcc = m_s1ap->m_s1ap_args.mcc; + attach_accept.guti.guti.mnc = m_s1ap->m_s1ap_args.mnc; attach_accept.guti.guti.mme_group_id = 0x0001; attach_accept.guti.guti.mme_code = 0x1a; - attach_accept.guti.guti.m_tmsi = 0x124ae; + attach_accept.guti.guti.m_tmsi = m_s1ap->allocate_m_tmsi(); /* typedef struct{ uint32 m_tmsi;