diff --git a/src/rlc.cpp b/src/rlc.cpp index 1a2aa0fb..1a055468 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -37,3 +37,16 @@ void gprs_rlc_v_b::reset() for (size_t i = 0; i < ARRAY_SIZE(m_v_b); ++i) mark_invalid(i); } + +int gprs_rlc_v_b::resend_needed(const uint16_t v_a, const uint16_t v_s, + const uint16_t mod_sns, + const uint16_t mod_sns_half) +{ + for (uint8_t bsn = v_a; bsn != v_s; bsn = (bsn + 1) & mod_sns) { + uint16_t index = bsn & mod_sns_half; + if (is_nacked(index) || is_resend(index)) + return bsn; + } + + return -1; +} diff --git a/src/rlc.h b/src/rlc.h index e75a0781..3f65a2c2 100644 --- a/src/rlc.h +++ b/src/rlc.h @@ -44,6 +44,10 @@ struct gprs_rlc { }; struct gprs_rlc_v_b { + int resend_needed(const uint16_t acked, const uint16_t sent, + const uint16_t mod_sns, const uint16_t mod_sns_half); + + /* Check for an individual frame */ bool is_unacked(int index) const; bool is_nacked(int index) const; bool is_acked(int index) const; @@ -52,6 +56,7 @@ struct gprs_rlc_v_b { char state(int index) const; + /* Mark a RLC frame for something */ void mark_unacked(int index); void mark_nacked(int index); void mark_acked(int index); diff --git a/src/tbf.cpp b/src/tbf.cpp index 54eb3cb6..747678c6 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -880,8 +880,8 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts) struct rlc_li_field *li; struct msgb *msg; uint8_t bsn; - uint16_t mod_sns = m_sns - 1; - uint16_t mod_sns_half = (m_sns >> 1) - 1; + const uint16_t mod_sns = m_sns - 1; + const uint16_t mod_sns_half = (m_sns >> 1) - 1; uint16_t index; uint8_t *delimiter, *data, *e_pointer; uint16_t space, chunk; @@ -892,17 +892,16 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts) do_resend: /* check if there is a block with negative acknowledgement */ - for (bsn = dir.dl.v_a; bsn != dir.dl.v_s; - bsn = (bsn + 1) & mod_sns) { - index = (bsn & mod_sns_half); - if (dir.dl.v_b.is_nacked(index) || dir.dl.v_b.is_resend(index)) { - LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", - bsn); - /* re-send block with negative aknowlegement */ - dir.dl.v_b.mark_unacked(index); - bts->rlc_resent(); - return create_dl_acked_block(fn, ts, index, first_fin_ack); - } + int resend_bsn = dir.dl.v_b.resend_needed(dir.dl.v_a, dir.dl.v_s, + mod_sns, mod_sns_half); + if (resend_bsn >= 0) { + LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", resend_bsn); + + uint16_t index = resend_bsn & mod_sns_half; + /* re-send block with negative aknowlegement */ + dir.dl.v_b.mark_unacked(index); + bts->rlc_resent(); + return create_dl_acked_block(fn, ts, index, first_fin_ack); } /* if the window has stalled, or transfer is complete,