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.
master
Andre Puschmann 5 years ago
parent 67877d15d5
commit e981d5ee70

@ -351,6 +351,8 @@ public:
const phy_interface_rrc_lte::phy_cell_t& found_cell); const phy_interface_rrc_lte::phy_cell_t& found_cell);
void cell_select_completed(bool cs_ret); void cell_select_completed(bool cs_ret);
bool srbs_flushed(); //< Check if data on SRBs still needs to be sent
protected: protected:
// Moved to protected to be accessible by unit tests // 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); void set_serving_cell(phy_interface_rrc_lte::phy_cell_t phy_cell, bool discard_serving);

@ -259,7 +259,7 @@ public:
static const char* name() { return "Go Idle"; } static const char* name() { return "Go Idle"; }
private: 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; rrc* rrc_ptr;
srslte::timer_handler::unique_timer rlc_flush_timer; srslte::timer_handler::unique_timer rlc_flush_timer;

@ -1270,6 +1270,27 @@ void rrc::cell_select_completed(bool cs_ret)
phy_cell_selector.trigger(cell_select_event_t{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 * Interface from RRC measurements class

@ -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_) 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 = 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() 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; return proc_outcome_t::success;
} }
// If the RLC SRB1 is not suspended // wait for RLC of SRB1 and SRB2 to be flushed
// wait for max. 2s for RLC on SRB1 to be flushed if (rrc_ptr->srbs_flushed()) {
if (rrc_ptr->rlc->is_suspended(RB_ID_SRB1) || not rrc_ptr->rlc->has_data(RB_ID_SRB1)) {
rrc_ptr->leave_connected(); rrc_ptr->leave_connected();
Info("Left connected state\n"); Info("Left connected state\n");
return proc_outcome_t::success; return proc_outcome_t::success;
} else { } 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; return proc_outcome_t::yield;
} }

@ -25,6 +25,7 @@
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
#include <numeric> #include <numeric>
#include <thread>
using namespace srslte; using namespace srslte;
@ -180,15 +181,13 @@ bool ue_stack_lte::switch_off()
nas.detach_request(true); nas.detach_request(true);
// wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) // 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_ms = 5000;
int cnt = 0, timeout = 5000; while (not rrc.srbs_flushed() && ++cnt <= timeout_ms) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
while (rlc.has_data(RB_ID_SRB1) && ++cnt <= timeout) {
usleep(1000);
} }
bool detach_sent = true; bool detach_sent = true;
if (rlc.has_data(RB_ID_SRB1)) { if (not rrc.srbs_flushed()) {
logmap::get("NAS ")->warning("Detach couldn't be sent after %ds.\n", timeout); logmap::get("NAS ")->warning("Detach couldn't be sent after %dms.\n", timeout_ms);
detach_sent = false; detach_sent = false;
} }

Loading…
Cancel
Save