diff options
-rw-r--r-- | src/encoding.cpp | 6 | ||||
-rw-r--r-- | src/rlc.cpp | 29 | ||||
-rw-r--r-- | src/rlc.h | 148 | ||||
-rw-r--r-- | 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()); @@ -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); |