From 0de1565e523f595b28ceeccec895435f9e03647e Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 4 Apr 2022 14:49:35 +0100 Subject: [PATCH] rrc,s1ap: configurable target eNB TACs during LTE handover. --- .../srsran/interfaces/enb_rrc_interface_types.h | 1 + lib/include/srsran/interfaces/enb_s1ap_interfaces.h | 1 + srsenb/hdr/stack/rrc/rrc_mobility.h | 4 +++- srsenb/hdr/stack/s1ap/s1ap.h | 8 ++++++-- srsenb/src/enb_cfg_parser.cc | 10 +++++++++- srsenb/src/stack/rrc/rrc_mobility.cc | 8 ++++++-- srsenb/src/stack/s1ap/s1ap.cc | 11 ++++++++--- srsenb/test/common/dummy_classes.h | 1 + srsenb/test/rrc/test_helpers.h | 1 + 9 files changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/include/srsran/interfaces/enb_rrc_interface_types.h b/lib/include/srsran/interfaces/enb_rrc_interface_types.h index 00e9f664f..091241445 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interface_types.h +++ b/lib/include/srsran/interfaces/enb_rrc_interface_types.h @@ -34,6 +34,7 @@ struct meas_cell_cfg_t { asn1::rrc::q_offset_range_e cell_individual_offset; uint32_t allowed_meas_bw; bool direct_forward_path_available; + int tac; }; // neigh measurement Cell info diff --git a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h index 41013bc37..b6b2a0741 100644 --- a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h +++ b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h @@ -80,6 +80,7 @@ public: */ virtual bool send_ho_required(uint16_t rnti, uint32_t target_eci, + uint16_t target_tac, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index 8664be0a2..4b706269c 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -57,7 +57,8 @@ private: asn1::rrc::meas_cfg_s* diff_meas_cfg); // Handover from source cell - bool start_ho_preparation(uint32_t target_eci, uint8_t measobj_id, bool fwd_direct_path_available); + bool + start_ho_preparation(uint32_t target_eci, uint16_t target_tac, uint8_t measobj_id, bool fwd_direct_path_available); // Handover to target cell void fill_mobility_reconf_common(asn1::rrc::dl_dcch_msg_s& msg, @@ -81,6 +82,7 @@ private: // events struct ho_meas_report_ev { uint32_t target_eci = 0; + uint16_t target_tac = 0; const asn1::rrc::meas_obj_to_add_mod_s* meas_obj = nullptr; bool direct_fwd_path = false; }; diff --git a/srsenb/hdr/stack/s1ap/s1ap.h b/srsenb/hdr/stack/s1ap/s1ap.h index 0698dbc08..15951086f 100644 --- a/srsenb/hdr/stack/s1ap/s1ap.h +++ b/srsenb/hdr/stack/s1ap/s1ap.h @@ -81,6 +81,7 @@ public: bool is_mme_connected() override; bool send_ho_required(uint16_t rnti, uint32_t target_eci, + uint16_t target_tac, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, @@ -107,7 +108,7 @@ public: // Stack interface bool - handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void start_pcap(srsran::s1ap_pcap* pcap_); private: @@ -212,6 +213,7 @@ private: struct ts1_reloc_prep_expired {}; ho_prep_proc_t(s1ap::ue* ue_); srsran::proc_outcome_t init(uint32_t target_eci_, + uint16_t target_tac_, srsran::plmn_id_t target_plmn_, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, @@ -228,6 +230,7 @@ private: s1ap* s1ap_ptr = nullptr; uint32_t target_eci = 0; + uint16_t target_tac = 0; srsran::plmn_id_t target_plmn; srsran::unique_byte_buffer_t rrc_container; const asn1::s1ap::ho_cmd_s* ho_cmd_msg = nullptr; @@ -260,7 +263,7 @@ private: bool was_uectxtrelease_requested() const { return release_requested; } void - set_state(s1ap_proc_id_t state, const erab_id_list& erabs_updated, const erab_item_list& erabs_failed_to_update); + set_state(s1ap_proc_id_t state, const erab_id_list& erabs_updated, const erab_item_list& erabs_failed_to_update); s1ap_proc_id_t get_state() const { return current_state; } ue_ctxt_t ctxt = {}; @@ -268,6 +271,7 @@ private: private: bool send_ho_required(uint32_t target_eci_, + uint16_t target_tac_, srsran::plmn_id_t target_plmn_, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index cefade786..15d9e9061 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -776,6 +776,7 @@ static int parse_meas_cell_list(rrc_meas_cfg_t* meas_cfg, Setting& root) parse_default_field(cell.allowed_meas_bw, root[i], "allowed_meas_bw", 6u); asn1_parsers::default_number_to_enum( cell.cell_individual_offset, root[i], "cell_individual_offset", asn1::rrc::q_offset_range_opts::db0); + parse_default_field(cell.tac, root[i], "tac", -1); srsran_assert(srsran::is_lte_cell_nof_prb(cell.allowed_meas_bw), "Invalid measurement Bandwidth"); } return 0; @@ -1347,7 +1348,7 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ // Create dedicated cell configuration from RRC configuration for (auto it = rrc_cfg_->cell_list.begin(); it != rrc_cfg_->cell_list.end(); ++it) { - auto& cfg = *it; + cell_cfg_t& cfg = *it; phy_cell_cfg_t phy_cell_cfg = {}; phy_cell_cfg.cell = cell_cfg_; phy_cell_cfg.cell.id = cfg.pci; @@ -1396,6 +1397,13 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ } } + for (meas_cell_cfg_t& meas_cell : cfg.meas_cfg.meas_cells) { + if (meas_cell.tac < 0) { + // if meas cell TAC was not set, use current cell TAC. + meas_cell.tac = cfg.tac; + } + } + // Check if the enb cells PCIs won't lead to PSS detection issues auto is_pss_collision = [&cfg](const cell_cfg_t& c) { return c.pci % 3 == cfg.pci % 3 and c.dl_earfcn == cfg.dl_earfcn; diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 7c85668a5..bdecc72eb 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -273,9 +273,11 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr const enb_cell_common* c = rrc_enb->cell_common_list->get_pci(e.pci); if (meas_it != meas_list_cfg.end()) { meas_ev.target_eci = meas_it->eci; + meas_ev.target_tac = meas_it->tac; meas_ev.direct_fwd_path = meas_it->direct_forward_path_available; } else if (c != nullptr) { meas_ev.target_eci = (rrc_enb->cfg.enb_id << 8u) + c->cell_cfg.cell_id; + meas_ev.target_tac = pcell->cell_common->cell_cfg.tac; } else { logger.warning("The PCI=%d inside the MeasReport is not recognized.", e.pci); continue; @@ -296,6 +298,7 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg, srsr * - This struct goes in a transparent container to the S1AP */ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, + uint16_t target_tac, uint8_t measobj_id, bool fwd_direct_path_available) { @@ -405,7 +408,7 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, } return rrc_enb->s1ap->send_ho_required( - rrc_ue->rnti, target_eci, target_plmn, fwd_erabs, std::move(buffer), fwd_direct_path_available); + rrc_ue->rnti, target_eci, target_tac, target_plmn, fwd_erabs, std::move(buffer), fwd_direct_path_available); } /** @@ -653,7 +656,8 @@ void rrc::ue::rrc_mobility::s1_source_ho_st::enter(rrc_mobility* f, const ho_mea logger.info("Starting S1 Handover of rnti=0x%x to cellid=0x%x.", rrc_ue->rnti, ev.target_eci); report = ev; - if (not parent_fsm()->start_ho_preparation(report.target_eci, report.meas_obj->meas_obj_id, ev.direct_fwd_path)) { + if (not parent_fsm()->start_ho_preparation( + report.target_eci, report.target_tac, report.meas_obj->meas_obj_id, ev.direct_fwd_path)) { trigger(srsran::failure_ev{}); } } diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 6bb4174a8..6fb124728 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -118,6 +118,7 @@ void fill_erab_failed_setup_list(OutList& output_list, const s1ap::erab_item_lis s1ap::ue::ho_prep_proc_t::ho_prep_proc_t(s1ap::ue* ue_) : ue_ptr(ue_), s1ap_ptr(ue_->s1ap_ptr) {} srsran::proc_outcome_t s1ap::ue::ho_prep_proc_t::init(uint32_t target_eci_, + uint16_t target_tac_, srsran::plmn_id_t target_plmn_, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container_, @@ -125,11 +126,12 @@ srsran::proc_outcome_t s1ap::ue::ho_prep_proc_t::init(uint32_t { ho_cmd_msg = nullptr; target_eci = target_eci_; + target_tac = target_tac_; target_plmn = target_plmn_; procInfo("Sending HandoverRequired to MME id=%d", ue_ptr->ctxt.mme_ue_s1ap_id.value()); if (not ue_ptr->send_ho_required( - target_eci, target_plmn, fwd_erabs, std::move(rrc_container_), has_direct_fwd_path)) { + target_eci, target_tac, target_plmn, fwd_erabs, std::move(rrc_container_), has_direct_fwd_path)) { procError("Failed to send HORequired to cell 0x%x", target_eci); return srsran::proc_outcome_t::error; } @@ -1821,6 +1823,7 @@ void s1ap::ue::get_erab_addr(uint16_t erab_id, transp_addr_t& transp_addr, asn1: bool s1ap::send_ho_required(uint16_t rnti, uint32_t target_eci, + uint16_t target_tac, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, @@ -1835,7 +1838,8 @@ bool s1ap::send_ho_required(uint16_t rnti, } // launch procedure - if (not u->ho_prep_proc.launch(target_eci, target_plmn, fwd_erabs, std::move(rrc_container), has_direct_fwd_path)) { + if (not u->ho_prep_proc.launch( + target_eci, target_tac, target_plmn, fwd_erabs, std::move(rrc_container), has_direct_fwd_path)) { logger.error("Failed to initiate an HandoverPreparation procedure for user rnti=0x%x", u->ctxt.rnti); return false; } @@ -2101,6 +2105,7 @@ s1ap::ue::ue(s1ap* s1ap_ptr_) : s1ap_ptr(s1ap_ptr_), ho_prep_proc(this), logger( } bool s1ap::ue::send_ho_required(uint32_t target_eci, + uint16_t target_tac, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, @@ -2131,7 +2136,7 @@ bool s1ap::ue::send_ho_required(uint32_t target_eci, // set PLMN and TAI of target // NOTE: Only HO without TAU supported. uint16_t tmp16; - tmp16 = htons(s1ap_ptr->args.tac); + tmp16 = htons(target_tac); memcpy(targetenb.sel_tai.tac.data(), &tmp16, sizeof(uint16_t)); target_plmn.to_s1ap_plmn_bytes(targetenb.sel_tai.plm_nid.data()); // NOTE: Only HO to different Macro eNB is supported. diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 948f914d6..595a6e3d5 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -67,6 +67,7 @@ public: bool is_mme_connected() override { return true; } bool send_ho_required(uint16_t rnti, uint32_t target_eci, + uint16_t target_tac, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container, diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index 03a164a27..12c27c730 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -81,6 +81,7 @@ public: bool send_ho_required(uint16_t rnti, uint32_t target_eci, + uint16_t target_tac, srsran::plmn_id_t target_plmn, srsran::span fwd_erabs, srsran::unique_byte_buffer_t rrc_container,