diff --git a/lib/include/srslte/adt/circular_map.h b/lib/include/srsran/adt/circular_map.h similarity index 83% rename from lib/include/srslte/adt/circular_map.h rename to lib/include/srsran/adt/circular_map.h index 67d27a572..441dd913d 100644 --- a/lib/include/srslte/adt/circular_map.h +++ b/lib/include/srsran/adt/circular_map.h @@ -2,7 +2,7 @@ * * \section COPYRIGHT * - * Copyright 2013-2020 Software Radio Systems Limited + * 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 @@ -10,13 +10,15 @@ * */ -#ifndef SRSLTE_ID_MAP_H -#define SRSLTE_ID_MAP_H +#ifndef SRSRAN_ID_MAP_H +#define SRSRAN_ID_MAP_H #include "expected.h" #include #include +namespace srsran { + template class static_circular_map { @@ -26,63 +28,6 @@ class static_circular_map using obj_storage_t = typename std::aligned_storage::type; public: - bool has_key(K id) - { - size_t idx = id % N; - return present[idx] and get_obj_(idx).first == id; - } - - bool insert(K id, const T& obj) - { - size_t idx = id % N; - if (present[idx]) { - return false; - } - new (&buffer[idx]) obj_t(id, obj); - present[idx] = true; - count++; - return true; - } - srslte::error_type insert(K id, T&& obj) - { - size_t idx = id % N; - if (present[idx]) { - return srslte::error_type(std::move(obj)); - } - new (&buffer[idx]) obj_t(id, std::move(obj)); - present[idx] = true; - count++; - return {}; - } - - bool erase(K id) - { - if (not has_key(id)) { - return false; - } - size_t idx = id % N; - get_obj_(idx).~obj_t(); - present[idx] = false; - --count; - return true; - } - - T& operator[](K id) - { - assert(has_key(id)); - return get_obj_(id % N).second; - } - const T& operator[](K id) const - { - assert(has_key(id)); - return get_obj_(id % N).second; - } - - size_t size() const { return count; } - bool empty() const { return count == 0; } - bool full() const { return count == N; } - size_t capacity() const { return N; } - class iterator { public: @@ -137,6 +82,81 @@ public: size_t idx = 0; }; + bool contains(K id) + { + size_t idx = id % N; + return present[idx] and get_obj_(idx).first == id; + } + + bool insert(K id, const T& obj) + { + size_t idx = id % N; + if (present[idx]) { + return false; + } + new (&buffer[idx]) obj_t(id, obj); + present[idx] = true; + count++; + return true; + } + srsran::expected insert(K id, T&& obj) + { + size_t idx = id % N; + if (present[idx]) { + return srsran::expected(std::move(obj)); + } + new (&buffer[idx]) obj_t(id, std::move(obj)); + present[idx] = true; + count++; + return iterator(this, idx); + } + + bool erase(K id) + { + if (not contains(id)) { + return false; + } + size_t idx = id % N; + get_obj_(idx).~obj_t(); + present[idx] = false; + --count; + return true; + } + + iterator erase(iterator it) + { + assert(it->first < N); + iterator next = it; + ++next; + it->~obj_t(); + present[it->first] = false; + --count; + return next; + } + + void clear() + { + for (auto it = begin(); it != end();) { + it = erase(it); + } + } + + T& operator[](K id) + { + assert(contains(id)); + return get_obj_(id % N).second; + } + const T& operator[](K id) const + { + assert(contains(id)); + return get_obj_(id % N).second; + } + + size_t size() const { return count; } + bool empty() const { return count == 0; } + bool full() const { return count == N; } + size_t capacity() const { return N; } + iterator begin() { return iterator(this, 0); } iterator end() { return iterator(this, N); } const_iterator begin() const { return iterator(this, 0); } @@ -144,14 +164,14 @@ public: iterator find(K id) { - if (has_key(id)) { + if (contains(id)) { return iterator(this, id % N); } return end(); } const_iterator find(K id) const { - if (has_key(id)) { + if (contains(id)) { return iterator(this, id % N); } return end(); @@ -166,4 +186,6 @@ private: size_t count = 0; }; -#endif // SRSLTE_ID_MAP_H +} // namespace srsran + +#endif // SRSRAN_ID_MAP_H diff --git a/lib/test/adt/circular_map_test.cc b/lib/test/adt/circular_map_test.cc index 1a2d31c79..1db52a581 100644 --- a/lib/test/adt/circular_map_test.cc +++ b/lib/test/adt/circular_map_test.cc @@ -10,10 +10,10 @@ * */ -#include "srslte/adt/circular_map.h" -#include "srslte/common/test_common.h" +#include "srsran/common/test_common.h" +#include "srsran/adt/circular_map.h" -namespace srslte { +namespace srsran { int test_id_map() { @@ -21,15 +21,15 @@ int test_id_map() TESTASSERT(myobj.size() == 0 and myobj.empty() and not myobj.full()); TESTASSERT(myobj.begin() == myobj.end()); - TESTASSERT(not myobj.has_key(0)); + TESTASSERT(not myobj.contains(0)); TESTASSERT(myobj.insert(0, "obj0")); - TESTASSERT(myobj.has_key(0) and myobj[0] == "obj0"); + TESTASSERT(myobj.contains(0) and myobj[0] == "obj0"); TESTASSERT(myobj.size() == 1 and not myobj.empty() and not myobj.full()); TESTASSERT(myobj.begin() != myobj.end()); TESTASSERT(not myobj.insert(0, "obj0")); TESTASSERT(myobj.insert(1, "obj1")); - TESTASSERT(myobj.has_key(0) and myobj.has_key(1) and myobj[1] == "obj1"); + TESTASSERT(myobj.contains(0) and myobj.contains(1) and myobj[1] == "obj1"); TESTASSERT(myobj.size() == 2 and not myobj.empty() and not myobj.full()); TESTASSERT(myobj.find(1) != myobj.end()); @@ -52,10 +52,16 @@ int test_id_map() TESTASSERT(myobj.erase(1)); TESTASSERT(myobj.size() == 0 and myobj.empty()); - return SRSLTE_SUCCESS; + TESTASSERT(myobj.insert(0, "obj0")); + TESTASSERT(myobj.insert(1, "obj1")); + TESTASSERT(myobj.size() == 2 and not myobj.empty() and not myobj.full()); + myobj.clear(); + TESTASSERT(myobj.size() == 0 and myobj.empty()); + + return SRSRAN_SUCCESS; } -} // namespace srslte +} // namespace srsran int main() { @@ -65,6 +71,6 @@ int main() // Start the log backend. srslog::init(); - TESTASSERT(srslte::test_id_map() == SRSLTE_SUCCESS); - return SRSLTE_SUCCESS; + TESTASSERT(srsran::test_id_map() == SRSRAN_SUCCESS); + return SRSRAN_SUCCESS; } \ No newline at end of file diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index cb0061341..1ede59222 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -15,6 +15,7 @@ #include "sched.h" #include "srsenb/hdr/stack/mac/schedulers/sched_time_rr.h" +#include "srsran/adt/circular_map.h" #include "srsran/common/mac_pcap.h" #include "srsran/common/mac_pcap_net.h" #include "srsran/common/task_scheduler.h" @@ -134,8 +135,9 @@ private: sched_interface::dl_pdu_mch_t mch = {}; /* Map of active UEs */ - std::map > ue_db, ues_to_rem; - uint16_t last_rnti = 70; + srsran::static_circular_map, 64> 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); diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 7e48a6fdd..eeef5e7ba 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -139,7 +139,7 @@ int mac::rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint { srsran::rwlock_read_guard lock(rwlock); int ret = -1; - if (ue_db.count(rnti)) { + if (ue_db.contains(rnti)) { if (rnti != SRSRAN_MRNTI) { ret = scheduler.dl_rlc_buffer_state(rnti, lc_id, tx_queue, retx_queue); } else { @@ -160,7 +160,7 @@ int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer { int ret = -1; srsran::rwlock_read_guard lock(rwlock); - if (ue_db.count(rnti)) { + if (ue_db.contains(rnti)) { ret = scheduler.bearer_ue_cfg(rnti, lc_id, *cfg); } else { logger.error("User rnti=0x%x not found", rnti); @@ -172,7 +172,7 @@ int mac::bearer_ue_rem(uint16_t rnti, uint32_t lc_id) { srsran::rwlock_read_guard lock(rwlock); int ret = -1; - if (ue_db.count(rnti)) { + if (ue_db.contains(rnti)) { ret = scheduler.bearer_ue_rem(rnti, lc_id); } else { logger.error("User rnti=0x%x not found", rnti); @@ -215,7 +215,7 @@ int mac::ue_rem(uint16_t rnti) // Remove UE from the perspective of L2/L3 { srsran::rwlock_write_guard lock(rwlock); - if (ue_db.count(rnti)) { + if (ue_db.contains(rnti)) { ues_to_rem[rnti] = std::move(ue_db[rnti]); ue_db.erase(rnti); } else { @@ -440,38 +440,45 @@ uint16_t mac::allocate_rnti() uint16_t mac::allocate_ue() { - { - srsran::rwlock_read_guard lock(rwlock); - if (ue_db.size() >= args.max_nof_ues) { - logger.warning("Maximum number of connected UEs %d reached. Ignoring PRACH", args.max_nof_ues); + ue* inserted_ue = nullptr; + do { + // Get pre-allocated UE object + if (ue_pool.empty()) { + logger.error("Ignoring RACH attempt. UE pool empty."); return SRSRAN_INVALID_RNTI; } - } + std::unique_ptr ue_ptr = ue_pool.pop_blocking(); - // Get pre-allocated UE object - if (ue_pool.empty()) { - logger.error("Ignoring RACH attempt. UE pool empty."); - return SRSRAN_INVALID_RNTI; - } - std::unique_ptr ue_ptr = ue_pool.pop_blocking(); - uint16_t rnti = ue_ptr->get_rnti(); + // Add UE to map + { + srsran::rwlock_write_guard lock(rwlock); + if (ue_db.size() >= args.max_nof_ues) { + logger.warning("Maximum number of connected UEs %d reached. Ignoring PRACH", args.max_nof_ues); + return SRSRAN_INVALID_RNTI; + } + auto ret = ue_db.insert(ue_ptr->get_rnti(), std::move(ue_ptr)); + if (ret) { + inserted_ue = ret.value()->second.get(); + } + } + + // 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) { - ue_ptr->start_pcap(pcap); + inserted_ue->start_pcap(pcap); } if (pcap_net != nullptr) { - ue_ptr->start_pcap_net(pcap_net); + inserted_ue->start_pcap_net(pcap_net); } - { - srsran::rwlock_write_guard lock(rwlock); - ue_db[rnti] = std::move(ue_ptr); - } - - // Allocate one new UE object in advance - srsran::get_background_workers().push_task([this]() { prealloc_ue(1); }); return rnti; } @@ -590,7 +597,7 @@ int mac::get_dl_sched(uint32_t tti_tx_dl, dl_sched_list_t& dl_sched_res_list) // Get UE uint16_t rnti = sched_result.data[i].dci.rnti; - if (ue_db.count(rnti)) { + if (ue_db.contains(rnti)) { // Copy dci info dl_sched_res->pdsch[n].dci = sched_result.data[i].dci; @@ -905,7 +912,7 @@ int mac::get_ul_sched(uint32_t tti_tx_ul, ul_sched_list_t& ul_sched_res_list) // Get UE uint16_t rnti = sched_result.pusch[i].dci.rnti; - if (ue_db.count(rnti)) { + if (ue_db.contains(rnti)) { // Copy grant info phy_ul_sched_res->pusch[n].current_tx_nb = sched_result.pusch[i].current_tx_nb; phy_ul_sched_res->pusch[n].pid = TTI_RX(tti_tx_ul) % SRSRAN_FDD_NOF_HARQ; @@ -989,7 +996,7 @@ void mac::write_mcch(const srsran::sib2_mbms_t* sib2_, bool mac::check_ue_exists(uint16_t rnti) { - if (not ue_db.count(rnti)) { + if (not ue_db.contains(rnti)) { if (not ues_to_rem.count(rnti)) { logger.error("User rnti=0x%x not found", rnti); }