diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index 0b33584ed..4dd8fbf38 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -209,8 +209,7 @@ class mac_interface_rrc { public: /* Provides cell configuration including SIB periodicity, etc. */ - virtual int cell_cfg(const std::vector& cell_cfg) = 0; - virtual void reset() = 0; + virtual int cell_cfg(const std::vector& cell_cfg) = 0; /* Manages UE configuration context */ virtual int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) = 0; diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index a3b782603..284b6db3c 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -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" @@ -73,8 +74,7 @@ public: /******** Interface from RRC (RRC -> MAC) ****************/ /* Provides cell configuration including SIB periodicity, etc. */ - int cell_cfg(const std::vector& cell_cfg) override; - void reset() override; + int cell_cfg(const std::vector& cell_cfg) 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 > ue_db; - std::map > ues_to_rem; - uint16_t last_rnti = 70; - - srsran::static_blocking_queue, 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 > ue_db; + std::atomic ue_counter; uint8_t* assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32_t enb_cc_idx, diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index 07f84955a..3cce3e59e 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -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 active_state{true}; + uint32_t phr_counter = 0; uint32_t dl_cqi_counter = 0; uint32_t dl_ri_counter = 0; diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 14fe50b55..d71bd75ae 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -48,13 +48,9 @@ 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; + phy_h = phy; + rlc_h = rlc; + rrc_h = rrc; args = args_; cells = cells_; @@ -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( 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& 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 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; + ue* inserted_ue = nullptr; + uint16_t rnti = SRSRAN_INVALID_RNTI; + do { - // Get pre-allocated UE object - std::unique_ptr 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; - } - 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; - } - auto ret = ue_db.insert(rnti, std::move(ue_ptr)); - if (ret) { - inserted_ue = ret.value()->second.get(); - } else { - logger.info("Failed to allocate rnti=0x%x. Attempting a different rnti.", rnti); + srsran::rwlock_read_guard read_lock(rwlock); + if (not is_valid_rnti_unprotected(rnti)) { + continue; } } - // Allocate one new UE object in advance - srsran::get_background_workers().push_task([this]() { prealloc_ue(1); }); + // Allocate and initialize UE object + unique_rnti_ptr ue_ptr = make_rnti_obj( + 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.has_value()) { + inserted_ue = ret.value()->second.get(); + } else { + logger.info("Failed to allocate rnti=0x%x. Attempting a different rnti.", rnti); + } } 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 ptr = std::unique_ptr(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); - } + logger.error("User rnti=0x%x not found", rnti); return false; } - return true; + return ue_db[rnti]->is_active(); } } // namespace srsenb diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 6887b6546..68c50baa8 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -28,7 +28,6 @@ class mac_dummy : public mac_interface_rrc { public: int cell_cfg(const std::vector& 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; }