remove ENB_METRICS_MAX_USERS compile time macro and use run-time variable to set maximum number of UEs the srseNB can have connected at a given instant.

master
Francisco 4 years ago committed by Andre Puschmann
parent 2dfe335117
commit 68eda336bd

@ -551,6 +551,7 @@ typedef struct {
uint32_t nof_prb; ///< Needed to dimension MAC softbuffers for all cells
sched_interface::sched_args_t sched;
int nr_tb_size = -1;
uint32_t max_nof_ues;
} mac_args_t;
class stack_interface_s1ap_lte

@ -37,17 +37,17 @@
namespace srsenb {
struct stack_metrics_t {
mac_metrics_t mac[ENB_METRICS_MAX_USERS];
rrc_metrics_t rrc;
s1ap_metrics_t s1ap;
std::vector<mac_metrics_t> mac;
rrc_metrics_t rrc;
s1ap_metrics_t s1ap;
};
typedef struct {
srslte::rf_metrics_t rf;
phy_metrics_t phy[ENB_METRICS_MAX_USERS];
stack_metrics_t stack;
bool running;
} enb_metrics_t;
struct enb_metrics_t {
srslte::rf_metrics_t rf;
std::vector<phy_metrics_t> phy;
stack_metrics_t stack;
bool running;
};
// ENB interface
class enb_metrics_interface : public srslte::metrics_interface<enb_metrics_t>

@ -60,7 +60,7 @@ public:
stack_interface_phy_lte::ul_sched_t& ul_grants,
srslte_mbsfn_cfg_t* mbsfn_cfg);
uint32_t get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]);
uint32_t get_metrics(std::vector<phy_metrics_t>& metrics);
private:
constexpr static float PUSCH_RL_SNR_DB_TH = 1.0f;

@ -28,6 +28,7 @@
#define SRSENB_PHY_BASE_H
#include "srsenb/hdr/phy/phy_metrics.h"
#include <vector>
namespace srsenb {
@ -43,7 +44,7 @@ public:
virtual void start_plot() = 0;
virtual void get_metrics(phy_metrics_t* m) = 0;
virtual void get_metrics(std::vector<phy_metrics_t>& m) = 0;
virtual void cmd_cell_gain(uint32_t cell_idx, float gain_db) = 0;
};

@ -64,7 +64,7 @@ public:
void set_config(uint16_t rnti, const phy_rrc_cfg_list_t& phy_cfg_list) override;
void complete_config(uint16_t rnti) override;
void get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) override;
void get_metrics(std::vector<phy_metrics_t>& metrics) override;
void cmd_cell_gain(uint32_t cell_id, float gain_db) override;

@ -55,7 +55,7 @@ public:
int read_pucch_d(uint32_t cc_idx, cf_t* pusch_d);
void start_plot();
uint32_t get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]);
uint32_t get_metrics(std::vector<phy_metrics_t>& metrics);
private:
void work_imp() final;

@ -50,7 +50,7 @@ public:
void start_plot() override;
void get_metrics(srsenb::phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) override;
void get_metrics(std::vector<srsenb::phy_metrics_t>& metrics) override;
// MAC interface
int dl_config_request(const dl_config_request_t& request) override;

@ -98,7 +98,7 @@ public:
bool process_pdus();
void get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]);
void get_metrics(std::vector<mac_metrics_t>& metrics);
void write_mcch(const srslte::sib2_mbms_t* sib2_,
const srslte::sib13_t* sib13_,
const srslte::mcch_msg_t* mcch_,
@ -110,6 +110,7 @@ private:
bool check_ue_exists(uint16_t rnti);
uint16_t allocate_rnti();
uint16_t allocate_ue();
std::mutex rnti_mutex;

@ -60,7 +60,7 @@ public:
rrc_interface_mac_nr* rrc_);
void stop();
void get_metrics(srsenb::mac_metrics_t* metrics);
void get_metrics(std::vector<srsenb::mac_metrics_t>& metrics);
// MAC interface for RRC
int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg);

@ -23,6 +23,7 @@
#define SRSENB_RRC_METRICS_H
#include "srsenb/hdr/stack/upper/common_enb.h"
#include <vector>
namespace srsenb {
@ -44,8 +45,7 @@ struct rrc_ue_metrics_t {
};
struct rrc_metrics_t {
uint16_t n_ues;
rrc_ue_metrics_t ues[ENB_METRICS_MAX_USERS];
std::vector<rrc_ue_metrics_t> ues;
};
} // namespace srsenb

@ -30,7 +30,6 @@
namespace srsenb {
#define ENB_METRICS_MAX_USERS 64
#define SRSENB_RRC_MAX_N_PLMN_IDENTITIES 6
#define SRSENB_N_SRB 3

@ -204,6 +204,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("expert.print_buffer_state", bpo::value<bool>(&args->general.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds")
("expert.eea_pref_list", bpo::value<string>(&args->general.eea_pref_list)->default_value("EEA0, EEA2, EEA1"), "Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).")
("expert.eia_pref_list", bpo::value<string>(&args->general.eia_pref_list)->default_value("EIA2, EIA1, EIA0"), "Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).")
("expert.max_nof_ues", bpo::value<uint32_t>(&args->stack.mac.max_nof_ues)->default_value(64), "Maximum number of connected UEs")
// eMBMS section
("embms.enable", bpo::value<bool>(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB")

@ -70,11 +70,11 @@ void metrics_csv::set_metrics(const enb_metrics_t& metrics, const uint32_t perio
file << (metrics_report_period * n_reports) << ";";
// UEs
file << (metrics.stack.rrc.n_ues) << ";";
file << (metrics.stack.rrc.ues.size()) << ";";
// Sum up rates for all UEs
float dl_rate_sum = 0.0, ul_rate_sum = 0.0;
for (int i = 0; i < metrics.stack.rrc.n_ues; i++) {
for (size_t i = 0; i < metrics.stack.rrc.ues.size(); i++) {
dl_rate_sum += metrics.stack.mac[i].tx_brate / (metrics.stack.mac[i].nof_tti * 1e-3);
ul_rate_sum += metrics.stack.mac[i].rx_brate / (metrics.stack.mac[i].nof_tti * 1e-3);
}

@ -83,7 +83,7 @@ void metrics_stdout::set_metrics(const enb_metrics_t& metrics, const uint32_t pe
printf("RF status: O=%d, U=%d, L=%d\n", metrics.rf.rf_o, metrics.rf.rf_u, metrics.rf.rf_l);
}
if (metrics.stack.rrc.n_ues == 0) {
if (metrics.stack.rrc.ues.size() == 0) {
return;
}
@ -96,7 +96,7 @@ void metrics_stdout::set_metrics(const enb_metrics_t& metrics, const uint32_t pe
cout << "rnti cqi ri mcs brate ok nok (%) snr phr mcs brate ok nok (%) bsr" << endl;
}
for (int i = 0; i < metrics.stack.rrc.n_ues; i++) {
for (size_t i = 0; i < metrics.stack.rrc.ues.size(); i++) {
if (metrics.stack.mac[i].tx_errors > metrics.stack.mac[i].tx_pkts) {
printf("tx caution errors %d > %d\n", metrics.stack.mac[i].tx_errors, metrics.stack.mac[i].tx_pkts);
}

@ -314,7 +314,7 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
// Use last TBS for this TB in case of mcs>28
if (ul_grant.dci.tb.mcs_idx > 28) {
int rv_idx = grant.tb.rv;
grant.tb = phy->ue_db.get_last_ul_tb(rnti, cc_idx, ul_pid);
grant.tb = phy->ue_db.get_last_ul_tb(rnti, cc_idx, ul_pid);
grant.tb.rv = rv_idx;
Info("Adaptive retx: rnti=0x%x, pid=%d, rv_idx=%d, mcs=%d, old_tbs=%d\n",
rnti,
@ -591,16 +591,17 @@ int cc_worker::encode_pdsch(stack_interface_phy_lte::dl_sched_grant_t* grants, u
}
/************ METRICS interface ********************/
uint32_t cc_worker::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS])
uint32_t cc_worker::get_metrics(std::vector<phy_metrics_t>& metrics)
{
std::lock_guard<std::mutex> lock(mutex);
uint32_t cnt = 0;
metrics.resize(ue_db.size());
for (auto& ue : ue_db) {
if ((SRSLTE_RNTI_ISUSER(ue.first) || ue.first == SRSLTE_MRNTI) && cnt < ENB_METRICS_MAX_USERS) {
ue.second->metrics_read(&metrics[cnt]);
cnt++;
if ((SRSLTE_RNTI_ISUSER(ue.first) || ue.first == SRSLTE_MRNTI)) {
ue.second->metrics_read(&metrics[cnt++]);
}
}
metrics.resize(cnt);
return cnt;
}

@ -51,8 +51,7 @@ namespace srsenb {
phy::phy(srslte::logger* logger_) :
logger(logger_), workers_pool(MAX_WORKERS), workers(MAX_WORKERS), workers_common(), nof_workers(0)
{
}
{}
phy::~phy()
{
@ -190,14 +189,13 @@ void phy::set_activation_deactivation_scell(uint16_t rnti, const std::array<bool
}
}
void phy::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS])
void phy::get_metrics(std::vector<phy_metrics_t>& metrics)
{
phy_metrics_t metrics_tmp[ENB_METRICS_MAX_USERS] = {};
uint32_t nof_users = workers[0].get_nof_rnti();
bzero(metrics, sizeof(phy_metrics_t) * ENB_METRICS_MAX_USERS);
uint32_t nof_users = workers[0].get_nof_rnti();
std::vector<phy_metrics_t> metrics_tmp;
for (uint32_t i = 0; i < nof_workers; i++) {
workers[i].get_metrics(metrics_tmp);
metrics.resize(std::max(metrics_tmp.size(), metrics.size()));
for (uint32_t j = 0; j < nof_users; j++) {
metrics[j].dl.n_samples += metrics_tmp[j].dl.n_samples;
metrics[j].dl.mcs += metrics_tmp[j].dl.n_samples * metrics_tmp[j].dl.mcs;

@ -280,23 +280,24 @@ void sf_worker::work_imp()
}
/************ METRICS interface ********************/
uint32_t sf_worker::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS])
uint32_t sf_worker::get_metrics(std::vector<phy_metrics_t>& metrics)
{
uint32_t cnt = 0;
phy_metrics_t _metrics[ENB_METRICS_MAX_USERS] = {};
uint32_t cnt = 0;
std::vector<phy_metrics_t> metrics_;
for (uint32_t cc = 0; cc < phy->get_nof_carriers(); cc++) {
cnt = cc_workers[cc]->get_metrics(_metrics);
cnt = cc_workers[cc]->get_metrics(metrics_);
metrics.resize(std::max(metrics_.size(), metrics.size()));
for (uint32_t r = 0; r < cnt; r++) {
phy_metrics_t* m = &metrics[r];
phy_metrics_t* _m = &_metrics[r];
m->dl.mcs = SRSLTE_VEC_PMA(m->dl.mcs, m->dl.n_samples, _m->dl.mcs, _m->dl.n_samples);
m->dl.n_samples += _m->dl.n_samples;
m->ul.n = SRSLTE_VEC_PMA(m->ul.n, m->ul.n_samples, _m->ul.n, _m->ul.n_samples);
m->ul.sinr = SRSLTE_VEC_PMA(m->ul.sinr, m->ul.n_samples, _m->ul.sinr, _m->ul.n_samples);
m->ul.mcs = SRSLTE_VEC_PMA(m->ul.mcs, m->ul.n_samples, _m->ul.mcs, _m->ul.n_samples);
m->ul.rssi = SRSLTE_VEC_PMA(m->ul.rssi, m->ul.n_samples, _m->ul.rssi, _m->ul.n_samples);
m->ul.turbo_iters = SRSLTE_VEC_PMA(m->ul.turbo_iters, m->ul.n_samples, _m->ul.turbo_iters, _m->ul.n_samples);
m->ul.n_samples += _m->ul.n_samples;
phy_metrics_t* m_ = &metrics_[r];
m->dl.mcs = SRSLTE_VEC_PMA(m->dl.mcs, m->dl.n_samples, m_->dl.mcs, m_->dl.n_samples);
m->dl.n_samples += m_->dl.n_samples;
m->ul.n = SRSLTE_VEC_PMA(m->ul.n, m->ul.n_samples, m_->ul.n, m_->ul.n_samples);
m->ul.sinr = SRSLTE_VEC_PMA(m->ul.sinr, m->ul.n_samples, m_->ul.sinr, m_->ul.n_samples);
m->ul.mcs = SRSLTE_VEC_PMA(m->ul.mcs, m->ul.n_samples, m_->ul.mcs, m_->ul.n_samples);
m->ul.rssi = SRSLTE_VEC_PMA(m->ul.rssi, m->ul.n_samples, m_->ul.rssi, m_->ul.n_samples);
m->ul.turbo_iters = SRSLTE_VEC_PMA(m->ul.turbo_iters, m->ul.n_samples, m_->ul.turbo_iters, m_->ul.n_samples);
m->ul.n_samples += m_->ul.n_samples;
}
}
return cnt;

@ -69,7 +69,7 @@ void vnf_phy_nr::stop()
// Start GUI
void vnf_phy_nr::start_plot() {}
void vnf_phy_nr::get_metrics(srsenb::phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) {}
void vnf_phy_nr::get_metrics(std::vector<srsenb::phy_metrics_t>& metrics) {}
int vnf_phy_nr::dl_config_request(const dl_config_request_t& request)
{

@ -276,10 +276,11 @@ int mac::cell_cfg(const std::vector<sched_interface::cell_cfg_t>& cell_cfg_)
return scheduler.cell_cfg(cell_config);
}
void mac::get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS])
void mac::get_metrics(std::vector<mac_metrics_t>& metrics)
{
srslte::rwlock_read_guard lock(rwlock);
int cnt = 0;
metrics.resize(ue_db.size());
for (auto& u : ue_db) {
u.second->metrics_read(&metrics[cnt]);
cnt++;
@ -443,15 +444,23 @@ uint16_t mac::allocate_rnti()
return rnti;
}
uint16_t mac::reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg)
uint16_t mac::allocate_ue()
{
{
srslte::rwlock_read_guard lock(rwlock);
if (ue_db.size() >= args.max_nof_ues) {
Warning("Maximum number of connected UEs %d reached. Ignoring PRACH\n", args.max_nof_ues);
return SRSLTE_INVALID_RNTI;
}
}
// Get pre-allocated UE object
if (ue_pool.empty()) {
Error("Ignoring RACH attempt. UE pool empty.\n");
return SRSLTE_INVALID_RNTI;
}
auto ue_ptr = ue_pool.wait_pop();
uint16_t rnti = ue_ptr->get_rnti();
std::unique_ptr<ue> ue_ptr = ue_pool.wait_pop();
uint16_t rnti = ue_ptr->get_rnti();
// Set PCAP if available
if (pcap != nullptr) {
@ -463,14 +472,27 @@ uint16_t mac::reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg)
ue_db[rnti] = std::move(ue_ptr);
}
return rnti;
}
uint16_t mac::reserve_new_crnti(const sched_interface::ue_cfg_t& ue_cfg)
{
uint16_t rnti = allocate_ue();
if (rnti == SRSLTE_INVALID_RNTI) {
return rnti;
}
task_sched.enqueue_background_task([this](uint32_t wid) {
// Allocate one new UE object in advance
prealloc_ue(1);
});
// Add new user to the scheduler so that it can RX/TX SRB0
if (scheduler.ue_cfg(rnti, ue_cfg) != SRSLTE_SUCCESS) {
Error("Registering new user rnti=0x%x to SCHED\n", rnti);
return SRSLTE_INVALID_RNTI;
}
// Allocate one new UE object in advance
prealloc_ue(1);
return rnti;
}
@ -480,21 +502,9 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx
log_h->step(tti);
auto rach_tprof_meas = rach_tprof.start();
// Get pre-allocated UE object
if (ue_pool.empty()) {
Error("Ignoring RACH attempt. UE pool empty.\n");
}
auto ue_ptr = ue_pool.wait_pop();
uint16_t rnti = ue_ptr->get_rnti();
// Set PCAP if available
if (pcap != nullptr) {
ue_ptr->start_pcap(pcap);
}
{
srslte::rwlock_write_guard lock(rwlock);
ue_db[rnti] = std::move(ue_ptr);
uint16_t rnti = allocate_ue();
if (rnti == SRSLTE_INVALID_RNTI) {
return;
}
stack_task_queue.push([this, rnti, tti, enb_cc_idx, preamble_idx, time_adv, rach_tprof_meas]() mutable {
@ -532,11 +542,11 @@ void mac::rach_detected(uint32_t tti, uint32_t enb_cc_idx, uint32_t preamble_idx
time_adv,
rnti);
srslte::console("RACH: tti=%d, cc=%d, preamble=%d, offset=%d, temp_crnti=0x%x\n",
tti,
enb_cc_idx,
preamble_idx,
time_adv,
rnti);
tti,
enb_cc_idx,
preamble_idx,
time_adv,
rnti);
});
// Allocate one new UE object in advance

@ -85,7 +85,7 @@ void mac_nr::stop()
}
}
void mac_nr::get_metrics(srsenb::mac_metrics_t* metrics) {}
void mac_nr::get_metrics(std::vector<srsenb::mac_metrics_t>& metrics) {}
// Fills both, DL_CONFIG.request and TX.request structs
void mac_nr::get_dl_config(const uint32_t tti,

@ -109,10 +109,10 @@ void rrc::stop()
void rrc::get_metrics(rrc_metrics_t& m)
{
if (running) {
m.n_ues = 0;
for (auto iter = users.begin(); m.n_ues < ENB_METRICS_MAX_USERS && iter != users.end(); ++iter) {
ue* u = iter->second.get();
m.ues[m.n_ues++].state = u->get_state();
m.ues.resize(users.size());
size_t count = 0;
for (auto& ue : users) {
m.ues[count++].state = ue.second->get_state();
}
}
}

@ -45,8 +45,9 @@ public:
enb_dummy()
{
// first entry
metrics[0].rf.rf_o = 10;
metrics[0].stack.rrc.n_ues = 1;
metrics[0].rf.rf_o = 10;
metrics[0].stack.rrc.ues.resize(1);
metrics[0].stack.mac.resize(metrics[0].stack.rrc.ues.size());
metrics[0].stack.mac[0].rnti = 0x46;
metrics[0].stack.mac[0].tx_pkts = 1000;
metrics[0].stack.mac[0].tx_errors = 1000;
@ -60,13 +61,15 @@ public:
metrics[0].stack.mac[0].dl_ri = 1.5;
metrics[0].stack.mac[0].dl_pmi = 1.0;
metrics[0].stack.mac[0].phr = 12.0;
metrics[0].phy->dl.mcs = 28.0;
metrics[0].phy->ul.mcs = 20.2;
metrics[0].phy->ul.sinr = 14.2;
metrics[0].phy.resize(1);
metrics[0].phy[0].dl.mcs = 28.0;
metrics[0].phy[0].ul.mcs = 20.2;
metrics[0].phy[0].ul.sinr = 14.2;
// second
metrics[1].rf.rf_o = 10;
metrics[1].stack.rrc.n_ues = 1;
metrics[1].rf.rf_o = 10;
metrics[1].stack.rrc.ues.resize(1);
metrics[1].stack.mac.resize(metrics[1].stack.rrc.ues.size());
metrics[1].stack.mac[0].rnti = 0xffff;
metrics[1].stack.mac[0].tx_pkts = 100;
metrics[1].stack.mac[0].tx_errors = 0;
@ -80,13 +83,15 @@ public:
metrics[1].stack.mac[0].dl_ri = 1.5;
metrics[1].stack.mac[0].dl_pmi = 1.0;
metrics[1].stack.mac[0].phr = 99.1;
metrics[1].phy->dl.mcs = 6.2;
metrics[1].phy->ul.mcs = 28.0;
metrics[1].phy->ul.sinr = 22.2;
metrics[1].phy.resize(1);
metrics[1].phy[0].dl.mcs = 6.2;
metrics[1].phy[0].ul.mcs = 28.0;
metrics[1].phy[0].ul.sinr = 22.2;
// third entry
metrics[2].rf.rf_o = 10;
metrics[2].stack.rrc.n_ues = 1;
metrics[2].rf.rf_o = 10;
metrics[2].stack.rrc.ues.resize(1);
metrics[2].stack.mac.resize(metrics[2].stack.rrc.ues.size());
metrics[2].stack.mac[0].rnti = 0x1;
metrics[2].stack.mac[0].tx_pkts = 9999;
metrics[2].stack.mac[0].tx_errors = 1;
@ -100,15 +105,16 @@ public:
metrics[2].stack.mac[0].dl_ri = 1.5;
metrics[2].stack.mac[0].dl_pmi = 1.0;
metrics[2].stack.mac[0].phr = 12.0;
metrics[2].phy->dl.mcs = 28.0;
metrics[2].phy->ul.mcs = 20.2;
metrics[2].phy->ul.sinr = 14.2;
metrics[2].phy.resize(1);
metrics[2].phy[0].dl.mcs = 28.0;
metrics[2].phy[0].ul.mcs = 20.2;
metrics[2].phy[0].ul.sinr = 14.2;
}
bool get_metrics(enb_metrics_t* m)
{
// fill dummy values
memcpy(m, &metrics[counter % NUM_METRICS], sizeof(enb_metrics_t));
*m = metrics[counter % NUM_METRICS];
counter++;
return true;
}

Loading…
Cancel
Save