mirror of https://github.com/PentHertz/srsLTE.git
application of new circular map to mac::ue_db
This commit is contained in:
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,8 +135,9 @@ 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;
|
||||||
uint16_t last_rnti = 70;
|
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
|
srsran::static_blocking_queue<std::unique_ptr<ue>, 32> ue_pool; ///< Pool of pre-allocated UE objects
|
||||||
void prealloc_ue(uint32_t nof_ue);
|
void prealloc_ue(uint32_t nof_ue);
|
||||||
|
|
|
@ -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;
|
||||||
srsran::rwlock_read_guard lock(rwlock);
|
do {
|
||||||
if (ue_db.size() >= args.max_nof_ues) {
|
// Get pre-allocated UE object
|
||||||
logger.warning("Maximum number of connected UEs %d reached. Ignoring PRACH", args.max_nof_ues);
|
if (ue_pool.empty()) {
|
||||||
|
logger.error("Ignoring RACH attempt. UE pool empty.");
|
||||||
return SRSRAN_INVALID_RNTI;
|
return SRSRAN_INVALID_RNTI;
|
||||||
}
|
}
|
||||||
}
|
std::unique_ptr<ue> ue_ptr = ue_pool.pop_blocking();
|
||||||
|
|
||||||
// Get pre-allocated UE object
|
// Add UE to map
|
||||||
if (ue_pool.empty()) {
|
{
|
||||||
logger.error("Ignoring RACH attempt. UE pool empty.");
|
srsran::rwlock_write_guard lock(rwlock);
|
||||||
return SRSRAN_INVALID_RNTI;
|
if (ue_db.size() >= args.max_nof_ues) {
|
||||||
}
|
logger.warning("Maximum number of connected UEs %d reached. Ignoring PRACH", args.max_nof_ues);
|
||||||
std::unique_ptr<ue> ue_ptr = ue_pool.pop_blocking();
|
return SRSRAN_INVALID_RNTI;
|
||||||
uint16_t rnti = ue_ptr->get_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
|
// 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…
Reference in New Issue