stack lte: separate bearer manager into two classes, one for the ue and one for the enb

master
Francisco Paisana 3 years ago
parent cb2c339456
commit f4df55c245

@ -13,6 +13,7 @@
#ifndef SRSRAN_BEARER_MANAGER_H #ifndef SRSRAN_BEARER_MANAGER_H
#define SRSRAN_BEARER_MANAGER_H #define SRSRAN_BEARER_MANAGER_H
#include "srsenb/hdr/common/common_enb.h"
#include "srsran/common/common.h" #include "srsran/common/common.h"
#include "srsran/common/rwlock_guard.h" #include "srsran/common/rwlock_guard.h"
#include "srsran/srslog/srslog.h" #include "srsran/srslog/srslog.h"
@ -21,10 +22,53 @@
namespace srsran { 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<uint32_t, radio_bearer_t>;
eps_rb_map_t bearers;
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
};
} // namespace detail
} // namespace srsran
namespace srsue {
/** /**
* @brief Helper class to manage the mapping between EPS bearer and radio bearer * @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. * 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, * 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 * the GW/GTPU needs to query the Stack to check whether a
@ -40,20 +84,16 @@ namespace srsran {
* used by the eNB. * used by the eNB.
* *
*/ */
class bearer_manager class ue_bearer_manager
{ {
public: public:
bearer_manager(); using radio_bearer_t = srsran::detail::ue_bearer_manager_impl::radio_bearer_t;
~bearer_manager();
struct radio_bearer_t { ue_bearer_manager();
srsran::srsran_rat_t rat; ue_bearer_manager(const ue_bearer_manager&) = delete;
uint32_t lcid; ue_bearer_manager(ue_bearer_manager&&) noexcept = default;
uint32_t eps_bearer_id; ue_bearer_manager& operator=(const ue_bearer_manager&) = delete;
bool is_valid() const { return rat != srsran_rat_t::nulltype; } ~ue_bearer_manager();
};
/// Single user interface (for UE)
// RRC interface // RRC interface
/// Registers EPS bearer with PDCP RAT type and LCID /// Registers EPS bearer with PDCP RAT type and LCID
@ -65,36 +105,43 @@ public:
/// All registered bearer are removed (e.g. after connection release) /// All registered bearer are removed (e.g. after connection release)
void reset(); void reset();
// GW interface bool has_active_radio_bearer(uint32_t eps_bearer_id) { return impl.has_active_radio_bearer(eps_bearer_id); }
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) { return impl.get_radio_bearer(eps_bearer_id); }
radio_bearer_t get_radio_bearer(uint32_t 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) /// 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 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 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); 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_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id);
radio_bearer_t get_lcid_bearer(uint16_t rnti, uint32_t lcid);
private: private:
pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads
srslog::basic_logger& logger; srslog::basic_logger& logger;
typedef std::map<uint32_t, radio_bearer_t> eps_rb_map_t; srsenb::rnti_map_t<srsran::detail::ue_bearer_manager_impl> users_map;
struct user_bearers {
eps_rb_map_t bearers;
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
};
std::map<uint16_t, user_bearers> 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};
}; };
} // namespace srsran } // namespace srsenb
#endif // SRSRAN_BEARER_MANAGER_H #endif // SRSRAN_BEARER_MANAGER_H

@ -24,7 +24,7 @@ class stack_interface_rrc
public: 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 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 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; class stack_interface_phy_lte;

@ -14,140 +14,172 @@
namespace srsran { 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); return bearers.count(eps_bearer_id) > 0;
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());
} }
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); } // namespace detail
if (user_it == users_map.end()) { } // namespace srsran
logger.error("No EPS bearer registered for rnti=%x", rnti);
return;
}
auto bearer_it = user_it->second.bearers.find(eps_bearer_id); namespace srsue {
if (bearer_it == user_it->second.bearers.end()) {
logger.error("Can't remove EPS bearer ID %d", eps_bearer_id); ue_bearer_manager::ue_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false))
return; {
} pthread_rwlock_init(&rwlock, nullptr);
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);
} }
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); 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); void ue_bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id)
if (user_it == users_map.end()) { {
logger.error("No EPS bearer registered for rnti=%x", rnti); srsran::rwlock_write_guard rw_lock(rwlock);
return; 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(); void ue_bearer_manager::reset()
user_it->second.bearers.clear(); {
impl.reset();
logger.info("Reset EPS bearer manager"); logger.info("Reset EPS bearer manager");
} }
// GW interface } // namespace srsue
bool bearer_manager::has_active_radio_bearer(uint32_t eps_bearer_id)
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); auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) { 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 void enb_bearer_manager::rem_user(uint16_t rnti)
bearer_manager::radio_bearer_t bearer_manager::get_radio_bearer(uint32_t eps_bearer_id)
{ {
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); auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) { if (user_it == users_map.end()) {
return invalid_rb; return false;
}
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 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); auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) { 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()) { enb_bearer_manager::radio_bearer_t enb_bearer_manager::get_radio_bearer(uint16_t rnti, uint32_t eps_bearer_id)
return user_it->second.bearers.at(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 } // namespace srsenb

@ -139,7 +139,7 @@ public:
// interface for bearer manager // 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 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 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: private:
static const int STACK_MAIN_THREAD_PRIO = 4; 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; srsran::task_queue_handle enb_task_queue, sync_task_queue, metrics_task_queue;
// bearer management // 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_pdcp_adapter> gtpu_adapter; std::unique_ptr<gtpu_pdcp_adapter> gtpu_adapter;
srsenb::mac mac; srsenb::mac mac;

@ -29,7 +29,7 @@ public:
pdcp* pdcp_lte, pdcp* pdcp_lte,
pdcp* pdcp_nr, pdcp* pdcp_nr,
gtpu* gtpu_, gtpu* gtpu_,
srsran::bearer_manager& bearers_) : enb_bearer_manager& bearers_) :
logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_)
{} {}
@ -73,7 +73,7 @@ private:
gtpu* gtpu_obj = nullptr; gtpu* gtpu_obj = nullptr;
pdcp* pdcp_obj = nullptr; pdcp* pdcp_obj = nullptr;
pdcp* pdcp_nr_obj = nullptr; pdcp* pdcp_nr_obj = nullptr;
srsran::bearer_manager* bearers = nullptr; enb_bearer_manager* bearers = nullptr;
}; };
enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : 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); 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 } // namespace srsenb

@ -655,6 +655,7 @@ void rrc::rem_user(uint16_t rnti)
gtpu->rem_user(rnti); gtpu->rem_user(rnti);
// Now remove RLC and PDCP // Now remove RLC and PDCP
stack->remove_eps_bearers(rnti);
rlc->rem_user(rnti); rlc->rem_user(rnti);
pdcp->rem_user(rnti); pdcp->rem_user(rnti);

@ -406,12 +406,7 @@ srsran::expected<uint32_t> bearer_cfg_handler::add_gtpu_bearer(uint32_t
void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id) void bearer_cfg_handler::rem_gtpu_bearer(uint32_t erab_id)
{ {
auto it = erabs.find(erab_id); gtpu->rem_bearer(rnti, erab_id);
if (it == erabs.end()) {
logger->warning("Removing erab_id=%d from GTPU", erab_id);
return;
}
gtpu->rem_bearer(rnti, it->second.id);
} }
void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg) void bearer_cfg_handler::fill_pending_nas_info(asn1::rrc::rrc_conn_recfg_r8_ies_s* msg)

@ -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 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 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 } // namespace test_dummies

@ -231,7 +231,7 @@ private:
srsue::nas nas; srsue::nas nas;
std::unique_ptr<usim_base> usim; std::unique_ptr<usim_base> 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 // Metrics helper
uint32_t ul_dropped_sdus = 0; uint32_t ul_dropped_sdus = 0;

Loading…
Cancel
Save