aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/encoding.cpp6
-rw-r--r--src/rlc.cpp29
-rw-r--r--src/rlc.h148
-rw-r--r--src/tbf.cpp45
4 files changed, 112 insertions, 116 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 13390b9..085e7c3 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 dc5cf8b..915da87 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 b85b33e..0ecce40 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 cc8effa..3f4da56 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);