From e981d5ee70dd53bef87f12859b237d985f276b2a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 29 Jun 2020 15:49:29 +0200 Subject: [PATCH] rrc,ue: refactor wait conditions before transition to RRC idle before entering RRC idle, after receiving a RRC connection release for example, we need to wait until the RLC for SRB1 or SRB2 have been flushed, i.e. the RLC has acknowledged the reception of the message. Previously we have only waited for SRB1 but the message can also be received on SRB2 and in this case both bearers need to be checked. The method is now streamlined to check both SRBs and is also used when checking the msg transmission of an detach request. --- srsue/hdr/stack/rrc/rrc.h | 2 ++ srsue/hdr/stack/rrc/rrc_procedures.h | 2 +- srsue/src/stack/rrc/rrc.cc | 21 +++++++++++++++++++++ srsue/src/stack/rrc/rrc_procedures.cc | 9 ++++----- srsue/src/stack/ue_stack_lte.cc | 13 ++++++------- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 407b66d28..f8b3242ab 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -351,6 +351,8 @@ public: const phy_interface_rrc_lte::phy_cell_t& found_cell); void cell_select_completed(bool cs_ret); + bool srbs_flushed(); //< Check if data on SRBs still needs to be sent + protected: // Moved to protected to be accessible by unit tests void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, bool discard_serving); diff --git a/srsue/hdr/stack/rrc/rrc_procedures.h b/srsue/hdr/stack/rrc/rrc_procedures.h index cf1ad4de3..9f9b61e70 100644 --- a/srsue/hdr/stack/rrc/rrc_procedures.h +++ b/srsue/hdr/stack/rrc/rrc_procedures.h @@ -259,7 +259,7 @@ public: static const char* name() { return "Go Idle"; } private: - static const uint32_t rlc_flush_timeout = 2000; + static const uint32_t rlc_flush_timeout_ms = 60; // TS 36.331 Sec 5.3.8.3 rrc* rrc_ptr; srslte::timer_handler::unique_timer rlc_flush_timer; diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 0a7dac100..b78049a33 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -1270,6 +1270,27 @@ void rrc::cell_select_completed(bool cs_ret) phy_cell_selector.trigger(cell_select_event_t{cs_ret}); } +/** + * Check whether data on SRB1 or SRB2 still needs to be sent. + * If the bearer is suspended it will not be considered. + * + * @return True if no further data needs to be sent on SRBs, False otherwise + */ +bool rrc::srbs_flushed() +{ + // Check SRB1 + if (rlc->has_data(RB_ID_SRB1) && not rlc->is_suspended(RB_ID_SRB1)) { + return false; + } + + // Check SRB2 + if (rlc->has_data(RB_ID_SRB2) && not rlc->is_suspended(RB_ID_SRB2)) { + return false; + } + + return true; +} + /******************************************************************************* * * Interface from RRC measurements class diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index c12fbc49e..77e4857d9 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -1041,7 +1041,7 @@ proc_outcome_t rrc::process_pcch_proc::react(paging_complete e) rrc::go_idle_proc::go_idle_proc(srsue::rrc* rrc_) : rrc_ptr(rrc_) { rlc_flush_timer = rrc_ptr->stack->get_unique_timer(); - rlc_flush_timer.set(rlc_flush_timeout, [this](uint32_t tid) { rrc_ptr->idle_setter.trigger(true); }); + rlc_flush_timer.set(rlc_flush_timeout_ms, [this](uint32_t tid) { rrc_ptr->idle_setter.trigger(true); }); } proc_outcome_t rrc::go_idle_proc::init() @@ -1066,14 +1066,13 @@ proc_outcome_t rrc::go_idle_proc::step() return proc_outcome_t::success; } - // If the RLC SRB1 is not suspended - // wait for max. 2s for RLC on SRB1 to be flushed - if (rrc_ptr->rlc->is_suspended(RB_ID_SRB1) || not rrc_ptr->rlc->has_data(RB_ID_SRB1)) { + // wait for RLC of SRB1 and SRB2 to be flushed + if (rrc_ptr->srbs_flushed()) { rrc_ptr->leave_connected(); Info("Left connected state\n"); return proc_outcome_t::success; } else { - Debug("Postponing transition to RRC IDLE (%d ms < %d ms)\n", rlc_flush_timer.time_elapsed(), rlc_flush_timeout); + Debug("Postponing transition to RRC IDLE (%d ms < %d ms)\n", rlc_flush_timer.time_elapsed(), rlc_flush_timeout_ms); } return proc_outcome_t::yield; } diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index afd383a46..3ca6ad318 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -25,6 +25,7 @@ #include #include #include +#include using namespace srslte; @@ -180,15 +181,13 @@ bool ue_stack_lte::switch_off() nas.detach_request(true); // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) - const uint32_t RB_ID_SRB1 = 1; - int cnt = 0, timeout = 5000; - - while (rlc.has_data(RB_ID_SRB1) && ++cnt <= timeout) { - usleep(1000); + int cnt = 0, timeout_ms = 5000; + while (not rrc.srbs_flushed() && ++cnt <= timeout_ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } bool detach_sent = true; - if (rlc.has_data(RB_ID_SRB1)) { - logmap::get("NAS ")->warning("Detach couldn't be sent after %ds.\n", timeout); + if (not rrc.srbs_flushed()) { + logmap::get("NAS ")->warning("Detach couldn't be sent after %dms.\n", timeout_ms); detach_sent = false; }