From 1524e28c3a95df7f6338edf2731c6bdf979f5fed Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Thu, 31 Oct 2019 12:52:28 +0000 Subject: [PATCH] finished the function to compute diffs between cells/measObjs of two var_meas_cfg objects. Added tests for this. Now the update of a UE's var_meas_cfg is made via a shared pointer. --- lib/include/srslte/asn1/asn1_utils.h | 2 +- srsenb/hdr/stack/rrc/rrc_mobility.h | 12 +- srsenb/src/stack/rrc/rrc.cc | 4 + srsenb/src/stack/rrc/rrc_mobility.cc | 300 ++++++++++++++++--------- srsenb/test/upper/rrc_mobility_test.cc | 112 ++++++++- 5 files changed, 300 insertions(+), 130 deletions(-) diff --git a/lib/include/srslte/asn1/asn1_utils.h b/lib/include/srslte/asn1/asn1_utils.h index 3571d09b3..22d3b1655 100644 --- a/lib/include/srslte/asn1/asn1_utils.h +++ b/lib/include/srslte/asn1/asn1_utils.h @@ -196,7 +196,7 @@ public: const T* begin() const { return &data_[0]; } const T* end() const { return &data_[size()]; } using iterator = T*; - using const_iterator = T*; + using const_iterator = const T*; private: T* data_ = nullptr; diff --git a/srsenb/hdr/stack/rrc/rrc_mobility.h b/srsenb/hdr/stack/rrc/rrc_mobility.h index 869c94aa9..f0f3b5d7e 100644 --- a/srsenb/hdr/stack/rrc/rrc_mobility.h +++ b/srsenb/hdr/stack/rrc/rrc_mobility.h @@ -43,11 +43,11 @@ public: std::tuple add_cell_cfg(const meas_cell_cfg_t& cellcfg); uint32_t get_new_obj_id(); - void compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg); - void compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg); + void 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, - asn1::rrc::meas_obj_eutra_s& src_it, - asn1::rrc::meas_obj_to_add_mod_s* added_obj); + const asn1::rrc::meas_obj_eutra_s& src_it, + asn1::rrc::meas_obj_to_add_mod_s* added_obj) const; // getters const asn1::rrc::meas_obj_to_add_mod_list_l& meas_objs() const { return var_meas.meas_obj_list; } @@ -62,7 +62,7 @@ class rrc::mobility_cfg public: explicit mobility_cfg(rrc* outer_rrc); - var_meas_cfg_t current_meas_cfg; + std::shared_ptr current_meas_cfg; ///< const to enable ptr comparison as identity comparison private: rrc* rrc_enb = nullptr; @@ -82,7 +82,7 @@ private: srslte::log* rrc_log = nullptr; // vars - var_meas_cfg_t ue_var_meas; + std::shared_ptr ue_var_meas; class mobility_proc_t { diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 36189110c..22988a8ab 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -1908,6 +1908,10 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) conn_reconf->ded_info_nas_list.resize(0); } + if (mobility_handler != nullptr) { + mobility_handler->fill_conn_recfg_msg(conn_reconf); + } + // Reuse same PDU pdu->clear(); diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 1ef032b38..a760c1683 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -33,6 +33,49 @@ namespace srsenb { using namespace asn1::rrc; +/************************************************************************************************* + * Convenience Functions to handle ASN1 MeasObjs/MeasId/ReportCfg/Cells/etc. + ************************************************************************************************/ + +//! Convenience operator== overload to compare Fields of MeasObj/MeasId/ReportCfg/Cells/etc. +bool operator==(const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs) +{ + return lhs.cell_idx == rhs.cell_idx and lhs.pci == rhs.pci and + lhs.cell_individual_offset == rhs.cell_individual_offset; +} +bool operator==(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& rhs) +{ + if (lhs.meas_obj_id != rhs.meas_obj_id or lhs.meas_obj.type() != lhs.meas_obj.type()) { + return false; + } + auto &lhs_eutra = lhs.meas_obj.meas_obj_eutra(), &rhs_eutra = rhs.meas_obj.meas_obj_eutra(); + if (lhs_eutra.ext or rhs_eutra.ext) { + printf("[%d] extension of measObjToAddMod not supported\n", __LINE__); + return false; + } + + if (lhs_eutra.offset_freq_present != rhs_eutra.offset_freq_present or + (lhs_eutra.offset_freq_present and lhs_eutra.offset_freq != rhs_eutra.offset_freq)) { + return false; + } + + if (lhs_eutra.carrier_freq != rhs_eutra.carrier_freq or not(lhs_eutra.neigh_cell_cfg == rhs_eutra.neigh_cell_cfg) or + lhs_eutra.presence_ant_port1 != rhs_eutra.presence_ant_port1 or + lhs_eutra.allowed_meas_bw != rhs_eutra.allowed_meas_bw) { + return false; + } + + if (lhs_eutra.cells_to_add_mod_list.size() != rhs_eutra.cells_to_add_mod_list.size()) { + return false; + } + + auto cells_are_equal = [](const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs) { return lhs == rhs; }; + return std::equal(lhs_eutra.cells_to_add_mod_list.begin(), + lhs_eutra.cells_to_add_mod_list.end(), + rhs_eutra.cells_to_add_mod_list.begin(), + cells_are_equal); +} + namespace rrc_details { //! extract cell id from ECI @@ -41,21 +84,34 @@ uint32_t eci_to_cellid(uint32_t eci) return eci & 0xFFu; } -//! cell comparison based on content -bool cells_are_equal(const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs) +//! convenience function overload to extract Id from MeasObj/MeasId/ReportCfg/Cells +uint8_t get_id(const cells_to_add_mod_s& obj) { - return lhs.cell_idx == rhs.cell_idx and lhs.pci == rhs.pci and - lhs.cell_individual_offset == rhs.cell_individual_offset; + return obj.cell_idx; +} +uint8_t get_id(const meas_obj_to_add_mod_s& obj) +{ + return obj.meas_obj_id; +} + +//! convenience function overload to print MeasObj/MeasId/etc. fields +std::string to_string(const cells_to_add_mod_s& obj) +{ + char buf[128]; + std::snprintf( + buf, 128, "{cell_idx: %d, pci: %d, offset: %d}", obj.cell_idx, obj.pci, obj.cell_individual_offset.to_number()); + return {buf}; } //! meas field comparison based on ID solely -template +template struct field_id_cmp { - bool operator()(const T& lhs, const T& rhs) const { return lhs.*field < rhs.*field; } - bool operator()(const T& lhs, IdType id) const { return lhs.*field < id; } + using IdType = decltype(get_id(T{})); + bool operator()(const T& lhs, const T& rhs) const { return get_id(lhs) < get_id(rhs); } + bool operator()(const T& lhs, IdType id) const { return get_id(lhs) < id; } }; -using cell_id_cmp = field_id_cmp; -using meas_obj_id_cmp = field_id_cmp; +using cell_id_cmp = field_id_cmp; +using meas_obj_id_cmp = field_id_cmp; //! Find MeasObj with same earfcn meas_obj_to_add_mod_s* find_meas_obj(meas_obj_to_add_mod_list_l& l, uint32_t earfcn) @@ -96,8 +152,9 @@ cells_to_add_mod_s* meascfg_add_cell(meas_obj_eutra_s& eutra_obj, const cells_to { // 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. + // 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()) { @@ -115,8 +172,7 @@ cells_to_add_mod_s* meascfg_add_cell(meas_obj_eutra_s& eutra_obj, const cells_to /** * 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, bool add_cells_flag) +meas_obj_to_add_mod_s* meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj) { meas_cfg->meas_obj_to_add_mod_list_present = true; meas_obj_to_add_mod_list_l& l = meas_cfg->meas_obj_to_add_mod_list; @@ -139,47 +195,55 @@ meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj target_eutra.presence_ant_port1 = src_eutra.presence_ant_port1; target_eutra.neigh_cell_cfg = src_eutra.neigh_cell_cfg; - if (add_cells_flag) { - for (const cells_to_add_mod_s& cell_it : src_eutra.cells_to_add_mod_list) { - rrc_details::meascfg_add_cell(target_eutra, cell_it); - } - } - return found_it; } -//! Find difference between MeasObjs -bool meas_objs_are_equal(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& rhs) -{ - if (lhs.meas_obj_id != rhs.meas_obj_id or lhs.meas_obj.type() != lhs.meas_obj.type()) { - return false; - } - auto &lhs_eutra = lhs.meas_obj.meas_obj_eutra(), &rhs_eutra = rhs.meas_obj.meas_obj_eutra(); - if (lhs_eutra.ext or rhs_eutra.ext) { - printf("[%d] extension of measObjToAddMod not supported\n", __LINE__); - return false; +/* + * Algorithm to compare differences between Meas Fields. This is used for MeasObjs, Cells, ReportConfig, MeasId (and + * more in the future) + * Returns outcome==same_id, if two fields were spotted with same id, "id_removed" if an id was removed from the target + * "id_added" if an id was added to the target, and complete when the iteration is over + */ +enum class diff_outcome_t { same_id, id_removed, id_added, complete }; +template +struct compute_diff_generator { + using const_iterator = typename Container::const_iterator; + struct result_t { + diff_outcome_t outcome; + const_iterator src_it; + const_iterator target_it; + }; + + compute_diff_generator(const Container& src, const Container& target) : + src_it(src.begin()), + src_end(src.end()), + target_it(target.begin()), + target_end(target.end()) + { } - if (lhs_eutra.offset_freq_present != rhs_eutra.offset_freq_present or - (lhs_eutra.offset_freq_present and lhs_eutra.offset_freq != rhs_eutra.offset_freq)) { - return false; + result_t next() + { + bool src_left = src_it != src_end; + bool target_left = target_it != target_end; + if (not src_left and not target_left) { + return {diff_outcome_t::complete, nullptr, nullptr}; + } + if (not target_left or (src_left and get_id(*src_it) < get_id(*target_it))) { + // an object has been removed from the target + return {diff_outcome_t::id_removed, src_it++, target_it}; + } + if (not src_left or (target_left and get_id(*src_it) > get_id(*target_it))) { + // a new object has been added to target + return {diff_outcome_t::id_added, src_it, target_it++}; + } + // Same ID + return {diff_outcome_t::same_id, src_it++, target_it++}; } - if (lhs_eutra.carrier_freq != rhs_eutra.carrier_freq or not(lhs_eutra.neigh_cell_cfg == rhs_eutra.neigh_cell_cfg) or - lhs_eutra.presence_ant_port1 != rhs_eutra.presence_ant_port1 or - lhs_eutra.allowed_meas_bw != rhs_eutra.allowed_meas_bw) { - return false; - } - - if (lhs_eutra.cells_to_add_mod_list.size() != rhs_eutra.cells_to_add_mod_list.size()) { - return false; - } - - return std::equal(lhs_eutra.cells_to_add_mod_list.begin(), - lhs_eutra.cells_to_add_mod_list.end(), - rhs_eutra.cells_to_add_mod_list.begin(), - cells_are_equal); -} +private: + const_iterator src_it, src_end, target_it, target_end; +}; } // namespace rrc_details @@ -264,8 +328,9 @@ uint32_t var_meas_cfg_t::get_new_obj_id() return (prev_it == var_meas.meas_obj_list.end()) ? 1 : prev_it->meas_obj_id + 1; // starts at 1. } -void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) +void 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); @@ -280,75 +345,78 @@ void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn //! adds all the cells that got updated to MeasCfg. void var_meas_cfg_t::compute_diff_cells(const meas_obj_eutra_s& target_it, - meas_obj_eutra_s& src_it, - meas_obj_to_add_mod_s* added_obj) + const meas_obj_eutra_s& src_it, + meas_obj_to_add_mod_s* added_obj) const { - cells_to_add_mod_s* src_cell = src_it.cells_to_add_mod_list.begin(); - const cells_to_add_mod_s* target_cell = target_it.cells_to_add_mod_list.begin(); - bool src_left = src_cell != src_it.cells_to_add_mod_list.end(); - bool target_left = target_cell != target_it.cells_to_add_mod_list.end(); - while (src_left or target_left) { - if (not target_left or (src_left and src_cell->cell_idx < target_cell->cell_idx)) { - // a cell was removed from the eNB - // TODO: add cell to remove list - ++src_cell; - } else if (not src_left or (target_left and src_cell->cell_idx > target_cell->cell_idx)) { - // a cell was added to the eNB - Info("UE has now to measure activity of (earfcn,cell_id)=(%d,%d).\n", target_cell->cell_idx, target_cell->pci); - rrc_details::meascfg_add_cell(added_obj->meas_obj.meas_obj_eutra(), *target_cell); - } else { - // check if cells are the same. if not, update. - if (not rrc_details::cells_are_equal(*src_cell, *target_cell)) { - Info("UE has now to measure activity of (earfcn,cell_id)=(%d,%d) with updated params.\n", - target_cell->cell_idx, - target_cell->pci); - rrc_details::meascfg_add_cell(added_obj->meas_obj.meas_obj_eutra(), *target_cell); - *src_cell = *target_cell; - } - ++src_cell; - ++target_cell; + 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(); + + 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: + 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: + 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); + 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)) { + 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); + } + break; } - src_left = src_cell != src_it.cells_to_add_mod_list.end(); - target_left = target_cell != target_it.cells_to_add_mod_list.end(); } } //! 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) +void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, meas_cfg_s* meas_cfg) const { // TODO: black cells and white cells + rrc_details::compute_diff_generator diffs{var_meas.meas_obj_list, + target_cfg.var_meas.meas_obj_list}; - meas_obj_t * ue_it = var_meas.meas_obj_list.begin(), *ue_end = var_meas.meas_obj_list.end(); - const meas_obj_t *target_it = target_cfg.var_meas.meas_obj_list.begin(), - *target_end = target_cfg.var_meas.meas_obj_list.end(); - - bool ues_left = ue_it != ue_end; - bool enbs_left = target_it != target_end; - while (ues_left or enbs_left) { - if (not enbs_left or (ues_left and ue_it->meas_obj_id < target_it->meas_obj_id)) { - // an object has been removed from the target_var_meas - Info("UE can cease to measure activity in frequency earfcn=%d.\n", ue_it->meas_obj.meas_obj_eutra().carrier_freq); - // TODO: add to remove list - ++ue_it; - } else if (!ues_left or (enbs_left and ue_it->meas_obj_id > target_it->meas_obj_id)) { - // a new object has been added to enb_var_meas - Info("HO: UE has now to measure activity of new frequency earfcn=%d.\n", - target_it->meas_obj.meas_obj_eutra().carrier_freq); - rrc_details::meascfg_add_meas_obj(meas_cfg, *target_it, true); - ++target_it; - } else { - bool are_equal = rrc_details::meas_objs_are_equal(*ue_it, *target_it); - if (not are_equal) { - // if we found a difference in obj IDs - meas_obj_to_add_mod_s* added_obj = rrc_details::meascfg_add_meas_obj(meas_cfg, *target_it, false); - // Add cells/meas_obj if there were changes. - compute_diff_cells(target_it->meas_obj.meas_obj_eutra(), ue_it->meas_obj.meas_obj_eutra(), added_obj); - } - ++ue_it; - ++target_it; + 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: + 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: { + 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); + } + } break; + case rrc_details::diff_outcome_t::same_id: + bool are_equal = *result.src_it == *result.target_it; + if (not are_equal) { + // if we found a difference in obj IDs + meas_obj_to_add_mod_s* added_obj = rrc_details::meascfg_add_meas_obj(meas_cfg, *result.target_it); + // Add cells if there were changes. + compute_diff_cells( + result.target_it->meas_obj.meas_obj_eutra(), result.src_it->meas_obj.meas_obj_eutra(), added_obj); + } + break; } - ues_left = ue_it != ue_end; - enbs_left = target_it != target_end; } } @@ -356,14 +424,18 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me * mobility_cfg class ************************************************************************************************/ -rrc::mobility_cfg::mobility_cfg(rrc* outer_rrc) : rrc_enb(outer_rrc), current_meas_cfg(outer_rrc->rrc_log) +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) { for (meas_cell_cfg_t& meascell : rrc_enb->cfg.meas_cfg.meas_cells) { - current_meas_cfg.add_cell_cfg(meascell); + var_meas.add_cell_cfg(meascell); } } + + current_meas_cfg = std::make_shared(var_meas); } /************************************************************************************************* @@ -375,9 +447,9 @@ rrc::ue::rrc_mobility::rrc_mobility(rrc::ue* outer_ue) : rrc_enb(outer_ue->parent), cfg(outer_ue->parent->enb_mobility_cfg.get()), pool(outer_ue->pool), - rrc_log(outer_ue->parent->rrc_log), - ue_var_meas(outer_ue->parent->rrc_log) + rrc_log(outer_ue->parent->rrc_log) { + ue_var_meas = std::make_shared(outer_ue->parent->rrc_log); } bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg) @@ -387,8 +459,14 @@ bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies return false; } + // Check if there has been any update + if (ue_var_meas.get() == cfg->current_meas_cfg.get()) { + return false; + } + asn1::rrc::meas_cfg_s* meas_cfg = &conn_recfg->meas_cfg; - ue_var_meas.compute_diff_meas_cfg(cfg->current_meas_cfg, meas_cfg); + ue_var_meas->compute_diff_meas_cfg(*cfg->current_meas_cfg, meas_cfg); + 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 --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index 6729fd012..b093cb754 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -36,20 +36,32 @@ using namespace asn1::rrc; srslte::log_filter log_h("ALL"); -int test_correct_insertion() +meas_cell_cfg_t generate_cell1() { - meas_cell_cfg_t cell1{}, cell2{}, cell3{}, cell4{}; + meas_cell_cfg_t cell1{}; cell1.earfcn = 3400; cell1.pci = 1; cell1.q_offset = 0; cell1.cell_id = 0x19C01; - cell2 = cell1; - cell2.pci = 2; - cell2.cell_id = 0x19C02; - cell3 = cell1; - cell3.earfcn = 2850; - cell4 = cell1; - cell4.q_offset = 1; + return cell1; +} + +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 + cell.cell_idx == (cfg.cell_id & 0xFFu); +} + +int test_correct_insertion() +{ + meas_cell_cfg_t cell1 = generate_cell1(), cell2{}, cell3{}, cell4{}; + cell2 = cell1; + cell2.pci = 2; + cell2.cell_id = 0x19C02; + cell3 = cell1; + cell3.earfcn = 2850; + cell4 = cell1; + cell4.q_offset = 1; // TEST 1: cell insertion in empty varMeasCfg { @@ -63,9 +75,7 @@ int test_correct_insertion() auto& eutra = objs[0].meas_obj.meas_obj_eutra(); TESTASSERT(eutra.carrier_freq == cell1.earfcn); TESTASSERT(eutra.cells_to_add_mod_list.size() == 1); - TESTASSERT(eutra.cells_to_add_mod_list[0].pci == cell1.pci); - TESTASSERT(eutra.cells_to_add_mod_list[0].cell_idx == (cell1.cell_id & 0xFFu)); - TESTASSERT(eutra.cells_to_add_mod_list[0].cell_individual_offset.to_number() == (int8_t)round(cell1.q_offset)); + TESTASSERT(is_cell_cfg_equal(cell1, eutra.cells_to_add_mod_list[0])); } { @@ -106,9 +116,87 @@ int test_correct_insertion() return 0; } +int test_correct_meascfg_calculation() +{ + var_meas_cfg_t src_var(&log_h), target_var(&log_h); + + meas_cell_cfg_t cell1{}, cell2{}; + cell1.earfcn = 3400; + cell1.pci = 1; + cell1.q_offset = 0; + cell1.cell_id = 0x19C01; + cell2 = cell1; + cell2.pci = 2; + cell2.cell_id = 0x19C02; + + { + 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); + 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); + TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1); + auto* item = &result_meascfg.meas_obj_to_add_mod_list[0]; + TESTASSERT(item->meas_obj_id == 1 and + item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra); + auto& eutra = item->meas_obj.meas_obj_eutra(); + TESTASSERT(eutra.cells_to_add_mod_list_present and not eutra.cells_to_rem_list_present); + TESTASSERT(eutra.cells_to_add_mod_list.size() == 2); + auto* cell_item = &eutra.cells_to_add_mod_list[0]; + TESTASSERT(is_cell_cfg_equal(cell1, *cell_item)); + cell_item++; + TESTASSERT(is_cell_cfg_equal(cell2, *cell_item)); + + // 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); + + // TEST: Cell is added to cellsToAddModList if just a field was updated + cell1.pci = 3; + src_var = target_var; + target_var.add_cell_cfg(cell1); + 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); + item = &result_meascfg.meas_obj_to_add_mod_list[0]; + TESTASSERT(item->meas_obj_id == 1 and + item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra); + eutra = item->meas_obj.meas_obj_eutra(); + TESTASSERT(eutra.cells_to_add_mod_list_present and not eutra.cells_to_rem_list_present); + TESTASSERT(eutra.cells_to_add_mod_list.size() == 1); + 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 + src_var = target_var; + target_var = var_meas_cfg_t{&log_h}; + target_var.add_cell_cfg(cell2); + 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); + item = &result_meascfg.meas_obj_to_add_mod_list[0]; + TESTASSERT(item->meas_obj_id == 1 and + item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra); + eutra = item->meas_obj.meas_obj_eutra(); + 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)); + } + + return SRSLTE_SUCCESS; +} + int main() { TESTASSERT(test_correct_insertion() == 0); + TESTASSERT(test_correct_meascfg_calculation() == 0); + + printf("Success\n"); return 0; } \ No newline at end of file