mac,optimization: use rnti memory pool to create mac::ue objects

master
Francisco 4 years ago committed by Francisco Paisana
parent fd1d73666c
commit 7e77da6a15

@ -210,7 +210,6 @@ class mac_interface_rrc
public:
/* Provides cell configuration including SIB periodicity, etc. */
virtual int cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg) = 0;
virtual void reset() = 0;
/* Manages UE configuration context */
virtual int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) = 0;

@ -14,6 +14,7 @@
#define SRSENB_MAC_H
#include "sched.h"
#include "srsenb/hdr/common/rnti_pool.h"
#include "srsenb/hdr/stack/mac/schedulers/sched_time_rr.h"
#include "srsran/adt/circular_map.h"
#include "srsran/adt/pool/batch_mem_pool.h"
@ -74,7 +75,6 @@ public:
/******** Interface from RRC (RRC -> MAC) ****************/
/* Provides cell configuration including SIB periodicity, etc. */
int cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg) override;
void reset() override;
/* Manages UE scheduling context */
int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override;
@ -107,11 +107,9 @@ public:
private:
static const uint32_t cfi = 3;
bool check_ue_exists(uint16_t rnti);
uint16_t allocate_rnti();
bool check_ue_active(uint16_t rnti);
uint16_t allocate_ue();
std::mutex rnti_mutex;
bool is_valid_rnti_unprotected(uint16_t rnti);
srslog::basic_logger& logger;
@ -140,12 +138,9 @@ private:
sched_interface::dl_pdu_mch_t mch = {};
/* Map of active UEs */
rnti_map_t<std::unique_ptr<ue> > ue_db;
std::map<uint16_t, std::unique_ptr<ue> > ues_to_rem;
uint16_t last_rnti = 70;
srsran::static_blocking_queue<std::unique_ptr<ue>, 32> ue_pool; ///< Pool of pre-allocated UE objects
void prealloc_ue(uint32_t nof_ue);
static const uint16_t FIRST_RNTI = 0x46;
rnti_map_t<unique_rnti_ptr<ue> > ue_db;
std::atomic<uint16_t> ue_counter;
uint8_t* assemble_rar(sched_interface::dl_sched_rar_grant_t* grants,
uint32_t enb_cc_idx,

@ -142,6 +142,8 @@ public:
uint32_t set_ta_us(float ta_us) { return ta_fsm.push_value(ta_us); };
void tic();
void trigger_padding(int lcid);
void set_active(bool active) { active_state.store(active, std::memory_order_relaxed); }
bool is_active() const { return active_state.load(std::memory_order_relaxed); }
uint8_t* generate_pdu(uint32_t ue_cc_idx,
uint32_t harq_pid,
@ -189,6 +191,8 @@ private:
uint32_t last_tti = 0;
uint32_t nof_failures = 0;
std::atomic<bool> active_state{true};
uint32_t phr_counter = 0;
uint32_t dl_cqi_counter = 0;
uint32_t dl_ri_counter = 0;

@ -48,10 +48,6 @@ bool mac::init(const mac_args_t& args_,
rrc_interface_mac* rrc)
{
started = false;
if (not phy or not rlc) {
return false;
}
phy_h = phy;
rlc_h = rlc;
rrc_h = rrc;
@ -74,8 +70,6 @@ bool mac::init(const mac_args_t& args_,
srsran_softbuffer_tx_init(&cc.rar_softbuffer_tx, args.nof_prb);
}
reset();
// Initiate common pool of softbuffers
uint32_t nof_prb = args.nof_prb;
auto init_softbuffers = [nof_prb](void* ptr) {
@ -85,9 +79,6 @@ bool mac::init(const mac_args_t& args_,
softbuffer_pool.reset(new srsran::background_obj_pool<ue_cc_softbuffers>(
8, 8, args.nof_prealloc_ues, init_softbuffers, recycle_softbuffers));
// Pre-alloc UE objects for first attaching users
prealloc_ue(10);
detected_rachs.resize(cells.size());
started = true;
@ -108,21 +99,9 @@ void mac::stop()
srsran_softbuffer_tx_free(&cc.pcch_softbuffer_tx);
srsran_softbuffer_tx_free(&cc.rar_softbuffer_tx);
}
ue_pool.stop();
}
}
// Implement Section 5.9
void mac::reset()
{
logger.info("Resetting MAC");
last_rnti = 70;
/* Setup scheduler */
scheduler.reset();
}
void mac::start_pcap(srsran::mac_pcap* pcap_)
{
srsran::rwlock_read_guard lock(rwlock);
@ -148,11 +127,12 @@ void mac::start_pcap_net(srsran::mac_pcap_net* pcap_net_)
* RLC interface
*
*******************************************************/
int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue)
{
srsran::rwlock_read_guard lock(rwlock);
int ret = -1;
if (ue_db.contains(rnti)) {
if (check_ue_active(rnti)) {
if (rnti != SRSRAN_MRNTI) {
ret = scheduler.dl_rlc_buffer_state(rnti, lc_id, tx_queue, retx_queue);
} else {
@ -163,34 +143,20 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint
}
ret = 0;
}
} else {
logger.error("User rnti=0x%x not found", rnti);
}
return ret;
}
int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg)
{
int ret = -1;
srsran::rwlock_read_guard lock(rwlock);
if (ue_db.contains(rnti)) {
ret = scheduler.bearer_ue_cfg(rnti, lc_id, *cfg);
} else {
logger.error("User rnti=0x%x not found", rnti);
}
return ret;
return check_ue_active(rnti) ? scheduler.bearer_ue_cfg(rnti, lc_id, *cfg) : -1;
}
int mac::bearer_ue_rem(uint16_t rnti, uint32_t lc_id)
{
srsran::rwlock_read_guard lock(rwlock);
int ret = -1;
if (ue_db.contains(rnti)) {
ret = scheduler.bearer_ue_rem(rnti, lc_id);
} else {
logger.error("User rnti=0x%x not found", rnti);
}
return ret;
return check_ue_active(rnti) ? scheduler.bearer_ue_rem(rnti, lc_id) : -1;
}
void mac::phy_config_enabled(uint16_t rnti, bool enabled)
@ -202,14 +168,10 @@ void mac::phy_config_enabled(uint16_t rnti, bool enabled)
int mac::ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg)
{
srsran::rwlock_read_guard lock(rwlock);
auto it = ue_db.find(rnti);
ue* ue_ptr = nullptr;
if (it == ue_db.end()) {
logger.error("User rnti=0x%x not found", rnti);
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
ue_ptr = it->second.get();
ue* ue_ptr = ue_db[rnti].get();
// Start TA FSM in UE entity
ue_ptr->start_ta();
@ -227,10 +189,9 @@ int mac::ue_rem(uint16_t rnti)
{
// Remove UE from the perspective of L2/L3
{
srsran::rwlock_write_guard lock(rwlock);
if (ue_db.contains(rnti)) {
ues_to_rem[rnti] = std::move(ue_db[rnti]);
ue_db.erase(rnti);
srsran::rwlock_read_guard lock(rwlock);
if (check_ue_active(rnti)) {
ue_db[rnti]->set_active(false);
} else {
logger.error("User rnti=0x%x not found", rnti);
return SRSRAN_ERROR;
@ -242,7 +203,8 @@ int mac::ue_rem(uint16_t rnti)
// Note: Let any pending retx ACK to arrive, so that PHY recognizes rnti
task_sched.defer_callback(FDD_HARQ_DELAY_DL_MS + FDD_HARQ_DELAY_UL_MS, [this, rnti]() {
phy_h->rem_rnti(rnti);
ues_to_rem.erase(rnti);
srsran::rwlock_write_guard lock(rwlock);
ue_db.erase(rnti);
logger.info("User rnti=0x%x removed from MAC/PHY", rnti);
});
return SRSRAN_SUCCESS;
@ -259,11 +221,7 @@ int mac::ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_c
// Schedule ConRes Msg4
scheduler.dl_mac_buffer_state(crnti, (uint32_t)srsran::dl_sch_lcid::CON_RES_ID);
}
int ret = ue_cfg(crnti, cfg);
if (ret != SRSRAN_SUCCESS) {
return ret;
}
return ret;
return ue_cfg(crnti, cfg);
}
int mac::cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg_)
@ -313,7 +271,7 @@ int mac::ack_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t
logger.set_context(tti_rx);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -330,7 +288,7 @@ int mac::crc_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t
logger.set_context(tti_rx);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -352,7 +310,7 @@ int mac::push_pdu(uint32_t tti_rx,
{
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -380,8 +338,10 @@ int mac::push_pdu(uint32_t tti_rx,
(int)pdu->size());
auto process_pdu_task = [this, rnti, ul_nof_prbs](srsran::unique_byte_buffer_t& pdu) {
srsran::rwlock_read_guard lock(rwlock);
if (ue_db.contains(rnti)) {
if (check_ue_active(rnti)) {
ue_db[rnti]->process_pdu(std::move(pdu), ul_nof_prbs);
} else {
logger.debug("Discarding PDU rnti=0x%x", rnti);
}
};
auto ret = stack_task_queue.try_push(std::bind(process_pdu_task, std::move(pdu)));
@ -396,7 +356,7 @@ int mac::ri_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ri_v
logger.set_context(tti);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -411,7 +371,7 @@ int mac::pmi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t pmi
logger.set_context(tti);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -426,7 +386,7 @@ int mac::cqi_info(uint32_t tti, uint16_t rnti, uint32_t enb_cc_idx, uint32_t cqi
logger.set_context(tti);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -441,7 +401,7 @@ int mac::snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, float snr
logger.set_context(tti_rx);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
@ -454,13 +414,13 @@ int mac::ta_info(uint32_t tti, uint16_t rnti, float ta_us)
{
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
uint32_t nof_ta_count = ue_db[rnti]->set_ta_us(ta_us);
if (nof_ta_count) {
scheduler.dl_mac_buffer_state(rnti, (uint32_t)srsran::dl_sch_lcid::TA_CMD, nof_ta_count);
if (nof_ta_count > 0) {
return scheduler.dl_mac_buffer_state(rnti, (uint32_t)srsran::dl_sch_lcid::TA_CMD, nof_ta_count);
}
return SRSRAN_SUCCESS;
}
@ -470,65 +430,64 @@ int mac::sr_detected(uint32_t tti, uint16_t rnti)
logger.set_context(tti);
srsran::rwlock_read_guard lock(rwlock);
if (not check_ue_exists(rnti)) {
if (not check_ue_active(rnti)) {
return SRSRAN_ERROR;
}
return scheduler.ul_sr_info(tti, rnti);
}
uint16_t mac::allocate_rnti()
bool mac::is_valid_rnti_unprotected(uint16_t rnti)
{
std::lock_guard<std::mutex> lock(rnti_mutex);
// Assign a c-rnti
uint16_t rnti = last_rnti++;
if (last_rnti >= 60000) {
last_rnti = 70;
if (not started) {
logger.info("RACH ignored as eNB is being shutdown");
return false;
}
return rnti;
if (ue_db.full()) {
logger.warning("Maximum number of connected UEs %zd connected to the eNB. Ignoring PRACH", SRSENB_MAX_UES);
return false;
}
if (not ue_db.has_space(rnti)) {
logger.info("Failed to allocate rnti=0x%x. Attempting a different rnti.", rnti);
return false;
}
return true;
}
uint16_t mac::allocate_ue()
{
ue* inserted_ue = nullptr;
uint16_t rnti = SRSRAN_INVALID_RNTI;
do {
// Get pre-allocated UE object
std::unique_ptr<ue> ue_ptr;
if (not ue_pool.try_pop(ue_ptr)) {
logger.error("UE pool empty. Ignoring RACH attempt.");
return SRSRAN_INVALID_RNTI;
}
uint16_t rnti = ue_ptr->get_rnti();
// Assign new RNTI
rnti = FIRST_RNTI + (ue_counter.fetch_add(1, std::memory_order_relaxed) % 60000);
// Add UE to map
// Pre-check if rnti is valid
{
srsran::rwlock_write_guard lock(rwlock);
if (not started) {
logger.info("RACH ignored as eNB is being shutdown");
return SRSRAN_INVALID_RNTI;
srsran::rwlock_read_guard read_lock(rwlock);
if (not is_valid_rnti_unprotected(rnti)) {
continue;
}
if (ue_db.size() >= SRSENB_MAX_UES) {
logger.warning("Maximum number of connected UEs %zd connected to the eNB. Ignoring PRACH", SRSENB_MAX_UES);
return SRSRAN_INVALID_RNTI;
}
// Allocate and initialize UE object
unique_rnti_ptr<ue> ue_ptr = make_rnti_obj<ue>(
rnti, rnti, args.nof_prb, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get());
// Add UE to rnti map
srsran::rwlock_write_guard rw_lock(rwlock);
if (not is_valid_rnti_unprotected(rnti)) {
continue;
}
auto ret = ue_db.insert(rnti, std::move(ue_ptr));
if (ret) {
if (ret.has_value()) {
inserted_ue = ret.value()->second.get();
} else {
logger.info("Failed to allocate rnti=0x%x. Attempting a different rnti.", rnti);
}
}
// Allocate one new UE object in advance
srsran::get_background_workers().push_task([this]() { prealloc_ue(1); });
} while (inserted_ue == nullptr);
// RNTI allocation was successful
uint16_t rnti = inserted_ue->get_rnti();
// Set PCAP if available
if (pcap != nullptr) {
inserted_ue->start_pcap(pcap);
@ -614,18 +573,6 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx
});
}
void mac::prealloc_ue(uint32_t nof_ue)
{
for (uint32_t i = 0; i < nof_ue; i++) {
std::unique_ptr<ue> ptr = std::unique_ptr<ue>(new ue(
allocate_rnti(), args.nof_prb, &scheduler, rrc_h, rlc_h, phy_h, logger, cells.size(), softbuffer_pool.get()));
if (not ue_pool.try_push(std::move(ptr))) {
logger.info("Cannot preallocate more UEs as pool is full");
return;
}
}
}
int mac::get_dl_sched(uint32_t tti_tx_dl, dl_sched_list_t& dl_sched_res_list)
{
if (!started) {
@ -1045,15 +992,13 @@ void mac::write_mcch(const srsran::sib2_mbms_t* sib2_,
}
// Internal helper function, caller must hold UE DB rwlock
bool mac::check_ue_exists(uint16_t rnti)
bool mac::check_ue_active(uint16_t rnti)
{
if (not ue_db.contains(rnti)) {
if (not ues_to_rem.count(rnti)) {
logger.error("User rnti=0x%x not found", rnti);
}
return false;
}
return true;
return ue_db[rnti]->is_active();
}
} // namespace srsenb

@ -28,7 +28,6 @@ class mac_dummy : public mac_interface_rrc
{
public:
int cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg) override { return 0; }
void reset() override {}
int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override { return 0; }
int ue_rem(uint16_t rnti) override { return 0; }
int ue_set_crnti(uint16_t temp_crnti, uint16_t crnti, sched_interface::ue_cfg_t* cfg) override { return 0; }

Loading…
Cancel
Save