rlc_am_lte: fix handling of maxretx

this patch fixes the actions/handling after RLC detected
maxRetx reached for a given SN.

According to the TS, RLC should only inform upper layers and
not try to recover from the event itself.

As a consequence, we won't manipulate the Tx or Rx window.
As a result of this, we might retransmit a SN more than
the specified amount of times.

It's the task of RRC to reestablish the bearer to recover
from that.
master
Andre Puschmann 4 years ago
parent 44e7d41f57
commit ceacf8508d

@ -293,7 +293,7 @@ private:
// Helpers // Helpers
bool poll_required(); bool poll_required();
bool do_status(); bool do_status();
bool sn_reached_max_retx(uint32_t sn); void check_sn_reached_max_retx(uint32_t sn);
rlc_am_lte* parent = nullptr; rlc_am_lte* parent = nullptr;
byte_buffer_pool* pool = nullptr; byte_buffer_pool* pool = nullptr;

@ -290,41 +290,19 @@ bool rlc_am_lte::rlc_am_lte_tx::has_data()
* Helper to check if a SN has reached the max reTx threshold * Helper to check if a SN has reached the max reTx threshold
* *
* Caller _must_ hold the mutex when calling the function. * Caller _must_ hold the mutex when calling the function.
* If the retx has been reached for a SN. The SN is removed from the Tx window * If the retx has been reached for a SN the upper layers (i.e. RRC/PDCP) will be informed.
* and the RLC am state variables are advanced. * The SN is _not_ removed from the Tx window, so retransmissions of that SN can still occur.
* *
* @param sn The SN of the PDU to check * @param sn The SN of the PDU to check
* @return True if the max_retx counter has been reached and the SN has been removed, false otherwise
*/ */
bool rlc_am_lte::rlc_am_lte_tx::sn_reached_max_retx(uint32_t sn) void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
{ {
if (tx_window[sn].retx_count >= cfg.max_retx_thresh) { if (tx_window[sn].retx_count == cfg.max_retx_thresh) {
logger.warning("%s Signaling max number of reTx=%d for for SN=%d", RB_NAME, tx_window[sn].retx_count, sn); logger.warning("%s Signaling max number of reTx=%d for for SN=%d", RB_NAME, tx_window[sn].retx_count, sn);
parent->rrc->max_retx_attempted(); parent->rrc->max_retx_attempted();
parent->pdcp->notify_failure(parent->lcid, tx_window[sn].pdcp_sns); parent->pdcp->notify_failure(parent->lcid, tx_window[sn].pdcp_sns);
parent->metrics.num_lost_pdus++; parent->metrics.num_lost_pdus++;
// remove SN from Tx window
tx_window.remove_pdu(sn);
// advance window if this is was the lowest SN we've been waiting for
if (sn == vt_a) {
vt_a = (vt_a + 1) % MOD;
vt_ms = (vt_ms + 1) % MOD;
// Advance vt_a to the smallest SN for which ACK has not been received yet (Sec 5.1.3.1.1)
while (TX_MOD_BASE(vt_a) < TX_MOD_BASE(vt_s) && !tx_window.has_sn(vt_a)) {
logger.warning("SN=%d has already been removed, advance window vt_s=%d", vt_a, vt_s);
vt_a = (vt_a + 1) % MOD;
vt_ms = (vt_ms + 1) % MOD;
}
} else {
logger.warning("Don't advance window sn=%d not vt_a=%d", sn, vt_a);
}
return true;
} }
return false;
} }
uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state() uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
@ -664,9 +642,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
retx_queue.pop(); retx_queue.pop();
tx_window[retx.sn].retx_count++; tx_window[retx.sn].retx_count++;
if (sn_reached_max_retx(retx.sn)) { check_sn_reached_max_retx(retx.sn);
return 0;
}
logger.info(payload, logger.info(payload,
tx_window[retx.sn].buf->N_bytes, tx_window[retx.sn].buf->N_bytes,
@ -830,10 +806,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_byte
tx_window[retx.sn].retx_count++; tx_window[retx.sn].retx_count++;
} }
// Check max reTx counter and abort building segment if it passed the threshold check_sn_reached_max_retx(retx.sn);
if (sn_reached_max_retx(retx.sn)) {
return 0;
}
// Write header and pdu // Write header and pdu
uint8_t* ptr = payload; uint8_t* ptr = payload;

Loading…
Cancel
Save