Split split RLF timer and Inactivity timer

master
Pedro Alvarez 4 years ago
parent 47135cb75b
commit e1a852d4b8

@ -160,8 +160,6 @@ public:
int read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final; int read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final;
uint32_t ko_counter = 0;
private: private:
void allocate_sdu(srsran::sch_pdu* pdu, uint32_t lcid, uint32_t sdu_len); void allocate_sdu(srsran::sch_pdu* pdu, uint32_t lcid, uint32_t sdu_len);
bool process_ce(srsran::sch_subh* subh); bool process_ce(srsran::sch_subh* subh);

@ -35,14 +35,16 @@ public:
typedef enum { typedef enum {
MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs
UE_INACTIVITY_TIMEOUT, ///< UE inactivity timeout (usually bigger than reestablishment timeout) UE_INACTIVITY_TIMEOUT, ///< UE inactivity timeout (usually bigger than reestablishment timeout)
UE_REESTABLISH_TIMEOUT, ///< Maximum timeout in which UE reestablishment is expected
nulltype nulltype
} activity_timeout_type_t; } activity_timeout_type_t;
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 mac_ko_activity(); void mac_ko_activity();
void activity_timer_expired(const activity_timeout_type_t type); void activity_timer_expired(const activity_timeout_type_t type);
void rlf_timer_expired();
void max_retx_reached(); void max_retx_reached();
rrc_state_t get_state(); rrc_state_t get_state();
@ -157,6 +159,7 @@ public:
private: private:
// args // args
srsran::timer_handler::unique_timer activity_timer; srsran::timer_handler::unique_timer activity_timer;
srsran::timer_handler::unique_timer rlf_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;

@ -298,7 +298,6 @@ int mac::ack_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t
} }
} else { } else {
rrc_h->set_activity_user(rnti, false); rrc_h->set_activity_user(rnti, false);
logger.info("DL KO activity rnti=0x%x, n_bytes=%d", rnti, nof_bytes);
} }
return SRSRAN_SUCCESS; return SRSRAN_SUCCESS;
} }

@ -56,6 +56,7 @@ 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();
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
@ -103,6 +104,7 @@ void rrc::ue::set_activity()
{ {
// re-start activity timer with current timeout value // re-start activity timer with current timeout value
activity_timer.run(); activity_timer.run();
rlf_timer.stop();
consecutive_kos = 0; consecutive_kos = 0;
if (parent) { if (parent) {
parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration()); parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration());
@ -113,14 +115,14 @@ void rrc::ue::mac_ko_activity()
{ {
// 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
consecutive_kos++; if (rlf_timer.is_running()) {
parent->logger.debug("KO activity registered for rnti=0x%x (consecutive_kos=%d, max_mac_dl_kos=%d)", // RLF timer already running, no need to count KOs
rnti, return;
consecutive_kos, }
parent->cfg.max_mac_dl_kos);
consecutive_kos++;
if (consecutive_kos > parent->cfg.max_mac_dl_kos) { if (consecutive_kos > parent->cfg.max_mac_dl_kos) {
parent->logger.debug("Max KOs reached, triggering release rnti=0x%x", rnti); parent->logger.info("Max KOs reached, triggering release rnti=0x%x", rnti);
max_retx_reached(); max_retx_reached();
} }
} }
@ -134,9 +136,6 @@ void rrc::ue::activity_timer_expired(const activity_timeout_type_t type)
if (type == UE_INACTIVITY_TIMEOUT) { if (type == UE_INACTIVITY_TIMEOUT) {
parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::user_inactivity); parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::user_inactivity);
con_release_result = procedure_result_code::activity_timeout; con_release_result = procedure_result_code::activity_timeout;
} else if (type == UE_REESTABLISH_TIMEOUT) {
parent->s1ap->user_release(rnti, asn1::s1ap::cause_radio_network_opts::radio_conn_with_ue_lost);
con_release_result = procedure_result_code::radio_conn_with_ue_lost;
} else if (type == MSG3_RX_TIMEOUT) { } else if (type == MSG3_RX_TIMEOUT) {
// MSG3 timeout, no need to notify S1AP, just remove UE // MSG3 timeout, no need to notify S1AP, just remove UE
parent->rem_user_thread(rnti); parent->rem_user_thread(rnti);
@ -158,18 +157,53 @@ void rrc::ue::activity_timer_expired(const activity_timeout_type_t type)
state = RRC_STATE_RELEASE_REQUEST; state = RRC_STATE_RELEASE_REQUEST;
} }
void rrc::ue::rlf_timer_expired()
{
if (parent) {
parent->logger.info("RLF timer for rnti=0x%x expired after %d ms", rnti, rlf_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);
con_release_result = procedure_result_code::radio_conn_with_ue_lost;
} else {
if (rnti != SRSRAN_MRNTI) {
parent->rem_user(rnti);
}
}
}
state = RRC_STATE_RELEASE_REQUEST;
}
void rrc::ue::max_retx_reached() void rrc::ue::max_retx_reached()
{ {
if (parent) { if (parent) {
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
set_activity_timeout(UE_REESTABLISH_TIMEOUT); set_rlf_timeout();
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.debug("Setting RLF timer for rnti=0x%x to %dms", rnti, deadline);
rlf_timer.run();
}
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;
@ -185,13 +219,6 @@ void rrc::ue::set_activity_timeout(const activity_timeout_type_t type)
deadline_s = parent->cfg.inactivity_timeout_ms / 1000; deadline_s = parent->cfg.inactivity_timeout_ms / 1000;
deadline_ms = parent->cfg.inactivity_timeout_ms % 1000; deadline_ms = parent->cfg.inactivity_timeout_ms % 1000;
break; break;
case UE_REESTABLISH_TIMEOUT:
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;
break;
default: default:
parent->logger.error("Unknown timeout type %d", type); parent->logger.error("Unknown timeout type %d", type);
} }

Loading…
Cancel
Save