WIP: replace window update functions (TODO)

Ticket: OW#????
Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2016-01-14 13:40:01 +01:00
parent d1975ce201
commit dd68f16ed6
7 changed files with 181 additions and 7 deletions

View File

@ -892,6 +892,9 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
struct gprs_rlcmac_dl_tbf *tbf;
int rc;
struct pcu_l1_meas meas;
uint8_t bits_data[RLC_GPRS_WS/8];
bitvec bits;
int bsn_begin, bsn_end;
tfi = ack_nack->DOWNLINK_TFI;
tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
@ -918,10 +921,17 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n
LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Downlink Ack/Nack\n", tbf_name(tbf));
tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
bits.data = bits_data;
bits.data_len = sizeof(bits_data);
bits.cur_bit = 0;
Decoding::decode_gprs_acknack_bits(
&ack_nack->Ack_Nack_Description, &bits,
&bsn_begin, &bsn_end, &tbf->m_window);
rc = tbf->rcvd_dl_ack(
ack_nack->Ack_Nack_Description.FINAL_ACK_INDICATION,
ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
ack_nack->Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
bsn_begin, &bits);
if (rc == 1) {
tbf_free(tbf);
return;

View File

@ -328,6 +328,18 @@ void Decoding::extract_rbb(const uint8_t *rbb, char *show_rbb)
show_rbb[64] = '\0';
}
void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
{
unsigned int i;
for (i = 0; i < rbb->cur_bit; i++) {
uint8_t bit;
bit = bitvec_get_bit_pos(rbb, i);
show_rbb[i] = bit == 1 ? 'R' : 'I';
}
show_rbb[i] = '\0';
}
int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
const uint8_t *data, GprsCodingScheme cs)
{
@ -534,9 +546,34 @@ int Decoding::decode_egprs_acknack_bits(const EGPRS_AckNack_Desc_t *desc,
urbb.data_len = sizeof(desc->URBB);
for (int i = urbb_len; i > 0; i--) {
/* Set bit at the appropriate position (see 3GPP TS 04.60 12.3.1) */
/* Set bit at the appropriate position (see 3GPP TS 44.060 12.3.1) */
int is_ack = bitvec_get_bit_pos(&urbb, i-1);
bitvec_set_bit(bits, is_ack ? ONE : ZERO);
bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
}
return num_blocks;
}
int Decoding::decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
bitvec *bits, int *bsn_begin, int *bsn_end, gprs_rlc_dl_window *window)
{
int urbb_len = RLC_GPRS_WS;
int num_blocks;
struct bitvec urbb;
num_blocks = urbb_len;
*bsn_end = desc->STARTING_SEQUENCE_NUMBER;
*bsn_begin = window->mod_sns(*bsn_end - RLC_GPRS_WS);
urbb.cur_bit = 0;
urbb.data = (uint8_t *)desc->RECEIVED_BLOCK_BITMAP;
urbb.data_len = sizeof(desc->RECEIVED_BLOCK_BITMAP);
for (int i = urbb_len; i > 0; i--) {
/* Set bit at the appropriate position (see 3GPP TS 44.060 12.3) */
int is_ack = bitvec_get_bit_pos(&urbb, i-1);
bitvec_set_bit(bits, is_ack == 1 ? ONE : ZERO);
}
return num_blocks;

View File

@ -42,6 +42,7 @@ public:
static uint8_t get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
static void extract_rbb(const uint8_t *rbb, char *extracted_rbb);
static void extract_rbb(const struct bitvec *rbb, char *show_rbb);
static int rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
const uint8_t *data, GprsCodingScheme cs);
@ -57,4 +58,8 @@ public:
const EGPRS_AckNack_Desc_t *desc,
struct bitvec *bits, int *bsn_begin, int *bsn_end,
struct gprs_rlc_dl_window *window);
static int decode_gprs_acknack_bits(
const Ack_Nack_Description_t *desc,
bitvec *bits, int *bsn_begin, int *bsn_end,
gprs_rlc_dl_window *window);
};

View File

@ -114,6 +114,45 @@ static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn)
return (ssn - 1 - bitnum);
}
void gprs_rlc_dl_window::update(BTS *bts, const struct bitvec *rbb,
uint16_t first_bsn, uint16_t *lost,
uint16_t *received)
{
unsigned num_blocks = rbb->cur_bit;
unsigned bsn;
/* first_bsn is in range V(A)..V(S) */
/* All BSN before first_bsn are implicitly acknowledged */
for (bsn = v_a(); bsn != first_bsn; bsn = mod_sns(bsn + 1)) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got implicit ack for BSN=%d\n", bsn);
if (!m_v_b.is_acked(bsn))
*received += 1;
m_v_b.mark_acked(bsn);
}
for (unsigned int bitpos = 0; bitpos < num_blocks; bitpos++) {
bool is_ack;
bsn = mod_sns(first_bsn + bitpos);
if (bsn == mod_sns(v_a() - 1))
break;
is_ack = bitvec_get_bit_pos(rbb, bitpos) == 1;
if (is_ack) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn);
if (!m_v_b.is_acked(bsn))
*received += 1;
m_v_b.mark_acked(bsn);
} else {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got NACK for BSN=%d\n", bsn);
m_v_b.mark_nacked(bsn);
bts->rlc_nacked();
*lost += 1;
}
}
}
void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint16_t ssn,
uint16_t *lost, uint16_t *received)
{

View File

@ -32,6 +32,7 @@
#define RLC_EGPRS_MAX_WS 1024 /* min window size */
#define RLC_EGPRS_SNS 2048 /* EGPRS, must be power of 2 */
#define RLC_MAX_SNS RLC_EGPRS_SNS
#define RLC_MAX_WS RLC_EGPRS_MAX_WS
#define RLC_MAX_LEN 74 /* MCS-9 data unit */
struct BTS;
@ -173,6 +174,9 @@ struct gprs_rlc_dl_window {
int mark_for_resend();
void update(BTS *bts, char *show_rbb, uint16_t ssn,
uint16_t *lost, uint16_t *received);
void update(BTS *bts, const struct bitvec *rbb,
uint16_t first_bsn, uint16_t *lost,
uint16_t *received);
int move_window();
void show_state(char *show_rbb);
int count_unacked();

View File

@ -344,6 +344,7 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
const uint8_t *data, const uint16_t len);
int rcvd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb);
int rcvd_dl_ack(uint8_t final_ack, unsigned first_bsn, struct bitvec *rbb);
struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
void request_dl_ack();
bool need_control_ts() const;
@ -395,6 +396,7 @@ protected:
struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
const int index);
int update_window(const uint8_t ssn, const uint8_t *rbb);
int update_window(unsigned first_bsn, const struct bitvec *rbb);
int maybe_start_new_window();
bool dl_window_stalled() const;
void reuse_tbf();

View File

@ -644,9 +644,9 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
{
gprs_rlc_data *rlc_data;
uint16_t lost = 0, received = 0, skipped = 0;
char info[65];
memset(info, '.', sizeof(info));
info[64] = 0;
char info[RLC_MAX_WS + 1];
memset(info, '.', m_window.ws());
info[m_window.ws()] = 0;
uint16_t bsn = 0;
unsigned received_bytes = 0, lost_bytes = 0;
unsigned received_packets = 0, lost_packets = 0;
@ -717,6 +717,71 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn,
return lost * 100 / (lost + received);
}
int gprs_rlcmac_dl_tbf::update_window(unsigned first_bsn,
const struct bitvec *rbb)
{
int16_t dist; /* must be signed */
uint16_t lost = 0, received = 0;
char show_v_b[RLC_MAX_SNS + 1];
char show_rbb[RLC_MAX_SNS + 1];
int error_rate;
struct ana_result ana_res;
unsigned num_blocks = rbb->cur_bit;
unsigned behind_last_bsn = m_window.mod_sns(first_bsn + num_blocks);
Decoding::extract_rbb(rbb, show_rbb);
/* show received array in debug */
LOGP(DRLCMACDL, LOGL_DEBUG, "- ack: (BSN=%d)\"%s\""
"(BSN=%d) R=ACK I=NACK\n", first_bsn,
show_rbb, m_window.mod_sns(behind_last_bsn - 1));
/* apply received array to receive state (SSN-64..SSN-1) */
/* calculate distance of ssn from V(S) */
dist = m_window.mod_sns(m_window.v_s() - behind_last_bsn);
/* check if distance is less than distance V(A)..V(S) */
if (dist >= m_window.distance()) {
/* this might happpen, if the downlink assignment
* was not received by ms and the ack refers
* to previous TBF
* FIXME: we should implement polling for
* control ack!*/
LOGP(DRLCMACDL, LOGL_NOTICE, "- ack range is out of "
"V(A)..V(S) range %s Free TBF!\n", tbf_name(this));
return 1; /* indicate to free TBF */
}
error_rate = analyse_errors(show_rbb, behind_last_bsn, &ana_res);
if (bts_data()->cs_adj_enabled && ms())
ms()->update_error_rate(this, error_rate);
m_window.update(bts, rbb, first_bsn, &lost, &received);
/* report lost and received packets */
gprs_rlcmac_received_lost(this, received, lost);
/* Used to measure the leak rate */
gprs_bssgp_update_bytes_received(ana_res.received_bytes,
ana_res.received_packets + ana_res.lost_packets);
/* raise V(A), if possible */
m_window.raise(m_window.move_window());
/* show receive state array in debug (V(A)..V(S)-1) */
m_window.show_state(show_v_b);
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",
m_window.v_a(), show_v_b,
m_window.v_s_mod(-1));
if (state_is(GPRS_RLCMAC_FINISHED) && m_window.window_empty()) {
LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of "
"all blocks, but without final ack "
"inidcation (don't worry)\n");
}
return 0;
}
int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
{
@ -825,6 +890,18 @@ int gprs_rlcmac_dl_tbf::release()
}
int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, unsigned first_bsn,
struct bitvec *rbb)
{
LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this));
if (!final_ack)
return update_window(first_bsn, rbb);
LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
return maybe_start_new_window();
}
int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb)
{
LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this));