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
#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<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
*
* 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<uint32_t, radio_bearer_t> eps_rb_map_t;
struct user_bearers {
eps_rb_map_t bearers;
std::map<uint32_t, uint32_t> lcid_to_eps_bearer_id;
srsenb::rnti_map_t<srsran::detail::ue_bearer_manager_impl> users_map;
};
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

@ -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;

@ -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;
return bearers.count(eps_bearer_id) > 0;
}
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;
ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::get_radio_bearer(uint32_t eps_bearer_id)
{
auto it = bearers.find(eps_bearer_id);
return it != bearers.end() ? it->second : invalid_rb;
}
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());
ue_bearer_manager_impl::radio_bearer_t ue_bearer_manager_impl::get_lcid_bearer(uint32_t lcid)
{
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;
}
void bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id)
} // namespace detail
} // namespace srsran
namespace srsue {
ue_bearer_manager::ue_bearer_manager() : logger(srslog::fetch_basic_logger("STCK", false))
{
remove_eps_bearer(default_key, eps_bearer_id);
pthread_rwlock_init(&rwlock, nullptr);
}
void bearer_manager::remove_eps_bearer(uint16_t rnti, uint8_t eps_bearer_id)
ue_bearer_manager::~ue_bearer_manager()
{
srsran::rwlock_write_guard rw_lock(rwlock);
pthread_rwlock_destroy(&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;
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 bearer_it = user_it->second.bearers.find(eps_bearer_id);
if (bearer_it == user_it->second.bearers.end()) {
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);
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);
}
void bearer_manager::reset()
void ue_bearer_manager::reset()
{
reset(default_key);
impl.reset();
logger.info("Reset EPS bearer manager");
}
void bearer_manager::reset(uint16_t rnti)
{
srsran::rwlock_write_guard rw_lock(rwlock);
} // 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)
{
auto user_it = users_map.find(rnti);
if (user_it == users_map.end()) {
logger.error("No EPS bearer registered for rnti=%x", rnti);
return;
// add empty bearer map
auto p = users_map.insert(rnti, srsran::detail::ue_bearer_manager_impl{});
user_it = p.value();
}
user_it->second.lcid_to_eps_bearer_id.clear();
user_it->second.bearers.clear();
logger.info("Reset EPS bearer manager");
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);
}
// 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)
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
} // namespace srsenb

@ -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_pdcp_adapter> gtpu_adapter;
srsenb::mac mac;

@ -29,7 +29,7 @@ public:
pdcp* pdcp_lte,
pdcp* pdcp_nr,
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_)
{}
@ -73,7 +73,7 @@ private:
gtpu* gtpu_obj = nullptr;
pdcp* pdcp_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) :
@ -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

@ -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);

@ -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)
{
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)

@ -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

@ -231,7 +231,7 @@ private:
srsue::nas nas;
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
uint32_t ul_dropped_sdus = 0;

Loading…
Cancel
Save