aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/rlc.cpp13
-rw-r--r--src/rlc.h5
-rw-r--r--src/tbf.cpp25
3 files changed, 30 insertions, 13 deletions
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,