diff --git a/lib/include/srslte/asn1/asn1_utils.h b/lib/include/srslte/asn1/asn1_utils.h index 22d3b1655..afd464415 100644 --- a/lib/include/srslte/asn1/asn1_utils.h +++ b/lib/include/srslte/asn1/asn1_utils.h @@ -231,6 +231,13 @@ public: T* data() { return &data_[0]; } const T* data() const { return &data_[0]; } + T* begin() { return &data_[0]; } + T* end() { return &data_[size()]; } + const T* begin() const { return &data_[0]; } + const T* end() const { return &data_[size()]; } + using iterator = T*; + using const_iterator = const T*; + private: T data_[MAX_N]; uint32_t current_size; diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index f0f3b5d7e..fe02ec918 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -27,6 +27,8 @@ namespace srsenb { +bool operator==(const asn1::rrc::report_cfg_eutra_s& lhs, const asn1::rrc::report_cfg_eutra_s& rhs); + /** * This class is responsible for storing the UE Measurement Configuration at the eNB side. * Has the same fields as asn1::rrc::var_meas_cfg but stored in data structs that are easier to handle @@ -41,16 +43,20 @@ public: using report_cfg_t = asn1::rrc::report_cfg_to_add_mod_s; std::tuple add_cell_cfg(const meas_cell_cfg_t& cellcfg); - uint32_t get_new_obj_id(); + report_cfg_t* add_report_cfg(const asn1::rrc::report_cfg_eutra_s& reportcfg); + meas_id_t* add_measid_cfg(uint8_t measobjid, uint8_t repid); - void compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const; + bool compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const; void compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const; void compute_diff_cells(const asn1::rrc::meas_obj_eutra_s& target_it, const asn1::rrc::meas_obj_eutra_s& src_it, asn1::rrc::meas_obj_to_add_mod_s* added_obj) const; + void compute_diff_report_cfgs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const; + void compute_diff_meas_ids(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const; // getters - const asn1::rrc::meas_obj_to_add_mod_list_l& meas_objs() const { return var_meas.meas_obj_list; } + const asn1::rrc::meas_obj_to_add_mod_list_l& meas_objs() const { return var_meas.meas_obj_list; } + const asn1::rrc::report_cfg_to_add_mod_list_l& rep_cfgs() const { return var_meas.report_cfg_list; } private: asn1::rrc::var_meas_cfg_s var_meas; diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index a760c1683..35f72c64e 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -75,6 +75,49 @@ bool operator==(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& r rhs_eutra.cells_to_add_mod_list.begin(), cells_are_equal); } +bool operator==(const report_cfg_eutra_s& lhs, const report_cfg_eutra_s& rhs) +{ + if (lhs.ext or rhs.ext) { + printf("[%d] extension of reportCfgToAddMod not supported\n", __LINE__); + return false; + } + if (lhs.trigger_type.type() != rhs.trigger_type.type()) { + return false; + } + if (lhs.trigger_type.type().value == report_cfg_eutra_s::trigger_type_c_::types_opts::event) { + auto &lhs_ev = lhs.trigger_type.event(), &rhs_ev = rhs.trigger_type.event(); + if (lhs_ev.hysteresis != rhs_ev.hysteresis or lhs_ev.time_to_trigger != rhs_ev.time_to_trigger or + lhs_ev.event_id.type() != rhs_ev.event_id.type()) { + return false; + } + if (lhs_ev.event_id.type().value != eutra_event_s::event_id_c_::types_opts::event_a3) { + printf("[%d] event type != A3 of reportCfgToAddMod not supported\n", __LINE__); + return false; + } + if (lhs_ev.event_id.event_a3().report_on_leave != rhs_ev.event_id.event_a3().report_on_leave or + lhs_ev.event_id.event_a3().a3_offset != rhs_ev.event_id.event_a3().a3_offset) { + return false; + } + } else { + if (lhs.trigger_type.periodical().purpose != rhs.trigger_type.periodical().purpose) { + return false; + } + } + return lhs.trigger_quant == rhs.trigger_quant and lhs.report_quant == rhs.report_quant and + lhs.max_report_cells == rhs.max_report_cells and lhs.report_interv == rhs.report_interv and + lhs.report_amount == rhs.report_amount; +} +bool operator==(const report_cfg_to_add_mod_s& lhs, const report_cfg_to_add_mod_s& rhs) +{ + if (lhs.report_cfg_id != rhs.report_cfg_id or lhs.report_cfg.type() != rhs.report_cfg.type()) { + return false; + } + return lhs.report_cfg.report_cfg_eutra() == rhs.report_cfg.report_cfg_eutra(); +} +bool operator==(const meas_id_to_add_mod_s& lhs, const meas_id_to_add_mod_s& rhs) +{ + return lhs.meas_id == rhs.meas_id and lhs.meas_obj_id == rhs.meas_obj_id and lhs.report_cfg_id == rhs.report_cfg_id; +} namespace rrc_details { @@ -85,14 +128,22 @@ uint32_t eci_to_cellid(uint32_t eci) } //! convenience function overload to extract Id from MeasObj/MeasId/ReportCfg/Cells -uint8_t get_id(const cells_to_add_mod_s& obj) +constexpr uint8_t get_id(const cells_to_add_mod_s& obj) { return obj.cell_idx; } -uint8_t get_id(const meas_obj_to_add_mod_s& obj) +constexpr uint8_t get_id(const meas_obj_to_add_mod_s& obj) { return obj.meas_obj_id; } +constexpr uint8_t get_id(const report_cfg_to_add_mod_s& obj) +{ + return obj.report_cfg_id; +} +constexpr uint8_t get_id(const meas_id_to_add_mod_s& obj) +{ + return obj.meas_id; +} //! convenience function overload to print MeasObj/MeasId/etc. fields std::string to_string(const cells_to_add_mod_s& obj) @@ -147,30 +198,9 @@ find_cell(meas_obj_to_add_mod_list_l& l, uint32_t earfcn, uint8_t cell_id) return {obj, it}; } -//! Adds Cell to MeasCfg MeasObjToAddMod field -cells_to_add_mod_s* meascfg_add_cell(meas_obj_eutra_s& eutra_obj, const cells_to_add_mod_s& celltoadd) -{ - // create new cell_id in the provided eutra_obj. - // if the cell_id already exists, just update the fields. - eutra_obj.cells_to_add_mod_list_present = true; - - // find the cell. Assumes sorted list - auto& l = eutra_obj.cells_to_add_mod_list; - auto found_it = std::lower_bound(l.begin(), l.end(), celltoadd.cell_idx, rrc_details::cell_id_cmp{}); - if (found_it == l.end()) { - eutra_obj.cells_to_add_mod_list.push_back({}); - found_it = &eutra_obj.cells_to_add_mod_list.back(); - } - - *found_it = celltoadd; - // cell_obj->cell_idx = (uint8_t)(cell_id % 3); // 0-3 // FIXME: What? - // printf("The added cell has idx=%d, pci=%d\n", cell_obj->cell_idx, cell_obj->pci); - - return found_it; -} - /** - * Adds MeasObjtoAddMod to MeasCfg object + * Section 5.5.2.5 + * Description: Adds MeasObjtoAddMod to MeasCfg object */ meas_obj_to_add_mod_s* meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj) { @@ -194,6 +224,7 @@ meas_obj_to_add_mod_s* meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj target_eutra.allowed_meas_bw = src_eutra.allowed_meas_bw; target_eutra.presence_ant_port1 = src_eutra.presence_ant_port1; target_eutra.neigh_cell_cfg = src_eutra.neigh_cell_cfg; + // do not add cellsToAddModList, blacCells, whiteCells, etc. according to (5.5.2.5 1|1|1) return found_it; } @@ -245,6 +276,21 @@ private: const_iterator src_it, src_end, target_it, target_end; }; +template +IdType find_id_gap(const Container& c) +{ + auto prev_it = c.begin(); + if (prev_it != c.end() and get_id(*prev_it) == 1) { + auto it = prev_it; + for (++it; it != c.end(); prev_it = it, ++it) { + if (get_id(*it) > get_id(*prev_it) + 1) { + break; + } + } + } + return (prev_it == c.end()) ? 1 : get_id(*prev_it) + 1; // starts at 1. +} + } // namespace rrc_details /************************************************************************************************* @@ -290,7 +336,7 @@ var_meas_cfg_t::add_cell_cfg(const meas_cell_cfg_t& cellcfg) } else { // no measobj has been found with same earfcn, create a new one meas_obj_t new_obj; - new_obj.meas_obj_id = get_new_obj_id(); + new_obj.meas_obj_id = rrc_details::find_id_gap(var_meas.meas_obj_list); asn1::rrc::meas_obj_eutra_s& eutra = new_obj.meas_obj.set_meas_obj_eutra(); eutra.carrier_freq = cellcfg.earfcn; eutra.allowed_meas_bw.value = asn1::rrc::allowed_meas_bw_e::mbw6; // FIXME: What value to add here? @@ -310,37 +356,81 @@ var_meas_cfg_t::add_cell_cfg(const meas_cell_cfg_t& cellcfg) ret.second = &ret.first->meas_obj.meas_obj_eutra().cells_to_add_mod_list.back(); } + if (inserted_flag) { + var_meas.meas_obj_list_present = true; + } + return {inserted_flag, ret.first, ret.second}; } -//! Find first gap in meas_obj_id and return it -uint32_t var_meas_cfg_t::get_new_obj_id() +report_cfg_to_add_mod_s* var_meas_cfg_t::add_report_cfg(const report_cfg_eutra_s& reportcfg) { - meas_obj_t* prev_it = var_meas.meas_obj_list.begin(); - if (prev_it != var_meas.meas_obj_list.end() and prev_it->meas_obj_id == 1) { - meas_obj_t* it = prev_it; - for (++it; it != var_meas.meas_obj_list.end(); prev_it = it, ++it) { - if (it->meas_obj_id > prev_it->meas_obj_id + 1) { - break; - } - } + rrc_details::field_id_cmp cmp{}; + report_cfg_to_add_mod_s new_rep; + new_rep.report_cfg_id = rrc_details::find_id_gap(var_meas.report_cfg_list); + new_rep.report_cfg.set_report_cfg_eutra() = reportcfg; + + var_meas.report_cfg_list_present = true; + var_meas.report_cfg_list.push_back(new_rep); + std::sort(var_meas.report_cfg_list.begin(), var_meas.report_cfg_list.end(), cmp); + return std::lower_bound(var_meas.report_cfg_list.begin(), var_meas.report_cfg_list.end(), new_rep.report_cfg_id, cmp); +} + +meas_id_to_add_mod_s* var_meas_cfg_t::add_measid_cfg(uint8_t measobjid, uint8_t measrepid) +{ + // ensure MeasObjId and ReportCfgId already exist + auto objit = std::lower_bound( + var_meas.meas_obj_list.begin(), var_meas.meas_obj_list.end(), measobjid, rrc_details::meas_obj_id_cmp{}); + if (objit == var_meas.meas_obj_list.end() or objit->meas_obj_id != measobjid) { + ERROR("Failed to add MeasId because MeasObjId=%d is not found.\n", measobjid); + return nullptr; + } + auto repit = std::lower_bound(var_meas.report_cfg_list.begin(), + var_meas.report_cfg_list.end(), + measrepid, + rrc_details::field_id_cmp{}); + if (repit == var_meas.report_cfg_list.end() or repit->report_cfg_id != measrepid) { + ERROR("Failed to add MeasId because ReportCfgId=%d is not found.\n", measrepid); + return nullptr; } - return (prev_it == var_meas.meas_obj_list.end()) ? 1 : prev_it->meas_obj_id + 1; // starts at 1. + rrc_details::field_id_cmp cmp{}; + meas_id_to_add_mod_s new_measid; + new_measid.report_cfg_id = measrepid; + new_measid.meas_obj_id = measobjid; + new_measid.meas_id = rrc_details::find_id_gap(var_meas.meas_id_list); + + var_meas.meas_id_list_present = true; + var_meas.meas_id_list.push_back(new_measid); + std::sort(var_meas.meas_id_list.begin(), var_meas.meas_id_list.end(), cmp); + return std::lower_bound(var_meas.meas_id_list.begin(), var_meas.meas_id_list.end(), new_measid.meas_id, cmp); } -void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const +bool var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const { *meas_cfg = {}; // TODO: Create a flag to disable changing the "this" members (useful for transparent container) // Set a MeasConfig in the RRC Connection Reconfiguration for HO. compute_diff_meas_objs(target_cfg, meas_cfg); - // deltaconfig_meas_reports(target_cfg, meas_cfg); - // deltaconfig_meas_ids(target_cfg, meas_cfg); + compute_diff_report_cfgs(target_cfg, meas_cfg); + compute_diff_meas_ids(target_cfg, meas_cfg); // deltaconfig_meas_quantity_config(target_cfg, meas_cfg); meas_cfg->meas_gap_cfg_present = false; // NOTE: we do not support inter-freq. HO meas_cfg->s_measure_present = false; // NOTE: We do not support SCells meas_cfg->pre_regist_info_hrpd_present = false; // NOTE: not supported meas_cfg->speed_state_pars_present = false; // NOTE: not supported + + bool diff = meas_cfg->meas_obj_to_add_mod_list_present; + diff |= meas_cfg->meas_obj_to_rem_list_present; + diff |= meas_cfg->report_cfg_to_add_mod_list_present; + diff |= meas_cfg->report_cfg_to_rem_list_present; + diff |= meas_cfg->meas_id_to_add_mod_list_present; + diff |= meas_cfg->meas_id_to_rem_list_present; + diff |= meas_cfg->quant_cfg_present; + diff |= meas_cfg->meas_gap_cfg_present; + diff |= meas_cfg->s_measure_present; + diff |= meas_cfg->pre_regist_info_hrpd_present; + diff |= meas_cfg->speed_state_pars_present; + return diff; } //! adds all the cells that got updated to MeasCfg. @@ -350,37 +440,48 @@ void var_meas_cfg_t::compute_diff_cells(const meas_obj_eutra_s& target_it, { rrc_details::compute_diff_generator diffs{src_it.cells_to_add_mod_list, target_it.cells_to_add_mod_list}; - meas_obj_eutra_s* eutra_obj = &added_obj->meas_obj.meas_obj_eutra(); + meas_obj_eutra_s* eutra_obj = &added_obj->meas_obj.meas_obj_eutra(); while (true) { auto result = diffs.next(); switch (result.outcome) { case rrc_details::diff_outcome_t::complete: return; case rrc_details::diff_outcome_t::id_removed: + // case "entry with matching cellIndex exists in cellsToRemoveList Info("UE can now cease to measure activity of cell %s.\n", rrc_details::to_string(*result.target_it).c_str()); eutra_obj->cells_to_rem_list_present = true; eutra_obj->cells_to_rem_list.push_back(result.src_it->cell_idx); break; case rrc_details::diff_outcome_t::id_added: + // case "entry with matching cellIndex doesn't exist in cellsToAddModList" Info("UE has now to measure activity of %s.\n", rrc_details::to_string(*result.target_it).c_str()); - rrc_details::meascfg_add_cell(*eutra_obj, *result.target_it); + eutra_obj->cells_to_add_mod_list_present = true; + eutra_obj->cells_to_add_mod_list.push_back(*result.target_it); break; case rrc_details::diff_outcome_t::same_id: - // check if cells are the same. if not, update. if (not(*result.src_it == *result.target_it)) { + // case "entry with matching cellIndex exists in cellsToAddModList" Info("UE has now to measure activity of %s with updated params.\n", rrc_details::to_string(*result.target_it).c_str()); - rrc_details::meascfg_add_cell(*eutra_obj, *result.target_it); + eutra_obj->cells_to_add_mod_list_present = true; + eutra_obj->cells_to_add_mod_list.push_back(*result.target_it); } break; } } } -//! compute diff between target_cfg and var_meas -> depending on diff, add/remove/update meas_obj in meas_cfg +/** + * Section 5.5.2.4/5, Measurement Object removal and addition/modification + * Description: compute diff between target_cfg and var_meas -> depending on diff, add/remove/update meas_obj in + * meas_cfg + */ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, meas_cfg_s* meas_cfg) const { + if (not target_cfg.var_meas.meas_obj_list_present) { + return; + } // TODO: black cells and white cells rrc_details::compute_diff_generator diffs{var_meas.meas_obj_list, target_cfg.var_meas.meas_obj_list}; @@ -391,22 +492,26 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me case rrc_details::diff_outcome_t::complete: return; case rrc_details::diff_outcome_t::id_removed: + // case "entry with matching cellIndex exists in cellsToRemoveList Info("UE can cease to measure activity in frequency earfcn=%d.\n", result.src_it->meas_obj.meas_obj_eutra().carrier_freq); meas_cfg->meas_obj_to_rem_list_present = true; meas_cfg->meas_obj_to_rem_list.push_back(result.src_it->meas_obj_id); break; case rrc_details::diff_outcome_t::id_added: { + // case "entry with matching measObjectId doesn't exist in measObjToAddModList" Info("HO: UE has now to measure activity of new frequency earfcn=%d.\n", result.target_it->meas_obj.meas_obj_eutra().carrier_freq); auto& target_eutra = result.target_it->meas_obj.meas_obj_eutra(); auto& added_eutra = rrc_details::meascfg_add_meas_obj(meas_cfg, *result.target_it)->meas_obj.meas_obj_eutra(); // add all cells in measCfg for (const cells_to_add_mod_s& cell_it : target_eutra.cells_to_add_mod_list) { - rrc_details::meascfg_add_cell(added_eutra, cell_it); + added_eutra.cells_to_add_mod_list_present = true; + added_eutra.cells_to_add_mod_list.push_back(cell_it); } } break; case rrc_details::diff_outcome_t::same_id: + // case "entry with matching measObjectId exists in measObjToAddModList" bool are_equal = *result.src_it == *result.target_it; if (not are_equal) { // if we found a difference in obj IDs @@ -420,6 +525,71 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me } } +/** + * Section 5.5.2.6/7 - Reporting configuration removal and addition/modification + */ +void var_meas_cfg_t::compute_diff_report_cfgs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const +{ + if (not target_cfg.var_meas.report_cfg_list_present) { + return; + } + rrc_details::compute_diff_generator diffs{var_meas.report_cfg_list, + target_cfg.var_meas.report_cfg_list}; + + while (true) { + auto result = diffs.next(); + switch (result.outcome) { + case rrc_details::diff_outcome_t::complete: + return; + case rrc_details::diff_outcome_t::id_removed: + meas_cfg->report_cfg_to_rem_list_present = true; + meas_cfg->report_cfg_to_rem_list.push_back(result.src_it->report_cfg_id); + break; + case rrc_details::diff_outcome_t::id_added: + meas_cfg->report_cfg_to_add_mod_list_present = true; + meas_cfg->report_cfg_to_add_mod_list.push_back(*result.target_it); + break; + case rrc_details::diff_outcome_t::same_id: + if (not(*result.src_it == *result.target_it)) { + meas_cfg->report_cfg_to_add_mod_list_present = true; + meas_cfg->report_cfg_to_add_mod_list.push_back(*result.target_it); + } + break; + } + } +} + +void var_meas_cfg_t::compute_diff_meas_ids(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const +{ + if (not target_cfg.var_meas.meas_id_list_present) { + return; + } + rrc_details::compute_diff_generator diffs{var_meas.meas_id_list, + target_cfg.var_meas.meas_id_list}; + + while (true) { + auto result = diffs.next(); + switch (result.outcome) { + case rrc_details::diff_outcome_t::complete: + return; + case rrc_details::diff_outcome_t::id_removed: + meas_cfg->meas_id_to_rem_list_present = true; + meas_cfg->meas_id_to_rem_list.push_back(result.src_it->meas_id); + break; + case rrc_details::diff_outcome_t::id_added: + meas_cfg->meas_id_to_add_mod_list_present = true; + meas_cfg->meas_id_to_add_mod_list.push_back(*result.target_it); + break; + case rrc_details::diff_outcome_t::same_id: + if (not(*result.src_it == *result.target_it)) { + meas_cfg->meas_id_to_add_mod_list_present = true; + meas_cfg->meas_id_to_add_mod_list.push_back(*result.target_it); + } + break; + } + } +} + /************************************************************************************************* * mobility_cfg class ************************************************************************************************/ @@ -428,11 +598,22 @@ rrc::mobility_cfg::mobility_cfg(rrc* outer_rrc) : rrc_enb(outer_rrc) { var_meas_cfg_t var_meas{outer_rrc->rrc_log}; - // inserts all neighbor cells if (rrc_enb->cfg.meas_cfg_present) { + // inserts all neighbor cells for (meas_cell_cfg_t& meascell : rrc_enb->cfg.meas_cfg.meas_cells) { var_meas.add_cell_cfg(meascell); } + + // insert all report cfgs + for (const report_cfg_eutra_s& reportcfg : rrc_enb->cfg.meas_cfg.meas_reports) { + var_meas.add_report_cfg(reportcfg); + } + + // insert all meas ids + // FIXME: add this to the parser + for (const auto& measobj : var_meas.meas_objs()) { + var_meas.add_measid_cfg(measobj.meas_obj_id, var_meas.rep_cfgs().begin()->report_cfg_id); + } } current_meas_cfg = std::make_shared(var_meas); @@ -452,6 +633,7 @@ rrc::ue::rrc_mobility::rrc_mobility(rrc::ue* outer_ue) : ue_var_meas = std::make_shared(outer_ue->parent->rrc_log); } +//! Method to add Mobility Info to a RRC Connection Reconfiguration Message bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg) { // only reconfigure meas_cfg if no handover is occurring @@ -465,22 +647,11 @@ bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies } asn1::rrc::meas_cfg_s* meas_cfg = &conn_recfg->meas_cfg; - ue_var_meas->compute_diff_meas_cfg(*cfg->current_meas_cfg, meas_cfg); + bool updated = ue_var_meas->compute_diff_meas_cfg(*cfg->current_meas_cfg, meas_cfg); + // update ue var meas ue_var_meas = cfg->current_meas_cfg; - // if there is at least one difference, we tag a new measurement report in conn_reconf. - bool diff = meas_cfg->meas_obj_to_add_mod_list_present; - diff |= meas_cfg->meas_obj_to_rem_list_present; - diff |= meas_cfg->report_cfg_to_add_mod_list_present; - diff |= meas_cfg->report_cfg_to_rem_list_present; - diff |= meas_cfg->meas_id_to_add_mod_list_present; - diff |= meas_cfg->meas_id_to_rem_list_present; - diff |= meas_cfg->quant_cfg_present; - diff |= meas_cfg->meas_gap_cfg_present; - diff |= meas_cfg->s_measure_present; - diff |= meas_cfg->pre_regist_info_hrpd_present; - diff |= meas_cfg->speed_state_pars_present; - if (diff) { + if (updated) { conn_recfg->meas_cfg_present = true; return true; } diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index b093cb754..af1865473 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -46,6 +46,22 @@ meas_cell_cfg_t generate_cell1() return cell1; } +report_cfg_eutra_s generate_rep1() +{ + report_cfg_eutra_s rep{}; + rep.report_amount.value = report_cfg_eutra_s::report_amount_opts::r16; + rep.report_interv.value = report_interv_opts::ms240; + rep.max_report_cells = 2; + rep.report_quant.value = report_cfg_eutra_s::report_quant_opts::both; + rep.trigger_quant.value = report_cfg_eutra_s::trigger_quant_opts::rsrp; + rep.trigger_type.set_event().event_id.set_event_a3(); + rep.trigger_type.event().time_to_trigger.value = time_to_trigger_opts::ms100; + rep.trigger_type.event().hysteresis = 0; + rep.trigger_type.event().event_id.event_a3().a3_offset = 5; + rep.trigger_type.event().event_id.event_a3().report_on_leave = true; + return rep; +} + bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell) { return cfg.pci == cell.pci and cell.cell_individual_offset.to_number() == (int8_t)round(cfg.q_offset) and @@ -63,7 +79,9 @@ int test_correct_insertion() cell4 = cell1; cell4.q_offset = 1; - // TEST 1: cell insertion in empty varMeasCfg + report_cfg_eutra_s rep1 = generate_rep1(); + + // TEST 1: cell/rep insertion in empty varMeasCfg { var_meas_cfg_t var_cfg(&log_h); auto ret = var_cfg.add_cell_cfg(cell1); @@ -76,6 +94,10 @@ int test_correct_insertion() TESTASSERT(eutra.carrier_freq == cell1.earfcn); TESTASSERT(eutra.cells_to_add_mod_list.size() == 1); TESTASSERT(is_cell_cfg_equal(cell1, eutra.cells_to_add_mod_list[0])); + + auto ret2 = var_cfg.add_report_cfg(rep1); + TESTASSERT(ret2->report_cfg_id == 1); + TESTASSERT(ret2->report_cfg.report_cfg_eutra() == rep1); } { @@ -129,12 +151,22 @@ int test_correct_meascfg_calculation() cell2.pci = 2; cell2.cell_id = 0x19C02; + report_cfg_eutra_s rep1 = generate_rep1(), rep2{}, rep3{}; + rep2 = rep1; + rep2.trigger_quant.value = report_cfg_eutra_s::trigger_quant_opts::rsrq; + rep3 = rep2; + rep3.report_quant.value = report_cfg_eutra_s::report_quant_opts::same_as_trigger_quant; + { meas_cfg_s result_meascfg; // TEST: Insertion of two cells in var_meas propagates to the resulting meas_cfg_s cellsToAddMod list target_var.add_cell_cfg(cell1); target_var.add_cell_cfg(cell2); + target_var.add_report_cfg(rep1); + target_var.add_report_cfg(rep2); + target_var.add_measid_cfg(1, 1); + target_var.add_measid_cfg(1, 2); src_var.compute_diff_meas_cfg(target_var, &result_meascfg); TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present); TESTASSERT(not result_meascfg.meas_obj_to_rem_list_present); @@ -149,12 +181,26 @@ int test_correct_meascfg_calculation() TESTASSERT(is_cell_cfg_equal(cell1, *cell_item)); cell_item++; TESTASSERT(is_cell_cfg_equal(cell2, *cell_item)); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list_present and not result_meascfg.report_cfg_to_rem_list_present); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 2); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg_id == 1); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg.report_cfg_eutra() == rep1); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[1].report_cfg_id == 2); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[1].report_cfg.report_cfg_eutra() == rep2); + TESTASSERT(result_meascfg.meas_id_to_add_mod_list_present and not result_meascfg.meas_id_to_rem_list_present); + TESTASSERT(result_meascfg.meas_id_to_add_mod_list.size() == 2); + auto* measid_item = &result_meascfg.meas_id_to_add_mod_list[0]; + TESTASSERT(measid_item->meas_id == 1 and measid_item->meas_obj_id == 1 and measid_item->report_cfg_id == 1); + measid_item++; + TESTASSERT(measid_item->meas_id == 2 and measid_item->meas_obj_id == 1 and measid_item->report_cfg_id == 2); // TEST: if measCfg is empty if nothing was updated src_var = target_var; src_var.compute_diff_meas_cfg(target_var, &result_meascfg); TESTASSERT(not result_meascfg.meas_obj_to_add_mod_list_present); TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 0); + TESTASSERT(not result_meascfg.report_cfg_to_rem_list_present); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 0); // TEST: Cell is added to cellsToAddModList if just a field was updated cell1.pci = 3; @@ -172,10 +218,12 @@ int test_correct_meascfg_calculation() cell_item = &eutra.cells_to_add_mod_list[0]; TESTASSERT(is_cell_cfg_equal(cell1, *cell_item)); - // TEST: Removal of cell from target propagates to the resulting meas_cfg_s cellsToRemoveList + // TEST: Removal of cell/rep from target propagates to the resulting meas_cfg_s src_var = target_var; target_var = var_meas_cfg_t{&log_h}; target_var.add_cell_cfg(cell2); + target_var.add_report_cfg(rep1); + target_var.add_report_cfg(rep3); src_var.compute_diff_meas_cfg(target_var, &result_meascfg); TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present); TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1); @@ -186,6 +234,10 @@ int test_correct_meascfg_calculation() TESTASSERT(not eutra.cells_to_add_mod_list_present and eutra.cells_to_rem_list_present); TESTASSERT(eutra.cells_to_rem_list.size() == 1); TESTASSERT(eutra.cells_to_rem_list[0] == (cell1.cell_id & 0xFFu)); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list_present and not result_meascfg.report_cfg_to_rem_list_present); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 1); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg_id == 2); + TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg.report_cfg_eutra() == rep3); } return SRSLTE_SUCCESS;