From 73257c550c6ee4f6c8a435f42c33e5c1d8a19dfa Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 26 Nov 2013 21:43:58 +0100 Subject: rlc: Make the RLC types only operate on the BSN The code has an internal optimization to only use window_size space. This means that the caller needed to know that only half of the size was used. Change the API to work on the BSN and do the mapping internally. The compiler should have plenty of opportunity to propagate the constant(s) but this has not been verified. --- src/encoding.cpp | 6 +-- src/rlc.cpp | 29 +++++------ src/rlc.h | 148 +++++++++++++++++++++++++++++-------------------------- src/tbf.cpp | 45 ++++++++--------- 4 files changed, 112 insertions(+), 116 deletions(-) diff --git a/src/encoding.cpp b/src/encoding.cpp index 13390b90..24b5730a 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -363,7 +363,7 @@ void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, uint8_t rbb = 0; uint16_t i, bbn; - uint16_t mod_sns_half = (tbf->sns() >> 1) - 1; + uint16_t mod_sns = (tbf->sns() >> 1); char bit; LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s " @@ -383,8 +383,8 @@ void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, 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.window.v_r(); // STARTING_SEQUENCE_NUMBER // RECEIVE_BLOCK_BITMAP - for (i = 0, bbn = (tbf->dir.ul.window.v_r() - 64) & mod_sns_half; i < 64; - i++, bbn = (bbn + 1) & mod_sns_half) { + for (i = 0, bbn = (tbf->dir.ul.window.v_r() - 64) & mod_sns; i < 64; + i++, bbn = (bbn + 1) & mod_sns) { bit = tbf->dir.ul.v_n.state(bbn); show_v_n[i] = bit; if (bit == 'R') diff --git a/src/rlc.cpp b/src/rlc.cpp index 3f2048da..30b09103 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -49,8 +49,7 @@ void gprs_rlc_v_b::reset() int gprs_rlc_v_b::resend_needed(const gprs_rlc_dl_window &w) { 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)) + if (is_nacked(bsn) || is_resend(bsn)) return bsn; } @@ -62,10 +61,9 @@ int gprs_rlc_v_b::mark_for_resend(const gprs_rlc_dl_window &w) int resend = 0; 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)) { + if (is_unacked(bsn)) { /* mark to be re-send */ - mark_resend(index); + mark_resend(bsn); resend += 1; } } @@ -79,8 +77,7 @@ int gprs_rlc_v_b::count_unacked(const gprs_rlc_dl_window &w) uint16_t bsn; 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)) + if (!is_acked(bsn)) unacked += 1; } @@ -101,12 +98,12 @@ void gprs_rlc_v_b::update(BTS *bts, char *show_rbb, uint8_t ssn, if (show_rbb[i] == '1') { LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn); - if (!is_acked(bsn & w.mod_sns_half())) + if (!is_acked(bsn)) *received += 1; - mark_acked(bsn & w.mod_sns_half()); + mark_acked(bsn); } else { LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn); - mark_nacked(bsn & w.mod_sns_half()); + mark_nacked(bsn); bts->rlc_nacked(); *lost += 1; } @@ -120,9 +117,8 @@ int gprs_rlc_v_b::move_window(const gprs_rlc_dl_window &w) int moved = 0; 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); + if (is_acked(bsn)) { + mark_invalid(bsn); moved += 1; } else break; @@ -137,7 +133,7 @@ void gprs_rlc_v_b::state(char *show_v_b, const gprs_rlc_dl_window &w) uint16_t bsn; 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(); + 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] = ' '; @@ -159,7 +155,7 @@ 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() & mod_sns_half()); + v_n->mark_missing(v_r()); raise_v_r(1); } LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n", v_r()); @@ -175,8 +171,7 @@ 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)) + if (!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()); diff --git a/src/rlc.h b/src/rlc.h index b85b33ea..0ecce407 100644 --- a/src/rlc.h +++ b/src/rlc.h @@ -28,6 +28,12 @@ class BTS; struct gprs_rlc_v_n; + +static inline uint16_t mod_sns_half() +{ + return (RLC_MAX_SNS / 2) - 1; +} + struct gprs_rlc_data { uint8_t *prepare(size_t block_data_length); void put_data(const uint8_t *data, size_t len); @@ -43,7 +49,8 @@ struct gprs_rlc_data { * the routines to manipulate these arrays. */ struct gprs_rlc { - gprs_rlc_data blocks[RLC_MAX_SNS/2]; + gprs_rlc_data *block(int bsn); + gprs_rlc_data m_blocks[RLC_MAX_SNS/2]; }; @@ -56,7 +63,6 @@ struct gprs_rlc { */ 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; @@ -68,7 +74,6 @@ struct gprs_rlc_dl_window { 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; @@ -78,7 +83,6 @@ struct gprs_rlc_dl_window { 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; @@ -112,24 +116,24 @@ struct gprs_rlc_v_b { int count_unacked(const gprs_rlc_dl_window& window); /* Check for an individual frame */ - bool is_unacked(int index) const; - bool is_nacked(int index) const; - bool is_acked(int index) const; - bool is_resend(int index) const; - bool is_invalid(int index) const; + 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 index); - void mark_nacked(int index); - void mark_acked(int index); - void mark_resend(int index); - void mark_invalid(int index); + 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 index, const char state) const; - void mark(int index, const char state); + 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 */ }; @@ -137,13 +141,15 @@ private: struct gprs_rlc_v_n { void reset(); - void mark_received(int index); - void mark_missing(int index); + void mark_received(int bsn); + void mark_missing(int bsn); - bool is_received(int index) const; + bool is_received(int bsn) const; - char state(int index) 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 */ }; @@ -181,75 +187,75 @@ struct rlc_li_field { } __attribute__ ((packed)); } -inline bool gprs_rlc_v_b::is_state(int index, const char type) const +inline bool gprs_rlc_v_b::is_state(int bsn, const char type) const { - return m_v_b[index] == type; + return m_v_b[bsn & mod_sns_half()] == type; } -inline void gprs_rlc_v_b::mark(int index, const char type) +inline void gprs_rlc_v_b::mark(int bsn, const char type) { - m_v_b[index] = type; + m_v_b[bsn & mod_sns_half()] = type; } -inline bool gprs_rlc_v_b::is_nacked(int index) const +inline bool gprs_rlc_v_b::is_nacked(int bsn) const { - return is_state(index, 'N'); + return is_state(bsn, 'N'); } -inline bool gprs_rlc_v_b::is_acked(int index) const +inline bool gprs_rlc_v_b::is_acked(int bsn) const { - return is_state(index, 'A'); + return is_state(bsn, 'A'); } -inline bool gprs_rlc_v_b::is_unacked(int index) const +inline bool gprs_rlc_v_b::is_unacked(int bsn) const { - return is_state(index, 'U'); + return is_state(bsn, 'U'); } -inline bool gprs_rlc_v_b::is_resend(int index) const +inline bool gprs_rlc_v_b::is_resend(int bsn) const { - return is_state(index, 'X'); + return is_state(bsn, 'X'); } -inline bool gprs_rlc_v_b::is_invalid(int index) const +inline bool gprs_rlc_v_b::is_invalid(int bsn) const { - return is_state(index, 'I'); + return is_state(bsn, 'I'); } -inline void gprs_rlc_v_b::mark_resend(int index) +inline void gprs_rlc_v_b::mark_resend(int bsn) { - return mark(index, 'X'); + return mark(bsn, 'X'); } -inline void gprs_rlc_v_b::mark_unacked(int index) +inline void gprs_rlc_v_b::mark_unacked(int bsn) { - return mark(index, 'U'); + return mark(bsn, 'U'); } -inline void gprs_rlc_v_b::mark_acked(int index) +inline void gprs_rlc_v_b::mark_acked(int bsn) { - return mark(index, 'A'); + return mark(bsn, 'A'); } -inline void gprs_rlc_v_b::mark_nacked(int index) +inline void gprs_rlc_v_b::mark_nacked(int bsn) { - return mark(index, 'N'); + return mark(bsn, 'N'); } -inline void gprs_rlc_v_b::mark_invalid(int index) +inline void gprs_rlc_v_b::mark_invalid(int bsn) { - return mark(index, 'I'); + return mark(bsn, 'I'); } inline const uint16_t gprs_rlc_dl_window::sns() const { - return 128; + return RLC_MAX_SNS; } inline const uint16_t gprs_rlc_dl_window::ws() const { - return 64; + return RLC_MAX_WS; } inline const uint16_t gprs_rlc_dl_window::mod_sns() const @@ -257,21 +263,11 @@ 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(); @@ -320,12 +316,12 @@ inline bool gprs_rlc_ul_window::is_in_window(uint8_t bsn) const inline const uint16_t gprs_rlc_ul_window::sns() const { - return 128; + return RLC_MAX_SNS; } inline const uint16_t gprs_rlc_ul_window::ws() const { - return 64; + return RLC_MAX_WS; } inline const uint16_t gprs_rlc_ul_window::mod_sns() const @@ -333,11 +329,6 @@ 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; @@ -358,25 +349,40 @@ inline void gprs_rlc_ul_window::raise_v_q(int incr) m_v_q = (m_v_q + incr) & mod_sns(); } -inline void gprs_rlc_v_n::mark_received(int index) +inline void gprs_rlc_v_n::mark_received(int bsn) +{ + return mark(bsn, 'R'); +} + +inline void gprs_rlc_v_n::mark_missing(int bsn) { - m_v_n[index] = 'R'; + return mark(bsn, 'N'); } -inline void gprs_rlc_v_n::mark_missing(int index) +inline bool gprs_rlc_v_n::is_received(int bsn) const { - m_v_n[index] = 'N'; + return is_state(bsn, 'R'); } -inline bool gprs_rlc_v_n::is_received(int index) const +inline bool gprs_rlc_v_n::is_state(int bsn, const char type) const { - return m_v_n[index] == 'R'; + return m_v_n[bsn & mod_sns_half()] == type; } -inline char gprs_rlc_v_n::state(int index) const +inline void gprs_rlc_v_n::mark(int bsn, const char type) { - char bit = m_v_n[index]; + m_v_n[bsn & mod_sns_half()] = type; +} + +inline char gprs_rlc_v_n::state(int bsn) const +{ + char bit = m_v_n[bsn & mod_sns_half()]; if (bit == '\0') return ' '; return bit; } + +inline gprs_rlc_data *gprs_rlc::block(int bsn) +{ + return &m_blocks[bsn & mod_sns_half()]; +} diff --git a/src/tbf.cpp b/src/tbf.cpp index cc8effa2..3f4da560 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -839,12 +839,10 @@ do_resend: 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 & dir.dl.window.mod_sns_half(); /* re-send block with negative aknowlegement */ - dir.dl.v_b.mark_unacked(index); + dir.dl.v_b.mark_unacked(resend_bsn); bts->rlc_resent(); - return create_dl_acked_block(fn, ts, index, false); + return create_dl_acked_block(fn, ts, resend_bsn, false); } /* if the window has stalled, or transfer is complete, @@ -871,7 +869,7 @@ do_resend: 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.window.v_s_mod_half(-1); + int16_t index = dir.dl.window.v_s_mod(-1); bts->rlc_resent(); return create_dl_acked_block(fn, ts, index, false); } @@ -886,8 +884,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.window.v_s_mod_half(-1); - bts->rlc_resent(); + int16_t index = dir.dl.window.v_s_mod(-1); return create_dl_acked_block(fn, ts, index, false); } goto do_resend; @@ -901,10 +898,11 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts struct rlc_dl_header *rh; struct rlc_li_field *li; struct msgb *msg; - uint16_t index; uint8_t *delimiter, *data, *e_pointer; uint16_t space, chunk; + gprs_rlc_data *rlc_data; bool first_fin_ack = false; + const uint16_t bsn = dir.dl.window.v_s(); LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n", dir.dl.window.v_s()); @@ -921,8 +919,8 @@ 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.window.v_s_mod_half(0); - data = m_rlc.blocks[index].prepare(block_data_len); + rlc_data = m_rlc.block(bsn); + data = rlc_data->prepare(block_data_len); rh = (struct rlc_dl_header *)data; rh->pt = 0; /* Data Block */ @@ -931,7 +929,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.window.v_s(); /* Block Sequence Number */ + rh->bsn = bsn; /* Block Sequence Number */ rh->e = 0; /* Extension bit, maybe set later */ e_pointer = data + 2; /* points to E of current chunk */ data += sizeof(*rh); @@ -1052,14 +1050,14 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts break; } LOGP(DRLCMACDL, LOGL_DEBUG, "data block: %s\n", - osmo_hexdump(m_rlc.blocks[index].block, block_length)); + osmo_hexdump(rlc_data->block, block_length)); #warning "move this up?" - m_rlc.blocks[index].len = block_length; + rlc_data->len = block_length; /* raise send state and set ack state array */ - dir.dl.v_b.mark_unacked(index); + dir.dl.v_b.mark_unacked(bsn); dir.dl.window.increment_send(); - return create_dl_acked_block(fn, ts, index, first_fin_ack); + return create_dl_acked_block(fn, ts, bsn, first_fin_ack); } struct msgb *gprs_rlcmac_tbf::create_dl_acked_block( @@ -1072,8 +1070,8 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block( uint8_t len; /* get data and header from current block */ - data = m_rlc.blocks[index].block; - len = m_rlc.blocks[index].len; + data = m_rlc.block(index)->block; + len = m_rlc.block(index)->len; rh = (struct rlc_dl_header *)data; /* Clear Polling, if still set in history buffer */ @@ -1553,12 +1551,10 @@ int gprs_rlcmac_tbf::extract_tlli(const uint8_t *data, const size_t len) int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi) { - uint16_t 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); @@ -1607,13 +1603,12 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len } /* Write block to buffer and set receive state array. */ - index = rh->bsn & mod_sns_half; /* memory index of block */ - m_rlc.blocks[index].put_data(data, len); + m_rlc.block(rh->bsn)->put_data(data, len); LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n", rh->bsn, dir.ul.window.v_q(), (dir.ul.window.v_q() + ws - 1) & mod_sns); - dir.ul.v_n.mark_received(index); + 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. @@ -1624,15 +1619,15 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len /* 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]); + uint16_t index = (v_q_beg + i) & mod_sns; + assemble_forward_llc(m_rlc.block(index)); } /* Check CV of last frame in buffer */ if (this->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */ && 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.window.v_r() - 1) & mod_sns_half].block; + m_rlc.block((dir.ul.window.v_r() - 1) & mod_sns)->block; LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, " "last block: BSN=%d CV=%d\n", last_rh->bsn, last_rh->cv); -- cgit v1.2.3