rrc,nr: add msg5 and inactivity timers to RRC-NR

Signed-off-by: Carlo Galiotto <carlo@srs.io>
This commit is contained in:
Carlo Galiotto 2021-10-26 16:44:53 +02:00 committed by carlo-gal
parent 0cfcd612b0
commit 9c74dda039
6 changed files with 48 additions and 11 deletions

View File

@ -85,6 +85,13 @@ public:
*/ */
virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0;
/**
* @brief Signal timeout for inactivity or MSG5 timers
*
* @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition
*/
virtual void sgnb_inactivity_timeout(uint16_t eutra_rnti) = 0;
/** /**
* @brief Signal release of all UE resources on the NR cell * @brief Signal release of all UE resources on the NR cell
* *

View File

@ -121,6 +121,10 @@ public:
{ {
x2_task_queue.push([this, eutra_rnti, nr_rnti]() { rrc.sgnb_addition_complete(eutra_rnti, nr_rnti); }); x2_task_queue.push([this, eutra_rnti, nr_rnti]() { rrc.sgnb_addition_complete(eutra_rnti, nr_rnti); });
} }
void sgnb_inactivity_timeout(uint16_t eutra_rnti) final
{
x2_task_queue.push([this, eutra_rnti]() { rrc.sgnb_inactivity_timeout(eutra_rnti); });
}
void set_activity_user(uint16_t eutra_rnti) final void set_activity_user(uint16_t eutra_rnti) final
{ {
// Note: RRC processes activity asynchronously, so there is no need to use x2_task_queue // Note: RRC processes activity asynchronously, so there is no need to use x2_task_queue

View File

@ -131,6 +131,7 @@ public:
void sgnb_addition_ack(uint16_t eutra_rnti, const sgnb_addition_ack_params_t params) override; void sgnb_addition_ack(uint16_t eutra_rnti, const sgnb_addition_ack_params_t params) override;
void sgnb_addition_reject(uint16_t eutra_rnti) override; void sgnb_addition_reject(uint16_t eutra_rnti) override;
void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) override; void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) override;
void sgnb_inactivity_timeout(uint16_t eutra_rnti) override;
void sgnb_release_ack(uint16_t eutra_rnti) override; void sgnb_release_ack(uint16_t eutra_rnti) override;
// rrc_interface_pdcp // rrc_interface_pdcp

View File

@ -83,6 +83,13 @@ public:
} }
eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti); eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti);
} }
void sgnb_inactivity_timeout(uint16_t eutra_rnti) override
{
if (eutra_stack == nullptr) {
return;
}
eutra_stack->sgnb_inactivity_timeout(eutra_rnti);
}
void sgnb_release_ack(uint16_t eutra_rnti) override void sgnb_release_ack(uint16_t eutra_rnti) override
{ {

View File

@ -603,6 +603,17 @@ void rrc::sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti)
ue_it->second->endc_handler->trigger(ue::rrc_endc::sgnb_add_complete_ev{nr_rnti}); ue_it->second->endc_handler->trigger(ue::rrc_endc::sgnb_add_complete_ev{nr_rnti});
} }
void rrc::sgnb_inactivity_timeout(uint16_t eutra_rnti)
{
logger.error("Received NR inactivity timeout for rnti=%d - releasing UE", eutra_rnti);
auto ue_it = users.find(eutra_rnti);
if (ue_it == users.end()) {
logger.warning("rnti=0x%x does not exist", eutra_rnti);
return;
}
release_ue(eutra_rnti);
}
void rrc::sgnb_release_ack(uint16_t eutra_rnti) void rrc::sgnb_release_ack(uint16_t eutra_rnti)
{ {
auto ue_it = users.find(eutra_rnti); auto ue_it = users.find(eutra_rnti);

View File

@ -245,6 +245,8 @@ void rrc_nr::set_activity_user(uint16_t rnti)
// inform EUTRA RRC about user activity // inform EUTRA RRC about user activity
if (ue_ptr->is_endc()) { if (ue_ptr->is_endc()) {
// Restart inactivity timer for RRC-NR
ue_ptr->set_activity();
// inform EUTRA RRC about user activity // inform EUTRA RRC about user activity
rrc_eutra->set_activity_user(ue_ptr->get_eutra_rnti()); rrc_eutra->set_activity_user(ue_ptr->get_eutra_rnti());
} }
@ -567,7 +569,7 @@ rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg_,
// Set timer for MSG3_RX_TIMEOUT or UE_INACTIVITY_TIMEOUT // Set timer for MSG3_RX_TIMEOUT or UE_INACTIVITY_TIMEOUT
activity_timer = parent->task_sched.get_unique_timer(); activity_timer = parent->task_sched.get_unique_timer();
start_msg3_timer ? set_activity_timeout(MSG3_RX_TIMEOUT) : set_activity_timeout(UE_INACTIVITY_TIMEOUT); start_msg3_timer ? set_activity_timeout(MSG3_RX_TIMEOUT) : set_activity_timeout(MSG5_RX_TIMEOUT);
} }
void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type) void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type)
@ -579,15 +581,19 @@ void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type)
// TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 100ms // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 100ms
deadline_ms = 100; deadline_ms = 100;
break; break;
case MSG5_RX_TIMEOUT:
// TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 1s
deadline_ms = 1000;
break;
case UE_INACTIVITY_TIMEOUT: case UE_INACTIVITY_TIMEOUT:
// TODO: Add a value for the inactivity timeout - currently no activity set this case // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 5s
return; deadline_ms = 5000;
break;
default: default:
parent->logger.error("Unknown timeout type %d", type); parent->logger.error("Unknown timeout type %d", type);
return; return;
} }
// Currently we only set the timer for the MSG3_RX_TIMEOUT case
activity_timer.set(deadline_ms, [this, type](uint32_t tid) { activity_timer_expired(type); }); activity_timer.set(deadline_ms, [this, type](uint32_t tid) { activity_timer_expired(type); });
parent->logger.debug("Setting timer for %s for rnti=0x%x to %dms", to_string(type).c_str(), rnti, deadline_ms); parent->logger.debug("Setting timer for %s for rnti=0x%x to %dms", to_string(type).c_str(), rnti, deadline_ms);
@ -613,14 +619,15 @@ void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type)
{ {
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());
state = rrc_nr_state_t::RRC_IDLE;
switch (type) { switch (type) {
case MSG5_RX_TIMEOUT:
case UE_INACTIVITY_TIMEOUT: case UE_INACTIVITY_TIMEOUT:
// TODO: Add action to be executed state = rrc_nr_state_t::RRC_INACTIVE;
parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti);
break; break;
case MSG3_RX_TIMEOUT: { case MSG3_RX_TIMEOUT: {
// MSG3 timeout, no need to notify NGAP or LTE stack. Just remove UE // MSG3 timeout, no need to notify NGAP or LTE stack. Just remove UE
state = rrc_nr_state_t::RRC_IDLE;
uint32_t rnti_to_rem = rnti; uint32_t rnti_to_rem = rnti;
parent->task_sched.defer_task([this, rnti_to_rem]() { parent->rem_user(rnti_to_rem); }); parent->task_sched.defer_task([this, rnti_to_rem]() { parent->rem_user(rnti_to_rem); });
break; break;
@ -635,7 +642,7 @@ void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type)
std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type) std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type)
{ {
constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "UE reestablishment"}; constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "Msg5 reception"};
return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type); return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type);
} }
@ -1310,9 +1317,9 @@ void rrc_nr::ue::crnti_ce_received()
// send SgNB addition complete for ENDC users // send SgNB addition complete for ENDC users
parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti); parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti);
// stop RX MSG3 activity timer on MAC CE RNTI reception // stop RX MSG3/MSG5 activity timer on MAC CE RNTI reception
activity_timer.stop(); set_activity_timeout(UE_INACTIVITY_TIMEOUT);
parent->logger.debug("Received MAC CE-RNTI for 0x%x - stopping MSG3 timer", rnti); parent->logger.debug("Received MAC CE-RNTI for 0x%x - stopping MSG3/MSG5 timer, starting inactivity timer", rnti);
// Add DRB1 to MAC // Add DRB1 to MAC
for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) { for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) {