mirror of https://github.com/PentHertz/srsLTE.git
Add RLF-Reportv9 to srsUE
This commit is contained in:
parent
a366982e06
commit
7839ab09dc
|
@ -16,6 +16,7 @@
|
||||||
#include "rrc_cell.h"
|
#include "rrc_cell.h"
|
||||||
#include "rrc_common.h"
|
#include "rrc_common.h"
|
||||||
#include "rrc_metrics.h"
|
#include "rrc_metrics.h"
|
||||||
|
#include "rrc_rlf_report.h"
|
||||||
#include "srsran/asn1/rrc_utils.h"
|
#include "srsran/asn1/rrc_utils.h"
|
||||||
#include "srsran/common/bcd_helpers.h"
|
#include "srsran/common/bcd_helpers.h"
|
||||||
#include "srsran/common/block_queue.h"
|
#include "srsran/common/block_queue.h"
|
||||||
|
@ -218,6 +219,9 @@ private:
|
||||||
|
|
||||||
const char* get_rb_name(uint32_t lcid) { return srsran::is_lte_rb(lcid) ? rb_id_str[lcid].c_str() : "invalid RB"; }
|
const char* get_rb_name(uint32_t lcid) { return srsran::is_lte_rb(lcid) ? rb_id_str[lcid].c_str() : "invalid RB"; }
|
||||||
|
|
||||||
|
// Var-RLF-Report class
|
||||||
|
rrc_rlf_report var_rlf_report;
|
||||||
|
|
||||||
// Measurements private subclass
|
// Measurements private subclass
|
||||||
class rrc_meas;
|
class rrc_meas;
|
||||||
std::unique_ptr<rrc_meas> measurements;
|
std::unique_ptr<rrc_meas> measurements;
|
||||||
|
@ -375,6 +379,7 @@ private:
|
||||||
void handle_con_reest(const asn1::rrc::rrc_conn_reest_s& setup);
|
void handle_con_reest(const asn1::rrc::rrc_conn_reest_s& setup);
|
||||||
void handle_rrc_con_reconfig(uint32_t lcid, const asn1::rrc::rrc_conn_recfg_s& reconfig);
|
void handle_rrc_con_reconfig(uint32_t lcid, const asn1::rrc::rrc_conn_recfg_s& reconfig);
|
||||||
void handle_ue_capability_enquiry(const asn1::rrc::ue_cap_enquiry_s& enquiry);
|
void handle_ue_capability_enquiry(const asn1::rrc::ue_cap_enquiry_s& enquiry);
|
||||||
|
void handle_ue_info_request(const ue_info_request_r9_s& request);
|
||||||
void add_srb(const asn1::rrc::srb_to_add_mod_s& srb_cnfg);
|
void add_srb(const asn1::rrc::srb_to_add_mod_s& srb_cnfg);
|
||||||
void add_drb(const asn1::rrc::drb_to_add_mod_s& drb_cnfg);
|
void add_drb(const asn1::rrc::drb_to_add_mod_s& drb_cnfg);
|
||||||
void release_drb(uint32_t drb_id);
|
void release_drb(uint32_t drb_id);
|
||||||
|
|
|
@ -147,6 +147,7 @@ public:
|
||||||
bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const;
|
bool has_plmn_id(asn1::rrc::plmn_id_s plmn_id) const;
|
||||||
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
|
uint32_t nof_plmns() const { return has_sib1() ? sib1.cell_access_related_info.plmn_id_list.size() : 0; }
|
||||||
srsran::plmn_id_t get_plmn(uint32_t idx) const;
|
srsran::plmn_id_t get_plmn(uint32_t idx) const;
|
||||||
|
asn1::rrc::plmn_id_s get_plmn_asn1(uint32_t idx) const;
|
||||||
|
|
||||||
uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; }
|
uint16_t get_tac() const { return has_sib1() ? (uint16_t)sib1.cell_access_related_info.tac.to_number() : 0; }
|
||||||
|
|
||||||
|
@ -161,6 +162,7 @@ public:
|
||||||
const asn1::rrc::sib_type13_r9_s* sib13ptr() const { return has_sib13() ? &sib13 : nullptr; }
|
const asn1::rrc::sib_type13_r9_s* sib13ptr() const { return has_sib13() ? &sib13 : nullptr; }
|
||||||
|
|
||||||
uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
|
uint32_t get_cell_id() const { return (uint32_t)sib1.cell_access_related_info.cell_id.to_number(); }
|
||||||
|
asn1::fixed_bitstring<28> get_cell_id_bit() const { return sib1.cell_access_related_info.cell_id; }
|
||||||
|
|
||||||
bool has_sib13() const { return has_valid_sib13; }
|
bool has_sib13() const { return has_valid_sib13; }
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
namespace srsue {
|
namespace srsue {
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
// RRC states (3GPP 36.331 v10.0.0)
|
// RRC states (3GPP 36.331 v10.0.0)
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RRC_STATE_IDLE = 0,
|
RRC_STATE_IDLE = 0,
|
||||||
|
@ -23,6 +25,11 @@ typedef enum {
|
||||||
} rrc_state_t;
|
} rrc_state_t;
|
||||||
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "CONNECTED"};
|
static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "CONNECTED"};
|
||||||
|
|
||||||
|
enum quant_s { quant_rsrp, quant_rsrq };
|
||||||
|
|
||||||
|
uint8_t rrc_value_to_range(quant_s quant, const float value);
|
||||||
|
float rrc_range_to_value(quant_s quant, const uint8_t range);
|
||||||
|
|
||||||
} // namespace srsue
|
} // namespace srsue
|
||||||
|
|
||||||
#endif // SRSUE_RRC_COMMON_H
|
#endif // SRSUE_RRC_COMMON_H
|
||||||
|
|
|
@ -192,8 +192,6 @@ private:
|
||||||
rrc* rrc_ptr = nullptr;
|
rrc* rrc_ptr = nullptr;
|
||||||
|
|
||||||
// Static functions
|
// Static functions
|
||||||
static uint8_t value_to_range(const report_cfg_eutra_s::trigger_quant_opts::options q, float value);
|
|
||||||
static float range_to_value(const report_cfg_eutra_s::trigger_quant_opts::options q, const uint8_t range);
|
|
||||||
static uint8_t value_to_range_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const float value);
|
static uint8_t value_to_range_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const float value);
|
||||||
static float range_to_value_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const uint8_t range);
|
static float range_to_value_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const uint8_t range);
|
||||||
static uint8_t offset_val(const meas_obj_eutra_s& meas_obj);
|
static uint8_t offset_val(const meas_obj_eutra_s& meas_obj);
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef SRSRAN_RRC_RLF_REPORT_H_
|
||||||
|
#define SRSRAN_RRC_RLF_REPORT_H_
|
||||||
|
|
||||||
|
#include "rrc_cell.h"
|
||||||
|
#include "srsran/asn1/rrc.h"
|
||||||
|
#include "srsran/common/common.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
using namespace asn1::rrc;
|
||||||
|
|
||||||
|
// RRC RLF-Report class
|
||||||
|
class rrc_rlf_report
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum failure_type_t { rlf, hof };
|
||||||
|
|
||||||
|
void init(srsran::task_sched_handle task_sched);
|
||||||
|
|
||||||
|
// Returns true if VarRLF-Report structure has info available
|
||||||
|
bool has_info();
|
||||||
|
|
||||||
|
// Called upon T304 expiry (type == hof) or Detection of radio link failure (type == rlf)
|
||||||
|
void set_failure(meas_cell_list<meas_cell_eutra>& meas_cells, failure_type_t type);
|
||||||
|
|
||||||
|
// Called upon transmission of ReestablishmentRequest message
|
||||||
|
void set_reest_gci(const asn1::fixed_bitstring<28>& gci, const asn1::rrc::plmn_id_s& plmn_id);
|
||||||
|
|
||||||
|
// Called upon initiation of RadioReconfiguration message including MobilityInfo IE
|
||||||
|
void received_ho_command(const asn1::fixed_bitstring<28>& current_gci);
|
||||||
|
|
||||||
|
// Returns a copy of the rlf_report_r9 ASN1 struct
|
||||||
|
rlf_report_r9_s get_report();
|
||||||
|
|
||||||
|
// Clears VarRLF-Report contents
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
asn1::fixed_bitstring<28> ho_gci;
|
||||||
|
|
||||||
|
bool has_event = false;
|
||||||
|
rlf_report_r9_s rlf_report = {};
|
||||||
|
srsran::timer_handler::unique_timer timer_conn_failure = {};
|
||||||
|
};
|
||||||
|
} // namespace srsue
|
||||||
|
|
||||||
|
#endif // SRSRAN_RRC_RLF_REPORT_H_
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|
||||||
set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc phy_controller.cc)
|
set(SOURCES rrc.cc rrc_procedures.cc rrc_meas.cc rrc_cell.cc rrc_common.cc rrc_rlf_report.cc phy_controller.cc)
|
||||||
add_library(srsue_rrc STATIC ${SOURCES})
|
add_library(srsue_rrc STATIC ${SOURCES})
|
||||||
|
|
||||||
set(SOURCES rrc_nr.cc)
|
set(SOURCES rrc_nr.cc)
|
||||||
|
|
|
@ -139,6 +139,8 @@ void rrc::init(phy_interface_rrc_lte* phy_,
|
||||||
t311 = task_sched.get_unique_timer();
|
t311 = task_sched.get_unique_timer();
|
||||||
t304 = task_sched.get_unique_timer();
|
t304 = task_sched.get_unique_timer();
|
||||||
|
|
||||||
|
var_rlf_report.init(task_sched);
|
||||||
|
|
||||||
transaction_id = 0;
|
transaction_id = 0;
|
||||||
|
|
||||||
cell_clean_cnt = 0;
|
cell_clean_cnt = 0;
|
||||||
|
@ -674,6 +676,9 @@ void rrc::radio_link_failure_process()
|
||||||
// TODO: Generate and store failure report
|
// TODO: Generate and store failure report
|
||||||
srsran::console("Warning: Detected Radio-Link Failure\n");
|
srsran::console("Warning: Detected Radio-Link Failure\n");
|
||||||
|
|
||||||
|
// Store the information in VarRLF-Report
|
||||||
|
var_rlf_report.set_failure(meas_cells, rrc_rlf_report::rlf);
|
||||||
|
|
||||||
if (state == RRC_STATE_CONNECTED) {
|
if (state == RRC_STATE_CONNECTED) {
|
||||||
if (security_is_activated) {
|
if (security_is_activated) {
|
||||||
logger.info("Detected Radio-Link Failure with active AS security. Starting ConnectionReestablishment...");
|
logger.info("Detected Radio-Link Failure with active AS security. Starting ConnectionReestablishment...");
|
||||||
|
@ -857,6 +862,9 @@ void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint1
|
||||||
// Clean reestablishment type
|
// Clean reestablishment type
|
||||||
reestablishment_successful = false;
|
reestablishment_successful = false;
|
||||||
|
|
||||||
|
// set the reestablishmentCellId in the VarRLF-Report to the global cell identity of the selected cell;
|
||||||
|
var_rlf_report.set_reest_gci(meas_cells.serving_cell().get_cell_id_bit(), meas_cells.serving_cell().get_plmn_asn1(0));
|
||||||
|
|
||||||
if (cause.value != reest_cause_opts::ho_fail) {
|
if (cause.value != reest_cause_opts::ho_fail) {
|
||||||
if (cause.value != reest_cause_opts::other_fail) {
|
if (cause.value != reest_cause_opts::other_fail) {
|
||||||
pci = meas_cells.serving_cell().get_pci();
|
pci = meas_cells.serving_cell().get_pci();
|
||||||
|
@ -945,6 +953,15 @@ void rrc::send_con_restablish_complete()
|
||||||
ul_dcch_msg.msg.set_c1().set_rrc_conn_reest_complete().crit_exts.set_rrc_conn_reest_complete_r8();
|
ul_dcch_msg.msg.set_c1().set_rrc_conn_reest_complete().crit_exts.set_rrc_conn_reest_complete_r8();
|
||||||
ul_dcch_msg.msg.c1().rrc_conn_reest_complete().rrc_transaction_id = transaction_id;
|
ul_dcch_msg.msg.c1().rrc_conn_reest_complete().rrc_transaction_id = transaction_id;
|
||||||
|
|
||||||
|
// Include rlf-InfoAvailable
|
||||||
|
if (var_rlf_report.has_info()) {
|
||||||
|
ul_dcch_msg.msg.c1().rrc_conn_reest_complete().crit_exts.rrc_conn_reest_complete_r8().non_crit_ext_present = true;
|
||||||
|
ul_dcch_msg.msg.c1()
|
||||||
|
.rrc_conn_reest_complete()
|
||||||
|
.crit_exts.rrc_conn_reest_complete_r8()
|
||||||
|
.non_crit_ext.rlf_info_available_r9_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
||||||
|
|
||||||
reestablishment_successful = true;
|
reestablishment_successful = true;
|
||||||
|
@ -961,6 +978,13 @@ void rrc::send_con_setup_complete(srsran::unique_byte_buffer_t nas_msg)
|
||||||
|
|
||||||
ul_dcch_msg.msg.c1().rrc_conn_setup_complete().rrc_transaction_id = transaction_id;
|
ul_dcch_msg.msg.c1().rrc_conn_setup_complete().rrc_transaction_id = transaction_id;
|
||||||
|
|
||||||
|
// Include rlf-InfoAvailable
|
||||||
|
if (var_rlf_report.has_info()) {
|
||||||
|
rrc_conn_setup_complete->non_crit_ext_present = true;
|
||||||
|
rrc_conn_setup_complete->non_crit_ext.non_crit_ext_present = true;
|
||||||
|
rrc_conn_setup_complete->non_crit_ext.non_crit_ext.rlf_info_available_r10_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
rrc_conn_setup_complete->sel_plmn_id = 1;
|
rrc_conn_setup_complete->sel_plmn_id = 1;
|
||||||
rrc_conn_setup_complete->ded_info_nas.resize(nas_msg->N_bytes);
|
rrc_conn_setup_complete->ded_info_nas.resize(nas_msg->N_bytes);
|
||||||
memcpy(rrc_conn_setup_complete->ded_info_nas.data(), nas_msg->msg, nas_msg->N_bytes); // TODO Check!
|
memcpy(rrc_conn_setup_complete->ded_info_nas.data(), nas_msg->msg, nas_msg->N_bytes); // TODO Check!
|
||||||
|
@ -1005,6 +1029,13 @@ void rrc::send_rrc_con_reconfig_complete(bool contains_nr_complete)
|
||||||
&ul_dcch_msg.msg.set_c1().set_rrc_conn_recfg_complete().crit_exts.set_rrc_conn_recfg_complete_r8();
|
&ul_dcch_msg.msg.set_c1().set_rrc_conn_recfg_complete().crit_exts.set_rrc_conn_recfg_complete_r8();
|
||||||
ul_dcch_msg.msg.c1().rrc_conn_recfg_complete().rrc_transaction_id = transaction_id;
|
ul_dcch_msg.msg.c1().rrc_conn_recfg_complete().rrc_transaction_id = transaction_id;
|
||||||
|
|
||||||
|
// Include rlf-InfoAvailable
|
||||||
|
if (var_rlf_report.has_info()) {
|
||||||
|
rrc_conn_recfg_complete_r8->non_crit_ext_present = true;
|
||||||
|
rrc_conn_recfg_complete_r8->non_crit_ext.non_crit_ext_present = true;
|
||||||
|
rrc_conn_recfg_complete_r8->non_crit_ext.non_crit_ext.rlf_info_available_r10_present = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (contains_nr_complete == true) {
|
if (contains_nr_complete == true) {
|
||||||
logger.debug("Preparing RRC Connection Reconfig Complete with NR Complete");
|
logger.debug("Preparing RRC Connection Reconfig Complete with NR Complete");
|
||||||
|
|
||||||
|
@ -1055,6 +1086,10 @@ void rrc::start_go_idle()
|
||||||
void rrc::ho_failed()
|
void rrc::ho_failed()
|
||||||
{
|
{
|
||||||
ho_handler.trigger(ho_proc::t304_expiry{});
|
ho_handler.trigger(ho_proc::t304_expiry{});
|
||||||
|
|
||||||
|
// Store the information in VarRLF-Report
|
||||||
|
var_rlf_report.set_failure(meas_cells, rrc_rlf_report::hof);
|
||||||
|
|
||||||
start_con_restablishment(reest_cause_e::ho_fail);
|
start_con_restablishment(reest_cause_e::ho_fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1757,6 +1792,10 @@ void rrc::parse_dl_dcch(uint32_t lcid, unique_byte_buffer_t pdu)
|
||||||
case dl_dcch_msg_type_c::c1_c_::types::rrc_conn_release:
|
case dl_dcch_msg_type_c::c1_c_::types::rrc_conn_release:
|
||||||
rrc_connection_release(c1->rrc_conn_release().crit_exts.c1().rrc_conn_release_r8().release_cause.to_string());
|
rrc_connection_release(c1->rrc_conn_release().crit_exts.c1().rrc_conn_release_r8().release_cause.to_string());
|
||||||
break;
|
break;
|
||||||
|
case dl_dcch_msg_type_c::c1_c_::types::ue_info_request_r9:
|
||||||
|
transaction_id = c1->ue_info_request_r9().rrc_transaction_id;
|
||||||
|
handle_ue_info_request(c1->ue_info_request_r9());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
logger.error("The provided DL-CCCH message type is not recognized or supported");
|
logger.error("The provided DL-CCCH message type is not recognized or supported");
|
||||||
break;
|
break;
|
||||||
|
@ -2136,6 +2175,42 @@ void rrc::handle_ue_capability_enquiry(const ue_cap_enquiry_s& enquiry)
|
||||||
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* UEInformationRequest message
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*******************************************************************************/
|
||||||
|
void rrc::handle_ue_info_request(const ue_info_request_r9_s& request)
|
||||||
|
{
|
||||||
|
logger.debug("Preparing UEInformationResponse message");
|
||||||
|
|
||||||
|
ul_dcch_msg_s ul_dcch_msg;
|
||||||
|
ue_info_resp_r9_ies_s* resp =
|
||||||
|
&ul_dcch_msg.msg.set_c1().set_ue_info_resp_r9().crit_exts.set_c1().set_ue_info_resp_r9();
|
||||||
|
ul_dcch_msg.msg.c1().ue_info_resp_r9().rrc_transaction_id = transaction_id;
|
||||||
|
|
||||||
|
// if rach-ReportReq is set to true, set the contents of the rach-Report in the UEInformationResponse message as
|
||||||
|
// follows
|
||||||
|
if (request.crit_exts.c1().ue_info_request_r9().rach_report_req_r9) {
|
||||||
|
// todo...
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include rlf-Report if rlf-ReportReq is set to true
|
||||||
|
if (request.crit_exts.c1().ue_info_request_r9().rlf_report_req_r9 && var_rlf_report.has_info()) {
|
||||||
|
resp->rlf_report_r9_present = true;
|
||||||
|
resp->rlf_report_r9 = var_rlf_report.get_report();
|
||||||
|
|
||||||
|
// fixme: should be cleared upon successful delivery
|
||||||
|
var_rlf_report.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
send_ul_dcch_msg(srb_to_lcid(lte_srb::srb1), ul_dcch_msg);
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,6 +33,15 @@ srsran::plmn_id_t meas_cell_eutra::get_plmn(uint32_t idx) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asn1::rrc::plmn_id_s meas_cell_eutra::get_plmn_asn1(uint32_t idx) const
|
||||||
|
{
|
||||||
|
if (idx < sib1.cell_access_related_info.plmn_id_list.size() && has_valid_sib1) {
|
||||||
|
return sib1.cell_access_related_info.plmn_id_list[idx].plmn_id;
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void meas_cell_eutra::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
|
void meas_cell_eutra::set_sib1(const asn1::rrc::sib_type1_s& sib1_)
|
||||||
{
|
{
|
||||||
sib1 = sib1_;
|
sib1 = sib1_;
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsue/hdr/stack/rrc/rrc_common.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
uint8_t rrc_value_to_range(quant_s quant, const float value)
|
||||||
|
{
|
||||||
|
uint8_t range = 0;
|
||||||
|
if (quant == quant_rsrp) {
|
||||||
|
if (value < -140) {
|
||||||
|
range = 0;
|
||||||
|
} else if (value < -44) {
|
||||||
|
range = 1u + (uint8_t)(value + 140);
|
||||||
|
} else {
|
||||||
|
range = 97;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (value < -19.5) {
|
||||||
|
range = 0;
|
||||||
|
} else if (value < -3) {
|
||||||
|
range = 1u + (uint8_t)(2 * (value + 19.5));
|
||||||
|
} else {
|
||||||
|
range = 34;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rrc_range_to_value(quant_s quant, const uint8_t range)
|
||||||
|
{
|
||||||
|
float val = 0;
|
||||||
|
if (quant == quant_rsrp) {
|
||||||
|
val = -140 + (float)range;
|
||||||
|
} else {
|
||||||
|
val = -19.5f + (float)range / 2;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsue
|
|
@ -130,50 +130,6 @@ void rrc::rrc_meas::run_tti()
|
||||||
meas_cfg.report_triggers();
|
meas_cfg.report_triggers();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t rrc::rrc_meas::value_to_range(const report_cfg_eutra_s::trigger_quant_opts::options quant, const float value)
|
|
||||||
{
|
|
||||||
uint8_t range = 0;
|
|
||||||
switch (quant) {
|
|
||||||
case report_cfg_eutra_s::trigger_quant_opts::rsrp:
|
|
||||||
if (value < -140) {
|
|
||||||
range = 0;
|
|
||||||
} else if (value < -44) {
|
|
||||||
range = 1u + (uint8_t)(value + 140);
|
|
||||||
} else {
|
|
||||||
range = 97;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case report_cfg_eutra_s::trigger_quant_opts::rsrq:
|
|
||||||
if (value < -19.5) {
|
|
||||||
range = 0;
|
|
||||||
} else if (value < -3) {
|
|
||||||
range = 1u + (uint8_t)(2 * (value + 19.5));
|
|
||||||
} else {
|
|
||||||
range = 34;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return range;
|
|
||||||
}
|
|
||||||
|
|
||||||
float rrc::rrc_meas::range_to_value(const report_cfg_eutra_s::trigger_quant_opts::options quant, const uint8_t range)
|
|
||||||
{
|
|
||||||
float val = 0;
|
|
||||||
switch (quant) {
|
|
||||||
case report_cfg_eutra_s::trigger_quant_opts::rsrp:
|
|
||||||
val = -140 + (float)range;
|
|
||||||
break;
|
|
||||||
case report_cfg_eutra_s::trigger_quant_opts::rsrq:
|
|
||||||
val = -19.5f + (float)range / 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For thresholds, the actual value is (field value – 156) dBm, except for field value 127, in which case the actual
|
// For thresholds, the actual value is (field value – 156) dBm, except for field value 127, in which case the actual
|
||||||
// value is infinity.
|
// value is infinity.
|
||||||
float rrc::rrc_meas::range_to_value_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const uint8_t range)
|
float rrc::rrc_meas::range_to_value_nr(const asn1::rrc::thres_nr_r15_c::types_opts::options type, const uint8_t range)
|
||||||
|
@ -303,8 +259,8 @@ void rrc::rrc_meas::var_meas_report_list::generate_report_eutra(meas_results_s*
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc.pci = (uint16_t)cell.pci;
|
rc.pci = (uint16_t)cell.pci;
|
||||||
rc.meas_result.rsrp_result = value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrp, rsrp_value);
|
rc.meas_result.rsrp_result = rrc_value_to_range(quant_rsrp, rsrp_value);
|
||||||
rc.meas_result.rsrq_result = value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrq, rsrq_value);
|
rc.meas_result.rsrq_result = rrc_value_to_range(quant_rsrq, rsrq_value);
|
||||||
|
|
||||||
logger.info("MEAS: Adding to report neighbour=%d, pci=%d, earfcn=%d, rsrp=%+.1f, rsrq=%+.1f",
|
logger.info("MEAS: Adding to report neighbour=%d, pci=%d, earfcn=%d, rsrp=%+.1f, rsrq=%+.1f",
|
||||||
neigh_list.size(),
|
neigh_list.size(),
|
||||||
|
@ -448,10 +404,8 @@ void rrc::rrc_meas::var_meas_report_list::generate_report(const uint32_t measId)
|
||||||
meas_results_s* report = &ul_dcch_msg.msg.c1().meas_report().crit_exts.c1().meas_report_r8().meas_results;
|
meas_results_s* report = &ul_dcch_msg.msg.c1().meas_report().crit_exts.c1().meas_report_r8().meas_results;
|
||||||
|
|
||||||
report->meas_id = (uint8_t)measId;
|
report->meas_id = (uint8_t)measId;
|
||||||
report->meas_result_pcell.rsrp_result =
|
report->meas_result_pcell.rsrp_result = rrc_value_to_range(quant_rsrp, serv_cell->get_rsrp());
|
||||||
value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrp, serv_cell->get_rsrp());
|
report->meas_result_pcell.rsrq_result = rrc_value_to_range(quant_rsrq, serv_cell->get_rsrq());
|
||||||
report->meas_result_pcell.rsrq_result =
|
|
||||||
value_to_range(report_cfg_eutra_s::trigger_quant_opts::rsrq, serv_cell->get_rsrq());
|
|
||||||
|
|
||||||
logger.info("MEAS: Generate report MeasId=%d, Pcell rsrp=%f rsrq=%f",
|
logger.info("MEAS: Generate report MeasId=%d, Pcell rsrp=%f rsrq=%f",
|
||||||
report->meas_id,
|
report->meas_id,
|
||||||
|
@ -805,6 +759,14 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
||||||
float Ofs,
|
float Ofs,
|
||||||
float Ocs)
|
float Ocs)
|
||||||
{
|
{
|
||||||
|
auto asn1_quant_convert = [](report_cfg_eutra_s::trigger_quant_e_ q) {
|
||||||
|
if (q == report_cfg_eutra_s::trigger_quant_opts::rsrp) {
|
||||||
|
return quant_rsrp;
|
||||||
|
} else {
|
||||||
|
return quant_rsrq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
double hyst = 0.5 * report_cfg.trigger_type.event().hysteresis;
|
double hyst = 0.5 * report_cfg.trigger_type.event().hysteresis;
|
||||||
float Ms = is_rsrp(report_cfg.trigger_quant.value) ? serv_cell->get_rsrp() : serv_cell->get_rsrq();
|
float Ms = is_rsrp(report_cfg.trigger_quant.value) ? serv_cell->get_rsrp() : serv_cell->get_rsrq();
|
||||||
|
|
||||||
|
@ -823,17 +785,21 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
||||||
bool exit_condition = false;
|
bool exit_condition = false;
|
||||||
if (event_id.type() == eutra_event_s::event_id_c_::types::event_a1) {
|
if (event_id.type() == eutra_event_s::event_id_c_::types::event_a1) {
|
||||||
if (event_id.event_a1().a1_thres.type().value == thres_eutra_c::types::thres_rsrp) {
|
if (event_id.event_a1().a1_thres.type().value == thres_eutra_c::types::thres_rsrp) {
|
||||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a1().a1_thres.thres_rsrp());
|
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||||
|
event_id.event_a1().a1_thres.thres_rsrp());
|
||||||
} else {
|
} else {
|
||||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a1().a1_thres.thres_rsrq());
|
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||||
|
event_id.event_a1().a1_thres.thres_rsrq());
|
||||||
}
|
}
|
||||||
enter_condition = Ms - hyst > thresh;
|
enter_condition = Ms - hyst > thresh;
|
||||||
exit_condition = Ms + hyst < thresh;
|
exit_condition = Ms + hyst < thresh;
|
||||||
} else {
|
} else {
|
||||||
if (event_id.event_a2().a2_thres.type() == thres_eutra_c::types::thres_rsrp) {
|
if (event_id.event_a2().a2_thres.type() == thres_eutra_c::types::thres_rsrp) {
|
||||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a2().a2_thres.thres_rsrp());
|
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||||
|
event_id.event_a2().a2_thres.thres_rsrp());
|
||||||
} else {
|
} else {
|
||||||
thresh = range_to_value(report_cfg.trigger_quant, event_id.event_a2().a2_thres.thres_rsrq());
|
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant),
|
||||||
|
event_id.event_a2().a2_thres.thres_rsrq());
|
||||||
}
|
}
|
||||||
enter_condition = Ms + hyst < thresh;
|
enter_condition = Ms + hyst < thresh;
|
||||||
exit_condition = Ms - hyst > thresh;
|
exit_condition = Ms - hyst > thresh;
|
||||||
|
@ -884,7 +850,7 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
||||||
} else {
|
} else {
|
||||||
range = event_id.event_a4().a4_thres.thres_rsrq();
|
range = event_id.event_a4().a4_thres.thres_rsrq();
|
||||||
}
|
}
|
||||||
thresh = range_to_value(report_cfg.trigger_quant.value, range);
|
thresh = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant.value), range);
|
||||||
enter_condition = Mn + Ofn + Ocn - hyst > thresh;
|
enter_condition = Mn + Ofn + Ocn - hyst > thresh;
|
||||||
exit_condition = Mn + Ofn + Ocn + hyst < thresh;
|
exit_condition = Mn + Ofn + Ocn + hyst < thresh;
|
||||||
break;
|
break;
|
||||||
|
@ -899,8 +865,8 @@ void rrc::rrc_meas::var_meas_cfg::eval_triggers_eutra(uint32_t meas_i
|
||||||
} else {
|
} else {
|
||||||
range2 = event_id.event_a5().a5_thres2.thres_rsrq();
|
range2 = event_id.event_a5().a5_thres2.thres_rsrq();
|
||||||
}
|
}
|
||||||
th1 = range_to_value(report_cfg.trigger_quant.value, range);
|
th1 = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant.value), range);
|
||||||
th2 = range_to_value(report_cfg.trigger_quant.value, range2);
|
th2 = rrc_range_to_value(asn1_quant_convert(report_cfg.trigger_quant.value), range2);
|
||||||
enter_condition = (Ms + hyst < th1) && (Mn + Ofn + Ocn - hyst > th2);
|
enter_condition = (Ms + hyst < th1) && (Mn + Ofn + Ocn - hyst > th2);
|
||||||
exit_condition = (Ms - hyst > th1) && (Mn + Ofn + Ocn + hyst < th2);
|
exit_condition = (Ms - hyst > th1) && (Mn + Ofn + Ocn + hyst < th2);
|
||||||
break;
|
break;
|
||||||
|
@ -1470,19 +1436,18 @@ void rrc::rrc_meas::var_meas_cfg::log_debug_trigger_value_eutra(const eutra_even
|
||||||
switch (e.type()) {
|
switch (e.type()) {
|
||||||
case eutra_event_s::event_id_c_::types_opts::event_a1:
|
case eutra_event_s::event_id_c_::types_opts::event_a1:
|
||||||
logger.debug("MEAS: A1-threshold=%.1f dBm",
|
logger.debug("MEAS: A1-threshold=%.1f dBm",
|
||||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a1().a1_thres.thres_rsrp()));
|
rrc_range_to_value(quant_rsrp, e.event_a1().a1_thres.thres_rsrp()));
|
||||||
break;
|
break;
|
||||||
case eutra_event_s::event_id_c_::types_opts::event_a2:
|
case eutra_event_s::event_id_c_::types_opts::event_a2:
|
||||||
logger.debug("MEAS: A2-threshold=%.1f dBm",
|
logger.debug("MEAS: A2-threshold=%.1f dBm",
|
||||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a2().a2_thres.thres_rsrp()));
|
rrc_range_to_value(quant_rsrp, e.event_a2().a2_thres.thres_rsrp()));
|
||||||
break;
|
break;
|
||||||
case eutra_event_s::event_id_c_::types_opts::event_a3:
|
case eutra_event_s::event_id_c_::types_opts::event_a3:
|
||||||
logger.debug("MEAS: A3-offset=%.1f dB",
|
logger.debug("MEAS: A3-offset=%.1f dB", rrc_range_to_value(quant_rsrp, e.event_a3().a3_offset));
|
||||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a3().a3_offset));
|
|
||||||
break;
|
break;
|
||||||
case eutra_event_s::event_id_c_::types_opts::event_a4:
|
case eutra_event_s::event_id_c_::types_opts::event_a4:
|
||||||
logger.debug("MEAS: A4-threshold=%.1f dBm",
|
logger.debug("MEAS: A4-threshold=%.1f dBm",
|
||||||
range_to_value(report_cfg_eutra_s::trigger_quant_opts::rsrp, e.event_a4().a4_thres.thres_rsrp()));
|
rrc_range_to_value(quant_rsrp, e.event_a4().a4_thres.thres_rsrp()));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.debug("MEAS: Unsupported");
|
logger.debug("MEAS: Unsupported");
|
||||||
|
@ -1597,7 +1562,7 @@ bool rrc::rrc_meas::var_meas_cfg::parse_meas_config(const meas_cfg_s* cfg, bool
|
||||||
// set the parameter s-Measure within VarMeasConfig to the lowest value of the RSRP ranges indicated by the
|
// set the parameter s-Measure within VarMeasConfig to the lowest value of the RSRP ranges indicated by the
|
||||||
// received value of s-Measure
|
// received value of s-Measure
|
||||||
if (cfg->s_measure) {
|
if (cfg->s_measure) {
|
||||||
s_measure_value = range_to_value(report_cfg_eutra_s::trigger_quant_opts::options::rsrp, cfg->s_measure);
|
s_measure_value = rrc_range_to_value(quant_rsrp, cfg->s_measure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1656,6 +1656,9 @@ srsran::proc_outcome_t rrc::ho_proc::init(const asn1::rrc::rrc_conn_recfg_s& rrc
|
||||||
rrc_ptr->t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { rrc_ptr->timer_expired(tid); });
|
rrc_ptr->t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { rrc_ptr->timer_expired(tid); });
|
||||||
rrc_ptr->t304.run();
|
rrc_ptr->t304.run();
|
||||||
|
|
||||||
|
// Indicate RLF-Report that a new HO has been received
|
||||||
|
rrc_ptr->var_rlf_report.received_ho_command(rrc_ptr->meas_cells.serving_cell().get_cell_id_bit());
|
||||||
|
|
||||||
// starting at start synchronising to the DL of the target PCell
|
// starting at start synchronising to the DL of the target PCell
|
||||||
rrc_ptr->set_serving_cell(target_cell, false);
|
rrc_ptr->set_serving_cell(target_cell, false);
|
||||||
Info("Starting cell selection of target cell PCI=%d EARFCN=%d", target_cell.pci, target_cell.earfcn);
|
Info("Starting cell selection of target cell PCI=%d EARFCN=%d", target_cell.pci, target_cell.earfcn);
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsue/hdr/stack/rrc/rrc_rlf_report.h"
|
||||||
|
#include "srsue/hdr/stack/rrc/rrc_common.h"
|
||||||
|
|
||||||
|
namespace srsue {
|
||||||
|
|
||||||
|
void rrc_rlf_report::init(srsran::task_sched_handle task_sched)
|
||||||
|
{
|
||||||
|
timer_conn_failure = task_sched.get_unique_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if VarRLF-Report structure has info available
|
||||||
|
bool rrc_rlf_report::has_info()
|
||||||
|
{
|
||||||
|
return has_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called upon T304 expiry (type == hof) or Detection of radio link failure (type == rlf)
|
||||||
|
void rrc_rlf_report::set_failure(meas_cell_list<meas_cell_eutra>& meas_cells, failure_type_t type)
|
||||||
|
{
|
||||||
|
has_event = true;
|
||||||
|
|
||||||
|
// clear the information included in VarRLF-Report, if any
|
||||||
|
rlf_report = {};
|
||||||
|
|
||||||
|
// set the plmn-Identity to the RPLMN
|
||||||
|
|
||||||
|
// set the measResultLastServCell to include the RSRP and RSRQ, if available, of the PCell based on
|
||||||
|
// measurements collected up to the moment the UE detected radio link failure
|
||||||
|
rlf_report.meas_result_last_serv_cell_r9.rsrp_result_r9 =
|
||||||
|
rrc_value_to_range(quant_rsrp, meas_cells.serving_cell().get_rsrp());
|
||||||
|
rlf_report.meas_result_last_serv_cell_r9.rsrq_result_r9 =
|
||||||
|
rrc_value_to_range(quant_rsrq, meas_cells.serving_cell().get_rsrq());
|
||||||
|
rlf_report.meas_result_last_serv_cell_r9.rsrq_result_r9_present = true;
|
||||||
|
|
||||||
|
// set the measResultNeighCells to include the best measured cells, other than the PCell, ordered such that
|
||||||
|
// the best cell is listed first, and based on measurements collected up to the moment the UE detected radio
|
||||||
|
// link failure
|
||||||
|
if (meas_cells.nof_neighbours() > 0) {
|
||||||
|
rlf_report.meas_result_neigh_cells_r9_present = true;
|
||||||
|
rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present = true;
|
||||||
|
rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.clear();
|
||||||
|
meas_cells.sort_neighbour_cells();
|
||||||
|
// It is not clear how the sorting and grouping of cells per frequency must be done.
|
||||||
|
// We use a separate MeasResultList2EUTRA-r9 struct for each pci/frequency pair
|
||||||
|
for (const auto& f : meas_cells) {
|
||||||
|
meas_result2_eutra_r9_s meas2 = {};
|
||||||
|
meas2.carrier_freq_r9 = f->get_earfcn();
|
||||||
|
meas_result_eutra_s meas = {};
|
||||||
|
meas.pci = f->get_pci();
|
||||||
|
meas.meas_result.rsrp_result_present = true;
|
||||||
|
meas.meas_result.rsrq_result_present = true;
|
||||||
|
meas.meas_result.rsrp_result = rrc_value_to_range(quant_rsrp, f->get_rsrp());
|
||||||
|
meas.meas_result.rsrq_result = rrc_value_to_range(quant_rsrq, f->get_rsrq());
|
||||||
|
meas2.meas_result_list_r9.push_back(meas);
|
||||||
|
rlf_report.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.push_back(meas2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the failedPCellId to the global cell identity, if available, and otherwise to the physical cell identity and
|
||||||
|
// carrier frequency of the PCell where radio link failure is detected;
|
||||||
|
rlf_report.failed_pcell_id_r10.set_present(true);
|
||||||
|
if (meas_cells.serving_cell().has_sib1()) {
|
||||||
|
rlf_report.failed_pcell_id_r10->set_cell_global_id_r10().cell_id = meas_cells.serving_cell().get_cell_id_bit();
|
||||||
|
rlf_report.failed_pcell_id_r10->cell_global_id_r10().plmn_id = meas_cells.serving_cell().get_plmn_asn1(0);
|
||||||
|
} else {
|
||||||
|
rlf_report.failed_pcell_id_r10->set_pci_arfcn_r10();
|
||||||
|
rlf_report.failed_pcell_id_r10->pci_arfcn_r10().pci_r10 = meas_cells.serving_cell().get_pci();
|
||||||
|
rlf_report.failed_pcell_id_r10->pci_arfcn_r10().carrier_freq_r10 = meas_cells.serving_cell().get_earfcn();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if an RRCConnectionReconfiguration message including the mobilityControlInfo was received before the
|
||||||
|
// connection failure
|
||||||
|
if (timer_conn_failure.is_running()) {
|
||||||
|
timer_conn_failure.stop();
|
||||||
|
|
||||||
|
// include previousPCellId and set it to the global cell identity of the PCell where the last
|
||||||
|
// RRCConnectionReconfiguration including the mobilityControlInfo message was received;
|
||||||
|
rlf_report.prev_pcell_id_r10.set_present(true);
|
||||||
|
rlf_report.prev_pcell_id_r10->cell_id = ho_gci;
|
||||||
|
rlf_report.prev_pcell_id_r10->plmn_id = meas_cells.serving_cell().get_plmn_asn1(0);
|
||||||
|
|
||||||
|
// set the timeConnFailure to the elapsed time since reception of the last
|
||||||
|
// RRCConnectionReconfiguration message including the mobilityControlInfo;
|
||||||
|
rlf_report.time_conn_fail_r10_present = true;
|
||||||
|
rlf_report.time_conn_fail_r10 = timer_conn_failure.time_elapsed() / 100; // 1 unit = 100 ms
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the connectionFailureType
|
||||||
|
rlf_report.conn_fail_type_r10_present = true;
|
||||||
|
rlf_report.conn_fail_type_r10 =
|
||||||
|
type == rlf ? rlf_report_r9_s::conn_fail_type_r10_opts::rlf : rlf_report_r9_s::conn_fail_type_r10_opts::hof;
|
||||||
|
|
||||||
|
rlf_report.ext = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc_rlf_report::set_reest_gci(const asn1::fixed_bitstring<28>& gci, const asn1::rrc::plmn_id_s& plmn_id)
|
||||||
|
{
|
||||||
|
rlf_report.reest_cell_id_r10.set_present(true);
|
||||||
|
rlf_report.reest_cell_id_r10->cell_id = gci;
|
||||||
|
rlf_report.reest_cell_id_r10->plmn_id = plmn_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc_rlf_report::received_ho_command(const asn1::fixed_bitstring<28>& current_gci)
|
||||||
|
{
|
||||||
|
if (timer_conn_failure.is_valid()) {
|
||||||
|
timer_conn_failure.stop();
|
||||||
|
timer_conn_failure.run();
|
||||||
|
ho_gci = current_gci;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rlf_report_r9_s rrc_rlf_report::get_report()
|
||||||
|
{
|
||||||
|
return rlf_report;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears VarRLF-Report contents
|
||||||
|
void rrc_rlf_report::clear()
|
||||||
|
{
|
||||||
|
has_event = false;
|
||||||
|
rlf_report = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srsue
|
|
@ -22,6 +22,10 @@ add_executable(rrc_cell_test rrc_cell_test.cc)
|
||||||
target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
target_link_libraries(rrc_cell_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
||||||
add_test(rrc_cell_test rrc_cell_test)
|
add_test(rrc_cell_test rrc_cell_test)
|
||||||
|
|
||||||
|
add_executable(rrc_rlf_report_test rrc_rlf_report_test.cc)
|
||||||
|
target_link_libraries(rrc_rlf_report_test srsue_rrc srsue_upper srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
||||||
|
add_test(rrc_rlf_report_test rrc_rlf_report_test)
|
||||||
|
|
||||||
add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc)
|
add_executable(ue_rrc_nr_test ue_rrc_nr_test.cc)
|
||||||
target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
target_link_libraries(ue_rrc_nr_test srsue_rrc_nr srsue_upper srsran_common srsran_pdcp srsran_phy rrc_asn1 rrc_nr_asn1)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* \section COPYRIGHT
|
||||||
|
*
|
||||||
|
* Copyright 2013-2021 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* By using this file, you agree to the terms and conditions set
|
||||||
|
* forth in the LICENSE file which can be found at the top level of
|
||||||
|
* the distribution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srsran/common/test_common.h"
|
||||||
|
#include "srsue/hdr/stack/rrc/rrc_cell.h"
|
||||||
|
#include "srsue/hdr/stack/rrc/rrc_rlf_report.h"
|
||||||
|
|
||||||
|
using namespace srsue;
|
||||||
|
|
||||||
|
int test_single()
|
||||||
|
{
|
||||||
|
srsran::task_scheduler task_sched;
|
||||||
|
rrc_rlf_report rlf_report;
|
||||||
|
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||||
|
|
||||||
|
phy_meas_t pmeas;
|
||||||
|
pmeas.rsrp = -20;
|
||||||
|
pmeas.pci = 1;
|
||||||
|
pmeas.earfcn = 3400;
|
||||||
|
pmeas.rsrq = -10;
|
||||||
|
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
list.set_serving_cell(phy_cell_t{1, 3400}, false);
|
||||||
|
|
||||||
|
rlf_report.set_failure(list, rrc_rlf_report::rlf);
|
||||||
|
|
||||||
|
asn1::json_writer jw;
|
||||||
|
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||||
|
out.to_json(jw);
|
||||||
|
printf("test_single: %s\n", jw.to_string().c_str());
|
||||||
|
|
||||||
|
TESTASSERT(!out.meas_result_neigh_cells_r9_present);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.size() == 0);
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().pci_r10 == 1);
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().carrier_freq_r10 = 3400);
|
||||||
|
TESTASSERT(out.conn_fail_type_r10_present);
|
||||||
|
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::rlf);
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_neighbours()
|
||||||
|
{
|
||||||
|
srsran::task_scheduler task_sched;
|
||||||
|
rrc_rlf_report rlf_report;
|
||||||
|
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||||
|
|
||||||
|
phy_meas_t pmeas;
|
||||||
|
pmeas.rsrp = -20;
|
||||||
|
pmeas.pci = 1;
|
||||||
|
pmeas.earfcn = 3400;
|
||||||
|
pmeas.rsrq = -10;
|
||||||
|
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
pmeas.pci = 4;
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
pmeas.pci = 6;
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
list.set_serving_cell(phy_cell_t{4, 3400}, false);
|
||||||
|
|
||||||
|
TESTASSERT(!rlf_report.has_info());
|
||||||
|
|
||||||
|
rlf_report.set_failure(list, rrc_rlf_report::hof);
|
||||||
|
|
||||||
|
asn1::json_writer jw;
|
||||||
|
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||||
|
out.to_json(jw);
|
||||||
|
printf("test_neighbours: %s\n", jw.to_string().c_str());
|
||||||
|
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9_present);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9.size() == 2);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[0].carrier_freq_r9 = 3400);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[0].meas_result_list_r9[0].pci == 1);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[1].carrier_freq_r9 = 3400);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9[1].meas_result_list_r9[0].pci == 6);
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().pci_r10 == 4);
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10->pci_arfcn_r10().carrier_freq_r10 = 3400);
|
||||||
|
TESTASSERT(out.conn_fail_type_r10_present);
|
||||||
|
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::hof);
|
||||||
|
|
||||||
|
TESTASSERT(rlf_report.has_info());
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_reest()
|
||||||
|
{
|
||||||
|
srsran::task_scheduler task_sched;
|
||||||
|
rrc_rlf_report rlf_report;
|
||||||
|
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||||
|
|
||||||
|
phy_meas_t pmeas;
|
||||||
|
pmeas.rsrp = -20;
|
||||||
|
pmeas.pci = 1;
|
||||||
|
pmeas.earfcn = 3400;
|
||||||
|
pmeas.rsrq = -10;
|
||||||
|
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
pmeas.pci = 4;
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
pmeas.pci = 6;
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
list.set_serving_cell(phy_cell_t{4, 3400}, false);
|
||||||
|
|
||||||
|
TESTASSERT(!rlf_report.has_info());
|
||||||
|
|
||||||
|
rlf_report.set_failure(list, rrc_rlf_report::hof);
|
||||||
|
rlf_report.set_reest_gci(list.serving_cell().get_cell_id_bit(), list.serving_cell().get_plmn_asn1(0));
|
||||||
|
|
||||||
|
asn1::json_writer jw;
|
||||||
|
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||||
|
out.to_json(jw);
|
||||||
|
printf("test_reest: %s\n", jw.to_string().c_str());
|
||||||
|
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9_present);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present);
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||||
|
TESTASSERT(out.conn_fail_type_r10_present);
|
||||||
|
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::hof);
|
||||||
|
TESTASSERT(out.reest_cell_id_r10.is_present());
|
||||||
|
|
||||||
|
TESTASSERT(rlf_report.has_info());
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_ho()
|
||||||
|
{
|
||||||
|
srsran::task_scheduler task_sched;
|
||||||
|
rrc_rlf_report rlf_report;
|
||||||
|
meas_cell_list<meas_cell_eutra> list{&task_sched};
|
||||||
|
|
||||||
|
rlf_report.init(&task_sched);
|
||||||
|
|
||||||
|
phy_meas_t pmeas;
|
||||||
|
pmeas.rsrp = -20;
|
||||||
|
pmeas.pci = 1;
|
||||||
|
pmeas.earfcn = 3400;
|
||||||
|
pmeas.rsrq = -10;
|
||||||
|
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
pmeas.pci = 4;
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
pmeas.pci = 6;
|
||||||
|
list.add_meas_cell(pmeas);
|
||||||
|
list.set_serving_cell(phy_cell_t{4, 3400}, false);
|
||||||
|
|
||||||
|
TESTASSERT(!rlf_report.has_info());
|
||||||
|
|
||||||
|
rlf_report.received_ho_command(list.serving_cell().get_cell_id_bit());
|
||||||
|
for (int i = 0; i < 1000; i++) {
|
||||||
|
task_sched.tic();
|
||||||
|
task_sched.run_pending_tasks();
|
||||||
|
}
|
||||||
|
rlf_report.set_failure(list, rrc_rlf_report::hof);
|
||||||
|
rlf_report.set_reest_gci(list.serving_cell().get_cell_id_bit(), list.serving_cell().get_plmn_asn1(0));
|
||||||
|
|
||||||
|
asn1::json_writer jw;
|
||||||
|
asn1::rrc::rlf_report_r9_s out = rlf_report.get_report();
|
||||||
|
out.to_json(jw);
|
||||||
|
printf("test_ho: %s\n", jw.to_string().c_str());
|
||||||
|
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9_present);
|
||||||
|
TESTASSERT(out.meas_result_neigh_cells_r9.meas_result_list_eutra_r9_present);
|
||||||
|
TESTASSERT(out.failed_pcell_id_r10.is_present());
|
||||||
|
TESTASSERT(out.conn_fail_type_r10_present);
|
||||||
|
TESTASSERT(out.conn_fail_type_r10.value == asn1::rrc::rlf_report_r9_s::conn_fail_type_r10_e_::hof);
|
||||||
|
TESTASSERT(out.reest_cell_id_r10.is_present());
|
||||||
|
|
||||||
|
TESTASSERT(rlf_report.has_info());
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
TESTASSERT(test_single() == SRSRAN_SUCCESS);
|
||||||
|
TESTASSERT(test_neighbours() == SRSRAN_SUCCESS);
|
||||||
|
TESTASSERT(test_reest() == SRSRAN_SUCCESS);
|
||||||
|
TESTASSERT(test_ho() == SRSRAN_SUCCESS);
|
||||||
|
printf("Success\n");
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue