diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h new file mode 100644 index 000000000..9a585476b --- /dev/null +++ b/lib/include/srsran/common/bearer_manager.h @@ -0,0 +1,92 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_BEARER_MANAGER_H +#define SRSRAN_BEARER_MANAGER_H + +#include "srsran/common/common.h" +#include "srsran/common/rwlock_guard.h" +#include "srsran/srslog/srslog.h" +#include +#include + +namespace srsran { + +/** + * @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) + * 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 + * given EPS bearer is active, i.e. a DRB is established, or not. + * + * The class also maps between RATs since each LCID can exist on either EUTRA or NR RATs, or both. + * + * Since the access of this class is happening from two different threads (GW+RRC/Stack) + * it's public interface is protected. + * + * The class provides two interfaces to be used with RNTI or without. The version without + * RNTI is used by the UE. The version with RNTI in the interface is intented to be + * used by the eNB. + * + */ +class bearer_manager +{ +public: + bearer_manager(); + ~bearer_manager(); + + struct radio_bearer_t { + srsran::srsran_rat_t rat; + uint32_t lcid; + }; + + /// Single user interface (for UE) + + // RRC interface + /// Registers EPS bearer with PDCP RAT type and LCID + void 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 + void remove_eps_bearer(uint8_t eps_bearer_id); + + /// All registered bearer are removed (e.g. after connection release) + void reset(); + + // GW interface + bool has_active_radio_bearer(uint32_t eps_bearer_id); + + // Stack interface to retrieve active RB + radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id); + + /// 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); + 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); + +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; + 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}; +}; + +} // namespace srsran + +#endif // SRSRAN_BEARER_MANAGER_H \ No newline at end of file diff --git a/lib/src/common/CMakeLists.txt b/lib/src/common/CMakeLists.txt index 12a78d129..dce6eaf2b 100644 --- a/lib/src/common/CMakeLists.txt +++ b/lib/src/common/CMakeLists.txt @@ -6,12 +6,12 @@ # the distribution. # - set(SOURCES arch_select.cc enb_events.cc backtrace.c byte_buffer.cc band_helper.cc + bearer_manager.cc buffer_pool.cc crash_handler.cc gen_mch_tables.c diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc new file mode 100644 index 000000000..bef2048cb --- /dev/null +++ b/lib/src/common/bearer_manager.cc @@ -0,0 +1,133 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/common/bearer_manager.h" + +namespace srsran { + +bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) +{ + pthread_rwlock_init(&rwlock, nullptr); +} + +bearer_manager::~bearer_manager() +{ + pthread_rwlock_destroy(&rwlock); +} + +void bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + add_eps_bearer(default_key, eps_bearer_id, rat, lcid); +} + +void bearer_manager::add_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + // add empty bearer map + users_map.emplace(rnti, eps_rb_map_t{}); + user_it = users_map.find(rnti); + } + + auto bearer_it = user_it->second.find(eps_bearer_id); + if (bearer_it != user_it->second.end()) { + logger.error("EPS bearer ID %d already registered", eps_bearer_id); + return; + } + user_it->second.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); + logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); +} + +void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) +{ + remove_eps_bearer(default_key, eps_bearer_id); +} + +void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + logger.error("No EPS bearer registered for rnti=%x", rnti); + return; + } + + auto bearer_it = user_it->second.find(eps_bearer_id); + if (bearer_it == user_it->second.end()) { + logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); + return; + } + user_it->second.erase(bearer_it); + logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); +} + +void bearer_manager::reset() +{ + reset(default_key); +} + +void bearer_manager::reset(uint16_t rnti) +{ + srsran::rwlock_write_guard rw_lock(rwlock); + + auto user_it = users_map.find(rnti); + if (user_it == users_map.end()) { + logger.error("No EPS bearer registered for rnti=%x", rnti); + return; + } + + user_it->second.clear(); + logger.info("Reset EPS bearer manager"); +} + +// GW interface +bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) +{ + return has_active_radio_bearer(default_key, eps_bearer_id); +} + +bool 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 false; + } + + return user_it->second.find(eps_bearer_id) != user_it->second.end(); +} + +// Stack interface +bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bearer_id) +{ + return get_radio_bearer(default_key, eps_bearer_id); +} + +bearer_manager::radio_bearer_t bearer_manager::get_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; + } + + if (user_it->second.find(eps_bearer_id) != user_it->second.end()) { + return user_it->second.at(eps_bearer_id); + } + return invalid_rb; +} + +} // namespace srsue \ No newline at end of file diff --git a/srsue/hdr/stack/bearer_manager.h b/srsue/hdr/stack/bearer_manager.h deleted file mode 100644 index 7e2d3d779..000000000 --- a/srsue/hdr/stack/bearer_manager.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#ifndef SRSUE_BEARER_MANAGER_H -#define SRSUE_BEARER_MANAGER_H - -#include "srsran/common/common.h" -#include "srsran/common/rwlock_guard.h" -#include "srsran/srslog/srslog.h" -#include -#include - -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 and 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 needs to query the Stack to check whether a - * given EPS bearer is active, i.e. a DRB is established, or not. - * - * The class also maps between RATs since each LCID can exist on either EUTRA or NR RATs, or both. - * - * Since the access of this class is happening from two different threads (GW+RRC/Stack) - * it's public interface is protected. - * - */ -class bearer_manager -{ -public: - bearer_manager(); - ~bearer_manager(); - - // RRC interface - /// Registers EPS bearer with PDCP RAT type and LCID - void 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 - void remove_eps_bearer(uint8_t eps_bearer_id); - - /// All registered bearer are removed (e.g. after connection release) - void reset(); - - // GW interface - bool has_active_radio_bearer(uint32_t eps_bearer_id); - - // Stack interface to retrieve active RB - struct radio_bearer_t { - srsran::srsran_rat_t rat; - uint32_t lcid; - }; - radio_bearer_t& get_radio_bearer(uint32_t eps_bearer_id); - -private: - pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads - srslog::basic_logger& logger; - std::map eps_rb_map; - radio_bearer_t invalid_rb = {srsran::srsran_rat_t::nulltype, 0}; -}; - -} // namespace srsue - -#endif // SRSUE_BEARER_MANAGER_H \ No newline at end of file diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 55938bc3c..b6ed87e5f 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -31,7 +31,7 @@ #include "upper/nas.h" #include "upper/usim.h" -#include "bearer_manager.h" +#include "srsran/common/bearer_manager.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/multiqueue.h" #include "srsran/common/string_helpers.h" diff --git a/srsue/src/stack/CMakeLists.txt b/srsue/src/stack/CMakeLists.txt index 1d2e9e1aa..c2834833e 100644 --- a/srsue/src/stack/CMakeLists.txt +++ b/srsue/src/stack/CMakeLists.txt @@ -11,7 +11,7 @@ add_subdirectory(mac) add_subdirectory(rrc) add_subdirectory(upper) -set(SOURCES ue_stack_lte.cc bearer_manager.cc) +set(SOURCES ue_stack_lte.cc) add_library(srsue_stack STATIC ${SOURCES}) add_subdirectory(mac_nr) diff --git a/srsue/src/stack/bearer_manager.cc b/srsue/src/stack/bearer_manager.cc deleted file mode 100644 index 862fd1ba5..000000000 --- a/srsue/src/stack/bearer_manager.cc +++ /dev/null @@ -1,75 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2021 Software Radio Systems Limited - * - * By using this file, you agree to the terms and conditions set - * forth in the LICENSE file which can be found at the top level of - * the distribution. - * - */ - -#include "srsue/hdr/stack/bearer_manager.h" - -namespace srsue { - -bearer_manager::bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false)) -{ - pthread_rwlock_init(&rwlock, nullptr); -} - -bearer_manager::~bearer_manager() -{ - pthread_rwlock_destroy(&rwlock); -} - -void 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); - auto it = eps_rb_map.find(eps_bearer_id); - if (it != eps_rb_map.end()) { - logger.error("EPS bearer ID %d already registered", eps_bearer_id); - return; - } - eps_rb_map.emplace(eps_bearer_id, radio_bearer_t{rat, lcid}); - logger.info("Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); -} - -void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) -{ - srsran::rwlock_write_guard rw_lock(rwlock); - auto it = eps_rb_map.find(eps_bearer_id); - if (it == eps_rb_map.end()) { - logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); - return; - } - eps_rb_map.erase(it); - logger.info("Removed mapping for EPS bearer ID %d", eps_bearer_id); -} - -void bearer_manager::reset() -{ - srsran::rwlock_write_guard rw_lock(rwlock); - eps_rb_map.clear(); - logger.info("Reset EPS bearer manager"); -} - -// GW interface -bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id) -{ - srsran::rwlock_read_guard rw_lock(rwlock); - return eps_rb_map.find(eps_bearer_id) != eps_rb_map.end(); -} - -// Stack interface -bearer_manager::radio_bearer_t& bearer_manager::get_radio_bearer(uint32_t eps_bearer_id) -{ - srsran::rwlock_read_guard rw_lock(rwlock); - if (eps_rb_map.find(eps_bearer_id) != eps_rb_map.end()) { - return eps_rb_map.at(eps_bearer_id); - } - return invalid_rb; -} - -} // namespace srsue \ No newline at end of file