diff --git a/lib/include/srslte/asn1/rrc_asn1_utils.h b/lib/include/srslte/asn1/rrc_asn1_utils.h index 038252e5b..20b151d87 100644 --- a/lib/include/srslte/asn1/rrc_asn1_utils.h +++ b/lib/include/srslte/asn1/rrc_asn1_utils.h @@ -158,10 +158,18 @@ bool operator==(const quant_cfg_s& lhs, const quant_cfg_s& rhs); *************************/ uint8_t get_rrc_obj_id(const srb_to_add_mod_s& srb); -uint8_t get_rrc_obj_id(const drb_to_add_mod_s& srb); +uint8_t get_rrc_obj_id(const drb_to_add_mod_s& drb); +uint8_t get_rrc_obj_id(const cells_to_add_mod_s& obj); +uint8_t get_rrc_obj_id(const meas_obj_to_add_mod_s& obj); +uint8_t get_rrc_obj_id(const report_cfg_to_add_mod_s& obj); +uint8_t get_rrc_obj_id(const meas_id_to_add_mod_s& obj); void set_rrc_obj_id(srb_to_add_mod_s& srb, uint8_t id); -void set_rrc_obj_id(drb_to_add_mod_s& srb, uint8_t id); +void set_rrc_obj_id(drb_to_add_mod_s& drb, uint8_t id); +void set_rrc_obj_id(cells_to_add_mod_s& obj, uint8_t id); +void set_rrc_obj_id(meas_obj_to_add_mod_s& obj, uint8_t id); +void set_rrc_obj_id(report_cfg_to_add_mod_s& obj, uint8_t id); +void set_rrc_obj_id(meas_id_to_add_mod_s& obj, uint8_t id); } // namespace rrc } // namespace asn1 diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 851ffbdc6..5b9749cc8 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -347,6 +347,7 @@ public: virtual void rem_user(uint16_t rnti) = 0; virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::rlc_config_t cnfg) = 0; virtual void add_bearer_mrb(uint16_t rnti, uint32_t lcid) = 0; + virtual void del_bearer(uint16_t rnti, uint32_t lcid) = 0; virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0; virtual bool has_bearer(uint16_t rnti, uint32_t lcid) = 0; virtual bool suspend_bearer(uint16_t rnti, uint32_t lcid) = 0; diff --git a/lib/include/srslte/rrc/rrc_cfg_utils.h b/lib/include/srslte/rrc/rrc_cfg_utils.h index 4380c176d..340d1db40 100644 --- a/lib/include/srslte/rrc/rrc_cfg_utils.h +++ b/lib/include/srslte/rrc/rrc_cfg_utils.h @@ -24,12 +24,13 @@ #include "srslte/asn1/rrc_asn1_utils.h" #include +#include namespace srslte { //! Functor to compare RRC config elements (e.g. SRB/measObj/Rep) based on ID template -struct rrb_obj_id_cmp { +struct rrc_obj_id_cmp { bool operator()(const T& lhs, const T& rhs) const { return asn1::rrc::get_rrc_obj_id(lhs) < asn1::rrc::get_rrc_obj_id(rhs); @@ -46,7 +47,7 @@ struct rrb_obj_id_cmp { } }; template -using rrc_obj_id_list_cmp = rrb_obj_id_cmp; +using rrc_obj_id_list_cmp = rrc_obj_id_cmp; template typename Container::iterator find_rrc_obj_id(Container& c, IdType id) @@ -57,37 +58,76 @@ typename Container::iterator find_rrc_obj_id(Container& c, IdType id) template typename Container::const_iterator find_rrc_obj_id(const Container& c, IdType id) { - return std::find_if(c.begin(), c.end(), [id](const typename Container::value_type& e) { - return asn1::rrc::get_rrc_obj_id(*e) == id; - }); -} - -template -typename Container::iterator add_rrc_obj_id(Container& c, IdType id) -{ - auto it = find_rrc_obj_id(c, id); - if (it == c.end()) { - c.push_back({}); - it = c.end() - 1; - asn1::rrc::set_rrc_obj_id(*it, id); - } - return it; + return std::find_if( + c.begin(), c.end(), [id](const typename Container::value_type& e) { return asn1::rrc::get_rrc_obj_id(e) == id; }); } //! Search of rrc cfg element based on ID. Assumes sorted list. template -typename Container::iterator binary_find(Container& c, IdType id) +typename Container::iterator sorted_find_rrc_obj_id(Container& c, IdType id) { - auto it = std::lower_bound(c.begin(), c.end(), id, rrb_obj_id_cmp{}); + auto it = std::lower_bound(c.begin(), c.end(), id, rrc_obj_id_list_cmp{}); return (it == c.end() or asn1::rrc::get_rrc_obj_id(*it) != id) ? c.end() : it; } template -typename Container::const_iterator binary_find(const Container& c, IdType id) +typename Container::const_iterator sorted_find_rrc_obj_id(const Container& c, IdType id) { - auto it = std::lower_bound(c.begin(), c.end(), id, rrb_obj_id_cmp{}); + auto it = std::lower_bound(c.begin(), c.end(), id, rrc_obj_id_list_cmp{}); return (it == c.end() or asn1::rrc::get_rrc_obj_id(*it) != id) ? c.end() : it; } +//! Add Id to List in a sorted manner +template +typename Container::iterator add_rrc_obj_id(Container& c, IdType id) +{ + auto it = sorted_find_rrc_obj_id(c, id); + if (it == c.end()) { + c.push_back({}); + it = c.end() - 1; + asn1::rrc::set_rrc_obj_id(*it, id); + std::sort(c.begin(), c.end(), rrc_obj_id_list_cmp{}); + it = sorted_find_rrc_obj_id(c, id); + } + return it; +} + +template +typename Container::iterator add_rrc_obj(Container& c, const typename Container::value_type& v) +{ + auto it = sorted_find_rrc_obj_id(c, asn1::rrc::get_rrc_obj_id(v)); + if (it == c.end()) { + c.push_back(v); + std::sort(c.begin(), c.end(), rrc_obj_id_list_cmp{}); + it = sorted_find_rrc_obj_id(c, asn1::rrc::get_rrc_obj_id(v)); + } else { + *it = v; + } + return it; +} + +/** + * Find rrc obj id gap in list of rrc objs (e.g. {1, 2, 4} -> 3) + * Expects list to be sorted + * @return id value + */ +template +auto find_rrc_obj_id_gap(const Container& c) -> decltype(asn1::rrc::get_rrc_obj_id(c[0])) +{ + auto id_cmp_op = rrc_obj_id_list_cmp{}; + assert(std::is_sorted(c.begin(), c.end(), id_cmp_op)); + + auto prev_it = c.begin(); + if (prev_it != c.end() and asn1::rrc::get_rrc_obj_id(*prev_it) == 1) { + auto it = prev_it; + for (++it; it != c.end(); prev_it = it, ++it) { + if (asn1::rrc::get_rrc_obj_id(*it) > asn1::rrc::get_rrc_obj_id(*prev_it) + 1) { + break; + } + } + } + return (prev_it == c.end()) ? 1 : asn1::rrc::get_rrc_obj_id(*prev_it) + 1; // starts at 1. +} + /** * Apply toAddModList changes * @param src_list original list of rrc fields @@ -95,7 +135,7 @@ typename Container::const_iterator binary_find(const Container& c, IdType id) * @param target_list resulting list. (Can be same as src_list) */ template -void apply_addmodlist_diff(AddModList& src_list, AddModList& add_diff_list, AddModList& target_list) +void apply_addmodlist_diff(const AddModList& src_list, const AddModList& add_diff_list, AddModList& target_list) { // Shortcut for empty case if (add_diff_list.size() == 0) { @@ -104,10 +144,9 @@ void apply_addmodlist_diff(AddModList& src_list, AddModList& add_diff_list, AddM } return; } - // Sort Lists by ID auto id_cmp_op = rrc_obj_id_list_cmp{}; - std::sort(src_list.begin(), src_list.end(), id_cmp_op); - std::sort(add_diff_list.begin(), add_diff_list.end(), id_cmp_op); + assert(std::is_sorted(src_list.begin(), src_list.end(), id_cmp_op)); + assert(std::is_sorted(add_diff_list.begin(), add_diff_list.end(), id_cmp_op)); AddModList l; std::set_union( @@ -123,16 +162,21 @@ void apply_addmodlist_diff(AddModList& src_list, AddModList& add_diff_list, AddM * @param target_list resulting list. (Can be same as src_list) */ template -void apply_addmodremlist_diff(AddModList& src_list, - AddModList& add_diff_list, - RemoveList& rm_diff_list, - AddModList& target_list) +void apply_addmodremlist_diff(const AddModList& src_list, + const AddModList& add_diff_list, + RemoveList& rm_diff_list, + AddModList& target_list) { - // Sort Lists by ID + if (add_diff_list.size() == 0 and rm_diff_list.size() == 0) { + if (&target_list != &src_list) { + target_list = src_list; + } + return; + } auto id_cmp_op = rrc_obj_id_list_cmp{}; - std::sort(src_list.begin(), src_list.end(), id_cmp_op); - std::sort(add_diff_list.begin(), add_diff_list.end(), id_cmp_op); - std::sort(rm_diff_list.begin(), rm_diff_list.end()); + assert(std::is_sorted(src_list.begin(), src_list.end(), id_cmp_op)); + assert(std::is_sorted(add_diff_list.begin(), add_diff_list.end(), id_cmp_op)); + assert(std::is_sorted(rm_diff_list.begin(), rm_diff_list.end())); AddModList tmp_lst; // apply remove list @@ -155,15 +199,15 @@ void apply_addmodremlist_diff(AddModList& src_list, //! Update RRC field toAddModList template -void apply_cfg_list_updates(List& src_list, - List& target_list, - RemFunctor rem_func, - AddFunctor add_func, - ModFunctor mod_func) +void compute_cfg_diff(const List& src_list, + const List& target_list, + RemFunctor rem_func, + AddFunctor add_func, + ModFunctor mod_func) { - // Sort by ID - std::sort(src_list.begin(), src_list.end(), rrb_obj_id_cmp{}); - std::sort(target_list.begin(), target_list.end(), rrb_obj_id_cmp{}); + auto id_cmp_op = rrc_obj_id_list_cmp{}; + assert(std::is_sorted(src_list.begin(), src_list.end(), id_cmp_op)); + assert(std::is_sorted(target_list.begin(), target_list.end(), id_cmp_op)); auto src_it = src_list.begin(); auto target_it = target_list.begin(); @@ -171,10 +215,9 @@ void apply_cfg_list_updates(List& src_list, bool src_left = src_it != src_list.end(); bool target_left = target_it != target_list.end(); while (src_left or target_left) { - if (not target_left or (src_left and asn1::rrc::get_rrc_obj_id(*src_it) < asn1::rrc::get_rrc_obj_id(*target_it))) { + if (not target_left or (src_left and id_cmp_op(*src_it, *target_it))) { rem_func(src_it++); - } else if (not src_left or - (target_left and asn1::rrc::get_rrc_obj_id(*src_it) > asn1::rrc::get_rrc_obj_id(*target_it))) { + } else if (not src_left or (target_left and id_cmp_op(*target_it, *src_it))) { // a new object has been added to target add_func(target_it++); } else { @@ -185,6 +228,23 @@ void apply_cfg_list_updates(List& src_list, } } +template +void compute_cfg_diff(const toAddModList& src_list, + const toAddModList& target_list, + toAddModList& add_diff_list, + RemoveList& rem_diff_list) +{ + using it_t = typename toAddModList::const_iterator; + auto rem_func = [&rem_diff_list](it_t rem_it) { rem_diff_list.push_back(asn1::rrc::get_rrc_obj_id(*rem_it)); }; + auto add_func = [&add_diff_list](it_t add_it) { add_diff_list.push_back(*add_it); }; + auto mod_func = [&add_diff_list](it_t src_it, it_t target_it) { + if (not(*src_it == *target_it)) { + add_diff_list.push_back(*target_it); + } + }; + compute_cfg_diff(src_list, target_list, rem_func, add_func, mod_func); +} + } // namespace srslte #endif // SRSLTE_RRC_CFG_UTILS_H diff --git a/lib/src/asn1/rrc_asn1_utils.cc b/lib/src/asn1/rrc_asn1_utils.cc index 366cf3bee..99b7ac497 100644 --- a/lib/src/asn1/rrc_asn1_utils.cc +++ b/lib/src/asn1/rrc_asn1_utils.cc @@ -596,7 +596,10 @@ void set_phy_cfg_t_common_pdsch(phy_cfg_t* cfg, const asn1::rrc::pdsch_cfg_commo cfg->dl_cfg.pdsch.p_b = asn1_type.p_b; } -void set_phy_cfg_t_enable_64qam(phy_cfg_t* cfg, const bool enabled) { cfg->ul_cfg.pusch.enable_64qam = enabled; } +void set_phy_cfg_t_enable_64qam(phy_cfg_t* cfg, const bool enabled) +{ + cfg->ul_cfg.pusch.enable_64qam = enabled; +} void set_phy_cfg_t_common_pusch(phy_cfg_t* cfg, const asn1::rrc::pusch_cfg_common_s& asn1_type) { @@ -1085,11 +1088,55 @@ bool operator==(const asn1::rrc::quant_cfg_s& lhs, const asn1::rrc::quant_cfg_s& * RRC Obj Id *************************/ -uint8_t get_rrc_obj_id(const srb_to_add_mod_s& srb) { return srb.srb_id; } -uint8_t get_rrc_obj_id(const drb_to_add_mod_s& srb) { return srb.drb_id; } +uint8_t get_rrc_obj_id(const srb_to_add_mod_s& srb) +{ + return srb.srb_id; +} +uint8_t get_rrc_obj_id(const drb_to_add_mod_s& drb) +{ + return drb.drb_id; +} +uint8_t get_rrc_obj_id(const cells_to_add_mod_s& obj) +{ + return obj.cell_idx; +} +uint8_t get_rrc_obj_id(const meas_obj_to_add_mod_s& obj) +{ + return obj.meas_obj_id; +} +uint8_t get_rrc_obj_id(const report_cfg_to_add_mod_s& obj) +{ + return obj.report_cfg_id; +} +uint8_t get_rrc_obj_id(const meas_id_to_add_mod_s& obj) +{ + return obj.meas_id; +} -void set_rrc_obj_id(srb_to_add_mod_s& srb, uint8_t id) { srb.srb_id = id; } -void set_rrc_obj_id(drb_to_add_mod_s& srb, uint8_t id) { srb.drb_id = id; } +void set_rrc_obj_id(srb_to_add_mod_s& srb, uint8_t id) +{ + srb.srb_id = id; +} +void set_rrc_obj_id(drb_to_add_mod_s& drb, uint8_t id) +{ + drb.drb_id = id; +} +void set_rrc_obj_id(cells_to_add_mod_s& obj, uint8_t id) +{ + obj.cell_idx = id; +} +void set_rrc_obj_id(meas_obj_to_add_mod_s& obj, uint8_t id) +{ + obj.meas_obj_id = id; +} +void set_rrc_obj_id(report_cfg_to_add_mod_s& obj, uint8_t id) +{ + obj.report_cfg_id = id; +} +void set_rrc_obj_id(meas_id_to_add_mod_s& obj, uint8_t id) +{ + obj.meas_id = id; +} } // namespace rrc } // namespace asn1 diff --git a/srsenb/hdr/stack/upper/rlc.h b/srsenb/hdr/stack/upper/rlc.h index e3b3f2548..fabc2fd88 100644 --- a/srsenb/hdr/stack/upper/rlc.h +++ b/srsenb/hdr/stack/upper/rlc.h @@ -52,6 +52,7 @@ public: void rem_user(uint16_t rnti); void add_bearer(uint16_t rnti, uint32_t lcid, srslte::rlc_config_t cnfg); void add_bearer_mrb(uint16_t rnti, uint32_t lcid); + void del_bearer(uint16_t rnti, uint32_t lcid); bool has_bearer(uint16_t rnti, uint32_t lcid); bool suspend_bearer(uint16_t rnti, uint32_t lcid); bool resume_bearer(uint16_t rnti, uint32_t lcid); diff --git a/srsenb/src/stack/upper/rlc.cc b/srsenb/src/stack/upper/rlc.cc index e3e3075d1..ea835f63e 100644 --- a/srsenb/src/stack/upper/rlc.cc +++ b/srsenb/src/stack/upper/rlc.cc @@ -121,6 +121,15 @@ bool rlc::has_bearer(uint16_t rnti, uint32_t lcid) return result; } +void rlc::del_bearer(uint16_t rnti, uint32_t lcid) +{ + pthread_rwlock_rdlock(&rwlock); + if (users.count(rnti)) { + users[rnti].rlc->del_bearer(lcid); + } + pthread_rwlock_unlock(&rwlock); +} + bool rlc::suspend_bearer(uint16_t rnti, uint32_t lcid) { pthread_rwlock_rdlock(&rwlock); diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 0f7b7f2a0..44ef14d18 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -52,6 +52,7 @@ public: void rem_user(uint16_t rnti) override {} void add_bearer(uint16_t rnti, uint32_t lcid, srslte::rlc_config_t cnfg) override {} void add_bearer_mrb(uint16_t rnti, uint32_t lcid) override {} + void del_bearer(uint16_t rnti, uint32_t lcid) override {} void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) override {} bool has_bearer(uint16_t rnti, uint32_t lcid) override { return false; } bool suspend_bearer(uint16_t rnti, uint32_t lcid) override { return true; } diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index bb3a67a00..1c1290d4b 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -187,15 +187,16 @@ int test_correct_meascfg_calculation() 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 + // TEST 2: measConfig 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(not result_meascfg.meas_obj_to_add_mod_list_present and not result_meascfg.meas_obj_to_rem_list_present); TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 0); - TESTASSERT(not result_meascfg.report_cfg_to_rem_list_present); + TESTASSERT(not 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() == 0); - // TEST: Cell is added to cellsToAddModList if just a field was updated + // TEST 3: Cell is added to cellsToAddModList if just a field was updated cell1.pci = 3; src_var = target_var; target_var.add_cell_cfg(cell1); @@ -211,7 +212,7 @@ 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/rep from target propagates to the resulting meas_cfg_s + // TEST 4: Removal of cell/rep from target propagates to the resulting meas_cfg_s src_var = target_var; target_var = var_meas_cfg_t{}; target_var.add_cell_cfg(cell2); diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index 499ed8da2..30886cb47 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -145,6 +145,8 @@ int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args) args.general.eia_pref_list = "EIA2, EIA1, EIA0"; args.general.eea_pref_list = "EEA0, EEA2, EEA1"; + args.general.rrc_inactivity_timer = 60000; + phy_cfg_t phy_cfg; return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &phy_cfg);