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). # rrc_inactivity_timer Inactivity timeout used to remove UE context from RRC (in milliseconds).
# max_prach_offset_us: Maximum allowed RACH offset (in us) # 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) # 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). # 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). # 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). # 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_nof_kos = 100
#max_prach_offset_us = 30 #max_prach_offset_us = 30
#nof_prealloc_ues = 8 #nof_prealloc_ues = 8
#rlf_release_timer_ms = 4000
#eea_pref_list = EEA0, EEA2, EEA1 #eea_pref_list = EEA0, EEA2, EEA1
#eia_pref_list = EIA2, EIA1, EIA0 #eia_pref_list = EIA2, EIA1, EIA0
#gtpu_tunnel_timeout = 0 #gtpu_tunnel_timeout = 0

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

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

@ -40,8 +40,9 @@ public:
std::string to_string(const activity_timeout_type_t& type); std::string to_string(const activity_timeout_type_t& type);
void set_activity_timeout(const activity_timeout_type_t type); void set_activity_timeout(const activity_timeout_type_t type);
void set_rlf_timeout();
void set_activity(); void set_activity();
void start_rlf_timer();
void stop_rlf_timer();
void set_radiolink_dl_state(bool crc_res); void set_radiolink_dl_state(bool crc_res);
void set_radiolink_ul_state(bool crc_res); void set_radiolink_ul_state(bool crc_res);
void activity_timer_expired(const activity_timeout_type_t type); void activity_timer_expired(const activity_timeout_type_t type);
@ -158,8 +159,8 @@ public:
private: private:
// args // args
srsran::timer_handler::unique_timer activity_timer; srsran::unique_timer activity_timer;
srsran::timer_handler::unique_timer rlf_timer; srsran::unique_timer rlf_release_timer;
/// cached ASN1 fields for RRC config update checking, and ease of context transfer during HO /// cached ASN1 fields for RRC config update checking, and ease of context transfer during HO
ue_var_cfg_t current_ue_cfg; 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 // Set max number of KOs
rrc_cfg_->max_mac_dl_kos = args_->general.max_mac_dl_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_->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 // Set sync queue capacity to 1 for ZMQ
if (args_->rf.device_name == "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_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.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.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 // eMBMS section

@ -56,10 +56,14 @@ int rrc::ue::init()
// Configure // Configure
apply_setup_phy_common(parent->cfg.sibs[1].sib2().rr_cfg_common, true); 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(); activity_timer = parent->task_sched.get_unique_timer();
set_activity_timeout(MSG3_RX_TIMEOUT); // next UE response is Msg3 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); mobility_handler = make_rnti_obj<rrc_mobility>(rnti, this);
return SRSRAN_SUCCESS; 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) void rrc::ue::set_radiolink_dl_state(bool crc_res)
{ {
parent->logger.debug( parent->logger.debug(
@ -102,13 +120,13 @@ void rrc::ue::set_radiolink_dl_state(bool crc_res)
if (crc_res) { if (crc_res) {
consecutive_kos_dl = 0; consecutive_kos_dl = 0;
consecutive_kos_ul = 0; consecutive_kos_ul = 0;
rlf_timer.stop(); stop_rlf_timer();
return; return;
} }
// Count KOs in MAC and trigger release if it goes above a certain value. // Count KOs in MAC and trigger release if it goes above a certain value.
// This is done to detect out-of-coverage UEs // 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 // RLF timer already running, no need to count KOs
return; return;
} }
@ -129,13 +147,13 @@ void rrc::ue::set_radiolink_ul_state(bool crc_res)
if (crc_res) { if (crc_res) {
consecutive_kos_dl = 0; consecutive_kos_dl = 0;
consecutive_kos_ul = 0; consecutive_kos_ul = 0;
rlf_timer.stop(); stop_rlf_timer();
return; return;
} }
// Count KOs in MAC and trigger release if it goes above a certain value. // Count KOs in MAC and trigger release if it goes above a certain value.
// This is done to detect out-of-coverage UEs // 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 // RLF timer already running, no need to count KOs
return; 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) void rrc::ue::activity_timer_expired(const activity_timeout_type_t type)
{ {
rlf_timer.stop(); stop_rlf_timer();
if (parent) { if (parent) {
parent->logger.info("Activity timer for rnti=0x%x expired after %d ms", rnti, activity_timer.time_elapsed()); 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(); activity_timer.stop();
if (parent) { 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)) { if (parent->s1ap->user_exists(rnti)) {
parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost); 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); parent->logger.info("Max retx reached for rnti=0x%x", rnti);
// Give UE time to start re-establishment // Give UE time to start re-establishment
rlf_timer.run(); start_rlf_timer();
mac_ctrl.handle_max_retx(); 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) void rrc::ue::set_activity_timeout(const activity_timeout_type_t type)
{ {
uint32_t deadline_s = 0; 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>(rrc_event_type::con_reest_req),
static_cast<unsigned>(procedure_result_code::none), static_cast<unsigned>(procedure_result_code::none),
rnti); 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()) { if (not parent->s1ap->is_mme_connected()) {
parent->logger.error("MME isn't connected. Sending Connection Reject"); 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; return;
} }
parent->logger.debug("rnti=0x%x, phyid=0x%x, smac=0x%x, cause=%s", 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(), (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()); msg->crit_exts.rrc_conn_reest_request_r8().reest_cause.to_string());
if (is_idle()) { 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; 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); const enb_cell_common* old_cell = parent->cell_common_list->get_pci(old_pci);
auto ue_it = parent->users.find(old_rnti); 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 { } else {
parent->logger.error("Received ConnectionReestablishment for rnti=0x%x without context", old_rnti); parent->logger.error("Received ConnectionReestablishment for rnti=0x%x without context", old_rnti);
send_connection_reest_rej(procedure_result_code::error_unknown_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 { } else {
parent->logger.error("Received ReestablishmentRequest from an rnti=0x%x not in IDLE", rnti); 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