diff --git a/src/encoding.cpp b/src/encoding.cpp index 8ec93c98..51b0fbe5 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -382,7 +382,7 @@ void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, char rbb[65]; - tbf->dir.ul.window.update_rbb(&tbf->dir.ul.v_n, rbb); + tbf->dir.ul.window.update_rbb(rbb); LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s " "(final=%d)\n", tbf_name(tbf), final); diff --git a/src/rlc.cpp b/src/rlc.cpp index d115f767..36320dc9 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -46,24 +46,24 @@ void gprs_rlc_v_b::reset() mark_invalid(i); } -int gprs_rlc_v_b::resend_needed(const gprs_rlc_dl_window &w) +int gprs_rlc_dl_window::resend_needed() { - for (uint16_t bsn = w.v_a(); bsn != w.v_s(); bsn = (bsn + 1) & w.mod_sns()) { - if (is_nacked(bsn) || is_resend(bsn)) + for (uint16_t bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) { + if (m_v_b.is_nacked(bsn) || m_v_b.is_resend(bsn)) return bsn; } return -1; } -int gprs_rlc_v_b::mark_for_resend(const gprs_rlc_dl_window &w) +int gprs_rlc_dl_window::mark_for_resend() { int resend = 0; - for (uint16_t bsn = w.v_a(); bsn != w.v_s(); bsn = (bsn + 1) & w.mod_sns()) { - if (is_unacked(bsn)) { + for (uint16_t bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) { + if (m_v_b.is_unacked(bsn)) { /* mark to be re-send */ - mark_resend(bsn); + m_v_b.mark_resend(bsn); resend += 1; } } @@ -71,13 +71,13 @@ int gprs_rlc_v_b::mark_for_resend(const gprs_rlc_dl_window &w) return resend; } -int gprs_rlc_v_b::count_unacked(const gprs_rlc_dl_window &w) +int gprs_rlc_dl_window::count_unacked() { uint16_t unacked = 0; uint16_t bsn; - for (bsn = w.v_a(); bsn != w.v_s(); bsn = (bsn + 1) & w.mod_sns()) { - if (!is_acked(bsn)) + for (bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) { + if (!m_v_b.is_acked(bsn)) unacked += 1; } @@ -89,40 +89,39 @@ static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns) return (ssn - 1 - bitnum) & mod_sns; } -void gprs_rlc_v_b::update(BTS *bts, char *show_rbb, uint8_t ssn, - const gprs_rlc_dl_window &w, +void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint8_t ssn, uint16_t *lost, uint16_t *received) { /* SSN - 1 is in range V(A)..V(S)-1 */ - for (int bitpos = 0; bitpos < w.ws(); bitpos++) { - uint16_t bsn = bitnum_to_bsn(bitpos, ssn, w.mod_sns()); + for (int bitpos = 0; bitpos < ws(); bitpos++) { + uint16_t bsn = bitnum_to_bsn(bitpos, ssn, mod_sns()); - if (bsn == ((w.v_a() - 1) & w.mod_sns())) + if (bsn == ((v_a() - 1) & mod_sns())) break; - if (show_rbb[w.ws() - 1 - bitpos] == 'R') { + if (show_rbb[ws() - 1 - bitpos] == 'R') { LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); - if (!is_acked(bsn)) + if (!m_v_b.is_acked(bsn)) *received += 1; - mark_acked(bsn); + m_v_b.mark_acked(bsn); } else { LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); - mark_nacked(bsn); + m_v_b.mark_nacked(bsn); bts->rlc_nacked(); *lost += 1; } } } -int gprs_rlc_v_b::move_window(const gprs_rlc_dl_window &w) +int gprs_rlc_dl_window::move_window() { int i; uint16_t bsn; int moved = 0; - for (i = 0, bsn = w.v_a(); bsn != w.v_s(); i++, bsn = (bsn + 1) & w.mod_sns()) { - if (is_acked(bsn)) { - mark_invalid(bsn); + for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = (bsn + 1) & mod_sns()) { + if (m_v_b.is_acked(bsn)) { + m_v_b.mark_invalid(bsn); moved += 1; } else break; @@ -131,31 +130,45 @@ int gprs_rlc_v_b::move_window(const gprs_rlc_dl_window &w) return moved; } -void gprs_rlc_v_b::state(char *show_v_b, const gprs_rlc_dl_window &w) +void gprs_rlc_dl_window::show_state(char *show_v_b) { int i; uint16_t bsn; - for (i = 0, bsn = w.v_a(); bsn != w.v_s(); i++, bsn = (bsn + 1) & w.mod_sns()) { + for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = (bsn + 1) & mod_sns()) { uint16_t index = bsn & mod_sns_half(); - show_v_b[i] = m_v_b[index]; - if (show_v_b[i] == 0) - show_v_b[i] = ' '; + switch(m_v_b.get_state(index)) { + case GPRS_RLC_DL_BSN_INVALID: + show_v_b[i] = 'I'; + break; + case GPRS_RLC_DL_BSN_ACKED: + show_v_b[i] = 'A'; + break; + case GPRS_RLC_DL_BSN_RESEND: + show_v_b[i] = 'X'; + break; + case GPRS_RLC_DL_BSN_NACKED: + show_v_b[i] = 'N'; + break; + default: + show_v_b[i] = '?'; + } } show_v_b[i] = '\0'; } void gprs_rlc_v_n::reset() { - memset(m_v_n, 0x0, sizeof(m_v_n)); + for (size_t i = 0; i < ARRAY_SIZE(m_v_n); ++i) + m_v_n[i] = GPRS_RLC_UL_BSN_INVALID; } /* Update the receive block bitmap */ -void gprs_rlc_ul_window::update_rbb(const gprs_rlc_v_n *v_n, char *rbb) +void gprs_rlc_ul_window::update_rbb(char *rbb) { int i; for (i=0; i < ws(); i++) { - if (v_n->is_received(ssn()-1-i)) + if (m_v_n.is_received(ssn()-1-i)) rbb[ws()-1-i] = 'R'; else rbb[ws()-1-i] = 'I'; @@ -163,7 +176,7 @@ void gprs_rlc_ul_window::update_rbb(const gprs_rlc_v_n *v_n, char *rbb) } /* Raise V(R) to highest received sequence number not received. */ -void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n) +void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn) { uint16_t offset_v_r; offset_v_r = (bsn + 1 - v_r()) & mod_sns(); @@ -171,8 +184,8 @@ void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n) if (offset_v_r < (sns() >> 1)) { while (offset_v_r--) { if (offset_v_r) /* all except the received block */ - v_n->mark_missing(v_r()); - raise_v_r(1); + m_v_n.mark_missing(v_r()); + raise_v_r_to(1); } LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", v_r()); } @@ -182,12 +195,12 @@ void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n) * 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 gprs_rlc_ul_window::raise_v_q() { uint16_t count = 0; while (v_q() != v_r()) { - if (!v_n->is_received(v_q())) + if (!m_v_n.is_received(v_q())) break; LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising " "V(Q) to %d\n", v_q(), (v_q() + 1) & mod_sns()); @@ -197,3 +210,11 @@ uint16_t gprs_rlc_ul_window::raise_v_q(gprs_rlc_v_n *v_n) return count; } + +uint16_t gprs_rlc_ul_window::receive_bsn(const uint16_t bsn) +{ + m_v_n.mark_received(bsn); + raise_v_r(bsn); + + return raise_v_q(); +} diff --git a/src/rlc.h b/src/rlc.h index d68afab8..17a1360b 100644 --- a/src/rlc.h +++ b/src/rlc.h @@ -28,6 +28,23 @@ class BTS; struct gprs_rlc_v_n; +/* The state of a BSN in the send/receive window */ +enum gprs_rlc_ul_bsn_state { + GPRS_RLC_UL_BSN_INVALID, + GPRS_RLC_UL_BSN_RECEIVED, + GPRS_RLC_UL_BSN_MISSING, + GPRS_RLC_UL_BSN_MAX, +}; + +enum gprs_rlc_dl_bsn_state { + GPRS_RLC_DL_BSN_INVALID, + GPRS_RLC_DL_BSN_NACKED, + GPRS_RLC_DL_BSN_ACKED, + GPRS_RLC_DL_BSN_UNACKED, + GPRS_RLC_DL_BSN_RESEND, + GPRS_RLC_DL_BSN_MAX, +}; + static inline uint16_t mod_sns_half() { @@ -53,6 +70,36 @@ struct gprs_rlc { gprs_rlc_data m_blocks[RLC_MAX_SNS/2]; }; +/** + * TODO: for GPRS/EDGE maybe make sns a template parameter + * so we create specialized versions... + */ +struct gprs_rlc_v_b { + /* Check for an individual frame */ + bool is_unacked(int bsn) const; + bool is_nacked(int bsn) const; + bool is_acked(int bsn) const; + bool is_resend(int bsn) const; + bool is_invalid(int bsn) const; + gprs_rlc_dl_bsn_state get_state(int bsn) const; + + /* Mark a RLC frame for something */ + void mark_unacked(int bsn); + void mark_nacked(int bsn); + void mark_acked(int bsn); + void mark_resend(int bsn); + void mark_invalid(int bsn); + + void reset(); + + +private: + bool is_state(int bsn, const gprs_rlc_dl_bsn_state state) const; + void mark(int bsn, const gprs_rlc_dl_bsn_state state); + + gprs_rlc_dl_bsn_state m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */ +}; + /** * TODO: The UL/DL code could/should share a baseclass but @@ -77,8 +124,34 @@ struct gprs_rlc_dl_window { const uint16_t v_a() const; const int16_t distance() const; + /* Methods to manage reception */ + int resend_needed(); + int mark_for_resend(); + void update(BTS *bts, char *show_rbb, uint8_t ssn, + uint16_t *lost, uint16_t *received); + int move_window(); + void show_state(char *show_rbb); + int count_unacked(); + uint16_t m_v_s; /* send state */ uint16_t m_v_a; /* ack state */ + + gprs_rlc_v_b m_v_b; +}; + +struct gprs_rlc_v_n { + void reset(); + + void mark_received(int bsn); + void mark_missing(int bsn); + + bool is_received(int bsn) const; + + gprs_rlc_ul_bsn_state state(int bsn) const; +private: + bool is_state(int bsn, const gprs_rlc_ul_bsn_state state) const; + void mark(int bsn, const gprs_rlc_ul_bsn_state state); + gprs_rlc_ul_bsn_state m_v_n[RLC_MAX_SNS/2]; /* receive state array */ }; struct gprs_rlc_ul_window { @@ -93,67 +166,19 @@ struct gprs_rlc_ul_window { bool is_in_window(uint8_t bsn) const; - void update_rbb(const gprs_rlc_v_n *v_n, char *rbb); - 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 update_rbb(char *rbb); + void raise_v_r_to(int moves); + void raise_v_r(const uint16_t bsn); + uint16_t raise_v_q(); void raise_v_q(int); + uint16_t receive_bsn(const uint16_t bsn); + uint16_t m_v_r; /* receive state */ uint16_t m_v_q; /* receive window state */ -}; -/** - * TODO: for GPRS/EDGE maybe make sns a template parameter - * so we create specialized versions... - */ -struct gprs_rlc_v_b { - int resend_needed(const gprs_rlc_dl_window& window); - int mark_for_resend(const gprs_rlc_dl_window& window); - void update(BTS *bts, char *show_rbb, uint8_t ssn, - const gprs_rlc_dl_window& window, - uint16_t *lost, uint16_t *received); - int move_window(const gprs_rlc_dl_window& window); - void state(char *show_rbb, const gprs_rlc_dl_window& window); - int count_unacked(const gprs_rlc_dl_window& window); - - /* Check for an individual frame */ - bool is_unacked(int bsn) const; - bool is_nacked(int bsn) const; - bool is_acked(int bsn) const; - bool is_resend(int bsn) const; - bool is_invalid(int bsn) const; - - /* Mark a RLC frame for something */ - void mark_unacked(int bsn); - void mark_nacked(int bsn); - void mark_acked(int bsn); - void mark_resend(int bsn); - void mark_invalid(int bsn); - - void reset(); - -private: - bool is_state(int bsn, const char state) const; - void mark(int bsn, const char state); - - char m_v_b[RLC_MAX_SNS/2]; /* acknowledge state array */ -}; - -struct gprs_rlc_v_n { - void reset(); - - void mark_received(int bsn); - void mark_missing(int bsn); - - bool is_received(int bsn) const; - - char state(int bsn) const; -private: - bool is_state(int bsn, const char state) const; - void mark(int bsn, const char state); - char m_v_n[RLC_MAX_SNS/2]; /* receive state array */ + gprs_rlc_v_n m_v_n; }; extern "C" { @@ -190,67 +215,71 @@ struct rlc_li_field { } __attribute__ ((packed)); } -inline bool gprs_rlc_v_b::is_state(int bsn, const char type) const +inline bool gprs_rlc_v_b::is_state(int bsn, const gprs_rlc_dl_bsn_state type) const { return m_v_b[bsn & mod_sns_half()] == type; } -inline void gprs_rlc_v_b::mark(int bsn, const char type) +inline void gprs_rlc_v_b::mark(int bsn, const gprs_rlc_dl_bsn_state type) { m_v_b[bsn & mod_sns_half()] = type; } inline bool gprs_rlc_v_b::is_nacked(int bsn) const { - return is_state(bsn, 'N'); + return is_state(bsn, GPRS_RLC_DL_BSN_NACKED); } inline bool gprs_rlc_v_b::is_acked(int bsn) const { - return is_state(bsn, 'A'); + return is_state(bsn, GPRS_RLC_DL_BSN_ACKED); } inline bool gprs_rlc_v_b::is_unacked(int bsn) const { - return is_state(bsn, 'U'); + return is_state(bsn, GPRS_RLC_DL_BSN_UNACKED); } inline bool gprs_rlc_v_b::is_resend(int bsn) const { - return is_state(bsn, 'X'); + return is_state(bsn, GPRS_RLC_DL_BSN_RESEND); } inline bool gprs_rlc_v_b::is_invalid(int bsn) const { - return is_state(bsn, 'I'); + return is_state(bsn, GPRS_RLC_DL_BSN_INVALID); +} + +inline gprs_rlc_dl_bsn_state gprs_rlc_v_b::get_state(int bsn) const +{ + return m_v_b[bsn & mod_sns_half()]; } inline void gprs_rlc_v_b::mark_resend(int bsn) { - return mark(bsn, 'X'); + return mark(bsn, GPRS_RLC_DL_BSN_RESEND); } inline void gprs_rlc_v_b::mark_unacked(int bsn) { - return mark(bsn, 'U'); + return mark(bsn, GPRS_RLC_DL_BSN_UNACKED); } inline void gprs_rlc_v_b::mark_acked(int bsn) { - return mark(bsn, 'A'); + return mark(bsn, GPRS_RLC_DL_BSN_ACKED); } inline void gprs_rlc_v_b::mark_nacked(int bsn) { - return mark(bsn, 'N'); + return mark(bsn, GPRS_RLC_DL_BSN_NACKED); } inline void gprs_rlc_v_b::mark_invalid(int bsn) { - return mark(bsn, 'I'); + return mark(bsn, GPRS_RLC_DL_BSN_INVALID); } - inline const uint16_t gprs_rlc_dl_window::sns() const { return RLC_MAX_SNS; @@ -347,7 +376,7 @@ inline const uint16_t gprs_rlc_ul_window::ssn() const return m_v_r; } -inline void gprs_rlc_ul_window::raise_v_r(int moves) +inline void gprs_rlc_ul_window::raise_v_r_to(int moves) { m_v_r = (m_v_r + moves) & mod_sns(); } @@ -359,35 +388,32 @@ inline void gprs_rlc_ul_window::raise_v_q(int incr) inline void gprs_rlc_v_n::mark_received(int bsn) { - return mark(bsn, 'R'); + return mark(bsn, GPRS_RLC_UL_BSN_RECEIVED); } inline void gprs_rlc_v_n::mark_missing(int bsn) { - return mark(bsn, 'N'); + return mark(bsn, GPRS_RLC_UL_BSN_MISSING); } inline bool gprs_rlc_v_n::is_received(int bsn) const { - return is_state(bsn, 'R'); + return is_state(bsn, GPRS_RLC_UL_BSN_RECEIVED); } -inline bool gprs_rlc_v_n::is_state(int bsn, const char type) const +inline bool gprs_rlc_v_n::is_state(int bsn, gprs_rlc_ul_bsn_state type) const { return m_v_n[bsn & mod_sns_half()] == type; } -inline void gprs_rlc_v_n::mark(int bsn, const char type) +inline void gprs_rlc_v_n::mark(int bsn, gprs_rlc_ul_bsn_state type) { m_v_n[bsn & mod_sns_half()] = type; } -inline char gprs_rlc_v_n::state(int bsn) const +inline gprs_rlc_ul_bsn_state gprs_rlc_v_n::state(int bsn) const { - char bit = m_v_n[bsn & mod_sns_half()]; - if (bit == '\0') - return ' '; - return bit; + return m_v_n[bsn & mod_sns_half()]; } inline gprs_rlc_data *gprs_rlc::block(int bsn) diff --git a/src/tbf.cpp b/src/tbf.cpp index a91193d2..dfd1c67b 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -834,11 +834,11 @@ 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 */ - int resend_bsn = dir.dl.v_b.resend_needed(dir.dl.window); + int resend_bsn = dir.dl.window.resend_needed(); if (resend_bsn >= 0) { LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", resend_bsn); /* re-send block with negative aknowlegement */ - dir.dl.v_b.mark_unacked(resend_bsn); + dir.dl.window.m_v_b.mark_unacked(resend_bsn); bts->rlc_resent(); return create_dl_acked_block(fn, ts, resend_bsn, false); } @@ -873,7 +873,7 @@ do_resend: } /* cycle through all unacked blocks */ - int resend = dir.dl.v_b.mark_for_resend(dir.dl.window); + int resend = dir.dl.window.mark_for_resend(); /* At this point there should be at least one unacked block * to be resent. If not, this is an software error. */ @@ -1052,7 +1052,7 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts #warning "move this up?" rlc_data->len = block_length; /* raise send state and set ack state array */ - dir.dl.v_b.mark_unacked(bsn); + dir.dl.window.m_v_b.mark_unacked(bsn); dir.dl.window.increment_send(); return create_dl_acked_block(fn, ts, bsn, first_fin_ack); @@ -1364,17 +1364,17 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) return 1; /* indicate to free TBF */ } - dir.dl.v_b.update(bts, show_rbb, ssn, dir.dl.window, + dir.dl.window.update(bts, show_rbb, ssn, &lost, &received); /* report lost and received packets */ gprs_rlcmac_received_lost(this, received, lost); /* raise V(A), if possible */ - dir.dl.window.raise(dir.dl.v_b.move_window(dir.dl.window)); + dir.dl.window.raise(dir.dl.window.move_window()); /* show receive state array in debug (V(A)..V(S)-1) */ - dir.dl.v_b.state(show_v_b, dir.dl.window); + dir.dl.window.show_state(show_v_b); LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\"" "(V(S)-1=%d) A=Acked N=Nacked U=Unacked " "X=Resend-Unacked I=Invalid\n", @@ -1397,7 +1397,7 @@ int gprs_rlcmac_tbf::maybe_start_new_window() LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); /* range V(A)..V(S)-1 */ - received = dir.dl.v_b.count_unacked(dir.dl.window); + received = dir.dl.window.count_unacked(); /* report all outstanding packets as received */ gprs_rlcmac_received_lost(this, received, 0); @@ -1606,14 +1606,12 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len rh->bsn, dir.ul.window.v_q(), (dir.ul.window.v_q() + ws - 1) & mod_sns); - dir.ul.v_n.mark_received(rh->bsn); - 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.*/ 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); + + const uint16_t count = dir.ul.window.receive_bsn(rh->bsn); /* Retrieve LLC frames from blocks that are ready */ for (uint16_t i = 0; i < count; ++i) { @@ -1723,7 +1721,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(); + dir.dl.window.m_v_b.reset(); /* keep to flags */ state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; diff --git a/src/tbf.h b/src/tbf.h index de2543cc..02f0b444 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -168,13 +168,11 @@ struct gprs_rlcmac_tbf { union { struct { gprs_rlc_dl_window window; - 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; struct { gprs_rlc_ul_window window; - gprs_rlc_v_n v_n; int32_t rx_counter; /* count all received blocks */ uint8_t n3103; /* N3103 counter */ uint8_t usf[8]; /* list USFs per PDCH (timeslot) */ diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp index ea9fdbeb..8a464b1f 100644 --- a/tests/types/TypesTest.cpp +++ b/tests/types/TypesTest.cpp @@ -132,15 +132,15 @@ static void test_rlc_v_n() vn.reset(); OSMO_ASSERT(!vn.is_received(0x23)); - OSMO_ASSERT(vn.state(0x23) == ' '); + OSMO_ASSERT(vn.state(0x23) == GPRS_RLC_UL_BSN_INVALID); vn.mark_received(0x23); OSMO_ASSERT(vn.is_received(0x23)); - OSMO_ASSERT(vn.state(0x23) == 'R'); + OSMO_ASSERT(vn.state(0x23) == GPRS_RLC_UL_BSN_RECEIVED); vn.mark_missing(0x23); OSMO_ASSERT(!vn.is_received(0x23)); - OSMO_ASSERT(vn.state(0x23) == 'N'); + OSMO_ASSERT(vn.state(0x23) == GPRS_RLC_UL_BSN_MISSING); } } @@ -193,24 +193,23 @@ static void test_rlc_dl_ul_basic() { gprs_rlc_ul_window ul_win = { 0, }; - gprs_rlc_v_n v_n; int count; const char *rbb; char win_rbb[65]; uint8_t bin_rbb[8]; win_rbb[64] = '\0'; - v_n.reset(); + ul_win.m_v_n.reset(); OSMO_ASSERT(ul_win.is_in_window(0)); OSMO_ASSERT(ul_win.is_in_window(63)); OSMO_ASSERT(!ul_win.is_in_window(64)); - OSMO_ASSERT(!v_n.is_received(0)); + OSMO_ASSERT(!ul_win.m_v_n.is_received(0)); rbb = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"; OSMO_ASSERT(ul_win.ssn() == 0); - ul_win.update_rbb(&v_n, win_rbb); + ul_win.update_rbb(win_rbb); OSMO_ASSERT_STR_EQ(win_rbb, rbb); Encoding::encode_rbb(win_rbb, bin_rbb); printf("rbb: %s\n", osmo_hexdump(bin_rbb, sizeof(bin_rbb))); @@ -219,17 +218,15 @@ static void test_rlc_dl_ul_basic() /* simulate to have received 0, 1 and 5 */ OSMO_ASSERT(ul_win.is_in_window(0)); - v_n.mark_received(0); - ul_win.raise_v_r(0, &v_n); - count = ul_win.raise_v_q(&v_n); - OSMO_ASSERT(v_n.is_received(0)); + count = ul_win.receive_bsn(0); + OSMO_ASSERT(ul_win.m_v_n.is_received(0)); OSMO_ASSERT(ul_win.v_q() == 1); OSMO_ASSERT(ul_win.v_r() == 1); OSMO_ASSERT(count == 1); rbb = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIR"; OSMO_ASSERT(ul_win.ssn() == 1); - ul_win.update_rbb(&v_n, win_rbb); + ul_win.update_rbb(win_rbb); OSMO_ASSERT_STR_EQ(win_rbb, rbb); Encoding::encode_rbb(win_rbb, bin_rbb); printf("rbb: %s\n", osmo_hexdump(bin_rbb, sizeof(bin_rbb))); @@ -237,17 +234,15 @@ static void test_rlc_dl_ul_basic() OSMO_ASSERT_STR_EQ(win_rbb, rbb); OSMO_ASSERT(ul_win.is_in_window(1)); - v_n.mark_received(1); - ul_win.raise_v_r(1, &v_n); - count = ul_win.raise_v_q(&v_n); - OSMO_ASSERT(v_n.is_received(0)); + count = ul_win.receive_bsn(1); + OSMO_ASSERT(ul_win.m_v_n.is_received(0)); OSMO_ASSERT(ul_win.v_q() == 2); OSMO_ASSERT(ul_win.v_r() == 2); OSMO_ASSERT(count == 1); rbb = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRR"; OSMO_ASSERT(ul_win.ssn() == 2); - ul_win.update_rbb(&v_n, win_rbb); + ul_win.update_rbb(win_rbb); OSMO_ASSERT_STR_EQ(win_rbb, rbb); Encoding::encode_rbb(win_rbb, bin_rbb); printf("rbb: %s\n", osmo_hexdump(bin_rbb, sizeof(bin_rbb))); @@ -255,17 +250,15 @@ static void test_rlc_dl_ul_basic() OSMO_ASSERT_STR_EQ(win_rbb, rbb); OSMO_ASSERT(ul_win.is_in_window(5)); - v_n.mark_received(5); - ul_win.raise_v_r(5, &v_n); - count = ul_win.raise_v_q(&v_n); - OSMO_ASSERT(v_n.is_received(0)); + count = ul_win.receive_bsn(5); + OSMO_ASSERT(ul_win.m_v_n.is_received(0)); OSMO_ASSERT(ul_win.v_q() == 2); OSMO_ASSERT(ul_win.v_r() == 6); OSMO_ASSERT(count == 0); rbb = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRRIIIR"; OSMO_ASSERT(ul_win.ssn() == 6); - ul_win.update_rbb(&v_n, win_rbb); + ul_win.update_rbb(win_rbb); OSMO_ASSERT_STR_EQ(win_rbb, rbb); Encoding::encode_rbb(win_rbb, bin_rbb); printf("rbb: %s\n", osmo_hexdump(bin_rbb, sizeof(bin_rbb))); @@ -274,18 +267,16 @@ static void test_rlc_dl_ul_basic() OSMO_ASSERT(ul_win.is_in_window(65)); OSMO_ASSERT(ul_win.is_in_window(2)); - OSMO_ASSERT(v_n.is_received(5)); - v_n.mark_received(65); - ul_win.raise_v_r(65, &v_n); - count = ul_win.raise_v_q(&v_n); + OSMO_ASSERT(ul_win.m_v_n.is_received(5)); + count = ul_win.receive_bsn(65); OSMO_ASSERT(count == 0); - OSMO_ASSERT(v_n.is_received(5)); + OSMO_ASSERT(ul_win.m_v_n.is_received(5)); OSMO_ASSERT(ul_win.v_q() == 2); OSMO_ASSERT(ul_win.v_r() == 66); rbb = "IIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIR"; OSMO_ASSERT(ul_win.ssn() == 66); - ul_win.update_rbb(&v_n, win_rbb); + ul_win.update_rbb(win_rbb); OSMO_ASSERT_STR_EQ(win_rbb, rbb); Encoding::encode_rbb(win_rbb, bin_rbb); printf("rbb: %s\n", osmo_hexdump(bin_rbb, sizeof(bin_rbb))); @@ -294,33 +285,25 @@ static void test_rlc_dl_ul_basic() OSMO_ASSERT(ul_win.is_in_window(2)); OSMO_ASSERT(!ul_win.is_in_window(66)); - v_n.mark_received(2); - ul_win.raise_v_r(2, &v_n); - count = ul_win.raise_v_q(&v_n); + count = ul_win.receive_bsn(2); OSMO_ASSERT(count == 1); OSMO_ASSERT(ul_win.v_q() == 3); OSMO_ASSERT(ul_win.v_r() == 66); OSMO_ASSERT(ul_win.is_in_window(66)); - v_n.mark_received(66); - ul_win.raise_v_r(66, &v_n); - count = ul_win.raise_v_q(&v_n); + count = ul_win.receive_bsn(66); OSMO_ASSERT(count == 0); OSMO_ASSERT(ul_win.v_q() == 3); OSMO_ASSERT(ul_win.v_r() == 67); for (int i = 3; i <= 67; ++i) { - v_n.mark_received(i); - ul_win.raise_v_r(i, &v_n); - ul_win.raise_v_q(&v_n); + ul_win.receive_bsn(i); } OSMO_ASSERT(ul_win.v_q() == 68); OSMO_ASSERT(ul_win.v_r() == 68); - v_n.mark_received(68); - ul_win.raise_v_r(68, &v_n); - count = ul_win.raise_v_q(&v_n); + count = ul_win.receive_bsn(68); OSMO_ASSERT(ul_win.v_q() == 69); OSMO_ASSERT(ul_win.v_r() == 69); OSMO_ASSERT(count == 1); @@ -328,9 +311,7 @@ static void test_rlc_dl_ul_basic() /* now test the wrapping */ OSMO_ASSERT(ul_win.is_in_window(4)); OSMO_ASSERT(!ul_win.is_in_window(5)); - v_n.mark_received(4); - ul_win.raise_v_r(4, &v_n); - count = ul_win.raise_v_q(&v_n); + count = ul_win.receive_bsn(4); OSMO_ASSERT(count == 0); } @@ -341,9 +322,8 @@ static void test_rlc_dl_ul_basic() char show_rbb[65]; BTS dummy_bts; gprs_rlc_dl_window dl_win = { 0, }; - gprs_rlc_v_b v_b; - v_b.reset(); + dl_win.m_v_b.reset(); OSMO_ASSERT(dl_win.window_empty()); OSMO_ASSERT(!dl_win.window_stalled()); @@ -364,7 +344,7 @@ static void test_rlc_dl_ul_basic() Decoding::extract_rbb(rbb_cmp, show_rbb); printf("show_rbb: %s\n", show_rbb); - v_b.update(&dummy_bts, show_rbb, 35, dl_win, &lost, &recv); + dl_win.update(&dummy_bts, show_rbb, 35, &lost, &recv); OSMO_ASSERT(lost == 0); OSMO_ASSERT(recv == 35);