diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h index 4691c4962..44345a553 100644 --- a/lib/include/srsran/common/bearer_manager.h +++ b/lib/include/srsran/common/bearer_manager.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_BEARER_MANAGER_H #define SRSRAN_BEARER_MANAGER_H +#include "srsenb/hdr/common/common_enb.h" #include "srsran/common/common.h" #include "srsran/common/rwlock_guard.h" #include "srsran/srslog/srslog.h" @@ -21,10 +22,53 @@ namespace srsran { +namespace detail { + +/** + * @brief Implementation of UE bearer manager internal functionality that is common to both srsue and + * srsenb applications + */ +class ue_bearer_manager_impl +{ +public: + struct radio_bearer_t { + srsran::srsran_rat_t rat; + uint32_t lcid; + uint32_t eps_bearer_id; + bool is_valid() const { return rat != srsran_rat_t::nulltype; } + }; + static const radio_bearer_t invalid_rb; + + /// Registers EPS bearer with PDCP RAT type and LCID + bool add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); + + /// Single EPS bearer is removed from map when the associated DRB is deleted + bool remove_eps_bearer(uint8_t eps_bearer_id); + + void reset(); + + bool has_active_radio_bearer(uint32_t eps_bearer_id); + + radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id); + + radio_bearer_t get_lcid_bearer(uint32_t lcid); + +private: + using eps_rb_map_t = std::map; + + eps_rb_map_t bearers; + std::map lcid_to_eps_bearer_id; +}; + +} // namespace detail +} // namespace srsran + +namespace srsue { + /** * @brief Helper class to manage the mapping between EPS bearer and radio bearer * - * The class maps EPS bearers that are known to NAS and GW (UE) or GTPU (eNB) + * The class maps EPS bearers that are known to NAS and GW (UE) * to radio bearer (RB) that are only known to RRC. * Since the lifetime of a EPS bearer is usually longer than the lifetime of a RB, * the GW/GTPU needs to query the Stack to check whether a @@ -40,20 +84,16 @@ namespace srsran { * used by the eNB. * */ -class bearer_manager +class ue_bearer_manager { public: - bearer_manager(); - ~bearer_manager(); + using radio_bearer_t = srsran::detail::ue_bearer_manager_impl::radio_bearer_t; - struct radio_bearer_t { - srsran::srsran_rat_t rat; - uint32_t lcid; - uint32_t eps_bearer_id; - bool is_valid() const { return rat != srsran_rat_t::nulltype; } - }; - - /// Single user interface (for UE) + ue_bearer_manager(); + ue_bearer_manager(const ue_bearer_manager&) = delete; + ue_bearer_manager(ue_bearer_manager&&) noexcept = default; + ue_bearer_manager& operator=(const ue_bearer_manager&) = delete; + ~ue_bearer_manager(); // RRC interface /// Registers EPS bearer with PDCP RAT type and LCID @@ -65,36 +105,43 @@ public: /// All registered bearer are removed (e.g. after connection release) void reset(); - // GW interface - bool has_active_radio_bearer(uint32_t eps_bearer_id); + bool has_active_radio_bearer(uint32_t eps_bearer_id) { return impl.has_active_radio_bearer(eps_bearer_id); } - // Stack interface to retrieve active RB - radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id); + radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) { return impl.get_radio_bearer(eps_bearer_id); } - radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid); + radio_bearer_t get_lcid_bearer(uint32_t lcid) { return impl.get_lcid_bearer(lcid); } + +private: + pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads + srslog::basic_logger& logger; + srsran::detail::ue_bearer_manager_impl impl; +}; + +} // namespace srsue + +namespace srsenb { + +class enb_bearer_manager +{ +public: + using radio_bearer_t = srsran::detail::ue_bearer_manager_impl::radio_bearer_t; + + enb_bearer_manager(); /// Multi-user interface (see comments above) void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid); void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id); - void reset(uint16_t rnti); + void rem_user(uint16_t rnti); bool has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id); radio_bearer_t get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id); + radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid); private: - pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads srslog::basic_logger& logger; - typedef std::map eps_rb_map_t; - struct user_bearers { - eps_rb_map_t bearers; - std::map lcid_to_eps_bearer_id; - }; - std::map users_map; - - const uint16_t default_key = 0xffff; // dummy RNTI used for public interface without explicit RNTI - radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0, 0}; + srsenb::rnti_map_t users_map; }; -} // namespace srsran +} // namespace srsenb #endif // SRSRAN_BEARER_MANAGER_H \ No newline at end of file diff --git a/lib/include/srsran/interfaces/enb_interfaces.h b/lib/include/srsran/interfaces/enb_interfaces.h index 715edd0bf..b8e831203 100644 --- a/lib/include/srsran/interfaces/enb_interfaces.h +++ b/lib/include/srsran/interfaces/enb_interfaces.h @@ -24,7 +24,7 @@ class stack_interface_rrc public: virtual void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) = 0; virtual void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) = 0; - virtual void reset_eps_bearers(uint16_t rnti) = 0; + virtual void remove_eps_bearers(uint16_t rnti) = 0; }; class stack_interface_phy_lte; diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc index dd098a7fc..b56799145 100644 --- a/lib/src/common/bearer_manager.cc +++ b/lib/src/common/bearer_manager.cc @@ -14,140 +14,172 @@ namespace srsran { -bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) +namespace detail { + +const ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::invalid_rb{srsran::srsran_rat_t::nulltype, 0, 0}; + +bool ue_bearer_manager_impl::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) { - pthread_rwlock_init(&rwlock, nullptr); + auto bearer_it = bearers.find(eps_bearer_id); + if (bearer_it != bearers.end()) { + return false; + } + bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id}); + lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id); + return true; } -bearer_manager::~bearer_manager() +bool ue_bearer_manager_impl::remove_eps_bearer(uint8_t eps_bearer_id) { - pthread_rwlock_destroy(&rwlock); + auto bearer_it = bearers.find(eps_bearer_id); + if (bearer_it == bearers.end()) { + return false; + } + uint32_t lcid = bearer_it->second.lcid; + bearers.erase(bearer_it); + lcid_to_eps_bearer_id.erase(lcid); + return true; } -void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +void ue_bearer_manager_impl::reset() { - add_eps_bearer(default_key, eps_bearer_id, rat, lcid); + lcid_to_eps_bearer_id.clear(); + bearers.clear(); } -void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +bool ue_bearer_manager_impl::has_active_radio_bearer(uint32_t eps_bearer_id) { - srsran::rwlock_write_guard rw_lock(rwlock); - auto user_it = users_map.find(rnti); - if (user_it == users_map.end()) { - // add empty bearer map - auto p = users_map.emplace(rnti, user_bearers{}); - user_it = p.first; - } - - auto bearer_it = user_it->second.bearers.find(eps_bearer_id); - if (bearer_it != user_it->second.bearers.end()) { - logger.error("EPS bearer ID %d already registered", eps_bearer_id); - return; - } - user_it->second.bearers.emplace(eps_bearer_id, radio_bearer_t{rat, lcid, eps_bearer_id}); - user_it->second.lcid_to_eps_bearer_id.emplace(lcid, eps_bearer_id); - logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); + return bearers.count(eps_bearer_id) > 0; } -void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) +ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::get_radio_bearer(uint32_t eps_bearer_id) { - remove_eps_bearer(default_key, eps_bearer_id); + auto it = bearers.find(eps_bearer_id); + return it != bearers.end() ? it->second : invalid_rb; } -void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) +ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::get_lcid_bearer(uint32_t lcid) { - srsran::rwlock_write_guard rw_lock(rwlock); + auto lcid_it = lcid_to_eps_bearer_id.find(lcid); + return lcid_it != lcid_to_eps_bearer_id.end() ? bearers.at(lcid_it->second) : invalid_rb; +} - auto user_it = users_map.find(rnti); - if (user_it == users_map.end()) { - logger.error("No EPS bearer registered for rnti=%x", rnti); - return; - } +} // namespace detail +} // namespace srsran - auto bearer_it = user_it->second.bearers.find(eps_bearer_id); - if (bearer_it == user_it->second.bearers.end()) { - logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); - return; - } - uint32_t lcid = bearer_it->second.lcid; - user_it->second.bearers.erase(bearer_it); - user_it->second.lcid_to_eps_bearer_id.erase(lcid); - logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); +namespace srsue { + +ue_bearer_manager::ue_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) +{ + pthread_rwlock_init(&rwlock, nullptr); } -void bearer_manager::reset() +ue_bearer_manager::~ue_bearer_manager() { - reset(default_key); + pthread_rwlock_destroy(&rwlock); } -void bearer_manager::reset(uint16_t rnti) +void ue_bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) { srsran::rwlock_write_guard rw_lock(rwlock); + if (impl.add_eps_bearer(eps_bearer_id, rat, lcid)) { + logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); + } else { + logger.error("EPS bearer ID %d already registered", eps_bearer_id); + } +} - auto user_it = users_map.find(rnti); - if (user_it == users_map.end()) { - logger.error("No EPS bearer registered for rnti=%x", rnti); - return; +void ue_bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + if (impl.remove_eps_bearer(eps_bearer_id)) { + logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); + } else { + logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); } +} - user_it->second.lcid_to_eps_bearer_id.clear(); - user_it->second.bearers.clear(); +void ue_bearer_manager::reset() +{ + impl.reset(); logger.info("Reset EPS bearer manager"); } -// GW interface -bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) +} // namespace srsue + +namespace srsenb { + +enb_bearer_manager::enb_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) {} + +void enb_bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) { - return has_active_radio_bearer(default_key, eps_bearer_id); + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + // add empty bearer map + auto p = users_map.insert(rnti, srsran::detail::ue_bearer_manager_impl{}); + user_it = p.value(); + } + + if (user_it->second.add_eps_bearer(eps_bearer_id, rat, lcid)) { + logger.info("Registered EPS bearer ID %d for rnti=0x%x, lcid=%d over %s-PDCP", + eps_bearer_id, + rnti, + lcid, + to_string(rat).c_str()); + } else { + logger.error("EPS bearer ID %d for rnti=0x%x already registered", eps_bearer_id, rnti); + } } -bool bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) +void enb_bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) { - srsran::rwlock_read_guard rw_lock(rwlock); - auto user_it = users_map.find(rnti); if (user_it == users_map.end()) { - return false; + logger.error("No EPS bearer registered for rnti=0x%x", rnti); + return; } - return user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end(); + if (user_it->second.remove_eps_bearer(eps_bearer_id)) { + logger.info("Removed mapping for EPS bearer ID %d for rnti=0x%x", eps_bearer_id, rnti); + } else { + logger.error("Can't remove EPS bearer ID %d, rnti=0x%x", eps_bearer_id, rnti); + } } -// Stack interface -bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bearer_id) +void enb_bearer_manager::rem_user(uint16_t rnti) { - return get_radio_bearer(default_key, eps_bearer_id); + if (users_map.erase(rnti)) { + logger.info("Removed rnti=0x%x from EPS bearer manager", rnti); + } else { + logger.error("No EPS bearer registered for rnti=0x%x", rnti); + } } -bearer_manager::radio_bearer_t bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid) +bool enb_bearer_manager::has_active_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) { - srsran::rwlock_read_guard rw_lock(rwlock); - auto user_it = users_map.find(rnti); if (user_it == users_map.end()) { - return invalid_rb; - } - - auto lcid_it = user_it->second.lcid_to_eps_bearer_id.find(lcid); - if (lcid_it != user_it->second.lcid_to_eps_bearer_id.end()) { - return user_it->second.bearers.at(lcid_it->second); + return false; } - return invalid_rb; + return user_it->second.has_active_radio_bearer(eps_bearer_id); } -bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) +enb_bearer_manager::radio_bearer_t enb_bearer_manager::get_lcid_bearer(uint16_t rnti, uint32_t lcid) { - srsran::rwlock_read_guard rw_lock(rwlock); - auto user_it = users_map.find(rnti); if (user_it == users_map.end()) { - return invalid_rb; + return srsran::detail::ue_bearer_manager_impl::invalid_rb; } + return user_it->second.get_lcid_bearer(lcid); +} - if (user_it->second.bearers.find(eps_bearer_id) != user_it->second.bearers.end()) { - return user_it->second.bearers.at(eps_bearer_id); +enb_bearer_manager::radio_bearer_t enb_bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id) +{ + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + return srsran::detail::ue_bearer_manager_impl::invalid_rb; } - return invalid_rb; + return user_it->second.get_radio_bearer(eps_bearer_id); } -} // namespace srsran \ No newline at end of file +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 1c94ef9d9..ba0310c1d 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -139,7 +139,7 @@ public: // interface for bearer manager void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) override; void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) override; - void reset_eps_bearers(uint16_t rnti) override; + void remove_eps_bearers(uint16_t rnti) override; private: static const int STACK_MAIN_THREAD_PRIO = 4; @@ -176,7 +176,7 @@ private: srsran::task_queue_handle enb_task_queue, sync_task_queue, metrics_task_queue; // bearer management - srsran::bearer_manager bearers; // helper to manage mapping between EPS and radio bearers + enb_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers std::unique_ptr gtpu_adapter; srsenb::mac mac; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 41c75722d..d5d2b2620 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -25,11 +25,11 @@ namespace srsenb { class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interface_gtpu { public: - gtpu_pdcp_adapter(srslog::basic_logger& logger_, - pdcp* pdcp_lte, - pdcp* pdcp_nr, - gtpu* gtpu_, - srsran::bearer_manager& bearers_) : + gtpu_pdcp_adapter(srslog::basic_logger& logger_, + pdcp* pdcp_lte, + pdcp* pdcp_nr, + gtpu* gtpu_, + enb_bearer_manager& bearers_) : logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) {} @@ -69,11 +69,11 @@ public: } private: - srslog::basic_logger& logger; - gtpu* gtpu_obj = nullptr; - pdcp* pdcp_obj = nullptr; - pdcp* pdcp_nr_obj = nullptr; - srsran::bearer_manager* bearers = nullptr; + srslog::basic_logger& logger; + gtpu* gtpu_obj = nullptr; + pdcp* pdcp_obj = nullptr; + pdcp* pdcp_nr_obj = nullptr; + enb_bearer_manager* bearers = nullptr; }; enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : @@ -345,9 +345,9 @@ void enb_stack_lte::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) bearers.remove_eps_bearer(rnti, eps_bearer_id); } -void enb_stack_lte::reset_eps_bearers(uint16_t rnti) +void enb_stack_lte::remove_eps_bearers(uint16_t rnti) { - bearers.reset(rnti); + bearers.rem_user(rnti); } } // namespace srsenb diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 600fb1988..f49341f38 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -655,6 +655,7 @@ void rrc::rem_user(uint16_t rnti) gtpu->rem_user(rnti); // Now remove RLC and PDCP + stack->remove_eps_bearers(rnti); rlc->rem_user(rnti); pdcp->rem_user(rnti); diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index 0fac1d0c9..c300ba9ac 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -406,12 +406,7 @@ srsran::expected bearer_cfg_handler::add_gtpu_bearer(uint32_t void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id) { - auto it = erabs.find(erab_id); - if (it == erabs.end()) { - logger->warning("Removing erab_id=%d from GTPU", erab_id); - return; - } - gtpu->rem_bearer(rnti, it->second.id); + gtpu->rem_bearer(rnti, erab_id); } void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg) diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index 5f1c2b8fb..76897257c 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -205,7 +205,7 @@ class enb_stack_dummy : public stack_interface_rrc { void add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) {} void remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) {} - void reset_eps_bearers(uint16_t rnti){}; + void remove_eps_bearers(uint16_t rnti){}; }; } // namespace test_dummies diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index b6ed87e5f..62aefd034 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -231,7 +231,7 @@ private: srsue::nas nas; std::unique_ptr usim; - bearer_manager bearers; // helper to manage mapping between EPS and radio bearers + ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers // Metrics helper uint32_t ul_dropped_sdus = 0;