application of new circular map to mac::ue_db

This commit is contained in:
Francisco 2021-03-19 13:24:54 +00:00 committed by Francisco Paisana
parent 98d0637ded
commit 4869b14de3
4 changed files with 140 additions and 103 deletions

View File

@ -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 <array>
#include <cassert>
namespace srsran {
template <typename K, typename T, size_t N>
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;
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
{
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<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 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

View File

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

View File

@ -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<uint16_t, std::unique_ptr<ue> > ue_db, ues_to_rem;
uint16_t last_rnti = 70;
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;
srsran::static_blocking_queue<std::unique_ptr<ue>, 32> ue_pool; ///< Pool of pre-allocated UE objects
void prealloc_ue(uint32_t nof_ue);

View File

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