mirror of https://github.com/pvnis/srsRAN_4G.git
move rrc measconfig handling functions to separate file. Update measconfig tests
parent
1cb65f07f1
commit
25bfb6d84d
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_UE_MEAS_CFG_H
|
||||||
|
#define SRSLTE_UE_MEAS_CFG_H
|
||||||
|
|
||||||
|
#include "srslte/asn1/rrc/meascfg.h"
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
|
||||||
|
// fwd declarations
|
||||||
|
struct rrc_cfg_t;
|
||||||
|
struct meas_cell_cfg_t;
|
||||||
|
class cell_ctxt_dedicated_list;
|
||||||
|
|
||||||
|
using meas_obj_t = asn1::rrc::meas_obj_to_add_mod_s;
|
||||||
|
using meas_obj_list = asn1::rrc::meas_obj_to_add_mod_list_l;
|
||||||
|
using meas_cell_t = asn1::rrc::cells_to_add_mod_s;
|
||||||
|
using report_cfg_t = asn1::rrc::report_cfg_to_add_mod_s;
|
||||||
|
using report_cfg_list = asn1::rrc::report_cfg_to_add_mod_list_l;
|
||||||
|
using meas_id_t = asn1::rrc::meas_id_to_add_mod_s;
|
||||||
|
using meas_id_list = asn1::rrc::meas_id_to_add_mod_list_l;
|
||||||
|
|
||||||
|
int get_earfcn(const meas_obj_t& obj);
|
||||||
|
bool is_same_earfcn(const meas_obj_t& lhs, const meas_obj_t& rhs);
|
||||||
|
|
||||||
|
/// Find MeasObj with same earfcn. Assumes ordered list
|
||||||
|
meas_obj_t* find_meas_obj(meas_obj_list& l, uint32_t earfcn);
|
||||||
|
const meas_obj_t* find_meas_obj(const meas_obj_list& l, uint32_t earfcn);
|
||||||
|
|
||||||
|
/// Add EARFCN to the MeasObjToAddModList
|
||||||
|
std::pair<bool, meas_obj_t*> add_meas_obj(meas_obj_list& list, uint32_t dl_earfcn);
|
||||||
|
|
||||||
|
std::tuple<bool, meas_obj_t*, meas_cell_t*> add_cell_enb_cfg(meas_obj_list& meas_obj_list,
|
||||||
|
const meas_cell_cfg_t& cellcfg);
|
||||||
|
|
||||||
|
report_cfg_t* add_report_cfg(report_cfg_list& list, const asn1::rrc::report_cfg_eutra_s& reportcfg);
|
||||||
|
|
||||||
|
meas_id_t* add_measid_cfg(meas_id_list& meas_id_list, uint8_t measobjid, uint8_t measrepid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a cell in meas_obj_list based on pci and earfcn
|
||||||
|
* @return pair of (meas_obj,cell_obj). If no cell has frequency==earfcn, meas_obj=nullptr
|
||||||
|
*/
|
||||||
|
std::pair<meas_obj_t*, meas_cell_t*> find_cell(meas_obj_list& l, uint32_t earfcn, uint32_t pci);
|
||||||
|
|
||||||
|
bool compute_diff_meascfg(const asn1::rrc::meas_cfg_s& current_meascfg,
|
||||||
|
const asn1::rrc::meas_cfg_s& target_meascfg,
|
||||||
|
asn1::rrc::meas_cfg_s& diff_meascfg);
|
||||||
|
|
||||||
|
bool fill_meascfg_enb_cfg(asn1::rrc::meas_cfg_s& meascfg, const cell_ctxt_dedicated_list& ue_cell_list);
|
||||||
|
|
||||||
|
bool apply_meascfg_updates(asn1::rrc::meas_cfg_s& meascfg,
|
||||||
|
asn1::rrc::meas_cfg_s& current_meascfg,
|
||||||
|
const cell_ctxt_dedicated_list& ue_cell_list,
|
||||||
|
int prev_pci = -1);
|
||||||
|
|
||||||
|
} // namespace srsenb
|
||||||
|
|
||||||
|
#endif // SRSLTE_UE_MEAS_CFG_H
|
@ -0,0 +1,436 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsenb/hdr/stack/rrc/ue_meas_cfg.h"
|
||||||
|
#include "srsenb/hdr/stack/rrc/rrc_cell_cfg.h"
|
||||||
|
#include "srslte/rrc/rrc_cfg_utils.h"
|
||||||
|
|
||||||
|
using namespace asn1::rrc;
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* measObjToAddMod
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
int get_earfcn(const meas_obj_t& obj)
|
||||||
|
{
|
||||||
|
if (obj.meas_obj.type().value != meas_obj_t::meas_obj_c_::types_opts::meas_obj_eutra) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return obj.meas_obj.meas_obj_eutra().carrier_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_same_earfcn(const meas_obj_t& lhs, const meas_obj_t& rhs)
|
||||||
|
{
|
||||||
|
int freq1 = get_earfcn(lhs);
|
||||||
|
int freq2 = get_earfcn(rhs);
|
||||||
|
return freq1 != -1 and freq1 == freq2;
|
||||||
|
}
|
||||||
|
|
||||||
|
meas_obj_t* find_meas_obj(meas_obj_to_add_mod_list_l& l, uint32_t earfcn)
|
||||||
|
{
|
||||||
|
auto same_earfcn = [earfcn](const meas_obj_t& obj) { return (int)earfcn == get_earfcn(obj); };
|
||||||
|
auto it = std::find_if(l.begin(), l.end(), same_earfcn);
|
||||||
|
return it == l.end() ? nullptr : &(*it);
|
||||||
|
}
|
||||||
|
const meas_obj_t* find_meas_obj(const meas_obj_to_add_mod_list_l& l, uint32_t earfcn)
|
||||||
|
{
|
||||||
|
auto same_earfcn = [earfcn](const meas_obj_t& obj) { return (int)earfcn == get_earfcn(obj); };
|
||||||
|
auto it = std::find_if(l.begin(), l.end(), same_earfcn);
|
||||||
|
return it == l.end() ? nullptr : &(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<meas_obj_t*, cells_to_add_mod_s*> find_cell(meas_obj_to_add_mod_list_l& l, uint32_t earfcn, uint32_t pci)
|
||||||
|
{
|
||||||
|
// find meas_obj with same earfcn
|
||||||
|
meas_obj_t* obj = find_meas_obj(l, earfcn);
|
||||||
|
if (obj == nullptr) {
|
||||||
|
return std::make_pair(obj, (cells_to_add_mod_s*)nullptr);
|
||||||
|
}
|
||||||
|
// find cell with same id
|
||||||
|
auto& cells = obj->meas_obj.meas_obj_eutra().cells_to_add_mod_list;
|
||||||
|
auto cell_it = std::find_if(cells.begin(), cells.end(), [pci](const cells_to_add_mod_s& c) { return c.pci == pci; });
|
||||||
|
if (cell_it == cells.end()) {
|
||||||
|
cell_it = nullptr;
|
||||||
|
}
|
||||||
|
return std::make_pair(obj, cell_it);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add EARFCN to the MeasObjToAddModList
|
||||||
|
std::pair<bool, meas_obj_t*> add_meas_obj(meas_obj_list& list, uint32_t dl_earfcn)
|
||||||
|
{
|
||||||
|
meas_obj_t* obj = find_meas_obj(list, dl_earfcn);
|
||||||
|
if (obj != nullptr) {
|
||||||
|
return {false, obj};
|
||||||
|
}
|
||||||
|
|
||||||
|
meas_obj_t new_obj;
|
||||||
|
new_obj.meas_obj_id = srslte::find_rrc_obj_id_gap(list);
|
||||||
|
asn1::rrc::meas_obj_eutra_s& eutra = new_obj.meas_obj.set_meas_obj_eutra();
|
||||||
|
eutra.carrier_freq = dl_earfcn;
|
||||||
|
eutra.allowed_meas_bw.value = asn1::rrc::allowed_meas_bw_e::mbw6; // TODO: What value to add here?
|
||||||
|
eutra.neigh_cell_cfg.from_number(1); // No MBSFN subframes present in neighbors
|
||||||
|
eutra.offset_freq_present = false; // no offset
|
||||||
|
obj = srslte::add_rrc_obj(list, new_obj);
|
||||||
|
return {true, obj};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add cell parsed in configuration file to the varMeasCfg
|
||||||
|
std::tuple<bool, meas_obj_t*, cells_to_add_mod_s*> add_cell_enb_cfg(meas_obj_list& meas_obj_list,
|
||||||
|
const meas_cell_cfg_t& cellcfg)
|
||||||
|
{
|
||||||
|
bool inserted_flag = true;
|
||||||
|
|
||||||
|
cells_to_add_mod_s new_cell;
|
||||||
|
asn1::number_to_enum(new_cell.cell_individual_offset, (uint8_t)cellcfg.q_offset);
|
||||||
|
new_cell.pci = cellcfg.pci;
|
||||||
|
|
||||||
|
std::pair<meas_obj_t*, meas_cell_t*> ret = find_cell(meas_obj_list, cellcfg.earfcn, cellcfg.pci);
|
||||||
|
|
||||||
|
if (ret.first != nullptr) {
|
||||||
|
// there are cells with the same earfcn at least.
|
||||||
|
if (ret.second != nullptr) {
|
||||||
|
// the cell already existed.
|
||||||
|
if (ret.second->cell_individual_offset != new_cell.cell_individual_offset) {
|
||||||
|
// members of cell were updated
|
||||||
|
new_cell.cell_idx = ret.second->cell_idx;
|
||||||
|
*ret.second = new_cell;
|
||||||
|
} else {
|
||||||
|
inserted_flag = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto& eutra_obj = ret.first->meas_obj.meas_obj_eutra();
|
||||||
|
// pci not found. create new cell
|
||||||
|
new_cell.cell_idx = srslte::find_rrc_obj_id_gap(eutra_obj.cells_to_add_mod_list);
|
||||||
|
ret.second = srslte::add_rrc_obj(eutra_obj.cells_to_add_mod_list, new_cell);
|
||||||
|
eutra_obj.cells_to_add_mod_list_present = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// no measobj has been found with same earfcn, create a new one
|
||||||
|
auto ret2 = add_meas_obj(meas_obj_list, cellcfg.earfcn);
|
||||||
|
ret.first = ret2.second;
|
||||||
|
|
||||||
|
new_cell.cell_idx = 1;
|
||||||
|
auto& eutra = ret2.second->meas_obj.meas_obj_eutra();
|
||||||
|
eutra.cells_to_add_mod_list_present = true;
|
||||||
|
eutra.cells_to_add_mod_list.push_back(new_cell);
|
||||||
|
ret.second = &ret.first->meas_obj.meas_obj_eutra().cells_to_add_mod_list.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_tuple(inserted_flag, ret.first, ret.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TS 36.331 - Section 5.5.2.5
|
||||||
|
* Description: Adds MeasObjtoAddMod to MeasCfg object
|
||||||
|
*/
|
||||||
|
meas_obj_to_add_mod_s* meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj)
|
||||||
|
{
|
||||||
|
meas_cfg->meas_obj_to_add_mod_list_present = true;
|
||||||
|
|
||||||
|
// search for meas_obj by obj_id to ensure uniqueness (assume sorted)
|
||||||
|
auto meas_obj_it = srslte::add_rrc_obj_id(meas_cfg->meas_obj_to_add_mod_list, meas_obj.meas_obj_id);
|
||||||
|
// TODO: Assert dl_earfcn is the same
|
||||||
|
|
||||||
|
auto& target_eutra = meas_obj_it->meas_obj.set_meas_obj_eutra();
|
||||||
|
auto& src_eutra = meas_obj.meas_obj.meas_obj_eutra();
|
||||||
|
target_eutra.carrier_freq = src_eutra.carrier_freq;
|
||||||
|
target_eutra.offset_freq_present = src_eutra.offset_freq_present;
|
||||||
|
target_eutra.offset_freq = src_eutra.offset_freq;
|
||||||
|
target_eutra.allowed_meas_bw = src_eutra.allowed_meas_bw;
|
||||||
|
target_eutra.presence_ant_port1 = src_eutra.presence_ant_port1;
|
||||||
|
target_eutra.neigh_cell_cfg = src_eutra.neigh_cell_cfg;
|
||||||
|
// do not add cellsToAddModList, blackCells, whiteCells, etc. according to (5.5.2.5 1|1|1)
|
||||||
|
|
||||||
|
return meas_obj_it;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// adds all the cells that got updated to MeasCfg.
|
||||||
|
void compute_diff_cells(const meas_obj_eutra_s& src_it,
|
||||||
|
const meas_obj_eutra_s& target_it,
|
||||||
|
meas_obj_to_add_mod_s* added_obj)
|
||||||
|
{
|
||||||
|
meas_obj_eutra_s* eutra_obj = &added_obj->meas_obj.meas_obj_eutra();
|
||||||
|
srslte::compute_cfg_diff(src_it.cells_to_add_mod_list,
|
||||||
|
target_it.cells_to_add_mod_list,
|
||||||
|
eutra_obj->cells_to_add_mod_list,
|
||||||
|
eutra_obj->cells_to_rem_list);
|
||||||
|
eutra_obj->cells_to_add_mod_list_present = eutra_obj->cells_to_add_mod_list.size() > 0;
|
||||||
|
eutra_obj->cells_to_rem_list_present = eutra_obj->cells_to_rem_list.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Section 5.5.2.4/5, Measurement Object removal and addition/modification
|
||||||
|
* Description: compute diff between target_cfg and var_meas -> depending on diff, add/remove/update meas_obj in
|
||||||
|
* meas_cfg
|
||||||
|
*/
|
||||||
|
void compute_diff_meas_objs(const meas_cfg_s& prev_cfg, const meas_cfg_s& target_cfg, meas_cfg_s& meas_cfg)
|
||||||
|
{
|
||||||
|
auto rem_func = [&meas_cfg](const meas_obj_t* it) { meas_cfg.meas_obj_to_rem_list.push_back(it->meas_obj_id); };
|
||||||
|
auto add_func = [&meas_cfg](const meas_obj_t* it) { meas_cfg.meas_obj_to_add_mod_list.push_back(*it); };
|
||||||
|
auto mod_func = [&meas_cfg](const meas_obj_t* src_it, const meas_obj_t* target_it) {
|
||||||
|
if (*src_it != *target_it) {
|
||||||
|
meas_obj_t* added_obj = meascfg_add_meas_obj(&meas_cfg, *target_it);
|
||||||
|
// Add cells if there were changes.
|
||||||
|
compute_diff_cells(src_it->meas_obj.meas_obj_eutra(), target_it->meas_obj.meas_obj_eutra(), added_obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
srslte::compute_cfg_diff(
|
||||||
|
prev_cfg.meas_obj_to_add_mod_list, target_cfg.meas_obj_to_add_mod_list, rem_func, add_func, mod_func);
|
||||||
|
meas_cfg.meas_obj_to_add_mod_list_present = meas_cfg.meas_obj_to_add_mod_list.size() > 0;
|
||||||
|
meas_cfg.meas_obj_to_rem_list_present = meas_cfg.meas_obj_to_rem_list.size() > 0;
|
||||||
|
// TODO: black cells and white cells
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* reportToAddModList
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
report_cfg_to_add_mod_s* add_report_cfg(report_cfg_list& list, const report_cfg_eutra_s& reportcfg)
|
||||||
|
{
|
||||||
|
report_cfg_to_add_mod_s new_rep;
|
||||||
|
new_rep.report_cfg_id = srslte::find_rrc_obj_id_gap(list);
|
||||||
|
new_rep.report_cfg.set_report_cfg_eutra() = reportcfg;
|
||||||
|
|
||||||
|
return srslte::add_rrc_obj(list, new_rep);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TS 36.331 - Section 5.5.2.6/7 - Reporting configuration removal and addition/modification
|
||||||
|
*/
|
||||||
|
void compute_diff_report_cfgs(const meas_cfg_s& src_cfg, const meas_cfg_s& target_cfg, meas_cfg_s& meas_cfg)
|
||||||
|
{
|
||||||
|
srslte::compute_cfg_diff(src_cfg.report_cfg_to_add_mod_list,
|
||||||
|
target_cfg.report_cfg_to_add_mod_list,
|
||||||
|
meas_cfg.report_cfg_to_add_mod_list,
|
||||||
|
meas_cfg.report_cfg_to_rem_list);
|
||||||
|
meas_cfg.report_cfg_to_add_mod_list_present = meas_cfg.report_cfg_to_add_mod_list.size() > 0;
|
||||||
|
meas_cfg.report_cfg_to_rem_list_present = meas_cfg.report_cfg_to_rem_list.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
meas_id_to_add_mod_s* add_measid_cfg(meas_id_to_add_mod_list_l& meas_id_list, uint8_t measobjid, uint8_t measrepid)
|
||||||
|
{
|
||||||
|
meas_id_to_add_mod_s new_measid;
|
||||||
|
new_measid.report_cfg_id = measrepid;
|
||||||
|
new_measid.meas_obj_id = measobjid;
|
||||||
|
new_measid.meas_id = srslte::find_rrc_obj_id_gap(meas_id_list);
|
||||||
|
return srslte::add_rrc_obj(meas_id_list, new_measid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_diff_meas_ids(const meas_cfg_s& src_cfg, const meas_cfg_s& target_cfg, meas_cfg_s& meas_cfg)
|
||||||
|
{
|
||||||
|
srslte::compute_cfg_diff(src_cfg.meas_id_to_add_mod_list,
|
||||||
|
target_cfg.meas_id_to_add_mod_list,
|
||||||
|
meas_cfg.meas_id_to_add_mod_list,
|
||||||
|
meas_cfg.meas_id_to_rem_list);
|
||||||
|
meas_cfg.meas_id_to_add_mod_list_present = meas_cfg.meas_id_to_add_mod_list.size() > 0;
|
||||||
|
meas_cfg.meas_id_to_rem_list_present = meas_cfg.meas_id_to_rem_list.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
meas_gap_cfg_c make_measgap(const meas_obj_list& measobjs, const cell_ctxt_dedicated& pcell)
|
||||||
|
{
|
||||||
|
meas_gap_cfg_c meas_gap;
|
||||||
|
if (measobjs.size() == 1) {
|
||||||
|
// only add measGaps if PCell is not the only frequency to measure
|
||||||
|
return meas_gap;
|
||||||
|
}
|
||||||
|
switch (pcell.cell_common->cell_cfg.meas_cfg.meas_gap_period) {
|
||||||
|
case 40:
|
||||||
|
meas_gap.set_setup().gap_offset.set_gp0() = pcell.meas_gap_offset;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
meas_gap.set_setup().gap_offset.set_gp1() = pcell.meas_gap_offset;
|
||||||
|
break;
|
||||||
|
case 0: // no meas gaps configured
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
srslte::logmap::get("RRC")->error("Error setting measurement gap.\n");
|
||||||
|
}
|
||||||
|
return meas_gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* measConfig
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
bool set_meascfg_presence_flags(meas_cfg_s& meascfg)
|
||||||
|
{
|
||||||
|
meascfg.meas_obj_to_add_mod_list_present = meascfg.meas_obj_to_add_mod_list.size() > 0;
|
||||||
|
meascfg.meas_obj_to_rem_list_present = meascfg.meas_obj_to_rem_list.size() > 0;
|
||||||
|
meascfg.report_cfg_to_add_mod_list_present = meascfg.report_cfg_to_add_mod_list.size() > 0;
|
||||||
|
meascfg.report_cfg_to_rem_list_present = meascfg.report_cfg_to_rem_list.size() > 0;
|
||||||
|
meascfg.meas_id_to_add_mod_list_present = meascfg.meas_id_to_add_mod_list.size() > 0;
|
||||||
|
meascfg.meas_id_to_rem_list_present = meascfg.meas_id_to_rem_list.size() > 0;
|
||||||
|
meascfg.quant_cfg_present = meascfg.quant_cfg.quant_cfg_eutra_present;
|
||||||
|
meascfg.meas_gap_cfg_present = meascfg.meas_gap_cfg.type().value != setup_opts::nulltype;
|
||||||
|
|
||||||
|
return meascfg.meas_obj_to_add_mod_list_present or meascfg.meas_obj_to_rem_list_present or
|
||||||
|
meascfg.report_cfg_to_add_mod_list_present or meascfg.report_cfg_to_rem_list_present or
|
||||||
|
meascfg.meas_id_to_add_mod_list_present or meascfg.meas_id_to_rem_list_present or meascfg.quant_cfg_present or
|
||||||
|
meascfg.meas_gap_cfg_present;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fill_meascfg_enb_cfg(meas_cfg_s& meascfg, const cell_ctxt_dedicated_list& ue_cell_list)
|
||||||
|
{
|
||||||
|
const cell_ctxt_dedicated* pcell = ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
|
||||||
|
assert(pcell != nullptr);
|
||||||
|
const cell_info_common* pcell_cfg = pcell->cell_common;
|
||||||
|
const auto& pcell_meascfg = pcell_cfg->cell_cfg.meas_cfg;
|
||||||
|
|
||||||
|
// Add PCell+Scells to measObjToAddModList
|
||||||
|
for (uint32_t ue_cc_idx = 0; ue_cc_idx < ue_cell_list.nof_cells(); ++ue_cc_idx) {
|
||||||
|
const auto* cell = ue_cell_list.get_ue_cc_idx(ue_cc_idx);
|
||||||
|
add_meas_obj(meascfg.meas_obj_to_add_mod_list, cell->get_dl_earfcn());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inserts all cells in meas_cell_list that are not PCell or SCells
|
||||||
|
for (const meas_cell_cfg_t& meascell : pcell_meascfg.meas_cells) {
|
||||||
|
if (ue_cell_list.find_cell(meascell.earfcn, meascell.pci) == nullptr) {
|
||||||
|
add_cell_enb_cfg(meascfg.meas_obj_to_add_mod_list, meascell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert report cfg of PCell
|
||||||
|
for (const report_cfg_eutra_s& reportcfg : pcell_meascfg.meas_reports) {
|
||||||
|
add_report_cfg(meascfg.report_cfg_to_add_mod_list, reportcfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert quantity config
|
||||||
|
meascfg.quant_cfg.quant_cfg_eutra_present = true;
|
||||||
|
meascfg.quant_cfg.quant_cfg_eutra = pcell_meascfg.quant_cfg;
|
||||||
|
|
||||||
|
// Insert all measIds
|
||||||
|
// TODO: add this to the parser
|
||||||
|
if (meascfg.report_cfg_to_add_mod_list.size() > 0) {
|
||||||
|
for (const auto& measobj : meascfg.meas_obj_to_add_mod_list) {
|
||||||
|
add_measid_cfg(
|
||||||
|
meascfg.meas_id_to_add_mod_list, measobj.meas_obj_id, meascfg.report_cfg_to_add_mod_list[0].report_cfg_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set MeasGap
|
||||||
|
meascfg.meas_gap_cfg = make_measgap(meascfg.meas_obj_to_add_mod_list, *pcell);
|
||||||
|
|
||||||
|
return set_meascfg_presence_flags(meascfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compute_diff_meascfg(const meas_cfg_s& current_meascfg, const meas_cfg_s& target_meascfg, meas_cfg_s& diff_meascfg)
|
||||||
|
{
|
||||||
|
diff_meascfg = {};
|
||||||
|
compute_diff_meas_objs(current_meascfg, target_meascfg, diff_meascfg);
|
||||||
|
compute_diff_report_cfgs(current_meascfg, target_meascfg, diff_meascfg);
|
||||||
|
compute_diff_meas_ids(current_meascfg, target_meascfg, diff_meascfg);
|
||||||
|
if (target_meascfg.quant_cfg_present != current_meascfg.quant_cfg_present or
|
||||||
|
(target_meascfg.quant_cfg_present and target_meascfg.quant_cfg != current_meascfg.quant_cfg)) {
|
||||||
|
diff_meascfg.quant_cfg = target_meascfg.quant_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update measGap if it was not set before or periodicity changed
|
||||||
|
if (current_meascfg.meas_gap_cfg.type().value == setup_opts::setup) {
|
||||||
|
if (target_meascfg.meas_gap_cfg.type().value != setup_opts::setup) {
|
||||||
|
diff_meascfg.meas_gap_cfg.set(setup_opts::release);
|
||||||
|
} else if (target_meascfg.meas_gap_cfg.setup().gap_offset.type() !=
|
||||||
|
current_meascfg.meas_gap_cfg.setup().gap_offset.type()) {
|
||||||
|
diff_meascfg.meas_gap_cfg = target_meascfg.meas_gap_cfg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
diff_meascfg.meas_gap_cfg = target_meascfg.meas_gap_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_meascfg_presence_flags(diff_meascfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool apply_meascfg_updates(meas_cfg_s& meascfg,
|
||||||
|
meas_cfg_s& current_meascfg,
|
||||||
|
const cell_ctxt_dedicated_list& ue_cell_list,
|
||||||
|
int prev_pci)
|
||||||
|
{
|
||||||
|
meascfg = {};
|
||||||
|
|
||||||
|
const cell_ctxt_dedicated* pcell = ue_cell_list.get_ue_cc_idx(UE_PCELL_CC_IDX);
|
||||||
|
uint32_t prev_earfcn = 0, target_earfcn = pcell->get_dl_earfcn();
|
||||||
|
if (current_meascfg.meas_obj_to_add_mod_list_present) {
|
||||||
|
prev_earfcn = get_earfcn(current_meascfg.meas_obj_to_add_mod_list[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<uint32_t>(prev_pci) == pcell->get_pci() and prev_earfcn == target_earfcn) {
|
||||||
|
// Shortcut: No PCell change -> no measConfig updates
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply TS 36.331 5.5.6.1 - If Source and Target eNB EARFCNs do no match, update SourceMeasCfg.MeasIdList
|
||||||
|
if (prev_earfcn != target_earfcn) {
|
||||||
|
meas_obj_t* found_target_obj = find_meas_obj(current_meascfg.meas_obj_to_add_mod_list, target_earfcn);
|
||||||
|
meas_obj_t* found_src_obj = prev_earfcn != 0 ? ¤t_meascfg.meas_obj_to_add_mod_list[0] : nullptr;
|
||||||
|
if (found_target_obj != nullptr and found_src_obj != nullptr) {
|
||||||
|
for (auto& mid : current_meascfg.meas_id_to_add_mod_list) {
|
||||||
|
if (found_target_obj->meas_obj_id == mid.meas_obj_id) {
|
||||||
|
mid.meas_obj_id = found_src_obj->meas_obj_id;
|
||||||
|
} else if (found_src_obj->meas_obj_id == mid.meas_obj_id) {
|
||||||
|
mid.meas_obj_id = found_target_obj->meas_obj_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (found_src_obj != nullptr) {
|
||||||
|
for (auto it = current_meascfg.meas_id_to_add_mod_list.begin();
|
||||||
|
it != current_meascfg.meas_id_to_add_mod_list.end();) {
|
||||||
|
if (it->meas_obj_id == found_src_obj->meas_obj_id) {
|
||||||
|
auto rit = it++;
|
||||||
|
current_meascfg.meas_id_to_add_mod_list.erase(rit);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate final measConfig
|
||||||
|
meas_cfg_s target_meascfg;
|
||||||
|
fill_meascfg_enb_cfg(target_meascfg, ue_cell_list);
|
||||||
|
|
||||||
|
// Set a MeasConfig in the RRC Connection Reconfiguration for HO.
|
||||||
|
compute_diff_meas_objs(current_meascfg, target_meascfg, meascfg);
|
||||||
|
compute_diff_report_cfgs(current_meascfg, target_meascfg, meascfg);
|
||||||
|
compute_diff_meas_ids(current_meascfg, target_meascfg, meascfg);
|
||||||
|
if (target_meascfg.quant_cfg_present != current_meascfg.quant_cfg_present or
|
||||||
|
(target_meascfg.quant_cfg_present and target_meascfg.quant_cfg != current_meascfg.quant_cfg)) {
|
||||||
|
meascfg.quant_cfg = target_meascfg.quant_cfg;
|
||||||
|
}
|
||||||
|
// Only update measGap if it was not set before or periodicity changed
|
||||||
|
if (current_meascfg.meas_gap_cfg.type().value == setup_opts::setup) {
|
||||||
|
if (target_meascfg.meas_gap_cfg.type().value != setup_opts::setup) {
|
||||||
|
meascfg.meas_gap_cfg.set(setup_opts::release);
|
||||||
|
} else if (target_meascfg.meas_gap_cfg.setup().gap_offset.type() !=
|
||||||
|
current_meascfg.meas_gap_cfg.setup().gap_offset.type()) {
|
||||||
|
meascfg.meas_gap_cfg = target_meascfg.meas_gap_cfg;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
meascfg.meas_gap_cfg = target_meascfg.meas_gap_cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update current measconfig
|
||||||
|
bool ret = set_meascfg_presence_flags(meascfg);
|
||||||
|
current_meascfg = target_meascfg;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsenb
|
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsenb/hdr/enb.h"
|
||||||
|
#include "srsenb/hdr/stack/rrc/ue_meas_cfg.h"
|
||||||
|
#include "srslte/common/test_common.h"
|
||||||
|
#include "srslte/interfaces/enb_rrc_interface_types.h"
|
||||||
|
#include "test_helpers.h"
|
||||||
|
|
||||||
|
using namespace asn1::rrc;
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if measObjs and reportConfigs are correctly added to the ASN1 RRC measConfig. Current checks:
|
||||||
|
* - avoids repeated earfcns in the measObjsToAddModList
|
||||||
|
* - avoids repeated PCIs in the CellsToAddModList of same earfcn
|
||||||
|
* - measObjId, cellIdx, reportConfigId, measId are kept in order
|
||||||
|
* @return error code
|
||||||
|
*/
|
||||||
|
int test_correct_meascfg_insertion()
|
||||||
|
{
|
||||||
|
meas_cell_cfg_t cell1 = generate_cell1(), cell2{}, cell3{}, cell4{};
|
||||||
|
cell2 = cell1;
|
||||||
|
cell2.pci = 2;
|
||||||
|
cell2.eci = 0x19C02;
|
||||||
|
cell3 = cell1;
|
||||||
|
cell3.earfcn = 2850;
|
||||||
|
cell4 = cell1;
|
||||||
|
cell4.q_offset = 1;
|
||||||
|
|
||||||
|
report_cfg_eutra_s rep1 = generate_rep1();
|
||||||
|
|
||||||
|
// TEST 1: cell/rep insertion in empty MeasCfg
|
||||||
|
{
|
||||||
|
meas_cfg_s meas_cfg{};
|
||||||
|
const auto& objs = meas_cfg.meas_obj_to_add_mod_list;
|
||||||
|
auto ret = add_cell_enb_cfg(meas_cfg.meas_obj_to_add_mod_list, cell1);
|
||||||
|
TESTASSERT(std::get<0>(ret) and std::get<1>(ret) != nullptr);
|
||||||
|
TESTASSERT(objs.size() == 1 and objs[0].meas_obj_id == 1);
|
||||||
|
TESTASSERT(objs[0].meas_obj.type().value ==
|
||||||
|
asn1::rrc::meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
|
||||||
|
auto& eutra = objs[0].meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(eutra.carrier_freq == cell1.earfcn);
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list.size() == 1);
|
||||||
|
TESTASSERT(is_cell_cfg_equal(cell1, eutra.cells_to_add_mod_list[0]));
|
||||||
|
|
||||||
|
auto* ret2 = add_report_cfg(meas_cfg.report_cfg_to_add_mod_list, rep1);
|
||||||
|
TESTASSERT(ret2->report_cfg_id == 1);
|
||||||
|
TESTASSERT(ret2->report_cfg.report_cfg_eutra() == rep1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
meas_cfg_s meas_cfg{};
|
||||||
|
const auto& objs = meas_cfg.meas_obj_to_add_mod_list;
|
||||||
|
|
||||||
|
// TEST 2: insertion of out-of-order cell ids in same earfcn
|
||||||
|
add_cell_enb_cfg(meas_cfg.meas_obj_to_add_mod_list, cell2);
|
||||||
|
add_cell_enb_cfg(meas_cfg.meas_obj_to_add_mod_list, cell1);
|
||||||
|
TESTASSERT(objs.size() == 1 and objs[0].meas_obj_id == 1);
|
||||||
|
auto& eutra = objs[0].meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(eutra.carrier_freq == cell1.earfcn);
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list.size() == 2);
|
||||||
|
const cells_to_add_mod_s* cell_it = eutra.cells_to_add_mod_list.begin();
|
||||||
|
TESTASSERT(cell_it[0].cell_idx == 1);
|
||||||
|
TESTASSERT(cell_it[1].cell_idx == 2);
|
||||||
|
TESTASSERT(cell_it[0].pci == cell2.pci);
|
||||||
|
TESTASSERT(cell_it[1].pci == cell1.pci);
|
||||||
|
|
||||||
|
// TEST 3: insertion of cell in another frequency
|
||||||
|
auto ret1 = add_cell_enb_cfg(meas_cfg.meas_obj_to_add_mod_list, cell3);
|
||||||
|
TESTASSERT(std::get<0>(ret1) and std::get<1>(ret1)->meas_obj_id == 2);
|
||||||
|
TESTASSERT(objs.size() == 2 and objs[1].meas_obj_id == 2);
|
||||||
|
const auto& eutra2 = objs[1].meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(eutra2.carrier_freq == cell3.earfcn);
|
||||||
|
TESTASSERT(eutra2.cells_to_add_mod_list_present and eutra2.cells_to_add_mod_list.size() == 1);
|
||||||
|
TESTASSERT(eutra2.cells_to_add_mod_list[0].cell_idx == 1);
|
||||||
|
TESTASSERT(eutra2.cells_to_add_mod_list[0].pci == cell3.pci);
|
||||||
|
|
||||||
|
// TEST 4 : update of existing cell
|
||||||
|
auto ret2 = add_cell_enb_cfg(meas_cfg.meas_obj_to_add_mod_list, cell4);
|
||||||
|
TESTASSERT(std::get<0>(ret2) and std::get<1>(ret2)->meas_obj_id == 1);
|
||||||
|
auto& eutra3 = objs[0].meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(objs.size() == 2 and objs[0].meas_obj_id == 1);
|
||||||
|
TESTASSERT(eutra3.carrier_freq == cell4.earfcn);
|
||||||
|
TESTASSERT(eutra3.cells_to_add_mod_list.size() == 2);
|
||||||
|
TESTASSERT(eutra3.cells_to_add_mod_list[1].cell_idx == 2);
|
||||||
|
TESTASSERT(eutra3.cells_to_add_mod_list[1].pci == cell4.pci);
|
||||||
|
TESTASSERT(eutra3.cells_to_add_mod_list[1].cell_individual_offset.to_number() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_correct_meascfg_calculation()
|
||||||
|
{
|
||||||
|
meas_cfg_s src_var{}, target_var{};
|
||||||
|
|
||||||
|
meas_cell_cfg_t cell1{}, cell2{};
|
||||||
|
cell1.earfcn = 3400;
|
||||||
|
cell1.pci = 1;
|
||||||
|
cell1.q_offset = 0;
|
||||||
|
cell1.eci = 0x19C01;
|
||||||
|
cell2 = cell1;
|
||||||
|
cell2.pci = 2;
|
||||||
|
cell2.eci = 0x19C02;
|
||||||
|
|
||||||
|
report_cfg_eutra_s rep1 = generate_rep1(), rep2{}, rep3{};
|
||||||
|
rep2 = rep1;
|
||||||
|
rep2.trigger_quant.value = report_cfg_eutra_s::trigger_quant_opts::rsrq;
|
||||||
|
rep3 = rep2;
|
||||||
|
rep3.report_quant.value = report_cfg_eutra_s::report_quant_opts::same_as_trigger_quant;
|
||||||
|
|
||||||
|
{
|
||||||
|
meas_cfg_s result_meascfg;
|
||||||
|
|
||||||
|
// TEST 1: Insertion of two cells in target meas_cfg_s propagates to the diff meas_cfg_s
|
||||||
|
add_cell_enb_cfg(target_var.meas_obj_to_add_mod_list, cell1);
|
||||||
|
add_cell_enb_cfg(target_var.meas_obj_to_add_mod_list, cell2);
|
||||||
|
add_report_cfg(target_var.report_cfg_to_add_mod_list, rep1);
|
||||||
|
add_report_cfg(target_var.report_cfg_to_add_mod_list, rep2);
|
||||||
|
add_measid_cfg(target_var.meas_id_to_add_mod_list, 1, 1);
|
||||||
|
add_measid_cfg(target_var.meas_id_to_add_mod_list, 1, 2);
|
||||||
|
TESTASSERT(compute_diff_meascfg(src_var, target_var, result_meascfg));
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present);
|
||||||
|
TESTASSERT(not result_meascfg.meas_obj_to_rem_list_present);
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1);
|
||||||
|
auto* item = &result_meascfg.meas_obj_to_add_mod_list[0];
|
||||||
|
TESTASSERT(item->meas_obj_id == 1 and
|
||||||
|
item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
|
||||||
|
auto& eutra = item->meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list_present and not eutra.cells_to_rem_list_present);
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list.size() == 2);
|
||||||
|
auto* cell_item = &eutra.cells_to_add_mod_list[0];
|
||||||
|
TESTASSERT(is_cell_cfg_equal(cell1, *cell_item));
|
||||||
|
cell_item++;
|
||||||
|
TESTASSERT(is_cell_cfg_equal(cell2, *cell_item));
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list_present and not result_meascfg.report_cfg_to_rem_list_present);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 2);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg_id == 1);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg.report_cfg_eutra() == rep1);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[1].report_cfg_id == 2);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[1].report_cfg.report_cfg_eutra() == rep2);
|
||||||
|
TESTASSERT(result_meascfg.meas_id_to_add_mod_list_present and not result_meascfg.meas_id_to_rem_list_present);
|
||||||
|
TESTASSERT(result_meascfg.meas_id_to_add_mod_list.size() == 2);
|
||||||
|
auto* measid_item = &result_meascfg.meas_id_to_add_mod_list[0];
|
||||||
|
TESTASSERT(measid_item->meas_id == 1 and measid_item->meas_obj_id == 1 and measid_item->report_cfg_id == 1);
|
||||||
|
measid_item++;
|
||||||
|
TESTASSERT(measid_item->meas_id == 2 and measid_item->meas_obj_id == 1 and measid_item->report_cfg_id == 2);
|
||||||
|
|
||||||
|
// TEST 2: measConfig is empty if nothing was updated
|
||||||
|
src_var = target_var;
|
||||||
|
TESTASSERT(not compute_diff_meascfg(src_var, target_var, result_meascfg));
|
||||||
|
TESTASSERT(not result_meascfg.meas_obj_to_add_mod_list_present and not result_meascfg.meas_obj_to_rem_list_present);
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 0);
|
||||||
|
TESTASSERT(not result_meascfg.report_cfg_to_add_mod_list_present and
|
||||||
|
not result_meascfg.report_cfg_to_rem_list_present);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 0);
|
||||||
|
|
||||||
|
// TEST 3: Cell is added to cellsToAddModList if just a field was updated
|
||||||
|
cell1.q_offset = 5;
|
||||||
|
src_var = target_var;
|
||||||
|
add_cell_enb_cfg(target_var.meas_obj_to_add_mod_list, cell1);
|
||||||
|
TESTASSERT(compute_diff_meascfg(src_var, target_var, result_meascfg));
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present);
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1);
|
||||||
|
item = &result_meascfg.meas_obj_to_add_mod_list[0];
|
||||||
|
TESTASSERT(item->meas_obj_id == 1 and
|
||||||
|
item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
|
||||||
|
eutra = item->meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list_present and not eutra.cells_to_rem_list_present);
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list.size() == 1);
|
||||||
|
cell_item = &eutra.cells_to_add_mod_list[0];
|
||||||
|
TESTASSERT(is_cell_cfg_equal(cell1, *cell_item));
|
||||||
|
|
||||||
|
// TEST 4: Removal of cell/rep from target propagates to the resulting meas_cfg_s
|
||||||
|
src_var = target_var;
|
||||||
|
const auto& src_measobjs = src_var.meas_obj_to_add_mod_list;
|
||||||
|
TESTASSERT(src_measobjs.size() == 1);
|
||||||
|
TESTASSERT(src_measobjs[0].meas_obj.meas_obj_eutra().cells_to_add_mod_list.size() == 2);
|
||||||
|
target_var = {};
|
||||||
|
add_cell_enb_cfg(target_var.meas_obj_to_add_mod_list, cell2);
|
||||||
|
add_report_cfg(target_var.report_cfg_to_add_mod_list, rep1);
|
||||||
|
add_report_cfg(target_var.report_cfg_to_add_mod_list, rep3);
|
||||||
|
TESTASSERT(compute_diff_meascfg(src_var, target_var, result_meascfg));
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present);
|
||||||
|
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1);
|
||||||
|
item = &result_meascfg.meas_obj_to_add_mod_list[0];
|
||||||
|
TESTASSERT(item->meas_obj_id == 1 and
|
||||||
|
item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
|
||||||
|
eutra = item->meas_obj.meas_obj_eutra();
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list_present and eutra.cells_to_add_mod_list.size() == 1);
|
||||||
|
TESTASSERT(eutra.cells_to_add_mod_list[0].pci == cell2.pci);
|
||||||
|
TESTASSERT(eutra.cells_to_rem_list_present and eutra.cells_to_rem_list.size() == 1);
|
||||||
|
TESTASSERT(eutra.cells_to_rem_list[0] == 2);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list_present and not result_meascfg.report_cfg_to_rem_list_present);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list.size() == 1);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg_id == 2);
|
||||||
|
TESTASSERT(result_meascfg.report_cfg_to_add_mod_list[0].report_cfg.report_cfg_eutra() == rep3);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// TEST: creation of a meas_cfg using the srsenb::rrc_cfg_t
|
||||||
|
rrc_cfg_t cfg;
|
||||||
|
srsenb::all_args_t all_args;
|
||||||
|
TESTASSERT(test_helpers::parse_default_cfg(&cfg, all_args) == SRSLTE_SUCCESS);
|
||||||
|
cfg.enb_id = 0x19B;
|
||||||
|
cfg.cell.nof_prb = 6;
|
||||||
|
cfg.meas_cfg_present = true;
|
||||||
|
cfg.cell_list.resize(2);
|
||||||
|
cfg.cell_list[0].dl_earfcn = 2850;
|
||||||
|
cfg.cell_list[0].cell_id = 0x01;
|
||||||
|
cfg.cell_list[0].scell_list.resize(1);
|
||||||
|
cfg.cell_list[0].scell_list[0].cell_id = 0x02;
|
||||||
|
cfg.cell_list[0].meas_cfg.meas_cells.resize(1);
|
||||||
|
cfg.cell_list[0].meas_cfg.meas_cells[0] = generate_cell1();
|
||||||
|
cfg.cell_list[0].meas_cfg.meas_cells[0].pci = 3;
|
||||||
|
cfg.cell_list[1].dl_earfcn = 3400;
|
||||||
|
cfg.cell_list[1].cell_id = 0x02;
|
||||||
|
cfg.cell_list[0].meas_cfg.meas_reports.resize(1);
|
||||||
|
cfg.cell_list[0].meas_cfg.meas_reports[0] = generate_rep1();
|
||||||
|
|
||||||
|
// TEST: correct construction of list of cells
|
||||||
|
cell_info_common_list cell_list{cfg};
|
||||||
|
TESTASSERT(cell_list.nof_cells() == 2);
|
||||||
|
TESTASSERT(cell_list.get_cc_idx(0)->scells.size() == 1);
|
||||||
|
TESTASSERT(cell_list.get_cc_idx(0)->scells[0] == cell_list.get_cc_idx(1));
|
||||||
|
TESTASSERT(cell_list.get_cc_idx(1)->scells.empty());
|
||||||
|
freq_res_common_list freq_res{cfg};
|
||||||
|
|
||||||
|
// measConfig only includes earfcns of active carriers for a given pcell
|
||||||
|
meas_cfg_s cell_meas_cfg;
|
||||||
|
cell_ctxt_dedicated_list ue_cell_list{cfg, freq_res, cell_list};
|
||||||
|
ue_cell_list.set_cells({0});
|
||||||
|
TESTASSERT(fill_meascfg_enb_cfg(cell_meas_cfg, ue_cell_list));
|
||||||
|
const auto& measobjs = cell_meas_cfg.meas_obj_to_add_mod_list;
|
||||||
|
TESTASSERT(measobjs.size() == 2);
|
||||||
|
TESTASSERT(measobjs[0].meas_obj.meas_obj_eutra().carrier_freq == 2850);
|
||||||
|
TESTASSERT(not measobjs[0].meas_obj.meas_obj_eutra().cells_to_add_mod_list_present);
|
||||||
|
TESTASSERT(measobjs[1].meas_obj.meas_obj_eutra().carrier_freq == 3400);
|
||||||
|
TESTASSERT(measobjs[1].meas_obj.meas_obj_eutra().cells_to_add_mod_list_present);
|
||||||
|
TESTASSERT(measobjs[1].meas_obj.meas_obj_eutra().cells_to_add_mod_list.size() == 1);
|
||||||
|
TESTASSERT(measobjs[1].meas_obj.meas_obj_eutra().cells_to_add_mod_list[0].pci == 3);
|
||||||
|
TESTASSERT(cell_meas_cfg.report_cfg_to_add_mod_list_present);
|
||||||
|
TESTASSERT(cell_meas_cfg.report_cfg_to_add_mod_list.size() == 1);
|
||||||
|
TESTASSERT(cell_meas_cfg.report_cfg_to_add_mod_list[0].report_cfg.report_cfg_eutra() ==
|
||||||
|
cfg.cell_list[0].meas_cfg.meas_reports[0]);
|
||||||
|
TESTASSERT(cell_meas_cfg.meas_id_to_add_mod_list_present);
|
||||||
|
const auto& measid = cell_meas_cfg.meas_id_to_add_mod_list[0];
|
||||||
|
TESTASSERT(measid.meas_id == 1 and measid.meas_obj_id == 1 and measid.report_cfg_id == 1);
|
||||||
|
|
||||||
|
meas_cfg_s cell_meas_cfg2;
|
||||||
|
ue_cell_list.set_cells({1});
|
||||||
|
TESTASSERT(fill_meascfg_enb_cfg(cell_meas_cfg2, ue_cell_list));
|
||||||
|
const auto& measobjs2 = cell_meas_cfg2.meas_obj_to_add_mod_list;
|
||||||
|
TESTASSERT(measobjs2.size() == 1);
|
||||||
|
TESTASSERT(measobjs2[0].meas_obj.meas_obj_eutra().carrier_freq == 3400);
|
||||||
|
TESTASSERT(not measobjs2[0].meas_obj.meas_obj_eutra().cells_to_add_mod_list_present);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsenb
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
srslte::logmap::set_default_log_level(srslte::LOG_LEVEL_INFO);
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
argparse::usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
argparse::parse_args(argc, argv);
|
||||||
|
TESTASSERT(test_correct_meascfg_insertion() == 0);
|
||||||
|
TESTASSERT(test_correct_meascfg_calculation() == 0);
|
||||||
|
srslte::console("Success\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "test_helpers.h"
|
||||||
|
#include "srsenb/hdr/enb.h"
|
||||||
|
#include "srslte/common/test_common.h"
|
||||||
|
|
||||||
|
namespace argparse {
|
||||||
|
|
||||||
|
std::string repository_dir;
|
||||||
|
srslte::LOG_LEVEL_ENUM log_level;
|
||||||
|
|
||||||
|
} // namespace argparse
|
||||||
|
|
||||||
|
namespace test_helpers {
|
||||||
|
|
||||||
|
int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args)
|
||||||
|
{
|
||||||
|
args = {};
|
||||||
|
*rrc_cfg = {};
|
||||||
|
args.enb_files.sib_config = argparse::repository_dir + "/sib.conf.example";
|
||||||
|
args.enb_files.rr_config = argparse::repository_dir + "/rr.conf.example";
|
||||||
|
args.enb_files.drb_config = argparse::repository_dir + "/drb.conf.example";
|
||||||
|
srslte::logmap::get("TEST")->debug("sib file path=%s\n", args.enb_files.sib_config.c_str());
|
||||||
|
|
||||||
|
args.enb.enb_id = 0x19B;
|
||||||
|
args.enb.dl_earfcn = 3400;
|
||||||
|
args.enb.n_prb = 50;
|
||||||
|
TESTASSERT(srslte::string_to_mcc("001", &args.stack.s1ap.mcc));
|
||||||
|
TESTASSERT(srslte::string_to_mnc("01", &args.stack.s1ap.mnc));
|
||||||
|
args.enb.transmission_mode = 1;
|
||||||
|
args.enb.nof_ports = 1;
|
||||||
|
args.general.eia_pref_list = "EIA2, EIA1, EIA0";
|
||||||
|
args.general.eea_pref_list = "EEA0, EEA2, EEA1";
|
||||||
|
|
||||||
|
args.general.rrc_inactivity_timer = 60000;
|
||||||
|
|
||||||
|
phy_cfg_t phy_cfg;
|
||||||
|
|
||||||
|
return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &phy_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, uint16_t rnti)
|
||||||
|
{
|
||||||
|
srslte::unique_byte_buffer_t pdu;
|
||||||
|
|
||||||
|
// Send RRCConnectionRequest
|
||||||
|
uint8_t rrc_conn_request[] = {0x40, 0x12, 0xf6, 0xfb, 0xe2, 0xc6};
|
||||||
|
copy_msg_to_buffer(pdu, rrc_conn_request);
|
||||||
|
rrc.write_pdu(rnti, 0, std::move(pdu));
|
||||||
|
timers.step_all();
|
||||||
|
rrc.tti_clock();
|
||||||
|
|
||||||
|
// Send RRCConnectionSetupComplete
|
||||||
|
uint8_t rrc_conn_setup_complete[] = {0x20, 0x00, 0x40, 0x2e, 0x90, 0x50, 0x49, 0xe8, 0x06, 0x0e, 0x82, 0xa2,
|
||||||
|
0x17, 0xec, 0x13, 0xe2, 0x0f, 0x00, 0x02, 0x02, 0x5e, 0xdf, 0x7c, 0x58,
|
||||||
|
0x05, 0xc0, 0xc0, 0x00, 0x08, 0x04, 0x03, 0xa0, 0x23, 0x23, 0xc0};
|
||||||
|
copy_msg_to_buffer(pdu, rrc_conn_setup_complete);
|
||||||
|
rrc.write_pdu(rnti, 1, std::move(pdu));
|
||||||
|
timers.step_all();
|
||||||
|
rrc.tti_clock();
|
||||||
|
|
||||||
|
// S1AP receives InitialContextSetupRequest and forwards it to RRC
|
||||||
|
uint8_t s1ap_init_ctxt_setup_req[] = {
|
||||||
|
0x00, 0x09, 0x00, 0x80, 0xc6, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x08, 0x00, 0x02, 0x00,
|
||||||
|
0x01, 0x00, 0x42, 0x00, 0x0a, 0x18, 0x3b, 0x9a, 0xca, 0x00, 0x60, 0x3b, 0x9a, 0xca, 0x00, 0x00, 0x18, 0x00, 0x78,
|
||||||
|
0x00, 0x00, 0x34, 0x00, 0x73, 0x45, 0x00, 0x09, 0x3c, 0x0f, 0x80, 0x0a, 0x00, 0x21, 0xf0, 0xb7, 0x36, 0x1c, 0x56,
|
||||||
|
0x64, 0x27, 0x3e, 0x5b, 0x04, 0xb7, 0x02, 0x07, 0x42, 0x02, 0x3e, 0x06, 0x00, 0x09, 0xf1, 0x07, 0x00, 0x07, 0x00,
|
||||||
|
0x37, 0x52, 0x66, 0xc1, 0x01, 0x09, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63,
|
||||||
|
0x30, 0x37, 0x30, 0x06, 0x6d, 0x63, 0x63, 0x39, 0x30, 0x31, 0x04, 0x67, 0x70, 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8,
|
||||||
|
0x03, 0x02, 0x27, 0x0e, 0x80, 0x80, 0x21, 0x0a, 0x03, 0x00, 0x00, 0x0a, 0x81, 0x06, 0x08, 0x08, 0x08, 0x08, 0x50,
|
||||||
|
0x0b, 0xf6, 0x09, 0xf1, 0x07, 0x80, 0x01, 0x01, 0xf6, 0x7e, 0x72, 0x69, 0x13, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x23,
|
||||||
|
0x05, 0xf4, 0xf6, 0x7e, 0x72, 0x69, 0x00, 0x6b, 0x00, 0x05, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x49, 0x00, 0x20,
|
||||||
|
0x45, 0x25, 0xe4, 0x9a, 0x77, 0xc8, 0xd5, 0xcf, 0x26, 0x33, 0x63, 0xeb, 0x5b, 0xb9, 0xc3, 0x43, 0x9b, 0x9e, 0xb3,
|
||||||
|
0x86, 0x1f, 0xa8, 0xa7, 0xcf, 0x43, 0x54, 0x07, 0xae, 0x42, 0x2b, 0x63, 0xb9};
|
||||||
|
asn1::s1ap::s1ap_pdu_c s1ap_pdu;
|
||||||
|
srslte::byte_buffer_t byte_buf;
|
||||||
|
byte_buf.N_bytes = sizeof(s1ap_init_ctxt_setup_req);
|
||||||
|
memcpy(byte_buf.msg, s1ap_init_ctxt_setup_req, byte_buf.N_bytes);
|
||||||
|
asn1::cbit_ref bref(byte_buf.msg, byte_buf.N_bytes);
|
||||||
|
TESTASSERT(s1ap_pdu.unpack(bref) == asn1::SRSASN_SUCCESS);
|
||||||
|
rrc.setup_ue_ctxt(rnti, s1ap_pdu.init_msg().value.init_context_setup_request());
|
||||||
|
timers.step_all();
|
||||||
|
rrc.tti_clock();
|
||||||
|
|
||||||
|
// Send SecurityModeComplete
|
||||||
|
uint8_t sec_mode_complete[] = {0x28, 0x00};
|
||||||
|
copy_msg_to_buffer(pdu, sec_mode_complete);
|
||||||
|
rrc.write_pdu(rnti, 1, std::move(pdu));
|
||||||
|
timers.step_all();
|
||||||
|
rrc.tti_clock();
|
||||||
|
|
||||||
|
// send UE cap info
|
||||||
|
uint8_t ue_cap_info[] = {0x38, 0x01, 0x01, 0x0c, 0x98, 0x00, 0x00, 0x18, 0x00, 0x0f,
|
||||||
|
0x30, 0x20, 0x80, 0x00, 0x01, 0x00, 0x0e, 0x01, 0x00, 0x00};
|
||||||
|
copy_msg_to_buffer(pdu, ue_cap_info);
|
||||||
|
rrc.write_pdu(rnti, 1, std::move(pdu));
|
||||||
|
timers.step_all();
|
||||||
|
rrc.tti_clock();
|
||||||
|
|
||||||
|
// RRCConnectionReconfiguration was sent. Send RRCConnectionReconfigurationComplete
|
||||||
|
uint8_t rrc_conn_reconf_complete[] = {0x10, 0x00};
|
||||||
|
copy_msg_to_buffer(pdu, rrc_conn_reconf_complete);
|
||||||
|
rrc.write_pdu(rnti, 1, std::move(pdu));
|
||||||
|
timers.step_all();
|
||||||
|
rrc.tti_clock();
|
||||||
|
|
||||||
|
return SRSLTE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace test_helpers
|
||||||
|
|
||||||
|
namespace srsenb {
|
||||||
|
|
||||||
|
meas_cell_cfg_t generate_cell1()
|
||||||
|
{
|
||||||
|
meas_cell_cfg_t cell1{};
|
||||||
|
cell1.earfcn = 3400;
|
||||||
|
cell1.pci = 1;
|
||||||
|
cell1.q_offset = 0;
|
||||||
|
cell1.eci = 0x19C01;
|
||||||
|
return cell1;
|
||||||
|
}
|
||||||
|
|
||||||
|
report_cfg_eutra_s generate_rep1()
|
||||||
|
{
|
||||||
|
report_cfg_eutra_s rep{};
|
||||||
|
rep.report_amount.value = report_cfg_eutra_s::report_amount_opts::r16;
|
||||||
|
rep.report_interv.value = report_interv_opts::ms240;
|
||||||
|
rep.max_report_cells = 2;
|
||||||
|
rep.report_quant.value = report_cfg_eutra_s::report_quant_opts::both;
|
||||||
|
rep.trigger_quant.value = report_cfg_eutra_s::trigger_quant_opts::rsrp;
|
||||||
|
rep.trigger_type.set_event().event_id.set_event_a3();
|
||||||
|
rep.trigger_type.event().time_to_trigger.value = time_to_trigger_opts::ms100;
|
||||||
|
rep.trigger_type.event().hysteresis = 0;
|
||||||
|
rep.trigger_type.event().event_id.event_a3().a3_offset = 5;
|
||||||
|
rep.trigger_type.event().event_id.event_a3().report_on_leave = true;
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell)
|
||||||
|
{
|
||||||
|
return cfg.pci == cell.pci and cell.cell_individual_offset.to_number() == (int8_t)round(cfg.q_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsenb
|
Loading…
Reference in New Issue