diff options
-rw-r--r-- | src/encoding.cpp | 4 | ||||
-rw-r--r-- | src/rlc.cpp | 52 | ||||
-rw-r--r-- | src/rlc.h | 173 | ||||
-rw-r--r-- | src/tbf.cpp | 118 | ||||
-rw-r--r-- | src/tbf.h | 14 |
5 files changed, 242 insertions, 119 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp index 4855b226..b45657a4 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -381,9 +381,9 @@ void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, block->u.Packet_Uplink_Ack_Nack.UnionType = 0x0; // PU_AckNack_GPRS = on block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.CHANNEL_CODING_COMMAND = bts->initial_cs_ul - 1; // CS1 block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.FINAL_ACK_INDICATION = final; // FINAL ACK INDICATION - block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->dir.ul.v_r; // STARTING_SEQUENCE_NUMBER + block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->dir.ul.window.v_r(); // STARTING_SEQUENCE_NUMBER // RECEIVE_BLOCK_BITMAP - for (i = 0, bbn = (tbf->dir.ul.v_r - 64) & mod_sns_half; i < 64; + for (i = 0, bbn = (tbf->dir.ul.window.v_r() - 64) & mod_sns_half; i < 64; i++, bbn = (bbn + 1) & mod_sns_half) { bit = tbf->dir.ul.v_n[bbn]; if (bit == 0) diff --git a/src/rlc.cpp b/src/rlc.cpp index c4d43d3c..fda743f0 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -40,12 +40,10 @@ void gprs_rlc_v_b::reset() 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) +int gprs_rlc_v_b::resend_needed(const gprs_rlc_dl_window &w) { - for (uint16_t bsn = v_a; bsn != v_s; bsn = (bsn + 1) & mod_sns) { - uint16_t index = bsn & mod_sns_half; + for (uint16_t bsn = w.v_a(); bsn != w.v_s(); bsn = (bsn + 1) & w.mod_sns()) { + uint16_t index = bsn & w.mod_sns_half(); if (is_nacked(index) || is_resend(index)) return bsn; } @@ -53,14 +51,12 @@ int gprs_rlc_v_b::resend_needed(const uint16_t v_a, const uint16_t v_s, return -1; } -int gprs_rlc_v_b::mark_for_resend(const uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, - const uint16_t mod_sns_half) +int gprs_rlc_v_b::mark_for_resend(const gprs_rlc_dl_window &w) { int resend = 0; - for (uint16_t bsn = v_a; bsn != v_s; bsn = (bsn + 1) & mod_sns) { - uint16_t index = (bsn & mod_sns_half); + for (uint16_t bsn = w.v_a(); bsn != w.v_s(); bsn = (bsn + 1) & w.mod_sns()) { + uint16_t index = bsn & w.mod_sns_half(); if (is_unacked(index)) { /* mark to be re-send */ mark_resend(index); @@ -71,14 +67,13 @@ int gprs_rlc_v_b::mark_for_resend(const uint16_t v_a, const uint16_t v_s, return resend; } -int gprs_rlc_v_b::count_unacked(const uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, const uint16_t mod_sns_half) +int gprs_rlc_v_b::count_unacked(const gprs_rlc_dl_window &w) { uint16_t unacked = 0; uint16_t bsn; - for (bsn = v_a; bsn != v_s; bsn = (bsn + 1) & mod_sns) { - uint16_t index = bsn & mod_sns_half; + for (bsn = w.v_a(); bsn != w.v_s(); bsn = (bsn + 1) & w.mod_sns()) { + uint16_t index = bsn & w.mod_sns_half(); if (!is_acked(index)) unacked += 1; } @@ -87,41 +82,39 @@ int gprs_rlc_v_b::count_unacked(const uint16_t v_a, const uint16_t v_s, } void gprs_rlc_v_b::update(BTS *bts, char *show_rbb, uint8_t ssn, - const uint16_t v_a, - const uint16_t mod_sns, const uint16_t mod_sns_half, + const gprs_rlc_dl_window &w, uint16_t *lost, uint16_t *received) { uint16_t bsn; int i; /* SSN - 1 is in range V(A)..V(S)-1 */ - for (i = 63, bsn = (ssn - 1) & mod_sns; - i >= 0 && bsn != ((v_a - 1) & mod_sns); - i--, bsn = (bsn - 1) & mod_sns) { + for (i = 63, bsn = (ssn - 1) & w.mod_sns(); + i >= 0 && bsn != ((w.v_a() - 1) & w.mod_sns()); + i--, bsn = (bsn - 1) & w.mod_sns()) { if (show_rbb[i] == '1') { LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); - if (!is_acked(bsn & mod_sns_half)) + if (!is_acked(bsn & w.mod_sns_half())) *received += 1; - mark_acked(bsn & mod_sns_half); + mark_acked(bsn & w.mod_sns_half()); } else { LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); - mark_nacked(bsn & mod_sns_half); + mark_nacked(bsn & w.mod_sns_half()); bts->rlc_nacked(); *lost += 1; } } } -int gprs_rlc_v_b::move_window(const uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, const uint16_t mod_sns_half) +int gprs_rlc_v_b::move_window(const gprs_rlc_dl_window &w) { int i; uint16_t bsn; int moved = 0; - for (i = 0, bsn = v_a; bsn != v_s; i++, bsn = (bsn + 1) & mod_sns) { - uint16_t index = (bsn & mod_sns_half); + for (i = 0, bsn = w.v_a(); bsn != w.v_s(); i++, bsn = (bsn + 1) & w.mod_sns()) { + uint16_t index = bsn & w.mod_sns_half(); if (is_acked(index)) { mark_invalid(index); moved += 1; @@ -132,14 +125,13 @@ int gprs_rlc_v_b::move_window(const uint16_t v_a, const uint16_t v_s, return moved; } -void gprs_rlc_v_b::state(char *show_v_b, const uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, const uint16_t mod_sns_half) +void gprs_rlc_v_b::state(char *show_v_b, const gprs_rlc_dl_window &w) { int i; uint16_t bsn; - for (i = 0, bsn = v_a; bsn != v_s; i++, bsn = (bsn + 1) & mod_sns) { - uint16_t index = (bsn & mod_sns_half); + for (i = 0, bsn = w.v_a(); bsn != w.v_s(); i++, bsn = (bsn + 1) & w.mod_sns()) { + uint16_t index = bsn & w.mod_sns_half(); show_v_b[i] = m_v_b[index]; if (show_v_b[i] == 0) show_v_b[i] = ' '; @@ -44,24 +44,67 @@ struct gprs_rlc { gprs_rlc_data blocks[RLC_MAX_SNS/2]; }; + +/** + * TODO: The UL/DL code could/should share a baseclass but + * we are using llist_for_each_entry for the TBF which + * requires everything which creates a requirement for a POD + * type and in < C++11 something that is using even if the + * most simple form of inheritance is not a POD anymore. + */ +struct gprs_rlc_dl_window { + const uint16_t mod_sns() const; + const uint16_t mod_sns_half() const; + const uint16_t sns() const; + const uint16_t ws() const; + + bool window_stalled() const; + bool window_empty() const; + + void increment_send(); + void raise(int moves); + + const uint16_t v_s() const; + const uint16_t v_s_mod(int offset) const; + const uint16_t v_s_mod_half(int offset) const; + const uint16_t v_a() const; + const int16_t distance() const; + + uint16_t m_bsn; /* block sequence number */ + uint16_t m_v_s; /* send state */ + uint16_t m_v_a; /* ack state */ +}; + +struct gprs_rlc_ul_window { + const uint16_t mod_sns() const; + const uint16_t mod_sns_half() const; + const uint16_t sns() const; + const uint16_t ws() const; + + const uint16_t v_r() const; + const uint16_t v_q() const; + + void raise(int moves); + void increment_q(int); + + uint16_t m_bsn; /* block sequence number */ + 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 uint16_t acked, const uint16_t sent, - const uint16_t mod_sns, const uint16_t mod_sns_half); - int mark_for_resend(const uint16_t acked, const uint16_t sent, - const uint16_t mod_sns, const uint16_t mod_sns_half); - void update(BTS *bts, char *show_rbb, uint8_t ssn, const uint16_t v_a, - const uint16_t mod_sns, const uint16_t mod_sns_half, + 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 uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, const uint16_t mod_sns_half); - void state(char *show_rbb, const uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, const uint16_t mod_sns_half); - int count_unacked(const uint16_t v_a, const uint16_t v_s, - const uint16_t mod_sns, const uint16_t mod_sns_half); + 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 index) const; @@ -180,3 +223,109 @@ inline void gprs_rlc_v_b::mark_invalid(int index) { return mark(index, 'I'); } + + +inline const uint16_t gprs_rlc_dl_window::sns() const +{ + return 128; +} + +inline const uint16_t gprs_rlc_dl_window::ws() const +{ + return 64; +} + +inline const uint16_t gprs_rlc_dl_window::mod_sns() const +{ + return sns() - 1; +} + +inline const uint16_t gprs_rlc_dl_window::mod_sns_half() const +{ + return (sns() >> 1) - 1; +} + +inline const uint16_t gprs_rlc_dl_window::v_s() const +{ + return m_v_s; +} + +inline const uint16_t gprs_rlc_dl_window::v_s_mod_half(int offset) const +{ + return (m_v_s + offset) & mod_sns_half(); +} + +inline const uint16_t gprs_rlc_dl_window::v_s_mod(int offset) const +{ + return (m_v_s + offset) & mod_sns(); +} + +inline const uint16_t gprs_rlc_dl_window::v_a() const +{ + return m_v_a; +} + +inline bool gprs_rlc_dl_window::window_stalled() const +{ + return ((m_v_s - m_v_a) & mod_sns()) == ws(); +} + +inline bool gprs_rlc_dl_window::window_empty() const +{ + return m_v_s == m_v_a; +} + +inline void gprs_rlc_dl_window::increment_send() +{ + m_v_s = (m_v_s + 1) & mod_sns(); +} + +inline void gprs_rlc_dl_window::raise(int moves) +{ + m_v_a = (m_v_a + moves) & mod_sns(); +} + +inline const int16_t gprs_rlc_dl_window::distance() const +{ + return (m_v_s - m_v_a) & mod_sns(); +} + +inline const uint16_t gprs_rlc_ul_window::sns() const +{ + return 128; +} + +inline const uint16_t gprs_rlc_ul_window::ws() const +{ + return 64; +} + +inline const uint16_t gprs_rlc_ul_window::mod_sns() const +{ + return sns() - 1; +} + +inline const uint16_t gprs_rlc_ul_window::mod_sns_half() const +{ + return (sns() >> 1) - 1; +} + +inline const uint16_t gprs_rlc_ul_window::v_r() const +{ + return m_v_r; +} + +inline const uint16_t gprs_rlc_ul_window::v_q() const +{ + return m_v_q; +} + +inline void gprs_rlc_ul_window::raise(int moves) +{ + m_v_r = (m_v_r + moves) & mod_sns(); +} + +inline void gprs_rlc_ul_window::increment_q(int incr) +{ + m_v_q = (m_v_q + incr) & mod_sns(); +} diff --git a/src/tbf.cpp b/src/tbf.cpp index a75fe4a1..eca72296 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -520,8 +520,6 @@ struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts, tbf->m_tfi = tfi; tbf->trx = &bts->trx[trx]; tbf->ms_class = ms_class; - tbf->m_ws = 64; - tbf->m_sns = 128; /* select algorithm */ rc = bts->alloc_algorithm(bts, old_tbf, tbf, bts->alloc_algorithm_curst, single_slot); @@ -836,20 +834,17 @@ int gprs_rlcmac_tbf::assemble_forward_llc(const gprs_rlc_data *_data) */ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts) { - const uint16_t mod_sns = m_sns - 1; - const uint16_t mod_sns_half = (m_sns >> 1) - 1; - LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink (V(A)==%d .. " - "V(S)==%d)\n", tbf_name(this), dir.dl.v_a, dir.dl.v_s); + "V(S)==%d)\n", tbf_name(this), + dir.dl.window.v_a(), dir.dl.window.v_s()); do_resend: /* check if there is a block with negative acknowledgement */ - int resend_bsn = dir.dl.v_b.resend_needed(dir.dl.v_a, dir.dl.v_s, - mod_sns, mod_sns_half); + int resend_bsn = dir.dl.v_b.resend_needed(dir.dl.window); if (resend_bsn >= 0) { LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", resend_bsn); - uint16_t index = resend_bsn & mod_sns_half; + uint16_t index = resend_bsn & dir.dl.window.mod_sns_half(); /* re-send block with negative aknowlegement */ dir.dl.v_b.mark_unacked(index); bts->rlc_resent(); @@ -862,12 +857,12 @@ do_resend: if (state_is(GPRS_RLCMAC_FINISHED)) { LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, " "because all blocks have been transmitted.\n", - dir.dl.v_a); + dir.dl.window.v_a()); bts->rlc_restarted(); } else { LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, " "because all window is stalled.\n", - dir.dl.v_a); + dir.dl.window.v_a()); bts->rlc_stalled(); } /* If V(S) == V(A) and finished state, we would have received @@ -876,18 +871,17 @@ do_resend: * from MS. But in this case we did not receive the final ack * indication from MS. This should never happen if MS works * correctly. */ - if (dir.dl.v_s == dir.dl.v_a) { + if (dir.dl.window.window_empty()) { LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks, " "so we re-transmit final block!\n"); /* we just send final block again */ - int16_t index = (dir.dl.v_s - 1) & mod_sns_half; + int16_t index = dir.dl.window.v_s_mod_half(-1); bts->rlc_resent(); return create_dl_acked_block(fn, ts, index, false); } /* cycle through all unacked blocks */ - int resend = dir.dl.v_b.mark_for_resend(dir.dl.v_a, dir.dl.v_s, - mod_sns, mod_sns_half); + int resend = dir.dl.v_b.mark_for_resend(dir.dl.window); /* At this point there should be at least one unacked block * to be resent. If not, this is an software error. */ @@ -896,7 +890,7 @@ do_resend: "There are no unacknowledged blocks, but V(A) " " != V(S). PLEASE FIX!\n"); /* we just send final block again */ - int16_t index = (dir.dl.v_s - 1) & mod_sns_half; + int16_t index = dir.dl.window.v_s_mod_half(-1); bts->rlc_resent(); return create_dl_acked_block(fn, ts, index, false); } @@ -916,11 +910,8 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts uint16_t space, chunk; bool first_fin_ack = false; - const uint16_t mod_sns = m_sns - 1; - const uint16_t mod_sns_half = (m_sns >> 1) - 1; - LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n", - dir.dl.v_s); + dir.dl.window.v_s()); #warning "Selection of the CS doesn't belong here" if (cs == 0) { @@ -934,7 +925,7 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts const uint8_t block_data_len = gprs_rlcmac_cs[cs].block_data; /* now we still have untransmitted LLC data, so we fill mac block */ - index = dir.dl.v_s & mod_sns_half; + index = dir.dl.window.v_s_mod_half(0); data = m_rlc.blocks[index].prepare(block_data_len); rh = (struct rlc_dl_header *)data; @@ -944,7 +935,7 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts rh->pr = 0; /* FIXME: power reduction */ rh->tfi = m_tfi; /* TFI */ rh->fbi = 0; /* Final Block Indicator, set late, if true */ - rh->bsn = dir.dl.v_s; /* Block Sequence Number */ + rh->bsn = dir.dl.window.v_s(); /* Block Sequence Number */ rh->e = 0; /* Extension bit, maybe set later */ e_pointer = data + 2; /* points to E of current chunk */ data += sizeof(*rh); @@ -1070,7 +1061,7 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts m_rlc.blocks[index].len = block_length; /* raise send state and set ack state array */ dir.dl.v_b.mark_unacked(index); - dir.dl.v_s = (dir.dl.v_s + 1) & mod_sns; /* inc send state */ + dir.dl.window.increment_send(); return create_dl_acked_block(fn, ts, index, first_fin_ack); } @@ -1365,10 +1356,9 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) { int16_t dist; /* must be signed */ uint16_t lost = 0, received = 0; - const uint16_t mod_sns = m_sns - 1; - const uint16_t mod_sns_half = (m_sns >> 1) - 1; char show_rbb[65]; char show_v_b[RLC_MAX_SNS + 1]; + const uint16_t mod_sns = dir.dl.window.mod_sns(); Decoding::extract_rbb(rbb, show_rbb); /* show received array in debug (bit 64..1) */ @@ -1378,9 +1368,9 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) /* apply received array to receive state (SSN-64..SSN-1) */ /* calculate distance of ssn from V(S) */ - dist = (dir.dl.v_s - ssn) & mod_sns; + dist = (dir.dl.window.v_s() - ssn) & mod_sns; /* check if distance is less than distance V(A)..V(S) */ - if (dist >= ((dir.dl.v_s - dir.dl.v_a) & mod_sns)) { + if (dist >= dir.dl.window.distance()) { /* this might happpen, if the downlink assignment * was not received by ms and the ack refers * to previous TBF @@ -1391,25 +1381,24 @@ 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.v_a, - mod_sns, mod_sns_half, &lost, &received); + dir.dl.v_b.update(bts, show_rbb, ssn, dir.dl.window, + &lost, &received); /* report lost and received packets */ gprs_rlcmac_received_lost(this, received, lost); /* raise V(A), if possible */ - dir.dl.v_a += dir.dl.v_b.move_window(dir.dl.v_a, dir.dl.v_s, - mod_sns, mod_sns_half) & mod_sns; + dir.dl.window.raise(dir.dl.v_b.move_window(dir.dl.window)); /* show receive state array in debug (V(A)..V(S)-1) */ - dir.dl.v_b.state(show_v_b, dir.dl.v_a, dir.dl.v_s, - mod_sns, mod_sns_half); + dir.dl.v_b.state(show_v_b, dir.dl.window); 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", dir.dl.v_a, show_v_b, - (dir.dl.v_s - 1) & mod_sns); + "X=Resend-Unacked I=Invalid\n", + dir.dl.window.v_a(), show_v_b, + dir.dl.window.v_s_mod(-1)); - if (state_is(GPRS_RLCMAC_FINISHED) && dir.dl.v_s == dir.dl.v_a) { + if (state_is(GPRS_RLCMAC_FINISHED) && dir.dl.window.window_empty()) { LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of " "all blocks, but without final ack " "inidcation (don't worry)\n"); @@ -1420,15 +1409,12 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) int gprs_rlcmac_tbf::maybe_start_new_window() { - const uint16_t mod_sns = m_sns - 1; - const uint16_t mod_sns_half = (m_sns >> 1) - 1; struct msgb *msg; uint16_t received; LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); /* range V(A)..V(S)-1 */ - received = dir.dl.v_b.count_unacked(dir.dl.v_a, dir.dl.v_s, - mod_sns, mod_sns_half); + received = dir.dl.v_b.count_unacked(dir.dl.window); /* report all outstanding packets as received */ gprs_rlcmac_received_lost(this, received, 0); @@ -1534,14 +1520,19 @@ void gprs_rlcmac_tbf::update_tlli(uint32_t tlli) int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi) { - uint16_t mod_sns, mod_sns_half, offset_v_q, offset_v_r, index; + uint16_t offset_v_q, offset_v_r, index; struct rlc_ul_header *rh = (struct rlc_ul_header *)data; int rc; + const uint16_t mod_sns = dir.ul.window.mod_sns(); + const uint16_t mod_sns_half = dir.ul.window.mod_sns_half(); + const uint16_t ws = dir.ul.window.ws(); + this->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA); LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TFI=%d received (V(Q)=%d .. " - "V(R)=%d)\n", rh->tfi, this->dir.ul.v_q, this->dir.ul.v_r); + "V(R)=%d)\n", rh->tfi, this->dir.ul.window.v_q(), + this->dir.ul.window.v_r()); /* process RSSI */ gprs_rlcmac_rssi(this, rssi); @@ -1604,9 +1595,6 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len } } - mod_sns = m_sns - 1; - mod_sns_half = (m_sns >> 1) - 1; - /* restart T3169 */ tbf_timer_start(this, 3169, bts_data()->t3169, 0); @@ -1614,13 +1602,14 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len this->dir.ul.rx_counter++; /* current block relative to lowest unreceived block */ - offset_v_q = (rh->bsn - this->dir.ul.v_q) & mod_sns; + offset_v_q = (rh->bsn - this->dir.ul.window.v_q()) & mod_sns; /* If out of window (may happen if blocks below V(Q) are received * again. */ - if (offset_v_q >= m_ws) { + if (offset_v_q >= dir.ul.window.ws()) { LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window " - "%d..%d (it's normal)\n", rh->bsn, this->dir.ul.v_q, - (this->dir.ul.v_q + m_ws - 1) & mod_sns); + "%d..%d (it's normal)\n", rh->bsn, + dir.ul.window.v_q(), + (dir.ul.window.v_q() + ws - 1) & mod_sns); return 0; } /* Write block to buffer and set receive state array. */ @@ -1629,42 +1618,42 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len m_rlc.blocks[index].len = len; this->dir.ul.v_n[index] = 'R'; /* Mark received block. */ LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n", - rh->bsn, this->dir.ul.v_q, - (this->dir.ul.v_q + m_ws - 1) & mod_sns); + rh->bsn, dir.ul.window.v_q(), + (dir.ul.window.v_q() + ws - 1) & mod_sns); /* Raise V(R) to highest received sequence number not received. */ - offset_v_r = (rh->bsn + 1 - this->dir.ul.v_r) & mod_sns; - if (offset_v_r < (m_sns >> 1)) { /* Positive offset, so raise. */ + offset_v_r = (rh->bsn + 1 - dir.ul.window.v_r()) & mod_sns; + if (offset_v_r < (sns() >> 1)) { /* Positive offset, so raise. */ while (offset_v_r--) { if (offset_v_r) /* all except the received block */ - this->dir.ul.v_n[this->dir.ul.v_r & mod_sns_half] + dir.ul.v_n[dir.ul.window.v_r() & mod_sns_half] = 'N'; /* Mark block as not received */ - this->dir.ul.v_r = (this->dir.ul.v_r + 1) & mod_sns; + this->dir.ul.window.raise(1); /* Inc V(R). */ } LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", - this->dir.ul.v_r); + this->dir.ul.window.v_r()); } #warning "Move to TBF and remove the index side effect.." /* 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.v_q != this->dir.ul.v_r && this->dir.ul.v_n[ - (index = this->dir.ul.v_q & mod_sns_half)] == 'R') { + while (this->dir.ul.window.v_q() != this->dir.ul.window.v_r() && this->dir.ul.v_n[ + (index = this->dir.ul.window.v_q() & mod_sns_half)] == 'R') { LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising " - "V(Q) to %d\n", this->dir.ul.v_q, - (this->dir.ul.v_q + 1) & mod_sns); + "V(Q) to %d\n", this->dir.ul.window.v_q(), + (this->dir.ul.window.v_q() + 1) & mod_sns); /* get LLC data from block */ this->assemble_forward_llc(&m_rlc.blocks[index]); /* raise V(Q), because block already received */ - this->dir.ul.v_q = (this->dir.ul.v_q + 1) & mod_sns; + this->dir.ul.window.increment_q(1); } /* Check CV of last frame in buffer */ if (this->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */ - && this->dir.ul.v_q == this->dir.ul.v_r) { /* if complete */ + && this->dir.ul.window.v_q() == this->dir.ul.window.v_r()) { /* if complete */ struct rlc_ul_header *last_rh = (struct rlc_ul_header *) - m_rlc.blocks[(this->dir.ul.v_r - 1) & mod_sns_half].block; + m_rlc.blocks[(this->dir.ul.window.v_r() - 1) & mod_sns_half].block; LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, " "last block: BSN=%d CV=%d\n", last_rh->bsn, last_rh->cv); @@ -1773,6 +1762,5 @@ void gprs_rlcmac_tbf::reuse_tbf(const uint8_t *data, const uint16_t len) bool gprs_rlcmac_tbf::dl_window_stalled() const { - const uint16_t mod_sns = m_sns - 1; - return ((dir.dl.v_s - dir.dl.v_a) & mod_sns) == m_ws; + return dir.dl.window.window_stalled(); } @@ -157,9 +157,6 @@ struct gprs_rlcmac_tbf { enum gprs_rlcmac_tbf_poll_state poll_state; uint32_t poll_fn; /* frame number to poll */ - uint16_t m_ws; /* window size */ - uint16_t m_sns; /* sequence number space */ - /* Please note that all variables here will be reset when changing * from WAIT RELEASE back to FLOW state (re-use of TBF). * All states that need reset must be in this struct, so this is why @@ -167,17 +164,13 @@ struct gprs_rlcmac_tbf { */ union { struct { - uint16_t bsn; /* block sequence number */ - uint16_t v_s; /* send state */ - uint16_t v_a; /* ack state */ + 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 { - uint16_t bsn; /* block sequence number */ - uint16_t v_r; /* receive state */ - uint16_t v_q; /* receive window state */ + gprs_rlc_ul_window window; char v_n[RLC_MAX_SNS/2]; /* receive state array */ int32_t rx_counter; /* count all received blocks */ uint8_t n3103; /* N3103 counter */ @@ -306,7 +299,8 @@ inline const char *gprs_rlcmac_tbf::imsi() const inline uint16_t gprs_rlcmac_tbf::sns() const { - return m_sns; + /* assume dl/ul do the same thing */ + return dir.dl.window.sns(); } const char *tbf_name(gprs_rlcmac_tbf *tbf); |