aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-12-12 11:11:02 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-12-12 11:11:02 +0100
commit752a3b2baaf5c0b5323271ef1e03a3609b487286 (patch)
tree385a97840141752d9445ebea55930966972fa9c1 /src
parent11f2d58dbd0f590da3612a9f587a23b92857436f (diff)
parent5e94cd4fdedc44ba178a9d3d150f0d5ba7abc742 (diff)
Merge branch 'sysmocom/gprs-window-handling' into sysmocom/master
Daniel and me worked on the window handling. We now test that what we encode is compatible to what we decode. The char array now includes SSN-1 to the right of the array (reflecting a time axis that grows towards the right..)
Diffstat (limited to 'src')
-rw-r--r--src/decoding.cpp8
-rw-r--r--src/encoding.cpp53
-rw-r--r--src/encoding.h2
-rw-r--r--src/rlc.cpp30
-rw-r--r--src/rlc.h8
-rw-r--r--src/tbf.cpp2
6 files changed, 69 insertions, 34 deletions
diff --git a/src/decoding.cpp b/src/decoding.cpp
index 0f70872..fce8124 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -85,14 +85,16 @@ uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
/**
* show_rbb needs to be an array with 65 elements
+ * The index of the array is the bit position in the rbb
+ * (show_rbb[63] relates to BSN ssn-1)
*/
void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
{
- for (int i = 63; i >= 0; i--) {
+ for (int i = 0; i < 64; i++) {
uint8_t bit;
- bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
- show_rbb[i] = bit ? '1' : 'o';
+ bit = !!(rbb[i/8] & (1<<(7-i%8)));
+ show_rbb[i] = bit ? 'R' : 'I';
}
show_rbb[64] = '\0';
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 085e7c3..9479986 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -352,6 +352,27 @@ int Encoding::write_paging_request(bitvec * dest, uint8_t *ptmsi, uint16_t ptmsi
return plen;
}
+/**
+ * The index of the array show_rbb is the bit position inside the rbb
+ * (show_rbb[63] relates to BSN ssn-1)
+ */
+void Encoding::encode_rbb(const char *show_rbb, uint8_t *rbb)
+{
+ uint8_t rbb_byte = 0;
+
+ // RECEIVE_BLOCK_BITMAP
+ for (int i = 0; i < 64; i++) {
+ /* Set bit at the appropriate position (see 3GPP TS 04.60 9.1.8.1) */
+ if (show_rbb[i] == 'R')
+ rbb_byte |= 1<< (7-(i%8));
+
+ if((i%8) == 7) {
+ rbb[i/8] = rbb_byte;
+ rbb_byte = 0;
+ }
+ }
+}
+
/* generate uplink ack */
void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts,
RlcMacDownlink_t * block, struct gprs_rlcmac_tbf *tbf,
@@ -359,12 +380,9 @@ void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts,
{
// Packet Uplink Ack/Nack TS 44.060 11.2.28
- char show_v_n[65];
+ char rbb[65];
- uint8_t rbb = 0;
- uint16_t i, bbn;
- uint16_t mod_sns = (tbf->sns() - 1);
- char bit;
+ tbf->dir.ul.window.update_rbb(&tbf->dir.ul.v_n, rbb);
LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s "
"(final=%d)\n", tbf_name(tbf), final);
@@ -381,25 +399,14 @@ 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.window.v_r(); // STARTING_SEQUENCE_NUMBER
- // RECEIVE_BLOCK_BITMAP
- 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')
- rbb = (rbb << 1)|1;
- else
- rbb = (rbb << 1);
- if((i%8) == 7)
- {
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP[i/8] = rbb;
- rbb = 0;
- }
- }
- show_v_n[64] = '\0';
+ block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->dir.ul.window.ssn(); // STARTING_SEQUENCE_NUMBER
+
+ encode_rbb(rbb, block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
+
+ /* rbb is not NULL terminated */
+ rbb[64] = 0;
LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
- "N=Not-Received\n", show_v_n);
+ "I=Invalid\n", rbb);
block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.UnionType = 0x0; // Fixed Allocation Dummy = on
block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.u.FixedAllocationDummy = 0x0; // Fixed Allocation Dummy
diff --git a/src/encoding.h b/src/encoding.h
index d0f8f0a..e62c2c8 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -54,6 +54,8 @@ public:
uint8_t old_downlink, struct gprs_rlcmac_tbf *tbf, uint8_t poll,
uint8_t alpha, uint8_t gamma, int8_t ta_idx, uint8_t ta_ts);
+ static void encode_rbb(const char *show_rbb, uint8_t *rbb);
+
static void write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, RlcMacDownlink_t * block, struct gprs_rlcmac_tbf *tbf,
uint8_t final);
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 915da87..f31670e 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -84,19 +84,23 @@ int gprs_rlc_v_b::count_unacked(const gprs_rlc_dl_window &w)
return unacked;
}
+static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns)
+{
+ return (ssn - 1 - bitnum) & mod_sns;
+}
+
void gprs_rlc_v_b::update(BTS *bts, char *show_rbb, uint8_t ssn,
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) & w.mod_sns();
- i >= 0 && bsn != ((w.v_a() - 1) & w.mod_sns());
- i--, bsn = (bsn - 1) & w.mod_sns()) {
+ for (int bitpos = 0; bitpos < w.ws(); bitpos++) {
+ uint16_t bsn = bitnum_to_bsn(bitpos, ssn, w.mod_sns());
- if (show_rbb[i] == '1') {
+ if (bsn == ((w.v_a() - 1) & w.mod_sns()))
+ break;
+
+ if (show_rbb[w.ws() - 1 - bitpos] == 'R') {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn);
if (!is_acked(bsn))
*received += 1;
@@ -146,6 +150,18 @@ void gprs_rlc_v_n::reset()
memset(m_v_n, 0x0, sizeof(m_v_n));
}
+/* Update the receive block bitmap */
+void gprs_rlc_ul_window::update_rbb(const gprs_rlc_v_n *v_n, char *rbb)
+{
+ int i;
+ for (i=0; i < ws(); i++) {
+ if (v_n->is_received(ssn()-1-i))
+ rbb[ws()-1-i] = 'R';
+ else
+ rbb[ws()-1-i] = 'I';
+ }
+}
+
/* Raise V(R) to highest received sequence number not received. */
void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n)
{
diff --git a/src/rlc.h b/src/rlc.h
index 0ecce40..d68afab 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -89,8 +89,11 @@ struct gprs_rlc_ul_window {
const uint16_t v_r() const;
const uint16_t v_q() const;
+ const uint16_t ssn() const;
+
bool is_in_window(uint8_t bsn) const;
+ void update_rbb(const gprs_rlc_v_n *v_n, char *rbb);
void raise_v_r(int moves);
void raise_v_r(const uint16_t bsn, gprs_rlc_v_n *v_n);
uint16_t raise_v_q(gprs_rlc_v_n *v_n);
@@ -339,6 +342,11 @@ inline const uint16_t gprs_rlc_ul_window::v_q() const
return m_v_q;
}
+inline const uint16_t gprs_rlc_ul_window::ssn() const
+{
+ return m_v_r;
+}
+
inline void gprs_rlc_ul_window::raise_v_r(int moves)
{
m_v_r = (m_v_r + moves) & mod_sns();
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 3f4da56..8ffafce 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -1348,7 +1348,7 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
Decoding::extract_rbb(rbb, show_rbb);
/* show received array in debug (bit 64..1) */
LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
- "(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns,
+ "(BSN=%d) R=ACK I=NACK\n", (ssn - 64) & mod_sns,
show_rbb, (ssn - 1) & mod_sns);
/* apply received array to receive state (SSN-64..SSN-1) */