diff --git a/lib/include/srslte/asn1/asn1_utils.h b/lib/include/srslte/asn1/asn1_utils.h index 51bb4dce4..f842cce13 100644 --- a/lib/include/srslte/asn1/asn1_utils.h +++ b/lib/include/srslte/asn1/asn1_utils.h @@ -117,9 +117,7 @@ class bit_ref_impl public: bit_ref_impl() = default; bit_ref_impl(Ptr start_ptr_, uint32_t max_size_) : - ptr(start_ptr_), - start_ptr(start_ptr_), - max_ptr(max_size_ + start_ptr_) + ptr(start_ptr_), start_ptr(start_ptr_), max_ptr(max_size_ + start_ptr_) {} int distance(const bit_ref_impl& other) const; @@ -1123,6 +1121,7 @@ class copy_ptr public: copy_ptr() : ptr(nullptr) {} explicit copy_ptr(T* ptr_) : ptr(ptr_) {} + copy_ptr(copy_ptr&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; } copy_ptr(const copy_ptr& other) { ptr = (other.ptr == nullptr) ? nullptr : new T(*other.ptr); } ~copy_ptr() { destroy_(); } copy_ptr& operator=(const copy_ptr& other) @@ -1132,6 +1131,14 @@ public: } return *this; } + copy_ptr& operator=(copy_ptr&& other) noexcept + { + if (this != &other) { + ptr = other.ptr; + other.ptr = nullptr; + } + return *this; + } bool operator==(const copy_ptr& other) const { return *ptr == *other; } T* operator->() { return ptr; } const T* operator->() const { return ptr; } diff --git a/lib/include/srslte/interfaces/enb_rrc_interface_types.h b/lib/include/srslte/interfaces/enb_rrc_interface_types.h index 0608cd6fe..2bbbbadcb 100644 --- a/lib/include/srslte/interfaces/enb_rrc_interface_types.h +++ b/lib/include/srslte/interfaces/enb_rrc_interface_types.h @@ -47,8 +47,7 @@ struct rrc_meas_cfg_t { std::vector meas_cells; std::vector meas_reports; asn1::rrc::quant_cfg_eutra_s quant_cfg; - // TODO: Add blacklist cells - // TODO: Add multiple meas configs + uint32_t meas_gap_period; }; // Cell/Sector configuration diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index cc8c74a41..f32f059fd 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -145,7 +145,7 @@ private: std::unique_ptr cell_common_list; // state - std::unique_ptr pucch_res_list; + std::unique_ptr cell_res_list; std::map > users; // NOTE: has to have fixed addr std::map pending_paging; diff --git a/srsenb/hdr/stack/rrc/rrc_cell_cfg.h b/srsenb/hdr/stack/rrc/rrc_cell_cfg.h index 172c099da..c9edbfc11 100644 --- a/srsenb/hdr/stack/rrc/rrc_cell_cfg.h +++ b/srsenb/hdr/stack/rrc/rrc_cell_cfg.h @@ -27,18 +27,20 @@ namespace srsenb { -class pucch_res_common +class cell_res_common { public: struct pucch_idx_sched_t { uint32_t nof_users[100][80]; }; - const static uint32_t N_PUCCH_MAX_PRB = 4; // Maximum number of PRB to use for PUCCH ACK/NACK in CS mode - const static uint32_t N_PUCCH_MAX_RES = 3 * SRSLTE_NRE * N_PUCCH_MAX_PRB; - pucch_idx_sched_t sr_sched = {}; - pucch_idx_sched_t cqi_sched = {}; - std::array n_pucch_cs_used = {}; + const static uint32_t N_PUCCH_MAX_PRB = 4; // Maximum number of PRB to use for PUCCH ACK/NACK in CS mode + const static uint32_t N_PUCCH_MAX_RES = 3 * SRSLTE_NRE * N_PUCCH_MAX_PRB; + + uint32_t next_measgap_offset = 0; + pucch_idx_sched_t sr_sched = {}; + pucch_idx_sched_t cqi_sched = {}; + std::array n_pucch_cs_used = {}; }; /** Storage of CQI/SR/PUCCH CS resources across multiple frequencies and for multiple users */ @@ -47,11 +49,11 @@ class freq_res_common_list public: explicit freq_res_common_list(const rrc_cfg_t& cfg_); - pucch_res_common* get_earfcn(uint32_t earfcn); + cell_res_common* get_earfcn(uint32_t earfcn); private: - const rrc_cfg_t& cfg; - std::map pucch_res_list; + const rrc_cfg_t& cfg; + std::map pucch_res_list; }; /** Storage of cell-specific eNB config and derived params */ @@ -99,6 +101,8 @@ struct cell_ctxt_dedicated { uint32_t prb_idx = 0; uint32_t sf_idx = 0; } cqi_res; + uint32_t meas_gap_period = 0; + uint32_t meas_gap_offset = 0; explicit cell_ctxt_dedicated(uint32_t i_, const cell_info_common& c_) : ue_cc_idx(i_), cell_common(&c_) {} @@ -116,7 +120,7 @@ class cell_ctxt_dedicated_list { public: explicit cell_ctxt_dedicated_list(const rrc_cfg_t& cfg_, - freq_res_common_list& pucch_res_list_, + freq_res_common_list& cell_res_list_, const cell_info_common_list& enb_common_list); ~cell_ctxt_dedicated_list(); @@ -163,9 +167,9 @@ private: srslte::log_ref log_h{"RRC"}; const rrc_cfg_t& cfg; const cell_info_common_list& common_list; - freq_res_common_list& pucch_res_list; + freq_res_common_list& cell_res_list; - pucch_res_common* pucch_res = nullptr; + cell_res_common* pucch_res = nullptr; std::vector cell_ded_list; bool sr_res_present = false; bool n_pucch_cs_present = false; diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index 4c11c6d5b..247ff2811 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -54,24 +54,30 @@ struct rrc_cfg_t { asn1::rrc::sib_info_item_c sibs[ASN1_RRC_MAX_SIB]; asn1::rrc::mac_main_cfg_s mac_cnfg; - asn1::rrc::pusch_cfg_ded_s pusch_cfg; - asn1::rrc::ant_info_ded_s antenna_info; - asn1::rrc::pdsch_cfg_ded_s::p_a_e_ pdsch_cfg; - rrc_cfg_sr_t sr_cfg; - rrc_cfg_cqi_t cqi_cfg; - rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; - bool enable_mbsfn; - uint16_t mbms_mcs; - uint32_t inactivity_timeout_ms; + asn1::rrc::pusch_cfg_ded_s pusch_cfg; + asn1::rrc::ant_info_ded_s antenna_info; + asn1::rrc::pdsch_cfg_ded_s::p_a_e_ pdsch_cfg; + rrc_cfg_sr_t sr_cfg; + rrc_cfg_cqi_t cqi_cfg; + rrc_cfg_qci_t qci_cfg[MAX_NOF_QCI]; + bool enable_mbsfn; + uint16_t mbms_mcs; + uint32_t inactivity_timeout_ms; std::array eea_preference_list; std::array eia_preference_list; - bool meas_cfg_present = false; - srslte_cell_t cell; - cell_list_t cell_list; + bool meas_cfg_present = false; + srslte_cell_t cell; + cell_list_t cell_list; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; +struct ue_var_cfg_t { + asn1::rrc::rr_cfg_ded_s rr_cfg; + asn1::rrc::meas_gap_cfg_c meas_gaps; + asn1::rrc::scell_to_add_mod_list_r10_l scells; +}; + } // namespace srsenb #endif // SRSLTE_RRC_CONFIG_H diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index f716f4333..2e2bce3bb 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -104,8 +104,7 @@ private: srslte::timer_handler::unique_timer activity_timer; /// cached ASN1 fields for RRC config update checking, and ease of context transfer during HO - asn1::rrc::rr_cfg_ded_s current_rr_cfg; - asn1::rrc::scell_to_add_mod_list_r10_l current_scells; + ue_var_cfg_t current_ue_cfg; asn1::rrc::establishment_cause_e establishment_cause; diff --git a/srsenb/hdr/stack/rrc/ue_rr_cfg.h b/srsenb/hdr/stack/rrc/ue_rr_cfg.h index ba8eca057..e7a3ec8e6 100644 --- a/srsenb/hdr/stack/rrc/ue_rr_cfg.h +++ b/srsenb/hdr/stack/rrc/ue_rr_cfg.h @@ -52,6 +52,7 @@ namespace srsenb { struct rrc_cfg_t; class cell_ctxt_dedicated_list; class bearer_cfg_handler; +struct ue_var_cfg_t; /// Fill RadioResourceConfigDedicated with data known at the RRCSetup/Reestablishment stage void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, @@ -59,26 +60,18 @@ void fill_rr_cfg_ded_setup(asn1::rrc::rr_cfg_ded_s& rr_cfg, const cell_ctxt_dedicated_list& ue_cell_list); /// Apply Reconf updates and update current state -void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, - asn1::rrc::rr_cfg_ded_s& current_rr_cfg, - asn1::rrc::scell_to_add_mod_list_r10_l& current_scells, - const rrc_cfg_t& enb_cfg, - const cell_ctxt_dedicated_list& ue_cell_list, - bearer_cfg_handler& bearers, - const srslte::rrc_ue_capabilities_t& ue_caps, - bool phy_cfg_updated); +void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, + ue_var_cfg_t& current_ue_cfg, + const rrc_cfg_t& enb_cfg, + const cell_ctxt_dedicated_list& ue_cell_list, + bearer_cfg_handler& bearers, + const srslte::rrc_ue_capabilities_t& ue_caps, + bool phy_cfg_updated); /// Apply radioResourceConfigDedicated updates to the current UE RRC configuration void apply_rr_cfg_ded_diff(asn1::rrc::rr_cfg_ded_s& current_rr_cfg_ded, const asn1::rrc::rr_cfg_ded_s& pending_rr_cfg_ded); -/// Fill rrcConnectionReconfiguration with SCells that were added/mod/removed since last RRC config update -void fill_scells_reconf(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, - const asn1::rrc::scell_to_add_mod_list_r10_l& current_scells, - const rrc_cfg_t& enb_cfg, - const cell_ctxt_dedicated_list& ue_cell_list, - const srslte::rrc_ue_capabilities_t& ue_caps); - /// Apply Scell updates to the current UE RRC configuration void apply_scells_to_add_diff(asn1::rrc::scell_to_add_mod_list_r10_l& current_scells, const asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8); diff --git a/srsenb/rr.conf.example b/srsenb/rr.conf.example index 4ef5d8495..944cb033f 100644 --- a/srsenb/rr.conf.example +++ b/srsenb/rr.conf.example @@ -61,6 +61,7 @@ cell_list = dl_earfcn = 3350; //ul_earfcn = 21400; ho_active = false; + //meas_gap_period = 0; // CA cells scell_list = ( diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 06f189ce8..e81c22b68 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -743,6 +743,7 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root) parse_default_field( cell_cfg.root_seq_idx, cellroot, "root_seq_idx", rrc_cfg->sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx); parse_default_field(cell_cfg.initial_dl_cqi, cellroot, "initial_dl_cqi", 5u); + parse_default_field(cell_cfg.meas_cfg.meas_gap_period, cellroot, "meas_gap_period", 0u); if (cellroot.exists("ho_active") and cellroot["ho_active"]) { HANDLEPARSERCODE(parse_meas_cell_list(&cell_cfg.meas_cfg, cellroot["meas_cell_list"])); diff --git a/srsenb/src/stack/rrc/mac_controller.cc b/srsenb/src/stack/rrc/mac_controller.cc index ead1faf1f..b63f444de 100644 --- a/srsenb/src/stack/rrc/mac_controller.cc +++ b/srsenb/src/stack/rrc/mac_controller.cc @@ -470,9 +470,11 @@ void ue_cfg_apply_meas_cfg(ue_cfg_t& ue_cfg, const meas_cfg_s& meas_cfg, const r case meas_gap_cfg_c::setup_s_::gap_offset_c_::types_opts::gp0: ue_cfg.measgap_period = 40; ue_cfg.measgap_offset = setup.gap_offset.gp0(); + break; case meas_gap_cfg_c::setup_s_::gap_offset_c_::types_opts::gp1: ue_cfg.measgap_period = 80; ue_cfg.measgap_offset = setup.gap_offset.gp1(); + break; default: srslte::logmap::get("RRC")->warning("Invalid measGap configuration\n"); ue_cfg.measgap_period = 0; diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index c5a249424..fd2849a23 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -68,7 +68,7 @@ void rrc::init(const rrc_cfg_t& cfg_, configure_mbsfn_sibs(&cfg.sibs[1].sib2(), &cfg.sibs[12].sib13_v920()); } - pucch_res_list.reset(new freq_res_common_list{cfg}); + cell_res_list.reset(new freq_res_common_list{cfg}); // Loads the PRACH root sequence cfg.sibs[1].sib2().rr_cfg_common.prach_cfg.root_seq_idx = cfg.cell_list[0].root_seq_idx; diff --git a/srsenb/src/stack/rrc/rrc_cell_cfg.cc b/srsenb/src/stack/rrc/rrc_cell_cfg.cc index 9ae61cfd3..5579bb86a 100644 --- a/srsenb/src/stack/rrc/rrc_cell_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_cell_cfg.cc @@ -27,7 +27,7 @@ namespace srsenb { freq_res_common_list::freq_res_common_list(const rrc_cfg_t& cfg_) : cfg(cfg_) { - for (auto& c : cfg.cell_list) { + for (const auto& c : cfg.cell_list) { auto it = pucch_res_list.find(c.dl_earfcn); if (it == pucch_res_list.end()) { pucch_res_list[c.dl_earfcn] = {}; @@ -35,7 +35,7 @@ freq_res_common_list::freq_res_common_list(const rrc_cfg_t& cfg_) : cfg(cfg_) } } -pucch_res_common* freq_res_common_list::get_earfcn(uint32_t earfcn) +cell_res_common* freq_res_common_list::get_earfcn(uint32_t earfcn) { auto it = pucch_res_list.find(earfcn); return (it == pucch_res_list.end()) ? nullptr : &(it->second); @@ -143,11 +143,9 @@ std::vector get_measobj_earfcns(const cell_info_common& pcell) ************************/ cell_ctxt_dedicated_list::cell_ctxt_dedicated_list(const rrc_cfg_t& cfg_, - freq_res_common_list& pucch_res_list_, + freq_res_common_list& cell_res_list_, const cell_info_common_list& enb_common_list) : - cfg(cfg_), - pucch_res_list(pucch_res_list_), - common_list(enb_common_list) + cfg(cfg_), cell_res_list(cell_res_list_), common_list(enb_common_list) { cell_ded_list.reserve(common_list.nof_cells()); } @@ -186,7 +184,7 @@ cell_ctxt_dedicated* cell_ctxt_dedicated_list::add_cell(uint32_t enb_cc_idx) if (ue_cc_idx == UE_PCELL_CC_IDX) { // Fetch PUCCH resources if it's pcell - pucch_res = pucch_res_list.get_earfcn(cell_common->cell_cfg.dl_earfcn); + pucch_res = cell_res_list.get_earfcn(cell_common->cell_cfg.dl_earfcn); } cell_ded_list.emplace_back(cell_ded_list.size(), *cell_common); @@ -230,11 +228,17 @@ bool cell_ctxt_dedicated_list::alloc_cell_resources(uint32_t ue_cc_idx) return false; } } + + cell_ctxt_dedicated* cell = get_ue_cc_idx(UE_PCELL_CC_IDX); + cell->meas_gap_period = cell->cell_common->cell_cfg.meas_cfg.meas_gap_period; + cell->meas_gap_offset = pucch_res->next_measgap_offset; + pucch_res->next_measgap_offset += 6; } if (not alloc_cqi_resources(ue_cc_idx, cfg.cqi_cfg.period)) { log_h->error("Failed to allocate CQIresources for cell ue_cc_idx=%d\n", ue_cc_idx); return false; } + return true; } @@ -520,7 +524,7 @@ bool cell_ctxt_dedicated_list::alloc_pucch_cs_resources() const uint16_t N_pucch_1 = sib2.rr_cfg_common.pucch_cfg_common.n1_pucch_an; const uint32_t max_cce = srslte_max_cce(cfg.cell.nof_prb); // Loop through all available resources - for (uint32_t i = 0; i < pucch_res_common::N_PUCCH_MAX_RES; i++) { + for (uint32_t i = 0; i < cell_res_common::N_PUCCH_MAX_RES; i++) { if (!pucch_res->n_pucch_cs_used[i] && (i <= N_pucch_1 && i != sr_res.sr_N_pucch)) { // Allocate resource pucch_res->n_pucch_cs_used[i] = true; diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 9f0b51c32..20f40d321 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -711,8 +711,8 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci, } /*** fill AS-Config ***/ hoprep_r8.as_cfg_present = true; - hoprep_r8.as_cfg.source_rr_cfg = rrc_ue->current_rr_cfg; - hoprep_r8.as_cfg.source_scell_cfg_list_r10.reset(new scell_to_add_mod_list_r10_l{rrc_ue->current_scells}); + hoprep_r8.as_cfg.source_rr_cfg = rrc_ue->current_ue_cfg.rr_cfg; + hoprep_r8.as_cfg.source_scell_cfg_list_r10.reset(new scell_to_add_mod_list_r10_l{rrc_ue->current_ue_cfg.scells}); // NOTE: set source_meas_cnfg equal to the UE's current var_meas_cfg var_meas_cfg_t empty_meascfg{}, &target_var_meas = ue_var_meas; // // however, reset the MeasObjToAdd Cells, so that the UE does not measure again the target eNB @@ -890,17 +890,16 @@ void rrc::ue::rrc_mobility::fill_mobility_reconf_common(asn1::rrc::dl_dcch_msg_s intralte.key_change_ind = false; intralte.next_hop_chaining_count = rrc_ue->ue_security_cfg.get_ncc(); + // Add MeasConfig of target cell + recfg_r8.meas_cfg_present = update_ue_var_meas_cfg(src_dl_earfcn, target_cell, &recfg_r8.meas_cfg); + apply_reconf_updates(recfg_r8, - rrc_ue->current_rr_cfg, - rrc_ue->current_scells, + rrc_ue->current_ue_cfg, rrc_enb->cfg, rrc_ue->cell_ded_list, rrc_ue->bearer_list, rrc_ue->ue_capabilities, true); - - // Add MeasConfig of target cell - recfg_r8.meas_cfg_present = update_ue_var_meas_cfg(src_dl_earfcn, target_cell, &recfg_r8.meas_cfg); } /** @@ -1102,8 +1101,8 @@ void rrc::ue::rrc_mobility::handle_ho_req(idle_st& s, const ho_req_rx_ev& ho_req /* Configure remaining layers based on pending changes */ // Update RLC + PDCP SRBs (no DRBs until MME Status Transfer) - rrc_ue->apply_pdcp_srb_updates(rrc_ue->current_rr_cfg); - rrc_ue->apply_rlc_rb_updates(rrc_ue->current_rr_cfg); + rrc_ue->apply_pdcp_srb_updates(rrc_ue->current_ue_cfg.rr_cfg); + rrc_ue->apply_rlc_rb_updates(rrc_ue->current_ue_cfg.rr_cfg); // Update MAC rrc_ue->mac_ctrl->handle_target_enb_ho_cmd(recfg_r8, rrc_ue->ue_capabilities); // Apply PHY updates @@ -1181,7 +1180,7 @@ bool rrc::ue::rrc_mobility::apply_ho_prep_cfg(const ho_prep_info_r8_ies_s& ho rrc_ue->update_scells(); // Save source eNB UE RR cfg as a starting point - apply_rr_cfg_ded_diff(rrc_ue->current_rr_cfg, ho_prep.as_cfg.source_rr_cfg); + apply_rr_cfg_ded_diff(rrc_ue->current_ue_cfg.rr_cfg, ho_prep.as_cfg.source_rr_cfg); // Save source UE MAC configuration as a base rrc_ue->mac_ctrl->handle_ho_prep(ho_prep); @@ -1207,7 +1206,7 @@ void rrc::ue::rrc_mobility::handle_recfg_complete(wait_recfg_comp& s, const recf void rrc::ue::rrc_mobility::handle_status_transfer(s1_target_ho_st& s, const status_transfer_ev& erabs) { // Establish DRBs - rrc_ue->apply_pdcp_drb_updates(rrc_ue->current_rr_cfg); + rrc_ue->apply_pdcp_drb_updates(rrc_ue->current_ue_cfg.rr_cfg); // Set DRBs SNs for (const auto& erab : erabs) { @@ -1316,8 +1315,8 @@ void rrc::ue::rrc_mobility::handle_crnti_ce(intraenb_ho_st& s, const user_crnti_ rrc_enb->phy->set_config(rrc_ue->rnti, rrc_ue->phy_rrc_dedicated_list); rrc_ue->ue_security_cfg.regenerate_keys_handover(s.target_cell->cell_cfg.pci, s.target_cell->cell_cfg.dl_earfcn); - rrc_ue->apply_pdcp_srb_updates(rrc_ue->current_rr_cfg); - rrc_ue->apply_pdcp_drb_updates(rrc_ue->current_rr_cfg); + rrc_ue->apply_pdcp_srb_updates(rrc_ue->current_ue_cfg.rr_cfg); + rrc_ue->apply_pdcp_drb_updates(rrc_ue->current_ue_cfg.rr_cfg); } else { rrc_log->info("Received duplicate C-RNTI CE during rnti=0x%x handover.\n", rrc_ue->rnti); } diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index a01bcf2c4..21e964583 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -42,7 +42,7 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch rnti(rnti_), pool(srslte::byte_buffer_pool::get_instance()), phy_rrc_dedicated_list(sched_ue_cfg.supported_cc_list.size()), - cell_ded_list(parent->cfg, *outer_rrc->pucch_res_list, *outer_rrc->cell_common_list), + cell_ded_list(parent->cfg, *outer_rrc->cell_res_list, *outer_rrc->cell_common_list), bearer_list(rnti_, parent->cfg), ue_security_cfg(parent->cfg) { @@ -273,7 +273,7 @@ void rrc::ue::send_connection_setup() send_dl_ccch(&dl_ccch_msg); - apply_rr_cfg_ded_diff(current_rr_cfg, rr_cfg); + apply_rr_cfg_ded_diff(current_ue_cfg.rr_cfg, rr_cfg); } void rrc::ue::handle_rrc_con_setup_complete(rrc_conn_setup_complete_s* msg, srslte::unique_byte_buffer_t pdu) @@ -414,7 +414,7 @@ void rrc::ue::send_connection_reest(uint8_t ncc) send_dl_ccch(&dl_ccch_msg); - apply_rr_cfg_ded_diff(current_rr_cfg, rr_cfg); + apply_rr_cfg_ded_diff(current_ue_cfg.rr_cfg, rr_cfg); } void rrc::ue::handle_rrc_con_reest_complete(rrc_conn_reest_complete_s* msg, srslte::unique_byte_buffer_t pdu) @@ -476,21 +476,20 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu, bool phy_ rrc_conn_recfg.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); rrc_conn_recfg_r8_ies_s& recfg_r8 = rrc_conn_recfg.crit_exts.set_c1().set_rrc_conn_recfg_r8(); + // Add measConfig + if (mobility_handler != nullptr) { + mobility_handler->fill_conn_recfg_no_ho_cmd(&recfg_r8); + } + // Fill RR Config Ded and SCells apply_reconf_updates(recfg_r8, - current_rr_cfg, - current_scells, + current_ue_cfg, parent->cfg, cell_ded_list, bearer_list, ue_capabilities, phy_cfg_updated); - // Add measConfig - if (mobility_handler != nullptr) { - mobility_handler->fill_conn_recfg_no_ho_cmd(&recfg_r8); - } - // if no updates were detected, skip rrc reconfiguration if (not(recfg_r8.rr_cfg_ded_present or recfg_r8.meas_cfg_present or recfg_r8.mob_ctrl_info_present or recfg_r8.ded_info_nas_list_present or recfg_r8.security_cfg_ho_present or recfg_r8.non_crit_ext_present)) { diff --git a/srsenb/src/stack/rrc/ue_rr_cfg.cc b/srsenb/src/stack/rrc/ue_rr_cfg.cc index 72e6e783a..5f60fff20 100644 --- a/srsenb/src/stack/rrc/ue_rr_cfg.cc +++ b/srsenb/src/stack/rrc/ue_rr_cfg.cc @@ -38,6 +38,8 @@ using namespace asn1::rrc; namespace srsenb { +srslte::log_ref log_h = srslte::logmap::get("RRC"); + /****************************** * SRBs / DRBs *****************************/ @@ -45,7 +47,7 @@ namespace srsenb { srb_to_add_mod_s* add_srb(srb_to_add_mod_list_l& srbs, uint8_t srb_id) { if (srb_id > 2 or srb_id == 0) { - srslte::logmap::get("RRC")->error("Invalid SRB id=%d\n", srb_id); + log_h->error("Invalid SRB id=%d\n", srb_id); return nullptr; } @@ -114,7 +116,7 @@ int16_t get_ri(uint32_t m_ri) ri_idx = 805 - N_offset_ri; break; default: - srslte::logmap::get("RRC")->error("Allocating RI: invalid m_ri=%d\n", m_ri); + log_h->error("Allocating RI: invalid m_ri=%d\n", m_ri); return -1; } @@ -146,7 +148,7 @@ int fill_cqi_report_setup(cqi_report_cfg_s& cqi_rep, if (cqi_rep.cqi_report_periodic_present) { const cell_ctxt_dedicated* pcell = ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX); if (pcell == nullptr or not pcell->cqi_res_present) { - srslte::logmap::get("RRC")->warning("PCell CQI resources haven\'t been allocated yet\n"); + log_h->warning("PCell CQI resources haven\'t been allocated yet\n"); return SRSLTE_ERROR; } auto& cqi_periodic = cqi_rep.cqi_report_periodic.setup(); @@ -186,7 +188,7 @@ void fill_cqi_report_reconf(cqi_report_cfg_s& cqi_rep, cqi_setup.ri_cfg_idx_present = true; cqi_setup.ri_cfg_idx = ri_idx; } else { - srslte::logmap::get("RRC")->warning("Warning: Configured wrong M_ri parameter.\n"); + log_h->warning("Warning: Configured wrong M_ri parameter.\n"); } } } @@ -394,6 +396,7 @@ void apply_rr_cfg_ded_diff(rr_cfg_ded_s& current_rr_cfg_ded, const rr_cfg_ded_s& } } +/// Fill rrcConnectionReconfiguration with SCells that were added/mod/removed since last RRC config update void fill_scells_reconf(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, const scell_to_add_mod_list_r10_l& current_scells, const rrc_cfg_t& enb_cfg, @@ -435,8 +438,8 @@ void fill_scells_reconf(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, auto& nonul_cfg = asn1cell.rr_cfg_common_scell_r10.non_ul_cfg_r10; asn1::number_to_enum(nonul_cfg.dl_bw_r10, enb_cfg.cell.nof_prb); asn1::number_to_enum(nonul_cfg.ant_info_common_r10.ant_ports_count, enb_cfg.cell.nof_ports); - nonul_cfg.phich_cfg_r10 = scell_cfg.mib.phich_cfg; - nonul_cfg.pdsch_cfg_common_r10 = cc_cfg_sib.pdsch_cfg_common; + nonul_cfg.phich_cfg_r10 = scell_cfg.mib.phich_cfg; + nonul_cfg.pdsch_cfg_common_r10 = cc_cfg_sib.pdsch_cfg_common; // RadioResourceConfigCommonSCell-r10::ul-Configuration-r10 asn1cell.rr_cfg_common_scell_r10.ul_cfg_r10_present = true; auto& ul_cfg = asn1cell.rr_cfg_common_scell_r10.ul_cfg_r10; @@ -498,18 +501,18 @@ void fill_scells_reconf(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, } #if SRS_ENABLED - ul_cfg_ded.srs_ul_cfg_ded_r10_present = true; - auto& srs_setup = ul_cfg_ded.srs_ul_cfg_ded_r10.set_setup(); - srs_setup.srs_bw.value = srs_ul_cfg_ded_c::setup_s_::srs_bw_opts::bw0; - srs_setup.srs_hop_bw.value = srs_ul_cfg_ded_c::setup_s_::srs_hop_bw_opts::hbw0; - srs_setup.freq_domain_position = 0; - srs_setup.dur = true; - srs_setup.srs_cfg_idx = 167; - srs_setup.tx_comb = 0; - srs_setup.cyclic_shift.value = srs_ul_cfg_ded_c::setup_s_::cyclic_shift_opts::cs0; - ul_cfg_ded.srs_ul_cfg_ded_v1020_present = true; + ul_cfg_ded.srs_ul_cfg_ded_r10_present = true; + auto& srs_setup = ul_cfg_ded.srs_ul_cfg_ded_r10.set_setup(); + srs_setup.srs_bw.value = srs_ul_cfg_ded_c::setup_s_::srs_bw_opts::bw0; + srs_setup.srs_hop_bw.value = srs_ul_cfg_ded_c::setup_s_::srs_hop_bw_opts::hbw0; + srs_setup.freq_domain_position = 0; + srs_setup.dur = true; + srs_setup.srs_cfg_idx = 167; + srs_setup.tx_comb = 0; + srs_setup.cyclic_shift.value = srs_ul_cfg_ded_c::setup_s_::cyclic_shift_opts::cs0; + ul_cfg_ded.srs_ul_cfg_ded_v1020_present = true; asn1::number_to_enum(ul_cfg_ded.srs_ul_cfg_ded_v1020.srs_ant_port_r10, enb_cfg.cell.nof_ports); - ul_cfg_ded.srs_ul_cfg_ded_aperiodic_r10_present = true; + ul_cfg_ded.srs_ul_cfg_ded_aperiodic_r10_present = true; ul_cfg_ded.srs_ul_cfg_ded_aperiodic_r10.set(setup_opts::release); #endif // SRS_ENABLED } @@ -563,27 +566,70 @@ void apply_scells_to_add_diff(asn1::rrc::scell_to_add_mod_list_r10_l& current_sc } } +bool apply_measgap_updates(meas_gap_cfg_c& meas_gaps, + meas_gap_cfg_c& current_meas_gaps, + const cell_ctxt_dedicated_list& ue_cell_list) +{ + bool flag_set = false; + const cell_ctxt_dedicated* pcell = ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX); + + meas_gap_cfg_c target_meas_gap; + switch (pcell->cell_common->cell_cfg.meas_cfg.meas_gap_period) { + case 40: + target_meas_gap.set_setup().gap_offset.set_gp0() = pcell->meas_gap_offset; + break; + case 80: + target_meas_gap.set_setup().gap_offset.set_gp1() = pcell->meas_gap_offset; + break; + case 0: // no meas gaps + break; + default: + log_h->error("Error setting measurement gaps\n"); + } + + bool is_current_setup = current_meas_gaps.type().value == setup_opts::setup; + bool is_target_setup = target_meas_gap.type().value == setup_opts::setup; + if (is_target_setup) { + if (not is_current_setup or + current_meas_gaps.setup().gap_offset.type() != target_meas_gap.setup().gap_offset.type()) { + meas_gaps = target_meas_gap; + flag_set = true; + } + } else if (is_current_setup) { + meas_gaps.set(setup_opts::release); + flag_set = true; + } + + // update meas gaps + current_meas_gaps = target_meas_gap; + + return flag_set; +} + /// Apply Reconf updates and update current state -void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, - asn1::rrc::rr_cfg_ded_s& current_rr_cfg, - asn1::rrc::scell_to_add_mod_list_r10_l& current_scells, - const rrc_cfg_t& enb_cfg, - const cell_ctxt_dedicated_list& ue_cell_list, - bearer_cfg_handler& bearers, - const srslte::rrc_ue_capabilities_t& ue_caps, - bool phy_cfg_updated) +void apply_reconf_updates(asn1::rrc::rrc_conn_recfg_r8_ies_s& recfg_r8, + ue_var_cfg_t& current_ue_cfg, + const rrc_cfg_t& enb_cfg, + const cell_ctxt_dedicated_list& ue_cell_list, + bearer_cfg_handler& bearers, + const srslte::rrc_ue_capabilities_t& ue_caps, + bool phy_cfg_updated) { // Compute pending updates and fill reconf msg recfg_r8.rr_cfg_ded_present = true; - fill_rr_cfg_ded_reconf(recfg_r8.rr_cfg_ded, current_rr_cfg, enb_cfg, ue_cell_list, bearers, ue_caps, phy_cfg_updated); - fill_scells_reconf(recfg_r8, current_scells, enb_cfg, ue_cell_list, ue_caps); + fill_rr_cfg_ded_reconf( + recfg_r8.rr_cfg_ded, current_ue_cfg.rr_cfg, enb_cfg, ue_cell_list, bearers, ue_caps, phy_cfg_updated); + fill_scells_reconf(recfg_r8, current_ue_cfg.scells, enb_cfg, ue_cell_list, ue_caps); + recfg_r8.meas_cfg.meas_gap_cfg_present = + apply_measgap_updates(recfg_r8.meas_cfg.meas_gap_cfg, current_ue_cfg.meas_gaps, ue_cell_list); + recfg_r8.meas_cfg_present |= recfg_r8.meas_cfg.meas_gap_cfg_present; // Add pending NAS info bearers.fill_pending_nas_info(&recfg_r8); // Update current rr_cfg_ded and scells state - apply_rr_cfg_ded_diff(current_rr_cfg, recfg_r8.rr_cfg_ded); - apply_scells_to_add_diff(current_scells, recfg_r8); + apply_rr_cfg_ded_diff(current_ue_cfg.rr_cfg, recfg_r8.rr_cfg_ded); + apply_scells_to_add_diff(current_ue_cfg.scells, recfg_r8); } } // namespace srsenb diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index ecf67e9a8..a4d2bd454 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -21,7 +21,6 @@ #include "srsenb/hdr/enb.h" #include "srsenb/hdr/stack/rrc/rrc_mobility.h" -#include "srsenb/src/enb_cfg_parser.h" #include "srsenb/test/common/dummy_classes.h" #include "srslte/asn1/rrc_utils.h" #include "srslte/common/test_common.h" @@ -29,6 +28,8 @@ #include #include +using namespace asn1::rrc; + meas_cell_cfg_t generate_cell1() { meas_cell_cfg_t cell1{}; @@ -378,6 +379,7 @@ struct s1ap_mobility_tester : public mobility_tester { { TESTASSERT(generate_rrc_cfg_common() == SRSLTE_SUCCESS); cfg.cell_list[0].meas_cfg.meas_cells[0].eci = 0x19C02; + cfg.cell_list[0].meas_cfg.meas_gap_period = 40; return SRSLTE_SUCCESS; } }; @@ -388,12 +390,14 @@ struct intraenb_mobility_tester : public mobility_tester { { TESTASSERT(generate_rrc_cfg_common() == SRSLTE_SUCCESS); cfg.cell_list[0].meas_cfg.meas_cells[0].eci = 0x19B02; + cfg.cell_list[0].meas_cfg.meas_gap_period = 40; cell_cfg_t cell2 = cfg.cell_list[0]; cell2.pci = 2; cell2.cell_id = 2; cell2.meas_cfg.meas_cells[0].pci = 1; cell2.meas_cfg.meas_cells[0].eci = 0x19B01; + cell2.meas_cfg.meas_gap_period = 80; cfg.cell_list.push_back(cell2); return SRSLTE_SUCCESS; @@ -411,6 +415,15 @@ int test_s1ap_mobility(mobility_test_params test_params) TESTASSERT(tester.run_preamble() == SRSLTE_SUCCESS); test_dummies::s1ap_mobility_dummy& s1ap = tester.s1ap; + /* Receive correct measConfig */ + dl_dcch_msg_s dl_dcch_msg; + TESTASSERT(test_helpers::unpack_asn1(dl_dcch_msg, srslte::make_span(tester.pdcp.last_sdu.sdu))); + rrc_conn_recfg_r8_ies_s& recfg_r8 = dl_dcch_msg.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); + TESTASSERT(recfg_r8.meas_cfg_present and recfg_r8.meas_cfg.meas_gap_cfg_present); + TESTASSERT(recfg_r8.meas_cfg.meas_gap_cfg.type().value == setup_opts::setup); + TESTASSERT((1 + recfg_r8.meas_cfg.meas_gap_cfg.setup().gap_offset.type().value) * 40u == + tester.cfg.cell_list[0].meas_cfg.meas_gap_period); + /* Receive MeasReport from UE (correct if PCI=2) */ if (test_params.fail_at == mobility_test_params::test_event::wrong_measreport) { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x0D, 0xBC, 0x80}; // PCI == 3 @@ -479,7 +492,7 @@ int test_s1ap_mobility(mobility_test_params test_params) TESTASSERT(tester.rrc_log->error_counter == 0); asn1::rrc::dl_dcch_msg_s ho_cmd; TESTASSERT(test_helpers::unpack_asn1(ho_cmd, srslte::make_span(tester.pdcp.last_sdu.sdu))); - auto& recfg_r8 = ho_cmd.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); + recfg_r8 = ho_cmd.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); TESTASSERT(recfg_r8.mob_ctrl_info_present); return SRSLTE_SUCCESS; @@ -605,6 +618,16 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(tester.generate_rrc_cfg() == SRSLTE_SUCCESS); TESTASSERT(tester.setup_rrc() == SRSLTE_SUCCESS); TESTASSERT(tester.run_preamble() == SRSLTE_SUCCESS); + + /* Receive correct measConfig */ + dl_dcch_msg_s dl_dcch_msg; + TESTASSERT(test_helpers::unpack_asn1(dl_dcch_msg, srslte::make_span(tester.pdcp.last_sdu.sdu))); + rrc_conn_recfg_r8_ies_s& recfg_r8 = dl_dcch_msg.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); + TESTASSERT(recfg_r8.meas_cfg_present and recfg_r8.meas_cfg.meas_gap_cfg_present); + TESTASSERT(recfg_r8.meas_cfg.meas_gap_cfg.type().value == setup_opts::setup); + TESTASSERT((1 + recfg_r8.meas_cfg.meas_gap_cfg.setup().gap_offset.type().value) * 40u == + tester.cfg.cell_list[0].meas_cfg.meas_gap_period); + tester.pdcp.last_sdu.sdu = nullptr; tester.rlc.test_reset_all(); tester.phy.phy_cfg_set = false; @@ -648,7 +671,7 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(tester.pdcp.last_sdu.lcid == 1); // SRB1 asn1::rrc::dl_dcch_msg_s ho_cmd; TESTASSERT(test_helpers::unpack_asn1(ho_cmd, srslte::make_span(tester.pdcp.last_sdu.sdu))); - auto& recfg_r8 = ho_cmd.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); + recfg_r8 = ho_cmd.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); TESTASSERT(recfg_r8.mob_ctrl_info_present); TESTASSERT(recfg_r8.mob_ctrl_info.new_ue_id.to_number() == tester.rnti); TESTASSERT(recfg_r8.mob_ctrl_info.target_pci == 2); @@ -659,6 +682,11 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(phy_cfg_ded.cqi_report_cfg_present); // PHY should not be updated until the UE handovers to the new cell TESTASSERT(not tester.phy.phy_cfg_set); + // Correct measConfig + TESTASSERT(recfg_r8.meas_cfg_present and recfg_r8.meas_cfg.meas_gap_cfg_present); + TESTASSERT(recfg_r8.meas_cfg.meas_gap_cfg.type().value == setup_opts::setup); + TESTASSERT((1 + recfg_r8.meas_cfg.meas_gap_cfg.setup().gap_offset.type().value) * 40u == + tester.cfg.cell_list[1].meas_cfg.meas_gap_period); /* Test Case: The UE sends a C-RNTI CE. Bearers are reestablished, PHY is configured */ tester.pdcp.last_sdu.sdu = nullptr; diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index a09174517..f6937fcec 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -25,6 +25,7 @@ #include "srsenb/test/common/dummy_classes.h" #include "srslte/adt/span.h" #include "srslte/common/log_filter.h" +#include "srsenb/src/enb_cfg_parser.h" using namespace srsenb; using namespace asn1::rrc;