make eNB UE release timer after RLF detection configurable

master
Francisco 4 years ago committed by Francisco Paisana
parent 1396c2a1e2
commit 9464f36714

@ -305,6 +305,7 @@ enable = false
# rrc_inactivity_timer Inactivity timeout used to remove UE context from RRC (in milliseconds).
# max_prach_offset_us: Maximum allowed RACH offset (in us)
# nof_prealloc_ues: Number of UE memory resources to preallocate during eNB initialization for faster UE creation (Default 8)
# rlf_release_timer_ms: Time taken by eNB to release UE context after it detects an RLF
# eea_pref_list: Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).
# eia_pref_list: Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).
# gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer).
@ -330,6 +331,7 @@ enable = false
#max_nof_kos = 100
#max_prach_offset_us = 30
#nof_prealloc_ues = 8
#rlf_release_timer_ms = 4000
#eea_pref_list = EEA0, EEA2, EEA1
#eia_pref_list = EIA2, EIA1, EIA0
#gtpu_tunnel_timeout = 0

@ -96,6 +96,7 @@ struct general_args_t {
uint32_t max_mac_dl_kos;
uint32_t max_mac_ul_kos;
uint32_t gtpu_indirect_tunnel_timeout;
uint32_t rlf_release_timer_ms;
};
struct all_args_t {

@ -61,6 +61,7 @@ struct rrc_cfg_t {
cell_list_t cell_list_nr;
uint32_t max_mac_dl_kos;
uint32_t max_mac_ul_kos;
uint32_t rlf_release_timer_ms;
};
constexpr uint32_t UE_PCELL_CC_IDX = 0;

@ -40,8 +40,9 @@ public:
std::string to_string(const activity_timeout_type_t& type);
void set_activity_timeout(const activity_timeout_type_t type);
void set_rlf_timeout();
void set_activity();
void start_rlf_timer();
void stop_rlf_timer();
void set_radiolink_dl_state(bool crc_res);
void set_radiolink_ul_state(bool crc_res);
void activity_timer_expired(const activity_timeout_type_t type);
@ -158,8 +159,8 @@ public:
private:
// args
srsran::timer_handler::unique_timer activity_timer;
srsran::timer_handler::unique_timer rlf_timer;
srsran::unique_timer activity_timer;
srsran::unique_timer rlf_release_timer;
/// cached ASN1 fields for RRC config update checking, and ease of context transfer during HO
ue_var_cfg_t current_ue_cfg;

@ -1162,6 +1162,7 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_
// Set max number of KOs
rrc_cfg_->max_mac_dl_kos = args_->general.max_mac_dl_kos;
rrc_cfg_->max_mac_ul_kos = args_->general.max_mac_ul_kos;
rrc_cfg_->rlf_release_timer_ms = args_->general.rlf_release_timer_ms;
// Set sync queue capacity to 1 for ZMQ
if (args_->rf.device_name == "zmq") {

@ -219,6 +219,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("expert.max_mac_dl_kos", bpo::value<uint32_t>(&args->general.max_mac_dl_kos)->default_value(100), "Maximum number of consecutive KOs in DL before triggering the UE's release")
("expert.max_mac_ul_kos", bpo::value<uint32_t>(&args->general.max_mac_ul_kos)->default_value(100), "Maximum number of consecutive KOs in UL before triggering the UE's release")
("expert.gtpu_tunnel_timeout", bpo::value<uint32_t>(&args->stack.gtpu_indirect_tunnel_timeout_msec)->default_value(0), "Maximum time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU. (0 for infinity)")
("expert.rlf_release_timer_ms", bpo::value<uint32_t>(&args->general.rlf_release_timer_ms)->default_value(4000), "Time taken by eNB to release UE context after it detects an RLF")
// eMBMS section

@ -56,10 +56,14 @@ int rrc::ue::init()
// Configure
apply_setup_phy_common(parent->cfg.sibs[1].sib2().rr_cfg_common, true);
rlf_timer = parent->task_sched.get_unique_timer();
rlf_release_timer = parent->task_sched.get_unique_timer();
activity_timer = parent->task_sched.get_unique_timer();
set_activity_timeout(MSG3_RX_TIMEOUT); // next UE response is Msg3
set_rlf_timeout();
// Set timeout to release UE context after RLF detection
uint32_t deadline_ms = parent->cfg.rlf_release_timer_ms;
rlf_release_timer.set(deadline_ms, [this](uint32_t tid) { rlf_timer_expired(); });
parent->logger.info("Setting RLF timer for rnti=0x%x to %dms", rnti, deadline_ms);
mobility_handler = make_rnti_obj<rrc_mobility>(rnti, this);
return SRSRAN_SUCCESS;
@ -93,6 +97,20 @@ void rrc::ue::set_activity()
}
}
void rrc::ue::start_rlf_timer()
{
rlf_release_timer.run();
parent->logger.info("RLF timer started for rnti=0x%x (duration=%dms)", rnti, rlf_release_timer.duration());
}
void rrc::ue::stop_rlf_timer()
{
if (rlf_release_timer.is_running()) {
parent->logger.info("RLF timer stopped for rnti=0x%x (time elapsed=%dms)", rnti, rlf_release_timer.time_elapsed());
}
rlf_release_timer.stop();
}
void rrc::ue::set_radiolink_dl_state(bool crc_res)
{
parent->logger.debug(
@ -102,13 +120,13 @@ void rrc::ue::set_radiolink_dl_state(bool crc_res)
if (crc_res) {
consecutive_kos_dl = 0;
consecutive_kos_ul = 0;
rlf_timer.stop();
stop_rlf_timer();
return;
}
// Count KOs in MAC and trigger release if it goes above a certain value.
// This is done to detect out-of-coverage UEs
if (rlf_timer.is_running()) {
if (rlf_release_timer.is_running()) {
// RLF timer already running, no need to count KOs
return;
}
@ -129,13 +147,13 @@ void rrc::ue::set_radiolink_ul_state(bool crc_res)
if (crc_res) {
consecutive_kos_dl = 0;
consecutive_kos_ul = 0;
rlf_timer.stop();
stop_rlf_timer();
return;
}
// Count KOs in MAC and trigger release if it goes above a certain value.
// This is done to detect out-of-coverage UEs
if (rlf_timer.is_running()) {
if (rlf_release_timer.is_running()) {
// RLF timer already running, no need to count KOs
return;
}
@ -149,7 +167,7 @@ void rrc::ue::set_radiolink_ul_state(bool crc_res)
void rrc::ue::activity_timer_expired(const activity_timeout_type_t type)
{
rlf_timer.stop();
stop_rlf_timer();
if (parent) {
parent->logger.info("Activity timer for rnti=0x%x expired after %d ms", rnti, activity_timer.time_elapsed());
@ -182,7 +200,7 @@ void rrc::ue::rlf_timer_expired()
{
activity_timer.stop();
if (parent) {
parent->logger.info("RLF timer for rnti=0x%x expired after %d ms", rnti, rlf_timer.time_elapsed());
parent->logger.info("RLF timer for rnti=0x%x expired after %d ms", rnti, rlf_release_timer.time_elapsed());
if (parent->s1ap->user_exists(rnti)) {
parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost);
@ -203,28 +221,12 @@ void rrc::ue::max_retx_reached()
parent->logger.info("Max retx reached for rnti=0x%x", rnti);
// Give UE time to start re-establishment
rlf_timer.run();
start_rlf_timer();
mac_ctrl.handle_max_retx();
}
}
void rrc::ue::set_rlf_timeout()
{
uint32_t deadline_s = 0;
uint32_t deadline_ms = 0;
deadline_ms = static_cast<uint32_t>((get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.ue_timers_and_consts.t310.to_number()) +
(get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.ue_timers_and_consts.t311.to_number()) +
(get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.ue_timers_and_consts.n310.to_number()));
deadline_s = deadline_ms / 1000;
deadline_ms = deadline_ms % 1000;
uint32_t deadline = deadline_s * 1e3 + deadline_ms;
rlf_timer.set(deadline, [this](uint32_t tid) { rlf_timer_expired(); });
parent->logger.info("Setting RLF timer for rnti=0x%x to %dms", rnti, deadline);
}
void rrc::ue::set_activity_timeout(const activity_timeout_type_t type)
{
uint32_t deadline_s = 0;
@ -514,10 +516,16 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg)
static_cast<unsigned>(rrc_event_type::con_reest_req),
static_cast<unsigned>(procedure_result_code::none),
rnti);
const rrc_conn_reest_request_r8_ies_s& req_r8 = msg->crit_exts.rrc_conn_reest_request_r8();
uint16_t old_rnti = req_r8.ue_id.c_rnti.to_number();
srsran::console(
"User 0x%x requesting RRC Reestablishment as 0x%x. Cause: %s\n", rnti, old_rnti, req_r8.reest_cause.to_string());
if (not parent->s1ap->is_mme_connected()) {
parent->logger.error("MME isn't connected. Sending Connection Reject");
send_connection_reject(procedure_result_code::error_mme_not_connected);
send_connection_reest_rej(procedure_result_code::error_mme_not_connected);
srsran::console("User 0x%x RRC Reestablishment Request rejected\n", rnti);
return;
}
parent->logger.debug("rnti=0x%x, phyid=0x%x, smac=0x%x, cause=%s",
@ -526,7 +534,6 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg)
(uint32_t)msg->crit_exts.rrc_conn_reest_request_r8().ue_id.short_mac_i.to_number(),
msg->crit_exts.rrc_conn_reest_request_r8().reest_cause.to_string());
if (is_idle()) {
uint16_t old_rnti = msg->crit_exts.rrc_conn_reest_request_r8().ue_id.c_rnti.to_number();
uint16_t old_pci = msg->crit_exts.rrc_conn_reest_request_r8().ue_id.pci;
const enb_cell_common* old_cell = parent->cell_common_list->get_pci(old_pci);
auto ue_it = parent->users.find(old_rnti);
@ -581,9 +588,13 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg)
} else {
parent->logger.error("Received ConnectionReestablishment for rnti=0x%x without context", old_rnti);
send_connection_reest_rej(procedure_result_code::error_unknown_rnti);
srsran::console(
"User 0x%x RRC Reestablishment Request rejected. Cause: no rnti=0x%x context available\n", rnti, old_rnti);
}
} else {
parent->logger.error("Received ReestablishmentRequest from an rnti=0x%x not in IDLE", rnti);
send_connection_reest_rej(procedure_result_code::error_unknown_rnti);
srsran::console("ERROR: User 0x%x requesting Reestablishment is not in RRC_IDLE\n", rnti);
}
}

Loading…
Cancel
Save