mirror of https://github.com/PentHertz/srsLTE.git
updated rrc mobility parsing. added some utility methods
This commit is contained in:
parent
20f6655c6b
commit
0526ae8ab1
|
@ -484,6 +484,25 @@ private:
|
|||
std::list<proc_obj_t> proc_list;
|
||||
};
|
||||
|
||||
template <typename Functor>
|
||||
struct deferred_callback {
|
||||
explicit deferred_callback(Functor&& f_) : f(std::forward<Functor>(f_)) {}
|
||||
deferred_callback(const deferred_callback&) = delete;
|
||||
deferred_callback(deferred_callback&&) noexcept = default;
|
||||
deferred_callback& operator=(const deferred_callback&) = delete;
|
||||
deferred_callback& operator=(deferred_callback&&) noexcept = default;
|
||||
~deferred_callback() { f(); }
|
||||
|
||||
private:
|
||||
Functor f;
|
||||
};
|
||||
template <typename Functor>
|
||||
deferred_callback<Functor> defer_call(Functor&& f)
|
||||
{
|
||||
return deferred_callback<Functor>{std::forward<Functor>(f)};
|
||||
}
|
||||
#define DEFER(FUNC) auto on_exit_call = ::srslte::defer_call([&]() { FUNC })
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_RESUMABLE_PROCEDURES_H
|
||||
|
|
|
@ -390,30 +390,6 @@ public:
|
|||
virtual uint8_t* read_pdu_bcch_dlsch(const uint8_t enb_cc_idx, const uint32_t sib_index) = 0;
|
||||
};
|
||||
|
||||
// SCell configuration
|
||||
struct scell_cfg_t {
|
||||
uint32_t cell_id;
|
||||
bool cross_carrier_sched = false;
|
||||
uint32_t sched_cell_id;
|
||||
bool ul_allowed;
|
||||
};
|
||||
|
||||
// Cell/Sector configuration
|
||||
struct cell_cfg_t {
|
||||
uint32_t rf_port;
|
||||
uint32_t cell_id;
|
||||
uint16_t tac;
|
||||
uint32_t pci;
|
||||
uint16_t root_seq_idx;
|
||||
uint32_t dl_earfcn;
|
||||
double dl_freq_hz;
|
||||
uint32_t ul_earfcn;
|
||||
double ul_freq_hz;
|
||||
uint32_t initial_dl_cqi;
|
||||
std::vector<scell_cfg_t> scell_list;
|
||||
};
|
||||
typedef std::vector<cell_cfg_t> cell_list_t;
|
||||
|
||||
// RRC interface for PDCP
|
||||
class rrc_interface_pdcp
|
||||
{
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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_ENB_RRC_INTERFACE_TYPES_H
|
||||
#define SRSLTE_ENB_RRC_INTERFACE_TYPES_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
// SCell configuration
|
||||
struct scell_cfg_t {
|
||||
uint32_t cell_id;
|
||||
bool cross_carrier_sched = false;
|
||||
uint32_t sched_cell_id;
|
||||
bool ul_allowed;
|
||||
};
|
||||
|
||||
// Cell to measure for Handover
|
||||
struct meas_cell_cfg_t {
|
||||
uint32_t earfcn;
|
||||
uint16_t pci;
|
||||
uint32_t eci;
|
||||
float q_offset;
|
||||
};
|
||||
|
||||
// neigh measurement Cell info
|
||||
struct rrc_meas_cfg_t {
|
||||
std::vector<meas_cell_cfg_t> meas_cells;
|
||||
std::vector<asn1::rrc::report_cfg_eutra_s> meas_reports;
|
||||
asn1::rrc::quant_cfg_eutra_s quant_cfg;
|
||||
// TODO: Add blacklist cells
|
||||
// TODO: Add multiple meas configs
|
||||
};
|
||||
|
||||
// Cell/Sector configuration
|
||||
struct cell_cfg_t {
|
||||
uint32_t rf_port;
|
||||
uint32_t cell_id;
|
||||
uint16_t tac;
|
||||
uint32_t pci;
|
||||
uint16_t root_seq_idx;
|
||||
uint32_t dl_earfcn;
|
||||
double dl_freq_hz;
|
||||
uint32_t ul_earfcn;
|
||||
double ul_freq_hz;
|
||||
uint32_t initial_dl_cqi;
|
||||
std::vector<scell_cfg_t> scell_list;
|
||||
rrc_meas_cfg_t meas_cfg;
|
||||
};
|
||||
|
||||
typedef std::vector<cell_cfg_t> cell_list_t;
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSLTE_ENB_RRC_INTERFACE_TYPES_H
|
|
@ -38,6 +38,7 @@
|
|||
#include "srsenb/hdr/enb.h"
|
||||
#include "srslte/common/multiqueue.h"
|
||||
#include "srslte/interfaces/enb_interfaces.h"
|
||||
#include "srslte/interfaces/enb_rrc_interface_types.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "srslte/common/tti_sync_cv.h"
|
||||
#include "srslte/interfaces/enb_interfaces.h"
|
||||
#include "srslte/interfaces/enb_metrics_interface.h"
|
||||
#include "srslte/interfaces/enb_rrc_interface_types.h"
|
||||
#include "srslte/interfaces/sched_interface.h"
|
||||
#include "ta.h"
|
||||
#include "ue.h"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "srslte/common/stack_procedure.h"
|
||||
#include "srslte/common/timeout.h"
|
||||
#include "srslte/interfaces/enb_interfaces.h"
|
||||
#include "srslte/interfaces/enb_rrc_interface_types.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
|
@ -66,25 +67,6 @@ typedef struct {
|
|||
asn1::rrc::rlc_cfg_c rlc_cfg;
|
||||
} rrc_cfg_qci_t;
|
||||
|
||||
//! Cell to measure for HO. Filled by cfg file parser.
|
||||
struct meas_cell_cfg_t {
|
||||
uint32_t earfcn;
|
||||
uint16_t pci;
|
||||
uint32_t eci;
|
||||
float q_offset;
|
||||
};
|
||||
|
||||
// neigh measurement Cell info
|
||||
struct rrc_meas_cfg_t {
|
||||
std::vector<meas_cell_cfg_t> meas_cells;
|
||||
std::vector<asn1::rrc::report_cfg_eutra_s> meas_reports;
|
||||
asn1::rrc::quant_cfg_eutra_s quant_cfg;
|
||||
// uint32_t nof_meas_ids;
|
||||
// srslte::rrc_meas_id_t meas_ids[LIBLTE_RRC_MAX_MEAS_ID];
|
||||
// TODO: Add blacklist cells
|
||||
// TODO: Add multiple meas configs
|
||||
};
|
||||
|
||||
#define MAX_NOF_QCI 10
|
||||
|
||||
struct rrc_cfg_t {
|
||||
|
@ -105,7 +87,6 @@ struct rrc_cfg_t {
|
|||
srslte::CIPHERING_ALGORITHM_ID_ENUM eea_preference_list[srslte::CIPHERING_ALGORITHM_ID_N_ITEMS];
|
||||
srslte::INTEGRITY_ALGORITHM_ID_ENUM eia_preference_list[srslte::INTEGRITY_ALGORITHM_ID_N_ITEMS];
|
||||
bool meas_cfg_present = false;
|
||||
rrc_meas_cfg_t meas_cfg;
|
||||
srslte_cell_t cell;
|
||||
cell_list_t cell_list;
|
||||
};
|
||||
|
@ -269,7 +250,8 @@ private:
|
|||
uint16_t rnti = 0;
|
||||
rrc* parent = nullptr;
|
||||
|
||||
bool connect_notified = false;
|
||||
bool connect_notified = false;
|
||||
std::unique_ptr<rrc_mobility> mobility_handler;
|
||||
|
||||
bool is_csfb = false;
|
||||
|
||||
|
@ -283,7 +265,6 @@ private:
|
|||
asn1::rrc::security_algorithm_cfg_s last_security_mode_cmd;
|
||||
|
||||
asn1::rrc::establishment_cause_e establishment_cause;
|
||||
std::unique_ptr<rrc_mobility> mobility_handler;
|
||||
|
||||
// S-TMSI for this UE
|
||||
bool has_tmsi = false;
|
||||
|
@ -436,8 +417,8 @@ private:
|
|||
uint32_t nof_si_messages = 0;
|
||||
asn1::rrc::sib_type7_s sib7;
|
||||
|
||||
class mobility_cfg;
|
||||
std::unique_ptr<mobility_cfg> enb_mobility_cfg;
|
||||
class enb_mobility_handler;
|
||||
std::unique_ptr<enb_mobility_handler> enb_mobility_cfg;
|
||||
|
||||
void rem_user_thread(uint16_t rnti);
|
||||
|
||||
|
|
|
@ -63,21 +63,26 @@ public:
|
|||
asn1::rrc::report_cfg_to_add_mod_list_l& rep_cfgs() { return var_meas.report_cfg_list; }
|
||||
asn1::rrc::meas_id_to_add_mod_list_l& meas_ids() { return var_meas.meas_id_list; }
|
||||
|
||||
static var_meas_cfg_t make(const asn1::rrc::meas_cfg_s& meas_cfg);
|
||||
|
||||
private:
|
||||
asn1::rrc::var_meas_cfg_s var_meas;
|
||||
srslte::log_ref rrc_log;
|
||||
};
|
||||
|
||||
class rrc::mobility_cfg
|
||||
class rrc::enb_mobility_handler
|
||||
{
|
||||
public:
|
||||
explicit mobility_cfg(const rrc_cfg_t* cfg_);
|
||||
explicit enb_mobility_handler(rrc* rrc_);
|
||||
|
||||
std::shared_ptr<const var_meas_cfg_t> current_meas_cfg; ///< const to enable ptr comparison as identity comparison
|
||||
//! Variable used to store the MeasConfig expected for each cell.
|
||||
// Note: Made const to forbid silent updates and enable comparison based on addr
|
||||
std::vector<std::shared_ptr<const var_meas_cfg_t> > cell_meas_cfg_list;
|
||||
|
||||
private:
|
||||
// args
|
||||
const rrc_cfg_t* cfg = nullptr;
|
||||
rrc* rrc_ptr = nullptr;
|
||||
const rrc_cfg_t* cfg = nullptr;
|
||||
};
|
||||
|
||||
class rrc::ue::rrc_mobility
|
||||
|
@ -94,11 +99,18 @@ private:
|
|||
bool start_ho_preparation(uint32_t target_eci, uint8_t measobj_id, bool fwd_direct_path_available);
|
||||
bool start_enb_status_transfer();
|
||||
|
||||
rrc::ue* rrc_ue = nullptr;
|
||||
rrc* rrc_enb = nullptr;
|
||||
rrc::mobility_cfg* cfg = nullptr;
|
||||
srslte::byte_buffer_pool* pool = nullptr;
|
||||
srslte::log_ref rrc_log;
|
||||
bool update_ue_var_meas_cfg(const asn1::rrc::meas_cfg_s& source_meas_cfg,
|
||||
uint32_t target_enb_cc_idx,
|
||||
asn1::rrc::meas_cfg_s* diff_meas_cfg);
|
||||
bool update_ue_var_meas_cfg(const var_meas_cfg_t& source_var_meas_cfg,
|
||||
uint32_t target_enb_cc_idx,
|
||||
asn1::rrc::meas_cfg_s* diff_meas_cfg);
|
||||
|
||||
rrc::ue* rrc_ue = nullptr;
|
||||
rrc* rrc_enb = nullptr;
|
||||
rrc::enb_mobility_handler* cfg = nullptr;
|
||||
srslte::byte_buffer_pool* pool = nullptr;
|
||||
srslte::log_ref rrc_log;
|
||||
|
||||
// vars
|
||||
std::shared_ptr<const var_meas_cfg_t> ue_var_meas;
|
||||
|
|
|
@ -720,8 +720,8 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
|
|||
parse_default_field(cell_cfg.initial_dl_cqi, cellroot, "initial_dl_cqi", 5u);
|
||||
|
||||
if (cellroot["ho_active"]) {
|
||||
HANDLEPARSERCODE(parse_meas_cell_list(&rrc_cfg->meas_cfg, cellroot["meas_cell_list"]));
|
||||
HANDLEPARSERCODE(parse_meas_report_desc(&rrc_cfg->meas_cfg, cellroot["meas_report_desc"]));
|
||||
HANDLEPARSERCODE(parse_meas_cell_list(&cell_cfg.meas_cfg, cellroot["meas_cell_list"]));
|
||||
HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot["meas_report_desc"]));
|
||||
}
|
||||
|
||||
cell_cfg.scell_list.resize(cellroot["scell_list"].getLength());
|
||||
|
|
|
@ -74,7 +74,7 @@ void rrc::init(const rrc_cfg_t& cfg_,
|
|||
|
||||
nof_si_messages = generate_sibs();
|
||||
config_mac();
|
||||
enb_mobility_cfg.reset(new mobility_cfg(&cfg));
|
||||
enb_mobility_cfg.reset(new enb_mobility_handler(this));
|
||||
|
||||
bzero(&sr_sched, sizeof(sr_sched_t));
|
||||
running = true;
|
||||
|
@ -562,7 +562,7 @@ void rrc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size)
|
|||
|
||||
void rrc::ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t rrc_container)
|
||||
{
|
||||
users.at(rnti)->handle_ho_preparation_complete(is_success, std::move(rrc_container));
|
||||
users.at(rnti)->mobility_handler->handle_ho_preparation_complete(is_success, std::move(rrc_container));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -2100,6 +2100,7 @@ void rrc::ue::send_connection_reconf_new_bearer(const asn1::s1ap::erab_to_be_set
|
|||
srsenb::sched_interface::ue_bearer_cfg_t bearer_cfg;
|
||||
bearer_cfg.direction = srsenb::sched_interface::ue_bearer_cfg_t::BOTH;
|
||||
parent->mac->bearer_ue_cfg(rnti, lcid, &bearer_cfg);
|
||||
current_sched_ue_cfg.ue_bearers[lcid] = bearer_cfg;
|
||||
|
||||
// Configure DRB in RLC
|
||||
parent->rlc->add_bearer(rnti, lcid, srslte::make_rlc_config_t(drb_item.rlc_cfg));
|
||||
|
|
|
@ -52,6 +52,11 @@ uint32_t eci_to_cellid(uint32_t eci)
|
|||
{
|
||||
return eci & 0xFFu;
|
||||
}
|
||||
//! extract enb id from ECI
|
||||
uint32_t eci_to_enbid(uint32_t eci)
|
||||
{
|
||||
return (eci - eci_to_cellid(eci)) >> 8u;
|
||||
}
|
||||
uint16_t compute_mac_i(uint16_t crnti,
|
||||
uint32_t cellid,
|
||||
uint16_t pci,
|
||||
|
@ -250,8 +255,7 @@ struct compute_diff_generator {
|
|||
src_end(src.end()),
|
||||
target_it(target.begin()),
|
||||
target_end(target.end())
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
result_t next()
|
||||
{
|
||||
|
@ -415,7 +419,12 @@ asn1::rrc::quant_cfg_s* var_meas_cfg_t::add_quant_cfg(const asn1::rrc::quant_cfg
|
|||
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)
|
||||
|
||||
// Shortcut in case this is the same as target
|
||||
if (this == &target_cfg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set a MeasConfig in the RRC Connection Reconfiguration for HO.
|
||||
compute_diff_meas_objs(target_cfg, meas_cfg);
|
||||
compute_diff_report_cfgs(target_cfg, meas_cfg);
|
||||
|
@ -507,7 +516,7 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me
|
|||
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",
|
||||
Info("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();
|
||||
|
@ -606,38 +615,75 @@ void var_meas_cfg_t::compute_diff_quant_cfg(const var_meas_cfg_t& target_cfg, as
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert MeasCfg asn1 struct to var_meas_cfg_t
|
||||
* @param meas_cfg
|
||||
* @return
|
||||
*/
|
||||
var_meas_cfg_t var_meas_cfg_t::make(const asn1::rrc::meas_cfg_s& meas_cfg)
|
||||
{
|
||||
var_meas_cfg_t var;
|
||||
if (meas_cfg.meas_id_to_add_mod_list_present) {
|
||||
var.var_meas.meas_id_list_present = true;
|
||||
var.var_meas.meas_id_list = meas_cfg.meas_id_to_add_mod_list;
|
||||
}
|
||||
if (meas_cfg.meas_obj_to_add_mod_list_present) {
|
||||
var.var_meas.meas_obj_list_present = true;
|
||||
var.var_meas.meas_obj_list = meas_cfg.meas_obj_to_add_mod_list;
|
||||
}
|
||||
if (meas_cfg.report_cfg_to_add_mod_list_present) {
|
||||
var.var_meas.report_cfg_list_present = true;
|
||||
var.var_meas.report_cfg_list = meas_cfg.report_cfg_to_add_mod_list;
|
||||
}
|
||||
if (meas_cfg.quant_cfg_present) {
|
||||
var.var_meas.quant_cfg_present = true;
|
||||
var.var_meas.quant_cfg = meas_cfg.quant_cfg;
|
||||
}
|
||||
if (meas_cfg.report_cfg_to_rem_list_present or meas_cfg.meas_obj_to_rem_list_present or
|
||||
meas_cfg.meas_id_to_rem_list_present) {
|
||||
srslte::logmap::get("RRC")->warning("Remove lists not handled by the var_meas_cfg_t method\n");
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
/*************************************************************************************************
|
||||
* mobility_cfg class
|
||||
************************************************************************************************/
|
||||
|
||||
rrc::mobility_cfg::mobility_cfg(const rrc_cfg_t* cfg_) : cfg(cfg_)
|
||||
rrc::enb_mobility_handler::enb_mobility_handler(rrc* rrc_) : rrc_ptr(rrc_), cfg(&rrc_->cfg)
|
||||
{
|
||||
var_meas_cfg_t var_meas{};
|
||||
cell_meas_cfg_list.resize(cfg->cell_list.size());
|
||||
|
||||
if (cfg->meas_cfg_present) {
|
||||
// inserts all neighbor cells
|
||||
for (const meas_cell_cfg_t& meascell : cfg->meas_cfg.meas_cells) {
|
||||
var_meas.add_cell_cfg(meascell);
|
||||
}
|
||||
/* Create Template Cell VarMeasCfg List */
|
||||
|
||||
// insert all report cfgs
|
||||
for (const report_cfg_eutra_s& reportcfg : cfg->meas_cfg.meas_reports) {
|
||||
var_meas.add_report_cfg(reportcfg);
|
||||
}
|
||||
for (size_t i = 0; i < cfg->cell_list.size(); ++i) {
|
||||
std::unique_ptr<var_meas_cfg_t> var_meas{new var_meas_cfg_t{}};
|
||||
|
||||
// insert all meas ids
|
||||
// TODO: add this to the parser
|
||||
if (var_meas.rep_cfgs().size() > 0) {
|
||||
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);
|
||||
if (cfg->meas_cfg_present) {
|
||||
// inserts all neighbor cells
|
||||
for (const meas_cell_cfg_t& meascell : cfg->cell_list[i].meas_cfg.meas_cells) {
|
||||
var_meas->add_cell_cfg(meascell);
|
||||
}
|
||||
|
||||
// insert same report cfg for all cells
|
||||
for (const report_cfg_eutra_s& reportcfg : cfg->cell_list[i].meas_cfg.meas_reports) {
|
||||
var_meas->add_report_cfg(reportcfg);
|
||||
}
|
||||
|
||||
// insert all meas ids
|
||||
// TODO: add this to the parser
|
||||
if (var_meas->rep_cfgs().size() > 0) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// insert quantity config
|
||||
var_meas->add_quant_cfg(cfg->cell_list[i].meas_cfg.quant_cfg);
|
||||
}
|
||||
|
||||
// insert quantity config
|
||||
var_meas.add_quant_cfg(cfg->meas_cfg.quant_cfg);
|
||||
cell_meas_cfg_list[i].reset(var_meas.release());
|
||||
}
|
||||
|
||||
current_meas_cfg = std::make_shared<var_meas_cfg_t>(var_meas);
|
||||
}
|
||||
|
||||
/*************************************************************************************************
|
||||
|
@ -652,8 +698,7 @@ rrc::ue::rrc_mobility::rrc_mobility(rrc::ue* outer_ue) :
|
|||
rrc_log(outer_ue->parent->rrc_log),
|
||||
source_ho_proc(this),
|
||||
ue_var_meas(std::make_shared<var_meas_cfg_t>())
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
//! 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)
|
||||
|
@ -664,21 +709,11 @@ bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check if there has been any update
|
||||
if (ue_var_meas.get() == cfg->current_meas_cfg.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
asn1::rrc::meas_cfg_s* meas_cfg = &conn_recfg->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 (updated) {
|
||||
conn_recfg->meas_cfg_present = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// Check if there has been any update in ue_var_meas
|
||||
cell_ctxt_t* pcell = rrc_ue->get_ue_cc_cfg(UE_PCELL_CC_IDX);
|
||||
asn1::rrc::meas_cfg_s& meas_cfg = conn_recfg->meas_cfg;
|
||||
conn_recfg->meas_cfg_present = update_ue_var_meas_cfg(*ue_var_meas, pcell->enb_cc_idx, &meas_cfg);
|
||||
return conn_recfg->meas_cfg_present;
|
||||
}
|
||||
|
||||
//! Method called whenever the eNB receives a MeasReport from the UE. In normal situations, an HO procedure is started
|
||||
|
@ -727,8 +762,8 @@ void rrc::ue::rrc_mobility::handle_ue_meas_report(const meas_report_s& msg)
|
|||
// TODO: check what to do here to take the decision.
|
||||
// NOTE: for now just accept anything.
|
||||
|
||||
// HO going forward.
|
||||
auto& L = rrc_enb->cfg.meas_cfg.meas_cells;
|
||||
// Target cell to handover to was selected.
|
||||
auto& L = rrc_enb->cfg.cell_list[rrc_ue->get_ue_cc_cfg(UE_PCELL_CC_IDX)->enb_cc_idx].meas_cfg.meas_cells;
|
||||
uint32_t target_eci = std::find_if(L.begin(), L.end(), [pci](meas_cell_cfg_t& c) { return c.pci == pci; })->eci;
|
||||
if (not source_ho_proc.launch(*measid_it, *obj_it, *rep_it, *cell_it, eutra_list[i], target_eci)) {
|
||||
Error("Failed to start HO procedure, as it is already on-going\n");
|
||||
|
@ -896,6 +931,33 @@ void rrc::ue::rrc_mobility::handle_ho_preparation_complete(bool is_success, srsl
|
|||
source_ho_proc.trigger(sourceenb_ho_proc_t::ho_prep_result{is_success, std::move(container)});
|
||||
}
|
||||
|
||||
bool rrc::ue::rrc_mobility::update_ue_var_meas_cfg(const asn1::rrc::meas_cfg_s& source_meas_cfg,
|
||||
uint32_t target_enb_cc_idx,
|
||||
asn1::rrc::meas_cfg_s* diff_meas_cfg)
|
||||
{
|
||||
// Generate equivalent VarMeasCfg
|
||||
var_meas_cfg_t source_var = var_meas_cfg_t::make(source_meas_cfg);
|
||||
|
||||
// Compute difference measCfg and update UE VarMeasCfg
|
||||
return update_ue_var_meas_cfg(source_var, target_enb_cc_idx, diff_meas_cfg);
|
||||
}
|
||||
|
||||
bool rrc::ue::rrc_mobility::update_ue_var_meas_cfg(const var_meas_cfg_t& source_var_meas_cfg,
|
||||
uint32_t target_enb_cc_idx,
|
||||
asn1::rrc::meas_cfg_s* diff_meas_cfg)
|
||||
{
|
||||
// Fetch cell VarMeasCfg
|
||||
auto& target_var_ptr = rrc_enb->enb_mobility_cfg->cell_meas_cfg_list[target_enb_cc_idx];
|
||||
|
||||
// Calculate difference between source and target VarMeasCfg
|
||||
bool meas_cfg_present = source_var_meas_cfg.compute_diff_meas_cfg(*target_var_ptr, diff_meas_cfg);
|
||||
|
||||
// Update user varMeasCfg to target
|
||||
rrc_ue->mobility_handler->ue_var_meas = target_var_ptr;
|
||||
|
||||
return meas_cfg_present;
|
||||
}
|
||||
|
||||
/**
|
||||
* TS 36.413, Section 8.4.6 - eNB Status Transfer
|
||||
* Description: Send "eNBStatusTransfer" message from source eNB to MME
|
||||
|
|
|
@ -285,8 +285,6 @@ void s1ap::get_metrics(s1ap_metrics_t& m)
|
|||
void s1ap::build_tai_cgi()
|
||||
{
|
||||
uint32_t plmn;
|
||||
uint32_t tmp32;
|
||||
uint16_t tmp16;
|
||||
|
||||
// TAI
|
||||
s1ap_mccmnc_to_plmn(args.mcc, args.mnc, &plmn);
|
||||
|
|
|
@ -237,7 +237,7 @@ int test_correct_meascfg_calculation()
|
|||
}
|
||||
|
||||
struct mobility_test_params {
|
||||
enum class test_fail_at { success, wrong_measreport, concurrent_ho, ho_prep_failure } fail_at;
|
||||
enum class test_fail_at { success, wrong_measreport, concurrent_ho, ho_prep_failure, recover } fail_at;
|
||||
const char* to_string()
|
||||
{
|
||||
switch (fail_at) {
|
||||
|
@ -249,15 +249,17 @@ struct mobility_test_params {
|
|||
return "measreport while in handover";
|
||||
case test_fail_at::ho_prep_failure:
|
||||
return "ho preparation failure";
|
||||
case test_fail_at::recover:
|
||||
return "fail and success";
|
||||
default:
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int test_mobility_class(mobility_test_params test_params)
|
||||
int test_s1ap_mobility(mobility_test_params test_params)
|
||||
{
|
||||
printf("\n===== TEST: test_mobility_class() for event \"%s\" =====\n", test_params.to_string());
|
||||
printf("\n===== TEST: test_s1ap_mobility() for event \"%s\" =====\n", test_params.to_string());
|
||||
srslte::scoped_log<srslte::test_log_filter> rrc_log("RRC ");
|
||||
srslte::timer_handler timers;
|
||||
srslte::unique_byte_buffer_t pdu;
|
||||
|
@ -266,11 +268,11 @@ int test_mobility_class(mobility_test_params test_params)
|
|||
rrc_cfg_t cfg;
|
||||
TESTASSERT(test_helpers::parse_default_cfg(&cfg, args) == SRSLTE_SUCCESS);
|
||||
report_cfg_eutra_s rep = generate_rep1();
|
||||
cfg.meas_cfg.meas_reports.push_back(rep);
|
||||
cfg.cell_list[0].meas_cfg.meas_reports.push_back(rep);
|
||||
meas_cell_cfg_t cell2 = generate_cell1();
|
||||
cell2.pci = 2;
|
||||
cell2.eci = 0x19C02;
|
||||
cfg.meas_cfg.meas_cells.push_back(cell2);
|
||||
cfg.cell_list[0].meas_cfg.meas_cells.push_back(cell2);
|
||||
cfg.meas_cfg_present = true;
|
||||
|
||||
srsenb::rrc rrc;
|
||||
|
@ -332,7 +334,7 @@ int test_mobility_class(mobility_test_params test_params)
|
|||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check HO Required was sent to S1AP */
|
||||
/* Test Case: Check HO Required was sent to S1AP */
|
||||
TESTASSERT(s1ap.last_ho_required.rnti == rnti);
|
||||
TESTASSERT(s1ap.last_ho_required.target_eci == cell2.eci);
|
||||
TESTASSERT(s1ap.last_ho_required.target_plmn.to_string() == "00101");
|
||||
|
@ -360,9 +362,14 @@ int test_mobility_class(mobility_test_params test_params)
|
|||
0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0xa7, 0xd0, 0xc1, 0xf6, 0xaf, 0x3e, 0x12, 0xcc,
|
||||
0x86, 0x0d, 0x30, 0x00, 0x0b, 0x5a, 0x02, 0x17, 0x86, 0x00, 0x05, 0xa0, 0x20};
|
||||
test_helpers::copy_msg_to_buffer(pdu, ho_cmd_rrc_container, sizeof(ho_cmd_rrc_container));
|
||||
TESTASSERT(s1ap.last_enb_status.rnti != rnti);
|
||||
rrc.ho_preparation_complete(rnti, true, std::move(pdu));
|
||||
|
||||
TESTASSERT(rrc_log->error_counter == 0);
|
||||
asn1::rrc::dl_dcch_msg_s ho_cmd;
|
||||
TESTASSERT(test_helpers::unpack_asn1(ho_cmd, pdcp.last_sdu.sdu));
|
||||
auto& recfg_r8 = ho_cmd.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8();
|
||||
TESTASSERT(recfg_r8.mob_ctrl_info_present);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -377,14 +384,14 @@ int main(int argc, char** argv)
|
|||
argparse::parse_args(argc, argv);
|
||||
TESTASSERT(test_correct_insertion() == 0);
|
||||
TESTASSERT(test_correct_meascfg_calculation() == 0);
|
||||
TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::wrong_measreport}) == 0);
|
||||
TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::concurrent_ho}) == 0);
|
||||
TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::ho_prep_failure}) == 0);
|
||||
TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::success}) == 0);
|
||||
TESTASSERT(test_s1ap_mobility(mobility_test_params{mobility_test_params::test_fail_at::wrong_measreport}) == 0);
|
||||
TESTASSERT(test_s1ap_mobility(mobility_test_params{mobility_test_params::test_fail_at::concurrent_ho}) == 0);
|
||||
TESTASSERT(test_s1ap_mobility(mobility_test_params{mobility_test_params::test_fail_at::ho_prep_failure}) == 0);
|
||||
TESTASSERT(test_s1ap_mobility(mobility_test_params{mobility_test_params::test_fail_at::success}) == 0);
|
||||
|
||||
printf("\nSuccess\n");
|
||||
|
||||
srslte::byte_buffer_pool::get_instance()->cleanup();
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,11 @@ public:
|
|||
uint32_t target_eci;
|
||||
srslte::plmn_id_t target_plmn;
|
||||
srslte::unique_byte_buffer_t rrc_container;
|
||||
} last_ho_required;
|
||||
} last_ho_required = {};
|
||||
struct enb_status_transfer_info {
|
||||
uint16_t rnti;
|
||||
std::vector<bearer_status_info> bearer_list;
|
||||
} last_enb_status = {};
|
||||
|
||||
bool send_ho_required(uint16_t rnti,
|
||||
uint32_t target_eci,
|
||||
|
@ -130,6 +134,17 @@ int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args)
|
|||
return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &phy_cfg);
|
||||
}
|
||||
|
||||
template <typename ASN1Type>
|
||||
bool unpack_asn1(ASN1Type& asn1obj, const srslte::unique_byte_buffer_t& pdu)
|
||||
{
|
||||
asn1::cbit_ref bref{pdu->msg, pdu->N_bytes};
|
||||
if (asn1obj.unpack(bref) != asn1::SRSASN_SUCCESS) {
|
||||
srslte::logmap::get("TEST")->error("Failed to unpack ASN1 type\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void copy_msg_to_buffer(srslte::unique_byte_buffer_t& pdu, uint8_t* msg, size_t nof_bytes)
|
||||
{
|
||||
srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance();
|
||||
|
@ -201,4 +216,4 @@ int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, u
|
|||
|
||||
} // namespace test_helpers
|
||||
|
||||
#endif // SRSENB_TEST_HELPERS_H
|
||||
#endif // SRSENB_TEST_HELPERS_H
|
||||
|
|
Loading…
Reference in New Issue