From ba87819ff1420f429087852fc5c34d7c9d91e497 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 24 Sep 2018 15:15:35 +0200 Subject: [PATCH] retransmit random RLC AM PDU in case tx window is full --- lib/include/srslte/upper/rlc_am.h | 1 + lib/src/upper/rlc_am.cc | 50 ++++++++++++++----------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index c55962873..d18cc94d4 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -139,6 +139,7 @@ private: bool retx_queue_has_sn(uint32_t sn); int required_buffer_size(rlc_amd_retx_t retx); + void retransmit_random_pdu(); // Timer checks bool status_prohibited; diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 143996d02..a30e0c264 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -469,19 +469,9 @@ int rlc_am::rlc_am_tx::read_pdu(uint8_t *payload, uint32_t nof_bytes) goto unlock_and_exit; } - // if tx_window is full and retx_queue empty, retransmit next PDU to be ack'ed + // Section 5.2.2.3 in TS 36.311, if tx_window is full and retx_queue empty, retransmit random PDU if (tx_window.size() >= RLC_AM_WINDOW_SIZE && retx_queue.empty()) { - if (tx_window[vt_a].buf != NULL) { - log->warning("Full Tx window, ReTx'ing first outstanding PDU\n"); - rlc_amd_retx_t retx = {}; - retx.is_segment = false; - retx.so_start = 0; - retx.so_end = tx_window[vt_a].buf->N_bytes; - retx.sn = vt_a; - retx_queue.push_back(retx); - } else { - log->error("Found invalid PDU in tx_window.\n"); - } + retransmit_random_pdu(); } // RETX if required @@ -505,21 +495,10 @@ void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id) { pthread_mutex_lock(&mutex); if (poll_retx_timer != NULL && poll_retx_timer_id == timeout_id) { - // if both tx and retx buffer are empty, retransmit next PDU to be ack'ed (Section 5.2.2.3 in TS 36.322) - log->debug("Poll reTx timer expired (lcid=%d)\n", parent->lcid); - if ((not tx_window.empty() && retx_queue.empty() && tx_sdu_queue.size() == 0)) { - std::map::iterator it = tx_window.find(vt_s - 1); - if (it != tx_window.end()) { - log->info("Schedule last PDU (SN=%d) for reTx.\n", vt_s - 1); - rlc_amd_retx_t retx = {}; - retx.is_segment = false; - retx.so_start = 0; - retx.so_end = tx_window[vt_s - 1].buf->N_bytes; - retx.sn = vt_s - 1; - retx_queue.push_back(retx); - } else { - log->error("Found invalid PDU in tx_window.\n"); - } + log->debug("Poll reTx timer expired for LCID=%d after %d ms\n", parent->lcid, poll_retx_timer->get_timeout()); + // Section 5.2.2.3 in TS 36.311, if tx_window is full and retx_queue empty, retransmit random PDU + if ((tx_window.size() >= RLC_AM_WINDOW_SIZE && retx_queue.empty() && tx_sdu_queue.size() == 0)) { + retransmit_random_pdu(); } } else if (status_prohibit_timer != NULL && status_prohibit_timer_id == timeout_id) { @@ -528,6 +507,21 @@ void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id) pthread_mutex_unlock(&mutex); } +void rlc_am::rlc_am_tx::retransmit_random_pdu() +{ + // randomly select PDU in tx window for retransmission + std::map::iterator it = tx_window.begin(); + std::advance(it, rand() % tx_window.size()); + + log->info("Schedule SN=%d for reTx.\n", it->first); + rlc_amd_retx_t retx = {}; + retx.is_segment = false; + retx.so_start = 0; + retx.so_end = it->second.buf->N_bytes; + retx.sn = it->first; + retx_queue.push_back(retx); +} + uint32_t rlc_am::rlc_am_tx::get_num_tx_bytes() { return num_tx_bytes; @@ -556,7 +550,7 @@ bool rlc_am::rlc_am_tx::poll_required() if (poll_retx_timer != NULL) { if (poll_retx_timer->is_expired()) { - // re-arm timer + // re-arm timer (will be stopped when status PDU is received) poll_retx_timer->reset(); poll_retx_timer->run(); return true;