application of new circular map to mac::ue_db

master
Francisco 4 years ago committed by Francisco Paisana
parent 98d0637ded
commit 4869b14de3

@ -2,7 +2,7 @@
* *
* \section COPYRIGHT * \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 * 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 * forth in the LICENSE file which can be found at the top level of
@ -10,13 +10,15 @@
* *
*/ */
#ifndef SRSLTE_ID_MAP_H #ifndef SRSRAN_ID_MAP_H
#define SRSLTE_ID_MAP_H #define SRSRAN_ID_MAP_H
#include "expected.h" #include "expected.h"
#include <array> #include <array>
#include <cassert> #include <cassert>
namespace srsran {
template <typename K, typename T, size_t N> template <typename K, typename T, size_t N>
class static_circular_map class static_circular_map
{ {
@ -26,63 +28,6 @@ class static_circular_map
using obj_storage_t = typename std::aligned_storage<sizeof(obj_t), alignof(obj_t)>::type; using obj_storage_t = typename std::aligned_storage<sizeof(obj_t), alignof(obj_t)>::type;
public: 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<T> insert(K id, T&& obj)
{
size_t idx = id % N;
if (present[idx]) {
return srslte::error_type<T>(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 class iterator
{ {
public: public:
@ -137,6 +82,81 @@ public:
size_t idx = 0; 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<iterator, T> insert(K id, T&& obj)
{
size_t idx = id % N;
if (present[idx]) {
return srsran::expected<iterator, T>(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 begin() { return iterator(this, 0); }
iterator end() { return iterator(this, N); } iterator end() { return iterator(this, N); }
const_iterator begin() const { return iterator(this, 0); } const_iterator begin() const { return iterator(this, 0); }
@ -144,14 +164,14 @@ public:
iterator find(K id) iterator find(K id)
{ {
if (has_key(id)) { if (contains(id)) {
return iterator(this, id % N); return iterator(this, id % N);
} }
return end(); return end();
} }
const_iterator find(K id) const const_iterator find(K id) const
{ {
if (has_key(id)) { if (contains(id)) {
return iterator(this, id % N); return iterator(this, id % N);
} }
return end(); return end();
@ -166,4 +186,6 @@ private:
size_t count = 0; size_t count = 0;
}; };
#endif // SRSLTE_ID_MAP_H } // namespace srsran
#endif // SRSRAN_ID_MAP_H

@ -10,10 +10,10 @@
* *
*/ */
#include "srslte/adt/circular_map.h" #include "srsran/common/test_common.h"
#include "srslte/common/test_common.h" #include "srsran/adt/circular_map.h"
namespace srslte { namespace srsran {
int test_id_map() 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.size() == 0 and myobj.empty() and not myobj.full());
TESTASSERT(myobj.begin() == myobj.end()); TESTASSERT(myobj.begin() == myobj.end());
TESTASSERT(not myobj.has_key(0)); TESTASSERT(not myobj.contains(0));
TESTASSERT(myobj.insert(0, "obj0")); 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.size() == 1 and not myobj.empty() and not myobj.full());
TESTASSERT(myobj.begin() != myobj.end()); TESTASSERT(myobj.begin() != myobj.end());
TESTASSERT(not myobj.insert(0, "obj0")); TESTASSERT(not myobj.insert(0, "obj0"));
TESTASSERT(myobj.insert(1, "obj1")); 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.size() == 2 and not myobj.empty() and not myobj.full());
TESTASSERT(myobj.find(1) != myobj.end()); TESTASSERT(myobj.find(1) != myobj.end());
@ -52,10 +52,16 @@ int test_id_map()
TESTASSERT(myobj.erase(1)); TESTASSERT(myobj.erase(1));
TESTASSERT(myobj.size() == 0 and myobj.empty()); 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() int main()
{ {
@ -65,6 +71,6 @@ int main()
// Start the log backend. // Start the log backend.
srslog::init(); srslog::init();
TESTASSERT(srslte::test_id_map() == SRSLTE_SUCCESS); TESTASSERT(srsran::test_id_map() == SRSRAN_SUCCESS);
return SRSLTE_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -15,6 +15,7 @@
#include "sched.h" #include "sched.h"
#include "srsenb/hdr/stack/mac/schedulers/sched_time_rr.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.h"
#include "srsran/common/mac_pcap_net.h" #include "srsran/common/mac_pcap_net.h"
#include "srsran/common/task_scheduler.h" #include "srsran/common/task_scheduler.h"
@ -134,7 +135,8 @@ private:
sched_interface::dl_pdu_mch_t mch = {}; sched_interface::dl_pdu_mch_t mch = {};
/* Map of active UEs */ /* Map of active UEs */
std::map<uint16_t, std::unique_ptr<ue> > ue_db, ues_to_rem; srsran::static_circular_map<uint16_t, std::unique_ptr<ue>, 64> ue_db;
std::map<uint16_t, std::unique_ptr<ue> > ues_to_rem;
uint16_t last_rnti = 70; uint16_t last_rnti = 70;
srsran::static_blocking_queue<std::unique_ptr<ue>, 32> ue_pool; ///< Pool of pre-allocated UE objects srsran::static_blocking_queue<std::unique_ptr<ue>, 32> ue_pool; ///< Pool of pre-allocated UE objects

@ -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); srsran::rwlock_read_guard lock(rwlock);
int ret = -1; int ret = -1;
if (ue_db.count(rnti)) { if (ue_db.contains(rnti)) {
if (rnti != SRSRAN_MRNTI) { if (rnti != SRSRAN_MRNTI) {
ret = scheduler.dl_rlc_buffer_state(rnti, lc_id, tx_queue, retx_queue); ret = scheduler.dl_rlc_buffer_state(rnti, lc_id, tx_queue, retx_queue);
} else { } else {
@ -160,7 +160,7 @@ int mac::bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer
{ {
int ret = -1; int ret = -1;
srsran::rwlock_read_guard lock(rwlock); 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); ret = scheduler.bearer_ue_cfg(rnti, lc_id, *cfg);
} else { } else {
logger.error("User rnti=0x%x not found", rnti); 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); srsran::rwlock_read_guard lock(rwlock);
int ret = -1; int ret = -1;
if (ue_db.count(rnti)) { if (ue_db.contains(rnti)) {
ret = scheduler.bearer_ue_rem(rnti, lc_id); ret = scheduler.bearer_ue_rem(rnti, lc_id);
} else { } else {
logger.error("User rnti=0x%x not found", rnti); 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 // Remove UE from the perspective of L2/L3
{ {
srsran::rwlock_write_guard lock(rwlock); 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]); ues_to_rem[rnti] = std::move(ue_db[rnti]);
ue_db.erase(rnti); ue_db.erase(rnti);
} else { } else {
@ -440,38 +440,45 @@ uint16_t mac::allocate_rnti()
uint16_t mac::allocate_ue() uint16_t mac::allocate_ue()
{ {
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> ue_ptr = ue_pool.pop_blocking();
// Add UE to map
{ {
srsran::rwlock_read_guard lock(rwlock); srsran::rwlock_write_guard lock(rwlock);
if (ue_db.size() >= args.max_nof_ues) { if (ue_db.size() >= args.max_nof_ues) {
logger.warning("Maximum number of connected UEs %d reached. Ignoring PRACH", args.max_nof_ues); logger.warning("Maximum number of connected UEs %d reached. Ignoring PRACH", args.max_nof_ues);
return SRSRAN_INVALID_RNTI; 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();
} }
// 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> ue_ptr = ue_pool.pop_blocking();
uint16_t rnti = ue_ptr->get_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 // Set PCAP if available
if (pcap != nullptr) { if (pcap != nullptr) {
ue_ptr->start_pcap(pcap); inserted_ue->start_pcap(pcap);
} }
if (pcap_net != nullptr) { 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; 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 // Get UE
uint16_t rnti = sched_result.data[i].dci.rnti; uint16_t rnti = sched_result.data[i].dci.rnti;
if (ue_db.count(rnti)) { if (ue_db.contains(rnti)) {
// Copy dci info // Copy dci info
dl_sched_res->pdsch[n].dci = sched_result.data[i].dci; 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 // Get UE
uint16_t rnti = sched_result.pusch[i].dci.rnti; uint16_t rnti = sched_result.pusch[i].dci.rnti;
if (ue_db.count(rnti)) { if (ue_db.contains(rnti)) {
// Copy grant info // 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].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; 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) 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)) { 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);
} }

Loading…
Cancel
Save