From 7eebd71627b0e09b9077d8c5191945496af70da5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 9 Dec 2020 14:51:24 +0000 Subject: [PATCH] Added S1AP E-RAB release command/response handling to srsENB. Added the ability to srsEPC to send the E-RAB release command. --- lib/include/srslte/asn1/s1ap_utils.h | 1 + .../srslte/interfaces/enb_interfaces.h | 8 +- .../srslte/interfaces/epc_interfaces.h | 4 + srsenb/hdr/stack/rrc/rrc.h | 4 + srsenb/hdr/stack/rrc/rrc_bearer_cfg.h | 2 +- srsenb/hdr/stack/rrc/rrc_ue.h | 1 + srsenb/hdr/stack/upper/s1ap.h | 9 +- srsenb/src/stack/rrc/rrc.cc | 26 +++++ srsenb/src/stack/rrc/rrc_bearer_cfg.cc | 6 +- srsenb/src/stack/rrc/rrc_ue.cc | 25 ++--- srsenb/src/stack/upper/s1ap.cc | 69 +++++++++++++ srsepc/hdr/mme/s1ap.h | 14 ++- srsepc/hdr/mme/s1ap_erab_mngmt_proc.h | 56 +++++++++++ srsepc/src/mme/nas.cc | 43 ++++---- srsepc/src/mme/s1ap.cc | 11 +++ srsepc/src/mme/s1ap_erab_mngmt_proc.cc | 99 +++++++++++++++++++ 16 files changed, 333 insertions(+), 45 deletions(-) create mode 100644 srsepc/hdr/mme/s1ap_erab_mngmt_proc.h create mode 100644 srsepc/src/mme/s1ap_erab_mngmt_proc.cc diff --git a/lib/include/srslte/asn1/s1ap_utils.h b/lib/include/srslte/asn1/s1ap_utils.h index fd7178d3c..a5d6f16b3 100644 --- a/lib/include/srslte/asn1/s1ap_utils.h +++ b/lib/include/srslte/asn1/s1ap_utils.h @@ -25,6 +25,7 @@ namespace s1ap { struct init_context_setup_request_s; struct ue_context_mod_request_s; struct erab_setup_request_s; +struct erab_release_cmd_s; struct ue_paging_id_c; struct ho_request_s; struct sourceenb_to_targetenb_transparent_container_s; diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 55f6cea31..84d96cf01 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -411,6 +411,10 @@ public: virtual bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) = 0; virtual bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) = 0; virtual bool release_erabs(uint32_t rnti) = 0; + virtual void release_erabs(uint32_t rnti, + const asn1::s1ap::erab_release_cmd_s& msg, + std::vector* erabs_released, + std::vector* erabs_failed_to_release) = 0; virtual void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& ue_paging_id) = 0; /** @@ -456,12 +460,12 @@ public: }; virtual void - initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) = 0; + initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) = 0; virtual void initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu, uint32_t m_tmsi, - uint8_t mmec) = 0; + uint8_t mmec) = 0; virtual void write_pdu(uint16_t rnti, srslte::unique_byte_buffer_t pdu) = 0; virtual bool user_exists(uint16_t rnti) = 0; diff --git a/lib/include/srslte/interfaces/epc_interfaces.h b/lib/include/srslte/interfaces/epc_interfaces.h index f20f82058..1a0469198 100644 --- a/lib/include/srslte/interfaces/epc_interfaces.h +++ b/lib/include/srslte/interfaces/epc_interfaces.h @@ -59,6 +59,10 @@ public: virtual nas* find_nas_ctx_from_imsi(uint64_t imsi) = 0; virtual bool send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup) = 0; virtual bool send_ue_context_release_command(uint32_t mme_ue_s1ap_id) = 0; + virtual bool send_erab_release_command(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + std::vector erabs_to_release, + struct sctp_sndrcvinfo enb_sri) = 0; virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t* nas_msg, diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 5d4ce4085..14d97c9e0 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -77,6 +77,10 @@ public: bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) override; bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) override; bool release_erabs(uint32_t rnti) override; + void release_erabs(uint32_t rnti, + const asn1::s1ap::erab_release_cmd_s& msg, + std::vector* erabs_released, + std::vector* erabs_failed_to_release) override; void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& UEPagingID) override; void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t rrc_container) override; uint16_t diff --git a/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h b/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h index da0f8578a..bf4f0041e 100644 --- a/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h +++ b/srsenb/hdr/stack/rrc/rrc_bearer_cfg.h @@ -67,7 +67,7 @@ public: const asn1::bounded_bitstring<1, 160, true, true>& addr, uint32_t teid_out, const asn1::unbounded_octstring* nas_pdu); - void release_erab(uint8_t erab_id); + bool release_erab(uint8_t erab_id); void release_erabs(); // Methods to apply bearer updates diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 0ad127a56..3d5afad37 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -65,6 +65,7 @@ public: bool setup_erabs(const asn1::s1ap::erab_to_be_setup_list_ctxt_su_req_l& e); bool setup_erabs(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e); bool release_erabs(); + bool release_erab(uint32_t erab_id); // handover void handle_ho_preparation_complete(bool is_success, srslte::unique_byte_buffer_t container); diff --git a/srsenb/hdr/stack/upper/s1ap.h b/srsenb/hdr/stack/upper/s1ap.h index 3129e8522..f1e295dd4 100644 --- a/srsenb/hdr/stack/upper/s1ap.h +++ b/srsenb/hdr/stack/upper/s1ap.h @@ -55,7 +55,7 @@ public: // RRC interface void - initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) override; + initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu) override; void initial_ue(uint16_t rnti, asn1::s1ap::rrc_establishment_cause_e cause, srslte::unique_byte_buffer_t pdu, @@ -84,7 +84,7 @@ public: // Stack interface bool - handle_mme_rx_msg(srslte::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_mme_rx_msg(srslte::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void start_pcap(srslte::s1ap_pcap* pcap_); private: @@ -138,6 +138,7 @@ private: bool handle_uectxtreleasecommand(const asn1::s1ap::ue_context_release_cmd_s& msg); bool handle_s1setupfailure(const asn1::s1ap::s1_setup_fail_s& msg); bool handle_erabsetuprequest(const asn1::s1ap::erab_setup_request_s& msg); + bool handle_erabreleasecommand(const asn1::s1ap::erab_release_cmd_s& msg); bool handle_uecontextmodifyrequest(const asn1::s1ap::ue_context_mod_request_s& msg); // bool send_ue_capabilities(uint16_t rnti, LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *caps) @@ -156,7 +157,7 @@ private: struct ts1_reloc_prep_expired {}; ho_prep_proc_t(s1ap::ue* ue_); srslte::proc_outcome_t - init(uint32_t target_eci_, srslte::plmn_id_t target_plmn_, srslte::unique_byte_buffer_t rrc_container); + init(uint32_t target_eci_, srslte::plmn_id_t target_plmn_, srslte::unique_byte_buffer_t rrc_container); srslte::proc_outcome_t step() { return srslte::proc_outcome_t::yield; } srslte::proc_outcome_t react(ts1_reloc_prep_expired e); srslte::proc_outcome_t react(const asn1::s1ap::ho_prep_fail_s& msg); @@ -189,6 +190,8 @@ private: bool send_initial_ctxt_setup_response(const asn1::s1ap::init_context_setup_resp_s& res_); bool send_initial_ctxt_setup_failure(); bool send_erab_setup_response(const asn1::s1ap::erab_setup_resp_s& res_); + bool send_erab_release_response(const std::vector& erabs_successfully_released, + const std::vector& erabs_failed_to_release); bool was_uectxtrelease_requested() const { return release_requested; } ue_ctxt_t ctxt = {}; diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index d67277f5c..a10b364b6 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -307,6 +307,32 @@ bool rrc::release_erabs(uint32_t rnti) return ret; } +void rrc::release_erabs(uint32_t rnti, + const asn1::s1ap::erab_release_cmd_s& msg, + std::vector* erabs_released, + std::vector* erabs_failed_to_release) +{ + rrc_log->info("Releasing E-RAB for 0x%x\n", rnti); + auto user_it = users.find(rnti); + + if (user_it == users.end()) { + rrc_log->warning("Unrecognised rnti: 0x%x\n", rnti); + return; + } + + for (uint32_t i = 0; i < msg.protocol_ies.erab_to_be_released_list.value.size(); i++) { + const asn1::s1ap::erab_item_s& erab_to_release = + msg.protocol_ies.erab_to_be_released_list.value[i].value.erab_item(); + bool ret = user_it->second->release_erab(erab_to_release.erab_id); + if (ret) { + erabs_released->push_back(erab_to_release.erab_id); + } else { + erabs_failed_to_release->push_back(erab_to_release.erab_id); + } + } + return; +} + /******************************************************************************* Paging functions These functions use a different mutex because access different shared variables diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index abc028fe9..ab5778ea7 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -258,12 +258,12 @@ int bearer_cfg_handler::add_erab(uint8_t return SRSLTE_SUCCESS; } -void bearer_cfg_handler::release_erab(uint8_t erab_id) +bool bearer_cfg_handler::release_erab(uint8_t erab_id) { auto it = erabs.find(erab_id); if (it == erabs.end()) { log_h->warning("The user rnti=0x%x does not contain ERAB-ID=%d\n", rnti, erab_id); - return; + return false; } uint8_t drb_id = erab_id - 4; @@ -272,6 +272,8 @@ void bearer_cfg_handler::release_erab(uint8_t erab_id) erabs.erase(it); erab_info_list.erase(erab_id); + + return true; } void bearer_cfg_handler::release_erabs() diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 9cea7794d..cabd180b9 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -318,10 +318,10 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg) (uint32_t)msg->crit_exts.rrc_conn_reest_request_r8().ue_id.short_mac_i.to_number(), msg->crit_exts.rrc_conn_reest_request_r8().reest_cause.to_string().c_str()); if (is_idle()) { - uint16_t old_rnti = msg->crit_exts.rrc_conn_reest_request_r8().ue_id.c_rnti.to_number(); - uint16_t old_pci = msg->crit_exts.rrc_conn_reest_request_r8().ue_id.pci; + uint16_t old_rnti = msg->crit_exts.rrc_conn_reest_request_r8().ue_id.c_rnti.to_number(); + uint16_t old_pci = msg->crit_exts.rrc_conn_reest_request_r8().ue_id.pci; const enb_cell_common* old_cell = parent->cell_common_list->get_pci(old_pci); - auto ue_it = parent->users.find(old_rnti); + auto ue_it = parent->users.find(old_rnti); // Reject unrecognized rntis, and PCIs that do not belong to eNB if (ue_it != parent->users.end() and old_cell != nullptr and ue_it->second->ue_cell_list.get_enb_cc_idx(old_cell->enb_cc_idx) != nullptr) { @@ -333,7 +333,7 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg) // Recover security setup const enb_cell_common* pcell_cfg = get_ue_cc_cfg(UE_PCELL_CC_IDX); - ue_security_cfg = parent->users[old_rnti]->ue_security_cfg; + ue_security_cfg = parent->users[old_rnti]->ue_security_cfg; ue_security_cfg.regenerate_keys_handover(pcell_cfg->cell_cfg.pci, pcell_cfg->cell_cfg.dl_earfcn); // send reestablishment and restore bearer configuration @@ -467,12 +467,8 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu, bool phy_ rrc_conn_recfg_r8_ies_s& recfg_r8 = rrc_conn_recfg.crit_exts.set_c1().set_rrc_conn_recfg_r8(); // Fill RR Config Ded and SCells - apply_reconf_updates(recfg_r8, - current_ue_cfg, - parent->cfg, ue_cell_list, - bearer_list, - ue_capabilities, - phy_cfg_updated); + apply_reconf_updates( + recfg_r8, current_ue_cfg, parent->cfg, ue_cell_list, bearer_list, ue_capabilities, phy_cfg_updated); // Add measConfig if (mobility_handler != nullptr) { @@ -816,6 +812,11 @@ bool rrc::ue::release_erabs() return true; } +bool rrc::ue::release_erab(uint32_t erab_id) +{ + return bearer_list.release_erab(erab_id); +} + void rrc::ue::notify_s1ap_ue_erab_setup_response(const asn1::s1ap::erab_to_be_setup_list_bearer_su_req_l& e) { asn1::s1ap::erab_setup_resp_s res; @@ -856,8 +857,8 @@ enb_cell_common* rrc::ue::get_ue_cc_cfg(uint32_t ue_cc_idx) void rrc::ue::update_scells() { - const ue_cell_ded* pcell = ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX); - const enb_cell_common* pcell_cfg = pcell->cell_common; + const ue_cell_ded* pcell = ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX); + const enb_cell_common* pcell_cfg = pcell->cell_common; if (ue_cell_list.nof_cells() == pcell_cfg->scells.size() + 1) { // SCells already added diff --git a/srsenb/src/stack/upper/s1ap.cc b/srsenb/src/stack/upper/s1ap.cc index f36159b5a..eb655e338 100644 --- a/srsenb/src/stack/upper/s1ap.cc +++ b/srsenb/src/stack/upper/s1ap.cc @@ -566,6 +566,8 @@ bool s1ap::handle_initiatingmessage(const init_msg_s& msg) return handle_paging(msg.value.paging()); case s1ap_elem_procs_o::init_msg_c::types_opts::erab_setup_request: return handle_erabsetuprequest(msg.value.erab_setup_request()); + case s1ap_elem_procs_o::init_msg_c::types_opts::erab_release_cmd: + return handle_erabreleasecommand(msg.value.erab_release_cmd()); case s1ap_elem_procs_o::init_msg_c::types_opts::ue_context_mod_request: return handle_uecontextmodifyrequest(msg.value.ue_context_mod_request()); case s1ap_elem_procs_o::init_msg_c::types_opts::ho_request: @@ -704,6 +706,32 @@ bool s1ap::handle_erabsetuprequest(const erab_setup_request_s& msg) return rrc->setup_ue_erabs(u->ctxt.rnti, msg); } +bool s1ap::handle_erabreleasecommand(const erab_release_cmd_s& msg) +{ + s1ap_log->info("Received ERABReleaseCommand\n"); + if (msg.ext) { + s1ap_log->warning("Not handling S1AP message extension\n"); + } + ue* u = find_s1apmsg_user(msg.protocol_ies.enb_ue_s1ap_id.value.value, msg.protocol_ies.mme_ue_s1ap_id.value.value); + if (u == nullptr) { + return false; + } + + std::vector erab_successful_release = {}; + std::vector erab_failed_to_release = {}; + + // Release E-RABs from RRC + rrc->release_erabs(u->ctxt.rnti, msg, &erab_successful_release, &erab_failed_to_release); + + // Send E-RAB release response back to the MME + if (not u->send_erab_release_response(erab_successful_release, erab_failed_to_release)) { + s1ap_log->info("Failed to send ERABReleaseResponse\n"); + return false; + } + + return true; +} + bool s1ap::handle_uecontextmodifyrequest(const ue_context_mod_request_s& msg) { s1ap_log->info("Received UeContextModificationRequest\n"); @@ -1203,6 +1231,47 @@ bool s1ap::ue::send_uectxtmodifyfailure(const cause_c& cause) return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "UEContextModificationFailure"); } +bool s1ap::ue::send_erab_release_response(const std::vector& erabs_successfully_released, + const std::vector& erabs_failed_to_release) +{ + if (not s1ap_ptr->mme_connected) { + return false; + } + + asn1::s1ap::s1ap_pdu_c tx_pdu; + tx_pdu.set_successful_outcome().load_info_obj(ASN1_S1AP_ID_ERAB_RELEASE); + + auto& container = tx_pdu.successful_outcome().value.erab_release_resp().protocol_ies; + container.enb_ue_s1ap_id.value = ctxt.enb_ue_s1ap_id; + container.mme_ue_s1ap_id.value = ctxt.mme_ue_s1ap_id; + + // Fill in which E-RABs were successfully released + if (not erabs_successfully_released.empty()) { + container.erab_release_list_bearer_rel_comp_present = true; + container.erab_release_list_bearer_rel_comp.value.resize(erabs_successfully_released.size()); + for (uint32_t i = 0; i < container.erab_release_list_bearer_rel_comp.value.size(); i++) { + container.erab_release_list_bearer_rel_comp.value[i].load_info_obj( + ASN1_S1AP_ID_ERAB_RELEASE_ITEM_BEARER_REL_COMP); + container.erab_release_list_bearer_rel_comp.value[i].value.erab_release_item_bearer_rel_comp().erab_id = + erabs_successfully_released[i]; + } + } + + // Fill in which E-RABs were *not* successfully released + if (not erabs_failed_to_release.empty()) { + container.erab_failed_to_release_list_present = true; + container.erab_failed_to_release_list.value.resize(erabs_failed_to_release.size()); + for (uint32_t i = 0; i < container.erab_failed_to_release_list.value.size(); i++) { + container.erab_failed_to_release_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM); + container.erab_failed_to_release_list.value[i].value.erab_item().erab_id = erabs_failed_to_release[i]; + container.erab_failed_to_release_list.value[i].value.erab_item().cause.set(asn1::s1ap::cause_c::types::misc); + container.erab_failed_to_release_list.value[i].value.erab_item().cause.misc() = + asn1::s1ap::cause_misc_opts::unspecified; + } + } + + return s1ap_ptr->sctp_send_s1ap_pdu(tx_pdu, ctxt.rnti, "E_RABReleaseResponse"); +} /********************* * Handover Messages ********************/ diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index aa69bcf53..c458d8e1f 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -15,6 +15,7 @@ #include "mme_gtpc.h" #include "nas.h" #include "s1ap_ctx_mngmt_proc.h" +#include "s1ap_erab_mngmt_proc.h" #include "s1ap_mngmt_proc.h" #include "s1ap_nas_transport.h" #include "s1ap_paging.h" @@ -89,10 +90,11 @@ public: srslte::log_filter* m_s1ap_log; srslte::log_filter* m_nas_log; - s1ap_mngmt_proc* m_s1ap_mngmt_proc; - s1ap_nas_transport* m_s1ap_nas_transport; - s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; - s1ap_paging* m_s1ap_paging; + s1ap_mngmt_proc* m_s1ap_mngmt_proc; + s1ap_nas_transport* m_s1ap_nas_transport; + s1ap_ctx_mngmt_proc* m_s1ap_ctx_mngmt_proc; + s1ap_erab_mngmt_proc* m_s1ap_erab_mngmt_proc; + s1ap_paging* m_s1ap_paging; std::map m_tmsi_to_imsi; std::map m_active_enbs; @@ -100,6 +102,10 @@ public: // Interfaces virtual bool send_initial_context_setup_request(uint64_t imsi, uint16_t erab_to_setup); virtual bool send_ue_context_release_command(uint32_t mme_ue_s1ap_id); + virtual bool send_erab_release_command(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + std::vector erabs_to_release, + struct sctp_sndrcvinfo enb_sri); virtual bool send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t* nas_msg, diff --git a/srsepc/hdr/mme/s1ap_erab_mngmt_proc.h b/srsepc/hdr/mme/s1ap_erab_mngmt_proc.h new file mode 100644 index 000000000..9541ca083 --- /dev/null +++ b/srsepc/hdr/mme/s1ap_erab_mngmt_proc.h @@ -0,0 +1,56 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2020 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ +#ifndef SRSEPC_S1AP_ERAB_MNGMT_PROC_H +#define SRSEPC_S1AP_ERAB_MNGMT_PROC_H + +#include "mme_gtpc.h" +#include "s1ap_common.h" +#include "srslte/asn1/s1ap.h" +#include "srslte/common/buffer_pool.h" +#include "srslte/common/common.h" +#include "srslte/common/log_filter.h" +#include + +namespace srsepc { + +class s1ap; + +class s1ap_erab_mngmt_proc +{ +public: + static s1ap_erab_mngmt_proc* m_instance; + static s1ap_erab_mngmt_proc* get_instance(void); + static void cleanup(void); + + void init(void); + + bool send_erab_release_command(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + std::vector erabs_to_release, + struct sctp_sndrcvinfo enb_sri); + bool handle_erab_release_response(const asn1::s1ap::init_context_setup_resp_s& in_ctxt_resp); + +private: + s1ap_erab_mngmt_proc(); + virtual ~s1ap_erab_mngmt_proc(); + + s1ap* m_s1ap = nullptr; + srslte::log_filter* m_s1ap_log = nullptr; + + s1ap_args_t m_s1ap_args; + + mme_gtpc* m_mme_gtpc = nullptr; + srslte::byte_buffer_pool* m_pool = nullptr; +}; + +} // namespace srsepc +#endif // SRSEPC_S1AP_CTX_MNGMT_PROC_H diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index e2c2cf5f8..420cfe70f 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -16,6 +16,7 @@ #include "srslte/common/security.h" #include #include // for printing uint64_t +#include #include #include @@ -115,14 +116,14 @@ bool nas::handle_attach_request(uint32_t enb_ue_s1ap_id, srslte::console("Attach request -- Attach type: %d\n", attach_req.eps_attach_type); nas_log->info("Attach request -- Attach type: %d\n", attach_req.eps_attach_type); srslte::console("Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d\n", - attach_req.ue_network_cap.eea[0], - attach_req.ue_network_cap.eea[1], - attach_req.ue_network_cap.eea[2], - attach_req.ue_network_cap.eea[3], - attach_req.ue_network_cap.eea[4], - attach_req.ue_network_cap.eea[5], - attach_req.ue_network_cap.eea[6], - attach_req.ue_network_cap.eea[7]); + attach_req.ue_network_cap.eea[0], + attach_req.ue_network_cap.eea[1], + attach_req.ue_network_cap.eea[2], + attach_req.ue_network_cap.eea[3], + attach_req.ue_network_cap.eea[4], + attach_req.ue_network_cap.eea[5], + attach_req.ue_network_cap.eea[6], + attach_req.ue_network_cap.eea[7]); nas_log->info("Attach Request -- UE Network Capabilities EEA: %d%d%d%d%d%d%d%d\n", attach_req.ue_network_cap.eea[0], attach_req.ue_network_cap.eea[1], @@ -133,14 +134,14 @@ bool nas::handle_attach_request(uint32_t enb_ue_s1ap_id, attach_req.ue_network_cap.eea[6], attach_req.ue_network_cap.eea[7]); srslte::console("Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d\n", - attach_req.ue_network_cap.eia[0], - attach_req.ue_network_cap.eia[1], - attach_req.ue_network_cap.eia[2], - attach_req.ue_network_cap.eia[3], - attach_req.ue_network_cap.eia[4], - attach_req.ue_network_cap.eia[5], - attach_req.ue_network_cap.eia[6], - attach_req.ue_network_cap.eia[7]); + attach_req.ue_network_cap.eia[0], + attach_req.ue_network_cap.eia[1], + attach_req.ue_network_cap.eia[2], + attach_req.ue_network_cap.eia[3], + attach_req.ue_network_cap.eia[4], + attach_req.ue_network_cap.eia[5], + attach_req.ue_network_cap.eia[6], + attach_req.ue_network_cap.eia[7]); nas_log->info("Attach Request -- UE Network Capabilities EIA: %d%d%d%d%d%d%d%d\n", attach_req.ue_network_cap.eia[0], attach_req.ue_network_cap.eia[1], @@ -151,7 +152,7 @@ bool nas::handle_attach_request(uint32_t enb_ue_s1ap_id, attach_req.ue_network_cap.eia[6], attach_req.ue_network_cap.eia[7]); srslte::console("Attach Request -- MS Network Capabilities Present: %s\n", - attach_req.ms_network_cap_present ? "true" : "false"); + attach_req.ms_network_cap_present ? "true" : "false"); nas_log->info("Attach Request -- MS Network Capabilities Present: %s\n", attach_req.ms_network_cap_present ? "true" : "false"); srslte::console("PDN Connectivity Request -- EPS Bearer Identity requested: %d\n", pdn_con_req.eps_bearer_id); @@ -159,7 +160,7 @@ bool nas::handle_attach_request(uint32_t enb_ue_s1ap_id, srslte::console("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); nas_log->info("PDN Connectivity Request -- Procedure Transaction Id: %d\n", pdn_con_req.proc_transaction_id); srslte::console("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", - pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); + pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); nas_log->info("PDN Connectivity Request -- ESM Information Transfer requested: %s\n", pdn_con_req.esm_info_transfer_flag_present ? "true" : "false"); @@ -422,9 +423,9 @@ bool nas::handle_guti_attach_request_known_ue(nas* gtpc_interface_nas* gtpc = itf.gtpc; srslte::console("Found UE context. IMSI: %015" PRIu64 ", old eNB UE S1ap Id %d, old MME UE S1AP Id %d\n", - emm_ctx->imsi, - ecm_ctx->enb_ue_s1ap_id, - ecm_ctx->mme_ue_s1ap_id); + emm_ctx->imsi, + ecm_ctx->enb_ue_s1ap_id, + ecm_ctx->mme_ue_s1ap_id); // Check NAS integrity msg_valid = nas_ctx->integrity_check(nas_rx); diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 806850d23..d4ff52323 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -74,6 +74,8 @@ int s1ap::init(s1ap_args_t s1ap_args, srslte::log_filter* nas_log, srslte::log_f m_s1ap_nas_transport->init(); m_s1ap_ctx_mngmt_proc = s1ap_ctx_mngmt_proc::get_instance(); // Context Management Procedures m_s1ap_ctx_mngmt_proc->init(); + m_s1ap_erab_mngmt_proc = s1ap_erab_mngmt_proc::get_instance(); // E-RAB Management Procedures + m_s1ap_erab_mngmt_proc->init(); m_s1ap_paging = s1ap_paging::get_instance(); // Paging m_s1ap_paging->init(); @@ -619,6 +621,15 @@ bool s1ap::send_ue_context_release_command(uint32_t mme_ue_s1ap_id) return true; } +bool s1ap::send_erab_release_command(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + std::vector erabs_to_be_released, + struct sctp_sndrcvinfo enb_sri) +{ + return m_s1ap_erab_mngmt_proc->send_erab_release_command( + enb_ue_s1ap_id, mme_ue_s1ap_id, erabs_to_be_released, enb_sri); +} + bool s1ap::send_downlink_nas_transport(uint32_t enb_ue_s1ap_id, uint32_t mme_ue_s1ap_id, srslte::byte_buffer_t* nas_msg, diff --git a/srsepc/src/mme/s1ap_erab_mngmt_proc.cc b/srsepc/src/mme/s1ap_erab_mngmt_proc.cc new file mode 100644 index 000000000..c32aa8836 --- /dev/null +++ b/srsepc/src/mme/s1ap_erab_mngmt_proc.cc @@ -0,0 +1,99 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2020 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsepc/hdr/mme/s1ap_erab_mngmt_proc.h" +#include "srsepc/hdr/mme/s1ap.h" +#include "srslte/common/bcd_helpers.h" +#include "srslte/common/buffer_pool.h" +#include "srslte/common/int_helpers.h" +#include "srslte/common/liblte_security.h" +#include + +namespace srsepc { + +s1ap_erab_mngmt_proc* s1ap_erab_mngmt_proc::m_instance = NULL; +pthread_mutex_t s1ap_erab_mngmt_proc_instance_mutex = PTHREAD_MUTEX_INITIALIZER; + +s1ap_erab_mngmt_proc::s1ap_erab_mngmt_proc() +{ + return; +} + +s1ap_erab_mngmt_proc::~s1ap_erab_mngmt_proc() +{ + return; +} + +s1ap_erab_mngmt_proc* s1ap_erab_mngmt_proc::get_instance() +{ + pthread_mutex_lock(&s1ap_erab_mngmt_proc_instance_mutex); + if (NULL == m_instance) { + m_instance = new s1ap_erab_mngmt_proc(); + } + pthread_mutex_unlock(&s1ap_erab_mngmt_proc_instance_mutex); + return (m_instance); +} + +void s1ap_erab_mngmt_proc::cleanup() +{ + pthread_mutex_lock(&s1ap_erab_mngmt_proc_instance_mutex); + if (NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } + pthread_mutex_unlock(&s1ap_erab_mngmt_proc_instance_mutex); +} + +void s1ap_erab_mngmt_proc::init() +{ + m_s1ap = s1ap::get_instance(); + m_s1ap_log = m_s1ap->m_s1ap_log; + m_s1ap_args = m_s1ap->m_s1ap_args; + m_pool = srslte::byte_buffer_pool::get_instance(); +} + +bool s1ap_erab_mngmt_proc::send_erab_release_command(uint32_t enb_ue_s1ap_id, + uint32_t mme_ue_s1ap_id, + std::vector erabs_to_release, + struct sctp_sndrcvinfo enb_sri) +{ + m_s1ap_log->info("Preparing to send E-RAB Release Command\n"); + + // Prepare reply PDU + s1ap_pdu_t tx_pdu; + tx_pdu.set_init_msg().load_info_obj(ASN1_S1AP_ID_ERAB_RELEASE); + + asn1::s1ap::erab_release_cmd_ies_container& erab_rel_cmd = tx_pdu.init_msg().value.erab_release_cmd().protocol_ies; + + // Add MME and eNB S1AP Ids + erab_rel_cmd.mme_ue_s1ap_id.value = mme_ue_s1ap_id; + erab_rel_cmd.enb_ue_s1ap_id.value = enb_ue_s1ap_id; + + // Number of E-RABs to be setup + erab_rel_cmd.erab_to_be_released_list.value.resize(erabs_to_release.size()); + for (uint32_t i = 0; i < erab_rel_cmd.erab_to_be_released_list.value.size(); i++) { + erab_rel_cmd.erab_to_be_released_list.value[i].load_info_obj(ASN1_S1AP_ID_ERAB_ITEM); + erab_rel_cmd.erab_to_be_released_list.value[i].value.erab_item().erab_id = erabs_to_release[i]; + erab_rel_cmd.erab_to_be_released_list.value[i].value.erab_item().cause.set(asn1::s1ap::cause_c::types::misc); + erab_rel_cmd.erab_to_be_released_list.value[i].value.erab_item().cause.misc() = + asn1::s1ap::cause_misc_opts::unspecified; + m_s1ap_log->info("Sending release comman to %d\n", erabs_to_release[i]); + } + + if (!m_s1ap->s1ap_tx_pdu(tx_pdu, &enb_sri)) { + m_s1ap_log->error("Error sending Initial Context Setup Request.\n"); + return false; + } + return true; +} + +} // namespace srsepc