tbf/rlc: Move the parsing of RBB to Decoding, move window marking out

Move the parsing of the bitbmap out of the TBF code into Decoding.
Move the updating of the V_B into the V_B class. Add some comments
about handling the mod_sns, mod_sns_half parameters by using template
code.
This commit is contained in:
Holger Hans Peter Freyther 2013-11-24 17:05:48 +01:00
parent 9eb8ace260
commit df6b4f52e0
5 changed files with 61 additions and 26 deletions

View File

@ -83,3 +83,17 @@ uint8_t Decoding::get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
return 0;
}
/**
* show_rbb needs to be an array with 65 elements
*/
void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
{
for (int i = 63; i >= 0; i--) {
uint8_t bit;
bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
show_rbb[i] = bit ? '1' : 'o';
}
show_rbb[64] = '\0';
}

View File

@ -28,4 +28,6 @@ public:
static int tlli_from_ul_data(const uint8_t *data, uint8_t len,
uint32_t *tlli);
static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
static void extract_rbb(const uint8_t *rbb, char *extracted_rbb);
};

View File

@ -17,6 +17,8 @@
*/
#include "tbf.h"
#include "bts.h"
#include "gprs_debug.h"
extern "C" {
#include <osmocom/core/utils.h>
@ -68,3 +70,30 @@ int gprs_rlc_v_b::mark_for_resend(const uint16_t v_a, const uint16_t v_s,
return resend;
}
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,
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) {
if (show_rbb[i] == '1') {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn);
if (!is_acked(bsn & mod_sns_half))
*received += 1;
mark_acked(bsn & mod_sns_half);
} else {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn);
mark_nacked(bsn & mod_sns_half);
bts->rlc_nacked();
*lost += 1;
}
}
}

View File

@ -25,6 +25,7 @@
#define RLC_MAX_WS 64 /* max window size */
#define RLC_MAX_LEN 54 /* CS-4 including spare bits */
class BTS;
struct gprs_rlc_data {
uint8_t *prepare(size_t block_data_length);
@ -43,11 +44,18 @@ struct gprs_rlc {
gprs_rlc_data blocks[RLC_MAX_SNS/2];
};
/**
* 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,
uint16_t *lost, uint16_t *received);
/* Check for an individual frame */
bool is_unacked(int index) const;

View File

@ -1363,12 +1363,11 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ack(uint32_t fn)
int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
{
char show_rbb[65], show_v_b[RLC_MAX_SNS + 1];
char show_v_b[RLC_MAX_SNS + 1];
uint16_t mod_sns = m_sns - 1;
uint16_t mod_sns_half = (m_sns >> 1) - 1;
int i; /* must be signed */
int16_t dist; /* must be signed */
uint8_t bit;
uint16_t bsn;
struct msgb *msg;
uint16_t lost = 0, received = 0;
@ -1376,12 +1375,9 @@ int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this));
if (!final) {
char show_rbb[65];
Decoding::extract_rbb(rbb, show_rbb);
/* show received array in debug (bit 64..1) */
for (i = 63; i >= 0; i--) {
bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
show_rbb[i] = (bit) ? '1' : 'o';
}
show_rbb[64] = '\0';
LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
"(BSN=%d) 1=ACK o=NACK\n", (ssn - 64) & mod_sns,
show_rbb, (ssn - 1) & mod_sns);
@ -1400,25 +1396,11 @@ int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb)
"V(A)..V(S) range %s Free TBF!\n", tbf_name(this));
return 1; /* indicate to free TBF */
}
/* SSN - 1 is in range V(A)..V(S)-1 */
for (i = 63, bsn = (ssn - 1) & mod_sns;
i >= 0 && bsn != ((dir.dl.v_a - 1) & mod_sns);
i--, bsn = (bsn - 1) & mod_sns) {
bit = (rbb[i >> 3] >> (7 - (i&7))) & 1;
if (bit) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
"ack for BSN=%d\n", bsn);
if (!dir.dl.v_b.is_acked(bsn & mod_sns_half))
received++;
dir.dl.v_b.mark_acked(bsn & mod_sns_half);
} else {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got "
"NACK for BSN=%d\n", bsn);
dir.dl.v_b.mark_nacked(bsn & mod_sns_half);
bts->rlc_nacked();
lost++;
}
}
dir.dl.v_b.update(bts, show_rbb, ssn, dir.dl.v_a,
mod_sns, mod_sns_half,
&lost, &received);
/* report lost and received packets */
gprs_rlcmac_received_lost(this, received, lost);