aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-23 16:06:54 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-23 16:19:17 +0100
commit321f3c3104d7710d97fe373d6cf17da1e5931bef (patch)
tree430d7165b4d839451a484e7a09be71765a2f4c96
parent092478f294fedd4dc285ff817143679d3068242d (diff)
rlc: Move the ack state array into a separate class that can be tested
-rw-r--r--src/rlc.cpp6
-rw-r--r--src/tbf.cpp31
-rw-r--r--src/tbf.h85
3 files changed, 104 insertions, 18 deletions
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 4319c49..1a2aa0f 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -31,3 +31,9 @@ uint8_t *gprs_rlc_data::prepare(size_t block_data_len)
return block;
}
+
+void gprs_rlc_v_b::reset()
+{
+ for (size_t i = 0; i < ARRAY_SIZE(m_v_b); ++i)
+ mark_invalid(i);
+}
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 19a0d81..ab77d93 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -895,12 +895,11 @@ do_resend:
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[index] == 'N'
- || dir.dl.v_b[index] == 'X') {
+ 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[index] = 'U'; /* unacked */
+ dir.dl.v_b.mark_unacked(index);
bts->rlc_resent();
return create_dl_acked_block(fn, ts, index, first_fin_ack);
}
@@ -941,9 +940,9 @@ do_resend:
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[index] == 'U') {
+ if (dir.dl.v_b.is_unacked(index)) {
/* mark to be re-send */
- dir.dl.v_b[index] = 'X';
+ dir.dl.v_b.mark_resend(index);
resend++;
}
}
@@ -1111,7 +1110,7 @@ do_resend:
#warning "move this up?"
m_rlc.blocks[index].len = block_length;
/* raise send state and set ack state array */
- dir.dl.v_b[index] = 'U'; /* unacked */
+ dir.dl.v_b.mark_unacked(index);
dir.dl.v_s = (dir.dl.v_s + 1) & mod_sns; /* inc send state */
return create_dl_acked_block(fn, ts, index, first_fin_ack);
@@ -1463,14 +1462,13 @@ int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
if (bit) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
"ack for BSN=%d\n", bsn);
- if (dir.dl.v_b[bsn & mod_sns_half]
- != 'A')
+ if (!dir.dl.v_b.is_acked(bsn & mod_sns_half))
received++;
- dir.dl.v_b[bsn & mod_sns_half] = 'A';
+ dir.dl.v_b.mark_acked(bsn & mod_sns_half);
} else {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
"NACK for BSN=%d\n", bsn);
- dir.dl.v_b[bsn & mod_sns_half] = 'N';
+ dir.dl.v_b.mark_nacked(bsn & mod_sns_half);
bts->rlc_nacked();
lost++;
}
@@ -1481,11 +1479,9 @@ int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
/* raise V(A), if possible */
for (i = 0, bsn = dir.dl.v_a; bsn != dir.dl.v_s;
i++, bsn = (bsn + 1) & mod_sns) {
- if (dir.dl.v_b[bsn & mod_sns_half] == 'A') {
- dir.dl.v_b[bsn & mod_sns_half] = 'I';
- /* mark invalid */
- dir.dl.v_a = (dir.dl.v_a + 1)
- & mod_sns;
+ if (dir.dl.v_b.is_acked(bsn & mod_sns_half)) {
+ dir.dl.v_b.mark_invalid(bsn & mod_sns_half);
+ dir.dl.v_a = (dir.dl.v_a + 1) & mod_sns;
} else
break;
}
@@ -1493,7 +1489,7 @@ int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
/* show receive state array in debug (V(A)..V(S)-1) */
for (i = 0, bsn = dir.dl.v_a; bsn != dir.dl.v_s;
i++, bsn = (bsn + 1) & mod_sns) {
- show_v_b[i] = dir.dl.v_b[bsn & mod_sns_half];
+ show_v_b[i] = dir.dl.v_b.state(bsn & mod_sns_half);
if (show_v_b[i] == 0)
show_v_b[i] = ' ';
}
@@ -1517,7 +1513,7 @@ int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
/* range V(A)..V(S)-1 */
for (bsn = dir.dl.v_a; bsn != dir.dl.v_s;
bsn = (bsn + 1) & mod_sns) {
- if (dir.dl.v_b[bsn & mod_sns_half] != 'A')
+ if (!dir.dl.v_b.is_acked(bsn & mod_sns_half))
received++;
}
@@ -1852,6 +1848,7 @@ void gprs_rlcmac_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
/* reset rlc states */
memset(&dir.dl, 0, sizeof(dir.dl));
+ dir.dl.v_b.reset();
/* keep to flags */
state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
diff --git a/src/tbf.h b/src/tbf.h
index 0eacec5..a25f62d 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -102,6 +102,29 @@ struct gprs_rlc {
gprs_rlc_data blocks[RLC_MAX_SNS/2];
};
+struct gprs_rlc_v_b {
+ bool is_nacked(int index) const;
+ bool is_acked(int index) const;
+ bool is_unacked(int index) const;
+ bool is_resend(int index) const;
+
+ char state(int index) const;
+
+ void mark_unacked(int index);
+ void mark_nacked(int index);
+ void mark_acked(int index);
+ void mark_resend(int index);
+ void mark_invalid(int index);
+
+ void reset();
+
+private:
+ bool is_state(int index, const char state) const;
+ void mark(int index, const char state);
+
+ char m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
+};
+
struct gprs_rlcmac_tbf {
static void free_all(struct gprs_rlcmac_trx *trx);
@@ -188,7 +211,7 @@ struct gprs_rlcmac_tbf {
uint16_t bsn; /* block sequence number */
uint16_t v_s; /* send state */
uint16_t v_a; /* ack state */
- char v_b[RLC_MAX_SNS/2]; /* acknowledge state array */
+ gprs_rlc_v_b v_b;
int32_t tx_counter; /* count all transmitted blocks */
uint8_t wait_confirm; /* wait for CCCH IMM.ASS cnf */
} dl;
@@ -324,3 +347,63 @@ inline const char *gprs_rlcmac_tbf::imsi() const
}
const char *tbf_name(gprs_rlcmac_tbf *tbf);
+
+inline bool gprs_rlc_v_b::is_state(int index, const char type) const
+{
+ return m_v_b[index] == type;
+}
+
+inline void gprs_rlc_v_b::mark(int index, const char type)
+{
+ m_v_b[index] = type;
+}
+
+inline char gprs_rlc_v_b::state(int index) const
+{
+ return m_v_b[index];
+}
+
+inline bool gprs_rlc_v_b::is_nacked(int index) const
+{
+ return is_state(index, 'N');
+}
+
+inline bool gprs_rlc_v_b::is_acked(int index) const
+{
+ return is_state(index, 'A');
+}
+
+inline bool gprs_rlc_v_b::is_unacked(int index) const
+{
+ return is_state(index, 'U');
+}
+
+inline bool gprs_rlc_v_b::is_resend(int index) const
+{
+ return is_state(index, 'X');
+}
+
+inline void gprs_rlc_v_b::mark_resend(int index)
+{
+ return mark(index, 'X');
+}
+
+inline void gprs_rlc_v_b::mark_unacked(int index)
+{
+ return mark(index, 'U');
+}
+
+inline void gprs_rlc_v_b::mark_acked(int index)
+{
+ return mark(index, 'A');
+}
+
+inline void gprs_rlc_v_b::mark_nacked(int index)
+{
+ return mark(index, 'N');
+}
+
+inline void gprs_rlc_v_b::mark_invalid(int index)
+{
+ return mark(index, 'I');
+}