aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/encoding.cpp4
-rw-r--r--src/rlc.cpp52
-rw-r--r--src/rlc.h173
-rw-r--r--src/tbf.cpp118
-rw-r--r--src/tbf.h14
5 files changed, 242 insertions, 119 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 4855b22..b45657a 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 c4d43d3..fda743f 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] = ' ';
diff --git a/src/rlc.h b/src/rlc.h
index ba4d013..e08a5d7 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -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 a75fe4a..eca7229 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();
}
diff --git a/src/tbf.h b/src/tbf.h
index 6f5c48e..9560e3c 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -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);