aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-25 23:51:19 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-26 21:00:51 +0100
commit7f3e662b3412a028254796420d7761d8c84c8fd2 (patch)
tree3a09faa65d348b5db2264726c6175bc1c5b98b86
parentcbb00ebd04c11aade8503e407ab97ee8b632e99f (diff)
tbf/rlc: Move raising of V(Q) into the ul window code
-rw-r--r--src/rlc.cpp25
-rw-r--r--src/rlc.h11
-rw-r--r--src/tbf.cpp18
3 files changed, 36 insertions, 18 deletions
diff --git a/src/rlc.cpp b/src/rlc.cpp
index ecc7b9a..dc5cf8b 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -151,7 +151,7 @@ void gprs_rlc_v_n::reset()
}
/* Raise V(R) to highest received sequence number not received. */
-void gprs_rlc_ul_window::raise(const uint16_t bsn, gprs_rlc_v_n *v_n)
+void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n)
{
uint16_t offset_v_r;
offset_v_r = (bsn + 1 - v_r()) & mod_sns();
@@ -160,8 +160,29 @@ void gprs_rlc_ul_window::raise(const uint16_t bsn, gprs_rlc_v_n *v_n)
while (offset_v_r--) {
if (offset_v_r) /* all except the received block */
v_n->mark_missing(v_r() & mod_sns_half());
- raise(1);
+ raise_v_r(1);
}
LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", v_r());
}
}
+
+/*
+ * Raise V(Q) if possible. This is looped until there is a gap
+ * (non received block) or the window is empty.
+ */
+uint16_t gprs_rlc_ul_window::raise_v_q(gprs_rlc_v_n *v_n)
+{
+ uint16_t count = 0;
+
+ while (v_q() != v_r()) {
+ uint16_t index = v_q() & mod_sns_half();
+ if (!v_n->is_received(index))
+ break;
+ LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
+ "V(Q) to %d\n", v_q(), (v_q() + 1) & mod_sns());
+ raise_v_q(1);
+ count += 1;
+ }
+
+ return count;
+}
diff --git a/src/rlc.h b/src/rlc.h
index 328af6c..b85b33e 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -87,10 +87,11 @@ struct gprs_rlc_ul_window {
bool is_in_window(uint8_t bsn) const;
- void raise(int moves);
- void raise(const uint16_t bsn, gprs_rlc_v_n *v_n);
+ void raise_v_r(int moves);
+ void raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n);
+ uint16_t raise_v_q(gprs_rlc_v_n *v_n);
- void increment_q(int);
+ void raise_v_q(int);
uint16_t m_v_r; /* receive state */
uint16_t m_v_q; /* receive window state */
@@ -347,12 +348,12 @@ inline const uint16_t gprs_rlc_ul_window::v_q() const
return m_v_q;
}
-inline void gprs_rlc_ul_window::raise(int moves)
+inline void gprs_rlc_ul_window::raise_v_r(int moves)
{
m_v_r = (m_v_r + moves) & mod_sns();
}
-inline void gprs_rlc_ul_window::increment_q(int incr)
+inline void gprs_rlc_ul_window::raise_v_q(int incr)
{
m_v_q = (m_v_q + incr) & mod_sns();
}
diff --git a/src/tbf.cpp b/src/tbf.cpp
index a2667e4..88d4662 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -1613,22 +1613,18 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len
(dir.ul.window.v_q() + ws - 1) & mod_sns);
dir.ul.v_n.mark_received(index);
- dir.ul.window.raise(rh->bsn, &dir.ul.v_n);
+ dir.ul.window.raise_v_r(rh->bsn, &dir.ul.v_n);
/* Raise V(Q) if possible, and retrieve LLC frames from blocks.
* This is looped until there is a gap (non received block) or
* the window is empty.*/
- while (this->dir.ul.window.v_q() != this->dir.ul.window.v_r()) {
- index = dir.ul.window.v_q() & mod_sns_half;
- if (!dir.ul.v_n.is_received(index))
- break;
- LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
- "V(Q) to %d\n", dir.ul.window.v_q(),
- (dir.ul.window.v_q() + 1) & mod_sns);
- /* get LLC data from block */
+ const uint16_t v_q_beg = dir.ul.window.v_q();
+ const uint16_t count = dir.ul.window.raise_v_q(&dir.ul.v_n);
+
+ /* Retrieve LLC frames from blocks that are ready */
+ for (uint16_t i = 0; i < count; ++i) {
+ uint16_t index = (v_q_beg + i) & mod_sns_half;
assemble_forward_llc(&m_rlc.blocks[index]);
- /* raise V(Q), because block already received */
- dir.ul.window.increment_q(1);
}
/* Check CV of last frame in buffer */