Rename meas_cell to meas_cell_eutra

Added meas_cell_nr class

Make meas_cell list as template class

Inheritance rrc_cell to meas_cell_nr
Added process_new_cell_meas_nr function
This commit is contained in:
David Rupprecht 2020-12-02 17:57:15 +01:00 committed by Andre Puschmann
parent 62b558fccf
commit 826dd32c89
12 changed files with 298 additions and 145 deletions

View File

@ -15,7 +15,11 @@ target_link_libraries(srslte_asn1_rrc_mcch_test rrc_asn1 srslte_common)
add_test(srslte_asn1_rrc_mcch_test srslte_asn1_rrc_mcch_test)
add_executable(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test.cc)
if (ENABLE_5GNR)
target_link_libraries(srslte_asn1_rrc_meas_test rrc_asn1 rrc_nr_asn1 srslte_common)
else()
target_link_libraries(srslte_asn1_rrc_meas_test rrc_asn1 srslte_common)
endif(ENABLE_5GNR)
add_test(srslte_asn1_rrc_meas_test srslte_asn1_rrc_meas_test)
add_executable(srslte_asn1_rrc_ul_dcch_test srslte_asn1_rrc_ul_dcch_test.cc)

View File

@ -62,7 +62,9 @@ class rrc : public rrc_interface_nas,
public rrc_interface_phy_lte,
public rrc_interface_mac,
public rrc_interface_pdcp,
#ifdef HAVE_5GNR
public rrc_interface_rrc_nr,
#endif
public rrc_interface_rlc,
public srslte::timer_callback
{
@ -108,10 +110,10 @@ public:
bool connection_request(srslte::establishment_cause_t cause, srslte::unique_byte_buffer_t dedicated_info_nas);
void set_ue_identity(srslte::s_tmsi_t s_tmsi);
void paging_completed(bool outcome) final;
#ifdef HAVE_5GNR
// NR interface
void new_cell_meas_nr(const std::vector<phy_meas_nr_t>& meas);
#endif
// PHY interface
void in_sync() final;
void out_of_sync() final;
@ -238,8 +240,12 @@ private:
std::unique_ptr<rrc_meas> measurements;
// List of strongest neighbour cell
using unique_cell_t = std::unique_ptr<meas_cell>;
meas_cell_list meas_cells;
using unique_cell_t = std::unique_ptr<meas_cell_eutra>;
meas_cell_list<meas_cell_eutra> meas_cells;
#ifdef HAVE_5GNR
meas_cell_list<meas_cell_nr> meas_cells_nr;
#endif
bool initiated = false;
asn1::rrc::reest_cause_e m_reest_cause = asn1::rrc::reest_cause_e::nulltype;
@ -253,15 +259,17 @@ private:
std::set<uint32_t> get_cells(const uint32_t earfcn);
float get_cell_rsrp(const uint32_t earfcn, const uint32_t pci);
float get_cell_rsrq(const uint32_t earfcn, const uint32_t pci);
meas_cell* get_serving_cell();
meas_cell_eutra* get_serving_cell();
void process_cell_meas();
void process_new_cell_meas(const std::vector<phy_meas_t>& meas);
srslte::block_queue<std::vector<phy_meas_t> > cell_meas_q;
#ifdef HAVE_5GNR
void process_cell_meas_nr();
void process_new_cell_meas_nr(const std::vector<phy_meas_nr_t>& meas);
srslte::block_queue<std::vector<phy_meas_nr_t> > cell_meas_nr_q;
#endif
// Cell selection/reselection functions/variables
typedef struct {

View File

@ -15,6 +15,10 @@
#include "srslte/asn1/rrc.h"
#include "srslte/asn1/rrc_utils.h"
#if HAVE_5GNR
#include "srslte/asn1/rrc_nr.h"
#include "srslte/asn1/rrc_nr_utils.h"
#endif
#include "srslte/interfaces/ue_interfaces.h"
namespace srsue {
@ -43,14 +47,6 @@ public:
bool greater(const meas_cell* x) const { return rsrp > x->rsrp || std::isnan(rsrp); }
bool greater(const meas_cell& x) const { return rsrp > x.rsrp || std::isnan(rsrp); }
bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const;
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
srslte::plmn_id_t get_plmn(uint32_t idx) const;
uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; }
uint32_t get_earfcn() const { return phy_cell.earfcn; }
uint32_t get_pci() const { return phy_cell.pci; }
void set_rsrp(float rsrp_)
{
if (!std::isnan(rsrp_)) {
@ -71,10 +67,90 @@ public:
}
}
bool has_sib1() const { return has_valid_sib1; }
bool has_sib2() const { return has_valid_sib2; }
bool has_sib3() const { return has_valid_sib3; }
bool has_sib13() const { return has_valid_sib13; }
bool has_sib(uint32_t index) const;
bool has_sibs(srslte::span<const uint32_t> indexes) const;
bool is_sib_scheduled(uint32_t sib_index) const;
void reset_sibs()
{
has_valid_sib1 = false;
has_valid_sib2 = false;
has_valid_sib3 = false;
has_valid_sib13 = false;
}
uint32_t get_earfcn() const { return phy_cell.earfcn; }
uint32_t get_pci() const { return phy_cell.pci; }
float get_rsrp() const { return rsrp; }
float get_rsrq() const { return rsrq; }
float get_cfo_hz() const { return phy_cell.cfo_hz; }
phy_cell_t phy_cell = {0, 0, 0};
srslte::unique_timer timer;
protected:
float rsrp = NAN;
float rsrq = NAN;
bool has_valid_sib1 = false;
bool has_valid_sib2 = false;
bool has_valid_sib3 = false;
bool has_valid_sib13 = false;
std::map<uint32_t, uint32_t> sib_info_map; ///< map of sib_index to index of schedInfoList in SIB1
};
#ifdef HAVE_5GNR
class meas_cell_nr : public meas_cell
{
public:
explicit meas_cell_nr(srslte::unique_timer timer) : meas_cell(std::move(timer)){};
meas_cell_nr(const phy_cell_t& phy_cell_, srslte::unique_timer timer) : meas_cell(phy_cell_, std::move(timer)){};
bool has_plmn_id(asn1::rrc_nr::plmn_id_s plmn_id) const;
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
srslte::plmn_id_t get_plmn(uint32_t idx) const;
void set_sib1(const asn1::rrc_nr::sib1_s& sib1_);
void set_sib2(const asn1::rrc_nr::sib2_s& sib2_);
void set_sib3(const asn1::rrc_nr::sib3_s& sib3_);
const asn1::rrc_nr::sib1_s* sib1ptr() const { return has_sib1() ? &sib1 : nullptr; }
const asn1::rrc_nr::sib2_s* sib2ptr() const { return has_sib2() ? &sib2 : nullptr; }
const asn1::rrc_nr::sib3_s* sib3ptr() const { return has_sib3() ? &sib3 : nullptr; }
uint32_t get_cell_id() const { return (uint32_t)0xFFFF; } // TODO find the correct sib
uint16_t get_mcc() const;
uint16_t get_mnc() const;
std::string to_string() const;
bool has_mcch = false;
asn1::rrc_nr::sib1_s sib1 = {};
asn1::rrc_nr::sib2_s sib2 = {};
asn1::rrc_nr::sib3_s sib3 = {};
asn1::rrc::mcch_msg_s mcch = {};
};
#endif
class meas_cell_eutra : public meas_cell
{
public:
explicit meas_cell_eutra(srslte::unique_timer timer) : meas_cell(std::move(timer)){};
meas_cell_eutra(const phy_cell_t& phy_cell_, srslte::unique_timer timer) : meas_cell(phy_cell_, std::move(timer)){};
bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const;
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
srslte::plmn_id_t get_plmn(uint32_t idx) const;
uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; }
void set_sib1(const asn1::rrc::sib_type1_s& sib1_);
void set_sib2(const asn1::rrc::sib_type2_s& sib2_);
void set_sib3(const asn1::rrc::sib_type3_s& sib3_);
@ -87,46 +163,22 @@ public:
uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
bool has_sibs(srslte::span<const uint32_t> indexes) const;
bool has_sib(uint32_t index) const;
bool has_sib1() const { return has_valid_sib1; }
bool has_sib2() const { return has_valid_sib2; }
bool has_sib3() const { return has_valid_sib3; }
bool has_sib13() const { return has_valid_sib13; }
void reset_sibs()
{
has_valid_sib1 = false;
has_valid_sib2 = false;
has_valid_sib3 = false;
has_valid_sib13 = false;
}
uint16_t get_mcc() const;
uint16_t get_mnc() const;
std::string to_string() const;
bool is_sib_scheduled(uint32_t sib_index) const;
phy_cell_t phy_cell = {0, 0, 0};
bool has_mcch = false;
asn1::rrc::sib_type1_s sib1 = {};
asn1::rrc::sib_type2_s sib2 = {};
asn1::rrc::sib_type3_s sib3 = {};
asn1::rrc::sib_type13_r9_s sib13 = {};
asn1::rrc::mcch_msg_s mcch = {};
srslte::unique_timer timer;
private:
float rsrp = NAN;
float rsrq = NAN;
bool has_valid_sib1 = false;
bool has_valid_sib2 = false;
bool has_valid_sib3 = false;
bool has_valid_sib13 = false;
std::map<uint32_t, uint32_t> sib_info_map; ///< map of sib_index to index of schedInfoList in SIB1
};
//! Universal methods to extract pci/earfcn and compare the two values
@ -136,33 +188,47 @@ uint32_t get_pci(const T& t)
return t.pci;
}
template <>
inline uint32_t get_pci(const meas_cell& t)
inline uint32_t get_pci(const meas_cell_eutra& t)
{
return t.get_pci();
}
#ifdef HAVE_5GNR
template <>
inline uint32_t get_pci(const meas_cell_nr& t)
{
return t.get_pci();
}
#endif
template <typename T>
uint32_t get_earfcn(const T& t)
{
return t.earfcn;
}
template <>
inline uint32_t get_earfcn(const meas_cell& t)
inline uint32_t get_earfcn(const meas_cell_eutra& t)
{
return t.get_earfcn();
}
#ifdef HAVE_5GNR
template <>
inline uint32_t get_earfcn(const meas_cell_nr& t)
{
return t.get_earfcn();
}
#endif
template <typename T, typename U>
bool is_same_cell(const T& lhs, const U& rhs)
{
return get_pci(lhs) == get_pci(rhs) and get_earfcn(lhs) == get_earfcn(rhs);
}
template <class T>
class meas_cell_list
{
public:
const static int NEIGHBOUR_TIMEOUT = 5;
const static int MAX_NEIGHBOUR_CELLS = 8;
typedef std::unique_ptr<meas_cell> unique_meas_cell;
const static int NEIGHBOUR_TIMEOUT = 5;
const static int MAX_NEIGHBOUR_CELLS = 8;
typedef std::unique_ptr<T> unique_meas_cell;
explicit meas_cell_list(srslte::task_sched_handle task_sched_);
@ -173,28 +239,28 @@ public:
void clean_neighbours();
void sort_neighbour_cells();
bool process_new_cell_meas(const std::vector<phy_meas_t>& meas,
const std::function<void(meas_cell&, const phy_meas_t&)>& filter_meas);
bool process_new_cell_meas(const std::vector<phy_meas_t>& meas,
const std::function<void(T&, const phy_meas_t&)>& filter_meas);
meas_cell* get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci);
const meas_cell* get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci) const;
void log_neighbour_cells() const;
std::string print_neighbour_cells() const;
std::set<uint32_t> get_neighbour_pcis(uint32_t earfcn) const;
bool has_neighbour_cell(uint32_t earfcn, uint32_t pci) const;
size_t nof_neighbours() const { return neighbour_cells.size(); }
meas_cell& operator[](size_t idx) { return *neighbour_cells[idx]; }
const meas_cell& operator[](size_t idx) const { return *neighbour_cells[idx]; }
meas_cell& at(size_t idx) { return *neighbour_cells.at(idx); }
meas_cell* find_cell(uint32_t earfcn, uint32_t pci);
T* get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci);
const T* get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci) const;
void log_neighbour_cells() const;
std::string print_neighbour_cells() const;
std::set<uint32_t> get_neighbour_pcis(uint32_t earfcn) const;
bool has_neighbour_cell(uint32_t earfcn, uint32_t pci) const;
size_t nof_neighbours() const { return neighbour_cells.size(); }
T& operator[](size_t idx) { return *neighbour_cells[idx]; }
const T& operator[](size_t idx) const { return *neighbour_cells[idx]; }
T& at(size_t idx) { return *neighbour_cells.at(idx); }
T* find_cell(uint32_t earfcn, uint32_t pci);
// serving cell handling
int set_serving_cell(phy_cell_t phy_cell, bool discard_serving);
meas_cell& serving_cell() { return *serv_cell; }
const meas_cell& serving_cell() const { return *serv_cell; }
T& serving_cell() { return *serv_cell; }
const T& serving_cell() const { return *serv_cell; }
using iterator = std::vector<unique_meas_cell>::iterator;
using iterator = typename std::vector<unique_meas_cell>::iterator;
iterator begin() { return neighbour_cells.begin(); }
iterator end() { return neighbour_cells.end(); }

View File

@ -99,7 +99,12 @@ private:
void ho_reest_finish(const uint32_t src_earfcn, const uint32_t dst_earfcn);
bool parse_meas_config(const meas_cfg_s* meas_config, bool is_ho_reest, uint32_t src_earfcn);
void eval_triggers();
void eval_triggers_eutra(uint32_t meas_id, report_cfg_eutra_s& report_cfg, meas_obj_eutra_s& meas_obj, meas_cell* serv_cell, float Ofs, float Ocs);
void eval_triggers_eutra(uint32_t meas_id,
report_cfg_eutra_s& report_cfg,
meas_obj_eutra_s& meas_obj,
meas_cell_eutra* serv_cell,
float Ofs,
float Ocs);
void report_triggers();
void report_triggers_eutra(uint32_t meas_id, report_cfg_eutra_s& report_cfg, meas_obj_eutra_s& meas_obj);

View File

@ -128,12 +128,12 @@ private:
bool is_serv_cell_suitable() const;
bool is_sib_acq_required() const;
srslte::proc_outcome_t set_proc_complete();
srslte::proc_outcome_t start_phy_cell_selection(const meas_cell& cell);
srslte::proc_outcome_t start_phy_cell_selection(const meas_cell_eutra& cell);
srslte::proc_outcome_t start_sib_acquisition();
// consts
rrc* rrc_ptr;
meas_cell_list* meas_cells;
rrc* rrc_ptr;
meas_cell_list<meas_cell_eutra>* meas_cells;
// state variables
enum class search_state_t { cell_selection, serv_cell_camp, cell_config, cell_search };

View File

@ -61,6 +61,9 @@ rrc::rrc(stack_interface_rrc* stack_, srslte::task_sched_handle task_sched_) :
connection_reest(this),
ho_handler(this),
conn_recfg_proc(this),
#ifdef HAVE_5GNR
meas_cells_nr(task_sched_),
#endif
meas_cells(task_sched_)
{}
@ -111,7 +114,7 @@ void rrc::init(phy_interface_rrc_lte* phy_,
auto on_every_cell_selection = [this](uint32_t earfcn, uint32_t pci, bool csel_result) {
if (not csel_result) {
meas_cell* c = meas_cells.find_cell(earfcn, pci);
meas_cell_eutra* c = meas_cells.find_cell(earfcn, pci);
if (c != nullptr) {
c->set_rsrp(-INFINITY);
}
@ -364,6 +367,7 @@ void rrc::set_config_complete(bool status)
void rrc::set_scell_complete(bool status) {}
#ifdef HAVE_5GNR
/* This function is called from a NR PHY worker thus must return very quickly.
* Queue the values of the measurements and process them from the RRC thread
*/
@ -385,7 +389,31 @@ void rrc::process_cell_meas_nr()
}
}
void rrc::process_new_cell_meas_nr(const std::vector<phy_meas_nr_t>& meas) {}
void rrc::process_new_cell_meas_nr(const std::vector<phy_meas_nr_t>& meas)
{
// Convert vector
std::vector<phy_meas_t> meas_lte;
for (const auto& m : meas) {
phy_meas_t tmp_meas = {};
tmp_meas.cfo_hz = m.cfo_hz;
tmp_meas.earfcn = m.arfcn_nr;
tmp_meas.rsrp = m.rsrp;
tmp_meas.rsrq = m.rsrp;
tmp_meas.pci = m.pci_nr;
meas_lte.push_back(tmp_meas);
}
const std::function<void(meas_cell_nr&, const phy_meas_t&)> filter = [this](meas_cell_nr& c, const phy_meas_t& m) {
c.set_rsrp(measurements->rsrp_filter(m.rsrp, c.get_rsrp()));
c.set_rsrq(measurements->rsrq_filter(m.rsrq, c.get_rsrq()));
c.set_cfo(m.cfo_hz);
};
rrc_log->debug("MEAS: Processing measurement of %zd cells\n", meas.size());
bool neighbour_added = meas_cells_nr.process_new_cell_meas(meas_lte, filter);
}
#endif
/* This function is called from a PHY worker thus must return very quickly.
* Queue the values of the measurements and process them from the RRC thread
@ -394,7 +422,6 @@ void rrc::new_cell_meas(const std::vector<phy_meas_t>& meas)
{
cell_meas_q.push(meas);
}
/* Processes all pending PHY measurements in queue.
*/
void rrc::process_cell_meas()
@ -410,7 +437,8 @@ void rrc::process_cell_meas()
void rrc::process_new_cell_meas(const std::vector<phy_meas_t>& meas)
{
const std::function<void(meas_cell&, const phy_meas_t&)> filter = [this](meas_cell& c, const phy_meas_t& m) {
const std::function<void(meas_cell_eutra&, const phy_meas_t&)> filter = [this](meas_cell_eutra& c,
const phy_meas_t& m) {
c.set_rsrp(measurements->rsrp_filter(m.rsrp, c.get_rsrp()));
c.set_rsrq(measurements->rsrq_filter(m.rsrq, c.get_rsrq()));
c.set_cfo(m.cfo_hz);
@ -1080,17 +1108,17 @@ std::set<uint32_t> rrc::get_cells(const uint32_t earfcn)
float rrc::get_cell_rsrp(const uint32_t earfcn, const uint32_t pci)
{
meas_cell* c = meas_cells.get_neighbour_cell_handle(earfcn, pci);
meas_cell_eutra* c = meas_cells.get_neighbour_cell_handle(earfcn, pci);
return (c != nullptr) ? c->get_rsrp() : NAN;
}
float rrc::get_cell_rsrq(const uint32_t earfcn, const uint32_t pci)
{
meas_cell* c = meas_cells.get_neighbour_cell_handle(earfcn, pci);
meas_cell_eutra* c = meas_cells.get_neighbour_cell_handle(earfcn, pci);
return (c != nullptr) ? c->get_rsrq() : NAN;
}
meas_cell* rrc::get_serving_cell()
meas_cell_eutra* rrc::get_serving_cell()
{
return &meas_cells.serving_cell();
}

View File

@ -24,7 +24,7 @@ meas_cell::meas_cell(const phy_cell_t& phy_cell_, srslte::unique_timer timer) :
phy_cell = phy_cell_;
}
srslte::plmn_id_t meas_cell::get_plmn(uint32_t idx) const
srslte::plmn_id_t meas_cell_eutra::get_plmn(uint32_t idx) const
{
if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) {
return srslte::make_plmn_id_t(sib1.cell_access_related_info.plmn_id_list[idx].plmn_id);
@ -33,7 +33,7 @@ srslte::plmn_id_t meas_cell::get_plmn(uint32_t idx) const
}
}
void meas_cell::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
void meas_cell_eutra::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
{
sib1 = sib1_;
has_valid_sib1 = true;
@ -46,17 +46,17 @@ void meas_cell::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
}
}
void meas_cell::set_sib2(const asn1::rrc::sib_type2_s& sib2_)
void meas_cell_eutra::set_sib2(const asn1::rrc::sib_type2_s& sib2_)
{
sib2 = sib2_;
has_valid_sib2 = true;
}
void meas_cell::set_sib3(const asn1::rrc::sib_type3_s& sib3_)
void meas_cell_eutra::set_sib3(const asn1::rrc::sib_type3_s& sib3_)
{
sib3 = sib3_;
has_valid_sib3 = true;
}
void meas_cell::set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_)
void meas_cell_eutra::set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_)
{
sib13 = sib13_;
has_valid_sib13 = true;
@ -94,7 +94,23 @@ bool meas_cell::has_sib(uint32_t index) const
return false;
}
std::string meas_cell::to_string() const
#ifdef HAVE_5GNR
std::string meas_cell_nr::to_string() const
{
char buf[256];
snprintf(buf,
256,
"{cell_id: 0x%x, pci: %d, dl_arfcn_nr: %d, rsrp=%+.1f, cfo=%+.1f}",
get_cell_id(),
get_pci(),
get_earfcn(),
get_rsrp(),
get_cfo_hz());
return std::string{buf};
}
#endif
std::string meas_cell_eutra::to_string() const
{
char buf[256];
snprintf(buf,
@ -108,7 +124,7 @@ std::string meas_cell::to_string() const
return std::string{buf};
}
bool meas_cell::has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const
bool meas_cell_eutra::has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const
{
if (has_valid_sib1) {
for (const auto& e : sib1.cell_access_related_info.plmn_id_list) {
@ -120,7 +136,7 @@ bool meas_cell::has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const
return false;
}
uint16_t meas_cell::get_mcc() const
uint16_t meas_cell_eutra::get_mcc() const
{
uint16_t mcc;
if (has_valid_sib1) {
@ -133,7 +149,7 @@ uint16_t meas_cell::get_mcc() const
return 0;
}
uint16_t meas_cell::get_mnc() const
uint16_t meas_cell_eutra::get_mnc() const
{
uint16_t mnc;
if (has_valid_sib1) {
@ -151,21 +167,22 @@ uint16_t meas_cell::get_mnc() const
/*********************************************
* Neighbour Cell List
********************************************/
meas_cell_list::meas_cell_list(srslte::task_sched_handle task_sched_) :
serv_cell(new meas_cell(task_sched_.get_unique_timer())),
template <class T>
meas_cell_list<T>::meas_cell_list(srslte::task_sched_handle task_sched_) :
serv_cell(new T(task_sched_.get_unique_timer())),
task_sched(task_sched_)
{}
meas_cell* meas_cell_list::get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci)
template <class T>
T* meas_cell_list<T>::get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci)
{
auto it = find_if(neighbour_cells.begin(), neighbour_cells.end(), [&](const unique_meas_cell& cell) {
return cell->equals(earfcn, pci);
});
return it != neighbour_cells.end() ? it->get() : nullptr;
}
const meas_cell* meas_cell_list::get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci) const
template <class T>
const T* meas_cell_list<T>::get_neighbour_cell_handle(uint32_t earfcn, uint32_t pci) const
{
auto it = find_if(neighbour_cells.begin(), neighbour_cells.end(), [&](const unique_meas_cell& cell) {
return cell->equals(earfcn, pci);
@ -174,19 +191,20 @@ const meas_cell* meas_cell_list::get_neighbour_cell_handle(uint32_t earfcn, uint
}
// If only neighbour PCI is provided, copy full cell from serving cell
bool meas_cell_list::add_meas_cell(const phy_meas_t& meas)
template <class T>
bool meas_cell_list<T>::add_meas_cell(const phy_meas_t& meas)
{
phy_cell_t phy_cell = {};
phy_cell.earfcn = meas.earfcn;
phy_cell.pci = meas.pci;
unique_meas_cell c = unique_meas_cell(new meas_cell(phy_cell, task_sched.get_unique_timer()));
unique_meas_cell c = unique_meas_cell(new T(phy_cell, task_sched.get_unique_timer()));
c.get()->set_rsrp(meas.rsrp);
c.get()->set_rsrq(meas.rsrq);
c.get()->set_cfo(meas.cfo_hz);
return add_meas_cell(std::move(c));
}
bool meas_cell_list::add_meas_cell(unique_meas_cell cell)
template <class T>
bool meas_cell_list<T>::add_meas_cell(unique_meas_cell cell)
{
bool ret = add_neighbour_cell_unsorted(std::move(cell));
if (ret) {
@ -194,8 +212,8 @@ bool meas_cell_list::add_meas_cell(unique_meas_cell cell)
}
return ret;
}
bool meas_cell_list::add_neighbour_cell_unsorted(unique_meas_cell new_cell)
template <class T>
bool meas_cell_list<T>::add_neighbour_cell_unsorted(unique_meas_cell new_cell)
{
// Make sure cell is valid
if (!new_cell->is_valid()) {
@ -210,7 +228,7 @@ bool meas_cell_list::add_neighbour_cell_unsorted(unique_meas_cell new_cell)
}
// If cell exists, update RSRP value
meas_cell* existing_cell = get_neighbour_cell_handle(new_cell->get_earfcn(), new_cell->get_pci());
T* existing_cell = get_neighbour_cell_handle(new_cell->get_earfcn(), new_cell->get_pci());
if (existing_cell != nullptr) {
if (std::isnormal(new_cell.get()->get_rsrp())) {
existing_cell->set_rsrp(new_cell.get()->get_rsrp());
@ -234,8 +252,8 @@ bool meas_cell_list::add_neighbour_cell_unsorted(unique_meas_cell new_cell)
neighbour_cells.push_back(std::move(new_cell));
return true;
}
void meas_cell_list::rem_last_neighbour()
template <class T>
void meas_cell_list<T>::rem_last_neighbour()
{
if (not neighbour_cells.empty()) {
unique_meas_cell& c = neighbour_cells.back();
@ -243,8 +261,8 @@ void meas_cell_list::rem_last_neighbour()
neighbour_cells.pop_back();
}
}
meas_cell_list::unique_meas_cell meas_cell_list::remove_neighbour_cell(uint32_t earfcn, uint32_t pci)
template <class T>
typename meas_cell_list<T>::unique_meas_cell meas_cell_list<T>::remove_neighbour_cell(uint32_t earfcn, uint32_t pci)
{
auto it = find_if(neighbour_cells.begin(), neighbour_cells.end(), [&](const unique_meas_cell& cell) {
return cell->equals(earfcn, pci);
@ -258,7 +276,8 @@ meas_cell_list::unique_meas_cell meas_cell_list::remove_neighbour_cell(uint32_t
}
// Sort neighbour cells by decreasing order of RSRP
void meas_cell_list::sort_neighbour_cells()
template <class T>
void meas_cell_list<T>::sort_neighbour_cells()
{
std::sort(std::begin(neighbour_cells),
std::end(neighbour_cells),
@ -266,8 +285,8 @@ void meas_cell_list::sort_neighbour_cells()
log_neighbour_cells();
}
void meas_cell_list::log_neighbour_cells() const
template <class T>
void meas_cell_list<T>::log_neighbour_cells() const
{
if (not neighbour_cells.empty()) {
const int32_t MAX_STR_LEN = 512;
@ -289,7 +308,8 @@ void meas_cell_list::log_neighbour_cells() const
}
//! Called by main RRC thread to remove neighbours from which measurements have not been received in a while
void meas_cell_list::clean_neighbours()
template <class T>
void meas_cell_list<T>::clean_neighbours()
{
for (auto it = neighbour_cells.begin(); it != neighbour_cells.end();) {
if (it->get()->timer.is_expired()) {
@ -300,8 +320,8 @@ void meas_cell_list::clean_neighbours()
}
}
}
std::string meas_cell_list::print_neighbour_cells() const
template <class T>
std::string meas_cell_list<T>::print_neighbour_cells() const
{
if (neighbour_cells.empty()) {
return "";
@ -314,8 +334,8 @@ std::string meas_cell_list::print_neighbour_cells() const
s += neighbour_cells.back()->to_string();
return s;
}
std::set<uint32_t> meas_cell_list::get_neighbour_pcis(uint32_t earfcn) const
template <class T>
std::set<uint32_t> meas_cell_list<T>::get_neighbour_pcis(uint32_t earfcn) const
{
std::set<uint32_t> pcis = {};
for (const unique_meas_cell& cell : neighbour_cells) {
@ -325,21 +345,21 @@ std::set<uint32_t> meas_cell_list::get_neighbour_pcis(uint32_t earfcn) const
}
return pcis;
}
bool meas_cell_list::has_neighbour_cell(uint32_t earfcn, uint32_t pci) const
template <class T>
bool meas_cell_list<T>::has_neighbour_cell(uint32_t earfcn, uint32_t pci) const
{
return get_neighbour_cell_handle(earfcn, pci) != nullptr;
}
meas_cell* meas_cell_list::find_cell(uint32_t earfcn, uint32_t pci)
template <class T>
T* meas_cell_list<T>::find_cell(uint32_t earfcn, uint32_t pci)
{
if (serving_cell().phy_cell.pci == pci and serving_cell().phy_cell.earfcn == earfcn) {
return &serving_cell();
}
return get_neighbour_cell_handle(earfcn, pci);
}
int meas_cell_list::set_serving_cell(phy_cell_t phy_cell, bool discard_serving)
template <class T>
int meas_cell_list<T>::set_serving_cell(phy_cell_t phy_cell, bool discard_serving)
{
// don't update neighbor cell list unless serving cell changes
if (phy_cell.pci == serving_cell().get_pci() && phy_cell.earfcn == serving_cell().get_earfcn()) {
@ -367,12 +387,13 @@ int meas_cell_list::set_serving_cell(phy_cell_t phy_cell, bool discard_serving)
return SRSLTE_SUCCESS;
}
bool meas_cell_list::process_new_cell_meas(const std::vector<phy_meas_t>& meas,
const std::function<void(meas_cell&, const phy_meas_t&)>& filter_meas)
template <class T>
bool meas_cell_list<T>::process_new_cell_meas(const std::vector<phy_meas_t>& meas,
const std::function<void(T&, const phy_meas_t&)>& filter_meas)
{
bool neighbour_added = false;
for (const auto& m : meas) {
meas_cell* c = nullptr;
T* c = nullptr;
// Get serving_cell handle if it's the serving cell
bool is_serving_cell = m.earfcn == 0 or is_same_cell(m, serving_cell());
@ -405,4 +426,9 @@ bool meas_cell_list::process_new_cell_meas(const std::vector<phy_meas_t>&
return neighbour_added;
}
template class meas_cell_list<meas_cell_eutra>;
#ifdef HAVE_5GNR
template class meas_cell_list<meas_cell_nr>;
#endif
} // namespace srsue

View File

@ -197,7 +197,7 @@ void rrc::rrc_meas::var_meas_report_list::init(rrc* rrc_ptr_)
/* Generate report procedure 5.5.5 */
void rrc::rrc_meas::var_meas_report_list::generate_report(const uint32_t measId)
{
meas_cell* serv_cell = rrc_ptr->get_serving_cell();
meas_cell_eutra* serv_cell = rrc_ptr->get_serving_cell();
if (serv_cell == nullptr) {
log_h->warning("MEAS: Serving cell not set when evaluating triggers\n");
return;
@ -435,7 +435,7 @@ void rrc::rrc_meas::var_meas_cfg::report_triggers_eutra(uint32_t meas
}
}
{
meas_cell* serv_cell = rrc_ptr->get_serving_cell();
meas_cell_eutra* serv_cell = rrc_ptr->get_serving_cell();
if (serv_cell == nullptr) {
log_h->warning("MEAS: Serving cell not set when reporting triggers\n");
return;
@ -499,7 +499,7 @@ bool rrc::rrc_meas::var_meas_cfg::is_rsrp(report_cfg_eutra_s::trigger_quant_opts
void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_id,
report_cfg_eutra_s& report_cfg,
meas_obj_eutra_s& meas_obj,
meas_cell* serv_cell,
meas_cell_eutra* serv_cell,
float Ofs,
float Ocs)
{
@ -627,7 +627,7 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
/* Evaluate event trigger conditions for each cell 5.5.4 */
void rrc::rrc_meas::var_meas_cfg::eval_triggers()
{
meas_cell* serv_cell = rrc_ptr->get_serving_cell();
meas_cell_eutra* serv_cell = rrc_ptr->get_serving_cell();
if (serv_cell == nullptr) {
log_h->warning("MEAS: Serving cell not set when evaluating triggers\n");
@ -1226,7 +1226,7 @@ bool rrc::rrc_meas::var_meas_cfg::parse_meas_config(const meas_cfg_s* cfg, bool
// According to 5.5.6.1, if the new configuration after a HO/Reest does not configure the target frequency, we need to
// swap frequencies with source
if (is_ho_reest) {
meas_cell* serv_cell = rrc_ptr->get_serving_cell();
meas_cell_eutra* serv_cell = rrc_ptr->get_serving_cell();
if (serv_cell) {
// Check if the target frequency is configured
uint32_t target_earfcn = serv_cell->get_earfcn();

View File

@ -82,7 +82,7 @@ proc_outcome_t rrc::cell_search_proc::handle_cell_found(const phy_cell_t& new_ce
// Create a cell with NaN RSRP. Will be updated by new_phy_meas() during SIB search.
if (not rrc_ptr->meas_cells.add_meas_cell(
unique_cell_t(new meas_cell(new_cell, rrc_ptr->task_sched.get_unique_timer())))) {
unique_cell_t(new meas_cell_eutra(new_cell, rrc_ptr->task_sched.get_unique_timer())))) {
Error("Could not add new found cell\n");
return proc_outcome_t::error;
}
@ -552,7 +552,7 @@ proc_outcome_t rrc::cell_selection_proc::start_next_cell_selection()
// If serving is not available, use the stored information (known neighbours) to find the strongest
// cell that meets the selection criteria.
for (; neigh_index < meas_cells->nof_neighbours(); ++neigh_index) {
const meas_cell& neigh_cell = meas_cells->at(neigh_index);
const meas_cell_eutra& neigh_cell = meas_cells->at(neigh_index);
/*TODO: CHECK that PLMN matches. Currently we don't receive SIB1 of neighbour cells
* meas_cells[i]->plmn_equals(selected_plmn_id) && */
@ -598,7 +598,7 @@ proc_outcome_t rrc::cell_selection_proc::react(const bool& cell_selection_result
return start_next_cell_selection();
}
srslte::proc_outcome_t rrc::cell_selection_proc::start_phy_cell_selection(const meas_cell& cell)
srslte::proc_outcome_t rrc::cell_selection_proc::start_phy_cell_selection(const meas_cell_eutra& cell)
{
if (not is_same_cell(cell, meas_cells->serving_cell())) {
rrc_ptr->set_serving_cell(cell.phy_cell, discard_serving);
@ -1547,7 +1547,7 @@ srslte::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc
: rrc_ptr->meas_cells.serving_cell().get_earfcn();
// Target cell shall be either serving cell (intra-cell HO) or neighbour cell
meas_cell* cell_to_ho = rrc_ptr->meas_cells.find_cell(target_earfcn, mob_ctrl_info->target_pci);
meas_cell_eutra* cell_to_ho = rrc_ptr->meas_cells.find_cell(target_earfcn, mob_ctrl_info->target_pci);
if (cell_to_ho != nullptr) {
target_cell = cell_to_ho->phy_cell;
} else {

View File

@ -8,18 +8,26 @@
set(SOURCES ttcn3_ue.cc ttcn3_syssim.cc)
add_executable(ttcn3_dut ttcn3_dut.cc lte_ttcn3_phy.cc ${SOURCES})
target_link_libraries(ttcn3_dut srsue_stack
srsue_upper
srsue_rrc
srslte_upper
srslte_common
srslte_mac
srslte_phy
srslte_radio
srslte_upper
srsue_phy
srsue_mac
rrc_asn1
sctp
${Boost_LIBRARIES})
set(LINK_LIBRARIES srsue_stack
srsue_upper
srsue_rrc
srslte_upper
srslte_common
srslte_mac
srslte_phy
srslte_radio
srslte_upper
srsue_phy
srsue_mac
rrc_asn1
sctp
${Boost_LIBRARIES})
if (ENABLE_5GNR)
set(LINK_LIBRARIES ${LINK_LIBRARIES} rrc_nr_asn1)
endif (ENABLE_5GNR)
target_link_libraries(ttcn3_dut ${LINK_LIBRARIES})
include_directories(${PROJECT_SOURCE_DIR}/srsue/test/ttcn3/hdr)

View File

@ -20,7 +20,11 @@ target_link_libraries(rrc_reconfig_test srsue_upper srslte_upper srslte_phy rrc_
add_test(rrc_reconfig_test rrc_reconfig_test)
add_executable(rrc_meas_test rrc_meas_test.cc)
target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srslte_upper srslte_phy rrc_asn1)
if (ENABLE_5GNR)
target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srslte_upper srslte_phy rrc_asn1 rrc_nr_asn1)
else (ENABLE_5GNR)
target_link_libraries(rrc_meas_test srsue_rrc srsue_upper srslte_upper srslte_phy rrc_asn1)
endif(ENABLE_5GNR)
add_test(rrc_meas_test rrc_meas_test)
add_executable(nas_test nas_test.cc)
@ -36,7 +40,11 @@ target_link_libraries(rrc_phy_ctrl_test srslte_common srsue_rrc)
add_test(rrc_phy_ctrl_test rrc_phy_ctrl_test)
add_executable(rrc_cell_test rrc_cell_test.cc)
target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srslte_upper srslte_phy rrc_asn1)
if (ENABLE_5GNR)
target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srslte_upper srslte_phy rrc_asn1 rrc_nr_asn1)
else (ENABLE_5GNR)
target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srslte_upper srslte_phy rrc_asn1)
endif(ENABLE_5GNR)
add_test(rrc_cell_test rrc_cell_test)
########################################################################

View File

@ -18,7 +18,7 @@ using namespace srsue;
int test_meas_cell()
{
srslte::task_scheduler task_sched;
meas_cell invalid_cell{task_sched.get_unique_timer()}, cell{phy_cell_t{1, 3400}, task_sched.get_unique_timer()};
meas_cell_eutra invalid_cell{task_sched.get_unique_timer()}, cell{phy_cell_t{1, 3400}, task_sched.get_unique_timer()};
TESTASSERT(not invalid_cell.is_valid());
TESTASSERT(cell.is_valid());
@ -33,13 +33,13 @@ int test_meas_cell()
TESTASSERT(cell.get_rsrp() == -50);
// Test meas timer expiry
for (size_t i = 0; i < meas_cell::neighbour_timeout_ms; ++i) {
for (size_t i = 0; i < meas_cell_eutra::neighbour_timeout_ms; ++i) {
TESTASSERT(not cell.timer.is_expired());
task_sched.tic();
}
TESTASSERT(cell.timer.is_expired());
cell.set_rsrp(-20);
for (size_t i = 0; i < meas_cell::neighbour_timeout_ms; ++i) {
for (size_t i = 0; i < meas_cell_eutra::neighbour_timeout_ms; ++i) {
TESTASSERT(not cell.timer.is_expired());
task_sched.tic();
}
@ -50,8 +50,8 @@ int test_meas_cell()
int test_add_neighbours()
{
srslte::task_scheduler task_sched;
meas_cell_list list{&task_sched};
srslte::task_scheduler task_sched;
meas_cell_list<meas_cell_eutra> list{&task_sched};
TESTASSERT(list.nof_neighbours() == 0);
TESTASSERT(not list.serving_cell().is_valid());
TESTASSERT(list.get_neighbour_cell_handle(0, 0) == nullptr);
@ -65,7 +65,7 @@ int test_add_neighbours()
TESTASSERT(list.add_meas_cell(pmeas));
TESTASSERT(not list.serving_cell().is_valid());
TESTASSERT(list.nof_neighbours() == 1);
meas_cell* c = list.get_neighbour_cell_handle(3400, 1);
meas_cell_eutra* c = list.get_neighbour_cell_handle(3400, 1);
TESTASSERT(c != nullptr and c->is_valid() and c->equals(3400, 1));
TESTASSERT(c->get_rsrp() == pmeas.rsrp and c->get_rsrq() == pmeas.rsrq);
@ -91,7 +91,7 @@ int test_add_neighbours()
task_sched.tic();
task_sched.tic();
list.get_neighbour_cell_handle(3400, 1)->set_rsrp(-20);
for (size_t i = 0; i < meas_cell::neighbour_timeout_ms; ++i) {
for (size_t i = 0; i < meas_cell_eutra::neighbour_timeout_ms; ++i) {
TESTASSERT(list.nof_neighbours() == 1);
list.clean_neighbours();
task_sched.tic();