|
|
|
@ -75,6 +75,49 @@ bool operator==(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& r
|
|
|
|
|
rhs_eutra.cells_to_add_mod_list.begin(),
|
|
|
|
|
cells_are_equal);
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const report_cfg_eutra_s& lhs, const report_cfg_eutra_s& rhs)
|
|
|
|
|
{
|
|
|
|
|
if (lhs.ext or rhs.ext) {
|
|
|
|
|
printf("[%d] extension of reportCfgToAddMod not supported\n", __LINE__);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (lhs.trigger_type.type() != rhs.trigger_type.type()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (lhs.trigger_type.type().value == report_cfg_eutra_s::trigger_type_c_::types_opts::event) {
|
|
|
|
|
auto &lhs_ev = lhs.trigger_type.event(), &rhs_ev = rhs.trigger_type.event();
|
|
|
|
|
if (lhs_ev.hysteresis != rhs_ev.hysteresis or lhs_ev.time_to_trigger != rhs_ev.time_to_trigger or
|
|
|
|
|
lhs_ev.event_id.type() != rhs_ev.event_id.type()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (lhs_ev.event_id.type().value != eutra_event_s::event_id_c_::types_opts::event_a3) {
|
|
|
|
|
printf("[%d] event type != A3 of reportCfgToAddMod not supported\n", __LINE__);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (lhs_ev.event_id.event_a3().report_on_leave != rhs_ev.event_id.event_a3().report_on_leave or
|
|
|
|
|
lhs_ev.event_id.event_a3().a3_offset != rhs_ev.event_id.event_a3().a3_offset) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (lhs.trigger_type.periodical().purpose != rhs.trigger_type.periodical().purpose) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return lhs.trigger_quant == rhs.trigger_quant and lhs.report_quant == rhs.report_quant and
|
|
|
|
|
lhs.max_report_cells == rhs.max_report_cells and lhs.report_interv == rhs.report_interv and
|
|
|
|
|
lhs.report_amount == rhs.report_amount;
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const report_cfg_to_add_mod_s& lhs, const report_cfg_to_add_mod_s& rhs)
|
|
|
|
|
{
|
|
|
|
|
if (lhs.report_cfg_id != rhs.report_cfg_id or lhs.report_cfg.type() != rhs.report_cfg.type()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return lhs.report_cfg.report_cfg_eutra() == rhs.report_cfg.report_cfg_eutra();
|
|
|
|
|
}
|
|
|
|
|
bool operator==(const meas_id_to_add_mod_s& lhs, const meas_id_to_add_mod_s& rhs)
|
|
|
|
|
{
|
|
|
|
|
return lhs.meas_id == rhs.meas_id and lhs.meas_obj_id == rhs.meas_obj_id and lhs.report_cfg_id == rhs.report_cfg_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace rrc_details {
|
|
|
|
|
|
|
|
|
@ -85,14 +128,22 @@ uint32_t eci_to_cellid(uint32_t eci)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! convenience function overload to extract Id from MeasObj/MeasId/ReportCfg/Cells
|
|
|
|
|
uint8_t get_id(const cells_to_add_mod_s& obj)
|
|
|
|
|
constexpr uint8_t get_id(const cells_to_add_mod_s& obj)
|
|
|
|
|
{
|
|
|
|
|
return obj.cell_idx;
|
|
|
|
|
}
|
|
|
|
|
uint8_t get_id(const meas_obj_to_add_mod_s& obj)
|
|
|
|
|
constexpr uint8_t get_id(const meas_obj_to_add_mod_s& obj)
|
|
|
|
|
{
|
|
|
|
|
return obj.meas_obj_id;
|
|
|
|
|
}
|
|
|
|
|
constexpr uint8_t get_id(const report_cfg_to_add_mod_s& obj)
|
|
|
|
|
{
|
|
|
|
|
return obj.report_cfg_id;
|
|
|
|
|
}
|
|
|
|
|
constexpr uint8_t get_id(const meas_id_to_add_mod_s& obj)
|
|
|
|
|
{
|
|
|
|
|
return obj.meas_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! convenience function overload to print MeasObj/MeasId/etc. fields
|
|
|
|
|
std::string to_string(const cells_to_add_mod_s& obj)
|
|
|
|
@ -147,30 +198,9 @@ find_cell(meas_obj_to_add_mod_list_l& l, uint32_t earfcn, uint8_t cell_id)
|
|
|
|
|
return {obj, it};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Adds Cell to MeasCfg MeasObjToAddMod field
|
|
|
|
|
cells_to_add_mod_s* meascfg_add_cell(meas_obj_eutra_s& eutra_obj, const cells_to_add_mod_s& celltoadd)
|
|
|
|
|
{
|
|
|
|
|
// create new cell_id in the provided eutra_obj.
|
|
|
|
|
// if the cell_id already exists, just update the fields.
|
|
|
|
|
eutra_obj.cells_to_add_mod_list_present = true;
|
|
|
|
|
|
|
|
|
|
// find the cell. Assumes sorted list
|
|
|
|
|
auto& l = eutra_obj.cells_to_add_mod_list;
|
|
|
|
|
auto found_it = std::lower_bound(l.begin(), l.end(), celltoadd.cell_idx, rrc_details::cell_id_cmp{});
|
|
|
|
|
if (found_it == l.end()) {
|
|
|
|
|
eutra_obj.cells_to_add_mod_list.push_back({});
|
|
|
|
|
found_it = &eutra_obj.cells_to_add_mod_list.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*found_it = celltoadd;
|
|
|
|
|
// cell_obj->cell_idx = (uint8_t)(cell_id % 3); // 0-3 // FIXME: What?
|
|
|
|
|
// printf("The added cell has idx=%d, pci=%d\n", cell_obj->cell_idx, cell_obj->pci);
|
|
|
|
|
|
|
|
|
|
return found_it;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds MeasObjtoAddMod to MeasCfg object
|
|
|
|
|
* 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)
|
|
|
|
|
{
|
|
|
|
@ -194,6 +224,7 @@ meas_obj_to_add_mod_s* meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj
|
|
|
|
|
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, blacCells, whiteCells, etc. according to (5.5.2.5 1|1|1)
|
|
|
|
|
|
|
|
|
|
return found_it;
|
|
|
|
|
}
|
|
|
|
@ -245,6 +276,21 @@ private:
|
|
|
|
|
const_iterator src_it, src_end, target_it, target_end;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename Container, typename IdType = decltype(get_id(*Container{}.begin()))>
|
|
|
|
|
IdType find_id_gap(const Container& c)
|
|
|
|
|
{
|
|
|
|
|
auto prev_it = c.begin();
|
|
|
|
|
if (prev_it != c.end() and get_id(*prev_it) == 1) {
|
|
|
|
|
auto it = prev_it;
|
|
|
|
|
for (++it; it != c.end(); prev_it = it, ++it) {
|
|
|
|
|
if (get_id(*it) > get_id(*prev_it) + 1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (prev_it == c.end()) ? 1 : get_id(*prev_it) + 1; // starts at 1.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace rrc_details
|
|
|
|
|
|
|
|
|
|
/*************************************************************************************************
|
|
|
|
@ -290,7 +336,7 @@ var_meas_cfg_t::add_cell_cfg(const meas_cell_cfg_t& cellcfg)
|
|
|
|
|
} else {
|
|
|
|
|
// no measobj has been found with same earfcn, create a new one
|
|
|
|
|
meas_obj_t new_obj;
|
|
|
|
|
new_obj.meas_obj_id = get_new_obj_id();
|
|
|
|
|
new_obj.meas_obj_id = rrc_details::find_id_gap(var_meas.meas_obj_list);
|
|
|
|
|
asn1::rrc::meas_obj_eutra_s& eutra = new_obj.meas_obj.set_meas_obj_eutra();
|
|
|
|
|
eutra.carrier_freq = cellcfg.earfcn;
|
|
|
|
|
eutra.allowed_meas_bw.value = asn1::rrc::allowed_meas_bw_e::mbw6; // FIXME: What value to add here?
|
|
|
|
@ -310,37 +356,81 @@ var_meas_cfg_t::add_cell_cfg(const meas_cell_cfg_t& cellcfg)
|
|
|
|
|
ret.second = &ret.first->meas_obj.meas_obj_eutra().cells_to_add_mod_list.back();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inserted_flag) {
|
|
|
|
|
var_meas.meas_obj_list_present = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {inserted_flag, ret.first, ret.second};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Find first gap in meas_obj_id and return it
|
|
|
|
|
uint32_t var_meas_cfg_t::get_new_obj_id()
|
|
|
|
|
report_cfg_to_add_mod_s* var_meas_cfg_t::add_report_cfg(const report_cfg_eutra_s& reportcfg)
|
|
|
|
|
{
|
|
|
|
|
meas_obj_t* prev_it = var_meas.meas_obj_list.begin();
|
|
|
|
|
if (prev_it != var_meas.meas_obj_list.end() and prev_it->meas_obj_id == 1) {
|
|
|
|
|
meas_obj_t* it = prev_it;
|
|
|
|
|
for (++it; it != var_meas.meas_obj_list.end(); prev_it = it, ++it) {
|
|
|
|
|
if (it->meas_obj_id > prev_it->meas_obj_id + 1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rrc_details::field_id_cmp<report_cfg_to_add_mod_s> cmp{};
|
|
|
|
|
report_cfg_to_add_mod_s new_rep;
|
|
|
|
|
new_rep.report_cfg_id = rrc_details::find_id_gap(var_meas.report_cfg_list);
|
|
|
|
|
new_rep.report_cfg.set_report_cfg_eutra() = reportcfg;
|
|
|
|
|
|
|
|
|
|
var_meas.report_cfg_list_present = true;
|
|
|
|
|
var_meas.report_cfg_list.push_back(new_rep);
|
|
|
|
|
std::sort(var_meas.report_cfg_list.begin(), var_meas.report_cfg_list.end(), cmp);
|
|
|
|
|
return std::lower_bound(var_meas.report_cfg_list.begin(), var_meas.report_cfg_list.end(), new_rep.report_cfg_id, cmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
meas_id_to_add_mod_s* var_meas_cfg_t::add_measid_cfg(uint8_t measobjid, uint8_t measrepid)
|
|
|
|
|
{
|
|
|
|
|
// ensure MeasObjId and ReportCfgId already exist
|
|
|
|
|
auto objit = std::lower_bound(
|
|
|
|
|
var_meas.meas_obj_list.begin(), var_meas.meas_obj_list.end(), measobjid, rrc_details::meas_obj_id_cmp{});
|
|
|
|
|
if (objit == var_meas.meas_obj_list.end() or objit->meas_obj_id != measobjid) {
|
|
|
|
|
ERROR("Failed to add MeasId because MeasObjId=%d is not found.\n", measobjid);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
auto repit = std::lower_bound(var_meas.report_cfg_list.begin(),
|
|
|
|
|
var_meas.report_cfg_list.end(),
|
|
|
|
|
measrepid,
|
|
|
|
|
rrc_details::field_id_cmp<report_cfg_to_add_mod_s>{});
|
|
|
|
|
if (repit == var_meas.report_cfg_list.end() or repit->report_cfg_id != measrepid) {
|
|
|
|
|
ERROR("Failed to add MeasId because ReportCfgId=%d is not found.\n", measrepid);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
return (prev_it == var_meas.meas_obj_list.end()) ? 1 : prev_it->meas_obj_id + 1; // starts at 1.
|
|
|
|
|
rrc_details::field_id_cmp<meas_id_to_add_mod_s> cmp{};
|
|
|
|
|
meas_id_to_add_mod_s new_measid;
|
|
|
|
|
new_measid.report_cfg_id = measrepid;
|
|
|
|
|
new_measid.meas_obj_id = measobjid;
|
|
|
|
|
new_measid.meas_id = rrc_details::find_id_gap(var_meas.meas_id_list);
|
|
|
|
|
|
|
|
|
|
var_meas.meas_id_list_present = true;
|
|
|
|
|
var_meas.meas_id_list.push_back(new_measid);
|
|
|
|
|
std::sort(var_meas.meas_id_list.begin(), var_meas.meas_id_list.end(), cmp);
|
|
|
|
|
return std::lower_bound(var_meas.meas_id_list.begin(), var_meas.meas_id_list.end(), new_measid.meas_id, cmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const
|
|
|
|
|
bool var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const
|
|
|
|
|
{
|
|
|
|
|
*meas_cfg = {};
|
|
|
|
|
// TODO: Create a flag to disable changing the "this" members (useful for transparent container)
|
|
|
|
|
// Set a MeasConfig in the RRC Connection Reconfiguration for HO.
|
|
|
|
|
compute_diff_meas_objs(target_cfg, meas_cfg);
|
|
|
|
|
// deltaconfig_meas_reports(target_cfg, meas_cfg);
|
|
|
|
|
// deltaconfig_meas_ids(target_cfg, meas_cfg);
|
|
|
|
|
compute_diff_report_cfgs(target_cfg, meas_cfg);
|
|
|
|
|
compute_diff_meas_ids(target_cfg, meas_cfg);
|
|
|
|
|
// deltaconfig_meas_quantity_config(target_cfg, meas_cfg);
|
|
|
|
|
meas_cfg->meas_gap_cfg_present = false; // NOTE: we do not support inter-freq. HO
|
|
|
|
|
meas_cfg->s_measure_present = false; // NOTE: We do not support SCells
|
|
|
|
|
meas_cfg->pre_regist_info_hrpd_present = false; // NOTE: not supported
|
|
|
|
|
meas_cfg->speed_state_pars_present = false; // NOTE: not supported
|
|
|
|
|
|
|
|
|
|
bool diff = meas_cfg->meas_obj_to_add_mod_list_present;
|
|
|
|
|
diff |= meas_cfg->meas_obj_to_rem_list_present;
|
|
|
|
|
diff |= meas_cfg->report_cfg_to_add_mod_list_present;
|
|
|
|
|
diff |= meas_cfg->report_cfg_to_rem_list_present;
|
|
|
|
|
diff |= meas_cfg->meas_id_to_add_mod_list_present;
|
|
|
|
|
diff |= meas_cfg->meas_id_to_rem_list_present;
|
|
|
|
|
diff |= meas_cfg->quant_cfg_present;
|
|
|
|
|
diff |= meas_cfg->meas_gap_cfg_present;
|
|
|
|
|
diff |= meas_cfg->s_measure_present;
|
|
|
|
|
diff |= meas_cfg->pre_regist_info_hrpd_present;
|
|
|
|
|
diff |= meas_cfg->speed_state_pars_present;
|
|
|
|
|
return diff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! adds all the cells that got updated to MeasCfg.
|
|
|
|
@ -350,37 +440,48 @@ void var_meas_cfg_t::compute_diff_cells(const meas_obj_eutra_s& target_it,
|
|
|
|
|
{
|
|
|
|
|
rrc_details::compute_diff_generator<cells_to_add_mod_list_l> diffs{src_it.cells_to_add_mod_list,
|
|
|
|
|
target_it.cells_to_add_mod_list};
|
|
|
|
|
meas_obj_eutra_s* eutra_obj = &added_obj->meas_obj.meas_obj_eutra();
|
|
|
|
|
|
|
|
|
|
meas_obj_eutra_s* eutra_obj = &added_obj->meas_obj.meas_obj_eutra();
|
|
|
|
|
while (true) {
|
|
|
|
|
auto result = diffs.next();
|
|
|
|
|
switch (result.outcome) {
|
|
|
|
|
case rrc_details::diff_outcome_t::complete:
|
|
|
|
|
return;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_removed:
|
|
|
|
|
// case "entry with matching cellIndex exists in cellsToRemoveList
|
|
|
|
|
Info("UE can now cease to measure activity of cell %s.\n", rrc_details::to_string(*result.target_it).c_str());
|
|
|
|
|
eutra_obj->cells_to_rem_list_present = true;
|
|
|
|
|
eutra_obj->cells_to_rem_list.push_back(result.src_it->cell_idx);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_added:
|
|
|
|
|
// case "entry with matching cellIndex doesn't exist in cellsToAddModList"
|
|
|
|
|
Info("UE has now to measure activity of %s.\n", rrc_details::to_string(*result.target_it).c_str());
|
|
|
|
|
rrc_details::meascfg_add_cell(*eutra_obj, *result.target_it);
|
|
|
|
|
eutra_obj->cells_to_add_mod_list_present = true;
|
|
|
|
|
eutra_obj->cells_to_add_mod_list.push_back(*result.target_it);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::same_id:
|
|
|
|
|
// check if cells are the same. if not, update.
|
|
|
|
|
if (not(*result.src_it == *result.target_it)) {
|
|
|
|
|
// case "entry with matching cellIndex exists in cellsToAddModList"
|
|
|
|
|
Info("UE has now to measure activity of %s with updated params.\n",
|
|
|
|
|
rrc_details::to_string(*result.target_it).c_str());
|
|
|
|
|
rrc_details::meascfg_add_cell(*eutra_obj, *result.target_it);
|
|
|
|
|
eutra_obj->cells_to_add_mod_list_present = true;
|
|
|
|
|
eutra_obj->cells_to_add_mod_list.push_back(*result.target_it);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! compute diff between target_cfg and var_meas -> depending on diff, add/remove/update meas_obj in meas_cfg
|
|
|
|
|
/**
|
|
|
|
|
* 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 var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, meas_cfg_s* meas_cfg) const
|
|
|
|
|
{
|
|
|
|
|
if (not target_cfg.var_meas.meas_obj_list_present) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// TODO: black cells and white cells
|
|
|
|
|
rrc_details::compute_diff_generator<meas_obj_to_add_mod_list_l> diffs{var_meas.meas_obj_list,
|
|
|
|
|
target_cfg.var_meas.meas_obj_list};
|
|
|
|
@ -391,22 +492,26 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me
|
|
|
|
|
case rrc_details::diff_outcome_t::complete:
|
|
|
|
|
return;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_removed:
|
|
|
|
|
// case "entry with matching cellIndex exists in cellsToRemoveList
|
|
|
|
|
Info("UE can cease to measure activity in frequency earfcn=%d.\n",
|
|
|
|
|
result.src_it->meas_obj.meas_obj_eutra().carrier_freq);
|
|
|
|
|
meas_cfg->meas_obj_to_rem_list_present = true;
|
|
|
|
|
meas_cfg->meas_obj_to_rem_list.push_back(result.src_it->meas_obj_id);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_added: {
|
|
|
|
|
// case "entry with matching measObjectId doesn't exist in measObjToAddModList"
|
|
|
|
|
Info("HO: UE has now to measure activity of new frequency earfcn=%d.\n",
|
|
|
|
|
result.target_it->meas_obj.meas_obj_eutra().carrier_freq);
|
|
|
|
|
auto& target_eutra = result.target_it->meas_obj.meas_obj_eutra();
|
|
|
|
|
auto& added_eutra = rrc_details::meascfg_add_meas_obj(meas_cfg, *result.target_it)->meas_obj.meas_obj_eutra();
|
|
|
|
|
// add all cells in measCfg
|
|
|
|
|
for (const cells_to_add_mod_s& cell_it : target_eutra.cells_to_add_mod_list) {
|
|
|
|
|
rrc_details::meascfg_add_cell(added_eutra, cell_it);
|
|
|
|
|
added_eutra.cells_to_add_mod_list_present = true;
|
|
|
|
|
added_eutra.cells_to_add_mod_list.push_back(cell_it);
|
|
|
|
|
}
|
|
|
|
|
} break;
|
|
|
|
|
case rrc_details::diff_outcome_t::same_id:
|
|
|
|
|
// case "entry with matching measObjectId exists in measObjToAddModList"
|
|
|
|
|
bool are_equal = *result.src_it == *result.target_it;
|
|
|
|
|
if (not are_equal) {
|
|
|
|
|
// if we found a difference in obj IDs
|
|
|
|
@ -420,6 +525,71 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Section 5.5.2.6/7 - Reporting configuration removal and addition/modification
|
|
|
|
|
*/
|
|
|
|
|
void var_meas_cfg_t::compute_diff_report_cfgs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const
|
|
|
|
|
{
|
|
|
|
|
if (not target_cfg.var_meas.report_cfg_list_present) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
rrc_details::compute_diff_generator<report_cfg_to_add_mod_list_l> diffs{var_meas.report_cfg_list,
|
|
|
|
|
target_cfg.var_meas.report_cfg_list};
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
auto result = diffs.next();
|
|
|
|
|
switch (result.outcome) {
|
|
|
|
|
case rrc_details::diff_outcome_t::complete:
|
|
|
|
|
return;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_removed:
|
|
|
|
|
meas_cfg->report_cfg_to_rem_list_present = true;
|
|
|
|
|
meas_cfg->report_cfg_to_rem_list.push_back(result.src_it->report_cfg_id);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_added:
|
|
|
|
|
meas_cfg->report_cfg_to_add_mod_list_present = true;
|
|
|
|
|
meas_cfg->report_cfg_to_add_mod_list.push_back(*result.target_it);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::same_id:
|
|
|
|
|
if (not(*result.src_it == *result.target_it)) {
|
|
|
|
|
meas_cfg->report_cfg_to_add_mod_list_present = true;
|
|
|
|
|
meas_cfg->report_cfg_to_add_mod_list.push_back(*result.target_it);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void var_meas_cfg_t::compute_diff_meas_ids(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const
|
|
|
|
|
{
|
|
|
|
|
if (not target_cfg.var_meas.meas_id_list_present) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
rrc_details::compute_diff_generator<meas_id_to_add_mod_list_l> diffs{var_meas.meas_id_list,
|
|
|
|
|
target_cfg.var_meas.meas_id_list};
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
auto result = diffs.next();
|
|
|
|
|
switch (result.outcome) {
|
|
|
|
|
case rrc_details::diff_outcome_t::complete:
|
|
|
|
|
return;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_removed:
|
|
|
|
|
meas_cfg->meas_id_to_rem_list_present = true;
|
|
|
|
|
meas_cfg->meas_id_to_rem_list.push_back(result.src_it->meas_id);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::id_added:
|
|
|
|
|
meas_cfg->meas_id_to_add_mod_list_present = true;
|
|
|
|
|
meas_cfg->meas_id_to_add_mod_list.push_back(*result.target_it);
|
|
|
|
|
break;
|
|
|
|
|
case rrc_details::diff_outcome_t::same_id:
|
|
|
|
|
if (not(*result.src_it == *result.target_it)) {
|
|
|
|
|
meas_cfg->meas_id_to_add_mod_list_present = true;
|
|
|
|
|
meas_cfg->meas_id_to_add_mod_list.push_back(*result.target_it);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************************************************************************
|
|
|
|
|
* mobility_cfg class
|
|
|
|
|
************************************************************************************************/
|
|
|
|
@ -428,11 +598,22 @@ rrc::mobility_cfg::mobility_cfg(rrc* outer_rrc) : rrc_enb(outer_rrc)
|
|
|
|
|
{
|
|
|
|
|
var_meas_cfg_t var_meas{outer_rrc->rrc_log};
|
|
|
|
|
|
|
|
|
|
// inserts all neighbor cells
|
|
|
|
|
if (rrc_enb->cfg.meas_cfg_present) {
|
|
|
|
|
// inserts all neighbor cells
|
|
|
|
|
for (meas_cell_cfg_t& meascell : rrc_enb->cfg.meas_cfg.meas_cells) {
|
|
|
|
|
var_meas.add_cell_cfg(meascell);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// insert all report cfgs
|
|
|
|
|
for (const report_cfg_eutra_s& reportcfg : rrc_enb->cfg.meas_cfg.meas_reports) {
|
|
|
|
|
var_meas.add_report_cfg(reportcfg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// insert all meas ids
|
|
|
|
|
// FIXME: add this to the parser
|
|
|
|
|
for (const auto& measobj : var_meas.meas_objs()) {
|
|
|
|
|
var_meas.add_measid_cfg(measobj.meas_obj_id, var_meas.rep_cfgs().begin()->report_cfg_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
current_meas_cfg = std::make_shared<var_meas_cfg_t>(var_meas);
|
|
|
|
@ -452,6 +633,7 @@ rrc::ue::rrc_mobility::rrc_mobility(rrc::ue* outer_ue) :
|
|
|
|
|
ue_var_meas = std::make_shared<var_meas_cfg_t>(outer_ue->parent->rrc_log);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//! Method to add Mobility Info to a RRC Connection Reconfiguration Message
|
|
|
|
|
bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg)
|
|
|
|
|
{
|
|
|
|
|
// only reconfigure meas_cfg if no handover is occurring
|
|
|
|
@ -465,22 +647,11 @@ bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
asn1::rrc::meas_cfg_s* meas_cfg = &conn_recfg->meas_cfg;
|
|
|
|
|
ue_var_meas->compute_diff_meas_cfg(*cfg->current_meas_cfg, meas_cfg);
|
|
|
|
|
bool updated = ue_var_meas->compute_diff_meas_cfg(*cfg->current_meas_cfg, meas_cfg);
|
|
|
|
|
// update ue var meas
|
|
|
|
|
ue_var_meas = cfg->current_meas_cfg;
|
|
|
|
|
|
|
|
|
|
// if there is at least one difference, we tag a new measurement report in conn_reconf.
|
|
|
|
|
bool diff = meas_cfg->meas_obj_to_add_mod_list_present;
|
|
|
|
|
diff |= meas_cfg->meas_obj_to_rem_list_present;
|
|
|
|
|
diff |= meas_cfg->report_cfg_to_add_mod_list_present;
|
|
|
|
|
diff |= meas_cfg->report_cfg_to_rem_list_present;
|
|
|
|
|
diff |= meas_cfg->meas_id_to_add_mod_list_present;
|
|
|
|
|
diff |= meas_cfg->meas_id_to_rem_list_present;
|
|
|
|
|
diff |= meas_cfg->quant_cfg_present;
|
|
|
|
|
diff |= meas_cfg->meas_gap_cfg_present;
|
|
|
|
|
diff |= meas_cfg->s_measure_present;
|
|
|
|
|
diff |= meas_cfg->pre_regist_info_hrpd_present;
|
|
|
|
|
diff |= meas_cfg->speed_state_pars_present;
|
|
|
|
|
if (diff) {
|
|
|
|
|
if (updated) {
|
|
|
|
|
conn_recfg->meas_cfg_present = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|