diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 601c9a12d..74b218dbc 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -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 diff --git a/lib/include/srslte/interfaces/enb_metrics_interface.h b/lib/include/srslte/interfaces/enb_metrics_interface.h index 9e70ae6dd..b8138ab0e 100644 --- a/lib/include/srslte/interfaces/enb_metrics_interface.h +++ b/lib/include/srslte/interfaces/enb_metrics_interface.h @@ -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; + 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; + stack_metrics_t stack; + bool running; +}; // ENB interface class enb_metrics_interface : public srslte::metrics_interface diff --git a/srsenb/hdr/phy/cc_worker.h b/srsenb/hdr/phy/cc_worker.h index b9b56e87c..afa57fc2f 100644 --- a/srsenb/hdr/phy/cc_worker.h +++ b/srsenb/hdr/phy/cc_worker.h @@ -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& metrics); private: constexpr static float PUSCH_RL_SNR_DB_TH = 1.0f; diff --git a/srsenb/hdr/phy/enb_phy_base.h b/srsenb/hdr/phy/enb_phy_base.h index 3daf32965..ac2b99669 100644 --- a/srsenb/hdr/phy/enb_phy_base.h +++ b/srsenb/hdr/phy/enb_phy_base.h @@ -28,6 +28,7 @@ #define SRSENB_PHY_BASE_H #include "srsenb/hdr/phy/phy_metrics.h" +#include 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& m) = 0; virtual void cmd_cell_gain(uint32_t cell_idx, float gain_db) = 0; }; diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index 8ca9e3dec..efed33db7 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -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& metrics) override; void cmd_cell_gain(uint32_t cell_id, float gain_db) override; diff --git a/srsenb/hdr/phy/sf_worker.h b/srsenb/hdr/phy/sf_worker.h index ffc721b71..c8ac8e6b7 100644 --- a/srsenb/hdr/phy/sf_worker.h +++ b/srsenb/hdr/phy/sf_worker.h @@ -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& metrics); private: void work_imp() final; diff --git a/srsenb/hdr/phy/vnf_phy_nr.h b/srsenb/hdr/phy/vnf_phy_nr.h index d225d5b92..11fbe9324 100644 --- a/srsenb/hdr/phy/vnf_phy_nr.h +++ b/srsenb/hdr/phy/vnf_phy_nr.h @@ -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& metrics) override; // MAC interface int dl_config_request(const dl_config_request_t& request) override; diff --git a/srsenb/hdr/stack/mac/mac.h b/srsenb/hdr/stack/mac/mac.h index 81712c57e..792291a00 100644 --- a/srsenb/hdr/stack/mac/mac.h +++ b/srsenb/hdr/stack/mac/mac.h @@ -98,7 +98,7 @@ public: bool process_pdus(); - void get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]); + void get_metrics(std::vector& 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; diff --git a/srsenb/hdr/stack/mac/mac_nr.h b/srsenb/hdr/stack/mac/mac_nr.h index 91d39aa1d..eaab92fce 100644 --- a/srsenb/hdr/stack/mac/mac_nr.h +++ b/srsenb/hdr/stack/mac/mac_nr.h @@ -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& metrics); // MAC interface for RRC int cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg); diff --git a/srsenb/hdr/stack/rrc/rrc_metrics.h b/srsenb/hdr/stack/rrc/rrc_metrics.h index f720c6fe5..080c2dddd 100644 --- a/srsenb/hdr/stack/rrc/rrc_metrics.h +++ b/srsenb/hdr/stack/rrc/rrc_metrics.h @@ -23,6 +23,7 @@ #define SRSENB_RRC_METRICS_H #include "srsenb/hdr/stack/upper/common_enb.h" +#include 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 ues; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/upper/common_enb.h b/srsenb/hdr/stack/upper/common_enb.h index 36828a9ba..b82ffce21 100644 --- a/srsenb/hdr/stack/upper/common_enb.h +++ b/srsenb/hdr/stack/upper/common_enb.h @@ -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 diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 26191da78..be8433e5f 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -204,6 +204,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.print_buffer_state", bpo::value(&args->general.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds") ("expert.eea_pref_list", bpo::value(&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(&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(&args->stack.mac.max_nof_ues)->default_value(64), "Maximum number of connected UEs") // eMBMS section ("embms.enable", bpo::value(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB") diff --git a/srsenb/src/metrics_csv.cc b/srsenb/src/metrics_csv.cc index 443c9a955..2cddc342c 100644 --- a/srsenb/src/metrics_csv.cc +++ b/srsenb/src/metrics_csv.cc @@ -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); } diff --git a/srsenb/src/metrics_stdout.cc b/srsenb/src/metrics_stdout.cc index 677807d3c..4ab54aa85 100644 --- a/srsenb/src/metrics_stdout.cc +++ b/srsenb/src/metrics_stdout.cc @@ -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); } diff --git a/srsenb/src/phy/cc_worker.cc b/srsenb/src/phy/cc_worker.cc index 7ec3e8fb2..8cdee6ee1 100644 --- a/srsenb/src/phy/cc_worker.cc +++ b/srsenb/src/phy/cc_worker.cc @@ -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& metrics) { std::lock_guard 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; } diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 00d405008..16291bb4f 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -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& 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 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; diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index 82e65fe54..baf46684a 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -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& metrics) { - uint32_t cnt = 0; - phy_metrics_t _metrics[ENB_METRICS_MAX_USERS] = {}; + uint32_t cnt = 0; + std::vector 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; diff --git a/srsenb/src/phy/vnf_phy_nr.cc b/srsenb/src/phy/vnf_phy_nr.cc index 0d1c833e9..a187cb7df 100644 --- a/srsenb/src/phy/vnf_phy_nr.cc +++ b/srsenb/src/phy/vnf_phy_nr.cc @@ -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& metrics) {} int vnf_phy_nr::dl_config_request(const dl_config_request_t& request) { diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index d1345ac51..18f2e8245 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -276,10 +276,11 @@ int mac::cell_cfg(const std::vector& 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& 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_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 diff --git a/srsenb/src/stack/mac/mac_nr.cc b/srsenb/src/stack/mac/mac_nr.cc index 5db5e0721..92e58790d 100644 --- a/srsenb/src/stack/mac/mac_nr.cc +++ b/srsenb/src/stack/mac/mac_nr.cc @@ -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& metrics) {} // Fills both, DL_CONFIG.request and TX.request structs void mac_nr::get_dl_config(const uint32_t tti, diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 970938630..013601984 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -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(); } } } diff --git a/srsenb/test/enb_metrics_test.cc b/srsenb/test/enb_metrics_test.cc index e330c7657..b627c4866 100644 --- a/srsenb/test/enb_metrics_test.cc +++ b/srsenb/test/enb_metrics_test.cc @@ -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; }