diff options
-rw-r--r-- | src/rlc.cpp | 6 | ||||
-rw-r--r-- | src/tbf.cpp | 31 | ||||
-rw-r--r-- | src/tbf.h | 85 |
3 files changed, 104 insertions, 18 deletions
diff --git a/src/rlc.cpp b/src/rlc.cpp index 4319c499..1a2aa0fb 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 19a0d819..ab77d930 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; @@ -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'); +} |