aboutsummaryrefslogtreecommitdiffstats
path: root/src/rlc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rlc.cpp')
-rw-r--r--src/rlc.cpp733
1 files changed, 577 insertions, 156 deletions
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 79d8f48..c1b438a 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -20,26 +20,313 @@
#include "bts.h"
#include "gprs_debug.h"
-#include <errno.h>
-
extern "C" {
#include <osmocom/core/utils.h>
}
+const uint8_t* one_run_len_code_list[MAX_CDWDTBL_LEN] = {
+(uint8_t*)"00110101", (uint8_t*)"000111", (uint8_t*)"0111", (uint8_t*)"1000",
+(uint8_t*) "1011", (uint8_t*)"1100", (uint8_t*)"1110", (uint8_t*)"1111",
+(uint8_t*)"10011", (uint8_t*)"10100", (uint8_t*)"00111", (uint8_t*)"01000",
+(uint8_t*)"001000", (uint8_t*)"000011", (uint8_t*)"110100", (uint8_t*)"110101",
+(uint8_t*)"101010", (uint8_t*)"101011", (uint8_t*)"0100111", (uint8_t*)"0001100",
+(uint8_t*)"0001000", (uint8_t*)"0010111", (uint8_t*)"0000011", (uint8_t*)"0000100",
+(uint8_t*)"0101000", (uint8_t*)"0101011", (uint8_t*)"0010011", (uint8_t*)"0100100",
+(uint8_t*)"0011000", (uint8_t*)"00000010", (uint8_t*)"00000011", (uint8_t*)"00011010",
+(uint8_t*)"00011011", (uint8_t*)"00010010", (uint8_t*)"00010011", (uint8_t*)"00010100",
+(uint8_t*)"00010101", (uint8_t*)"00010110", (uint8_t*)"00010111", (uint8_t*)"00101000",
+(uint8_t*)"00101001", (uint8_t*)"00101010", (uint8_t*)"00101011", (uint8_t*)"00101100",
+(uint8_t*)"00101101", (uint8_t*)"00000100", (uint8_t*)"00000101", (uint8_t*)"00001010",
+(uint8_t*)"00001011", (uint8_t*)"01010010", (uint8_t*)"01010011", (uint8_t*)"01010100",
+(uint8_t*)"01010101", (uint8_t*)"00100100", (uint8_t*)"00100101", (uint8_t*)"01011000",
+(uint8_t*)"01011001", (uint8_t*)"01011010", (uint8_t*)"01011011", (uint8_t*)"01001010",
+(uint8_t*)"01001011", (uint8_t*)"00110010", (uint8_t*)"00110011", (uint8_t*)"00110100",
+(uint8_t*)"11011", (uint8_t*)"10010", (uint8_t*)"010111", (uint8_t*)"0110111",
+(uint8_t*)"00110110", (uint8_t*)"00110111", (uint8_t*)"01100100", (uint8_t*)"01100101",
+(uint8_t*)"01101000", (uint8_t*)"01100111", (uint8_t*)"011001100",(uint8_t*)"011001101",
+(uint8_t*)"011010010", (uint8_t*)"011010011",(uint8_t*)"011010100"
+};
+
+const uint8_t* zero_run_len_code_list[MAX_CDWDTBL_LEN] = {
+(uint8_t*)"0000110111", (uint8_t*)"10", (uint8_t*)"11", (uint8_t*)"010",
+(uint8_t*)"011", (uint8_t*)"0011", (uint8_t*)"0010", (uint8_t*)"00011",
+(uint8_t*)"000101", (uint8_t*)"000100", (uint8_t*)"0000100", (uint8_t*)"0000101",
+(uint8_t*)"0000111", (uint8_t*)"00000100", (uint8_t*)"00000111", (uint8_t*)"000011000",
+(uint8_t*)"0000010111", (uint8_t*)"0000011000", (uint8_t*)"0000001000", (uint8_t*)"00001100111",
+(uint8_t*)"00001101000", (uint8_t*)"00001101100", (uint8_t*)"00000110111", (uint8_t*)"00000101000",
+(uint8_t*)"00000010111", (uint8_t*)"00000011000", (uint8_t*)"000011001010",(uint8_t*)"000011001011",
+(uint8_t*)"000011001100",(uint8_t*)"000011001101",(uint8_t*)"000001101000",(uint8_t*)"000001101001",
+(uint8_t*)"000001101010",(uint8_t*)"000001101011",(uint8_t*)"000011010010",(uint8_t*)"000011010011",
+(uint8_t*)"000011010100",(uint8_t*)"000011010101",(uint8_t*)"000011010110",(uint8_t*)"000011010111",
+(uint8_t*)"000001101100",(uint8_t*)"000001101101",(uint8_t*)"000011011010",(uint8_t*)"000011011011",
+(uint8_t*)"000001010100",(uint8_t*)"000001010101",(uint8_t*)"000001010110",(uint8_t*)"000001010111",
+(uint8_t*)"000001100100",(uint8_t*)"000001100101",(uint8_t*)"000001010010",(uint8_t*)"000001010011",
+(uint8_t*)"000000100100",(uint8_t*)"000000110111",(uint8_t*)"000000111000",(uint8_t*)"000000100111",
+(uint8_t*)"000000101000",(uint8_t*)"000001011000",(uint8_t*)"000001011001",(uint8_t*)"000000101011",
+(uint8_t*)"000000101100",(uint8_t*)"000001011010",(uint8_t*)"000001100110",(uint8_t*)"000001100111",
+(uint8_t*)"0000001111", (uint8_t*)"000011001000",(uint8_t*)"000011001001",(uint8_t*)"000001011011",
+(uint8_t*)"000000110011",(uint8_t*)"000000110100",(uint8_t*)"000000110101",(uint8_t*)"0000001101100",
+(uint8_t*)"0000001101101",(uint8_t*)"0000001001010", (uint8_t*)"0000001001011",
+(uint8_t*)"0000001001100", (uint8_t*)"0000001001101", (uint8_t*)"0000001110010",
+(uint8_t*)"0000001110011"
+};
+/*
+*
+*
+* Desc: This function rebuilds a header from Type II to Type III
+* the source is header2 and the new header is put
+* into the enc structure
+*
+*/
+
+int gprs_rlc_data::egprs_build_header_type3_from_type2
+(
+uint8_t *enc, /* header to unpack */
+GprsCodingScheme *reseg_mcs, /* resegmentation MCS */
+uint8_t ps,
+uint8_t spb /* SPB field */
+)
+{
+ uint8_t byte;
+
+ /* Type 3 and type 2 are differed with only last byte to include spb offset */
+ memcpy(enc, this->hdr_ptr[0], EGPRS_TYPE3_HDR_SIZE);
+
+ struct gprs_rlc_dl_header_egprs_3 *header_type3 = (struct gprs_rlc_dl_header_egprs_3 *)enc;
+
+ byte = reseg_mcs->get_cps(ps, this->mcs8_retx);
+
+ header_type3->cps = byte;
+ header_type3->spb = spb;
+ return(1);
+} /* end of egprs_build_header_type3_from_type2*/
+
+/*
+*
+* Fun: egprs_build_header_type3_from_type1
+*
+* Desc: This function rebuilds a header from Type I to Type III
+* the source is header1 and the new header is put
+* into the enc structure
+* This function is needed for resegmentation from MCS7/8/9 to
+* MCS 2/3
+*
+* Ret: 1 if successful or,
+* -1, otherwise
+*
+* Notes: None
+*
+* File: gz_egprs1.c
+*
+*/
+
+int gprs_rlc_data::egprs_build_header_type3_from_type1
+(
+uint8_t *enc, /* header to unpack */
+GprsCodingScheme *reseg_mcs, /* resegmentation MCS */
+uint8_t ps,
+uint8_t spb/* SPB field */
+)
+{
+ uint8_t byte;
+
+ struct gprs_rlc_dl_header_egprs_3 *header_type3 = (struct gprs_rlc_dl_header_egprs_3 *) enc;
+
+ memcpy(enc, this->hdr_ptr[0], EGPRS_TYPE3_HDR_SIZE);
+
+ /* depending on wether if it is the first or the second
+ block of the original MCS-7/8/9 block we choose the BSN
+ */
+
+ header_type3->bsn_a = (this->bsn & 0x3);
+ header_type3->bsn_b = this->bsn >> 2 ;
+ header_type3->bsn_c = this->bsn & 0x0400 ;
+
+ byte = reseg_mcs->get_cps(ps, this->mcs8_retx);
+
+ header_type3->cps = byte;
+ header_type3->spb = spb;
+
+ return(1);
+} /* end of egprs_build_header_type3_from_type1 */
+
+
+/*
+*
+* Desc: This function rebuilds a header from Type I to Type II
+* the source is header1 and the new header is put
+* into the enc structure
+* In this case 2 headers are returned since the BSN for
+* each resegmented block is different
+*/
+
+int gprs_rlc_data::egprs_build_header_type2_from_type1
+(
+uint8_t *enc, /* header to unpack */
+GprsCodingScheme *reseg_mcs, /* resegmentation MCS */
+uint8_t ps
+)
+{
+ uint8_t byte;
+
+ struct gprs_rlc_dl_header_egprs_2 *header_type2 = (struct gprs_rlc_dl_header_egprs_2 *) enc;
+
+ memcpy(enc, this->hdr_ptr[0], EGPRS_TYPE2_HDR_SIZE);
+
+ /* depending on wether if it is the first or the second
+ block of the original MCS-7/8/9 block we choose the BSN
+ */
+ header_type2->bsn_a = (this->bsn & 0x3);
+ header_type2->bsn_b = this->bsn >> 2 ;
+ header_type2->bsn_c = this->bsn & 0x0400 ;
+
+ byte = reseg_mcs->get_cps(ps, this->mcs8_retx);
+
+ header_type2->cps = byte;
+
+ return(1);
+} /* end of egprs_build_header_type2_from_type1*/
+
+void gprs_rlc_data::update_cps( GprsCodingScheme *cs, const uint8_t next_ps)
+{
+ uint8_t cps = cs->get_cps(next_ps, false);
+ if((*cs == GprsCodingScheme::MCS1 ||
+ *cs == GprsCodingScheme::MCS2 ||
+ *cs == GprsCodingScheme::MCS3 ||
+ *cs == GprsCodingScheme::MCS4)){
+
+ this->last_ps = next_ps;
+ this->hdr_ptr[0][3] |= cps << 1 ;
+ }
+ else if( (*cs == GprsCodingScheme::MCS5) ||
+ (*cs == GprsCodingScheme::MCS6)){
+
+ this->last_ps = next_ps;
+ this->hdr_ptr[0][3] |= cps << 1 ;
+
+ }else if((*cs == GprsCodingScheme::MCS7) ||
+ (*cs == GprsCodingScheme::MCS8) ||
+ ( *cs == GprsCodingScheme::MCS9)){
+
+ this->last_ps = next_ps;
+ this->hdr_ptr[0][4] = cps<< 3 ;
+ }
+ else{
+ OSMO_ASSERT(*cs >= GprsCodingScheme::MCS9);
+ }
+}
+
+void gprs_rlc_data::fill_hdr_type3( GprsCodingScheme *cs, const uint16_t bsn, const uint16_t tfi,const uint16_t cps)
+{
+ /*Refer Header type from 10.3a.3.3 of 46.060*/
+ struct gprs_rlc_dl_header_egprs_3 *ptr = (struct gprs_rlc_dl_header_egprs_3 *)hdr_ptr[0];
+
+ ptr->usf = GPRS_RLCMAC_DATA_BLOCK;
+ ptr->tfi_a = tfi & 0x01;
+
+ ptr->tfi_b = tfi >> 1;
+ ptr->bsn_a = bsn & 0x3;
+
+ ptr->bsn_b = bsn >> 2 ;
+
+ ptr->bsn_c = bsn & 0x0400 ;
+
+ /* Need to check with cs */
+
+ ptr->cps = cps;
+ ptr->spb = 0;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "usf=%d\n tfi_a=%d\n tfi_b=%d\n bsna %d \n bsnb %d\n bsnc %d\n cps %d\n spb %d\n",
+ ptr->usf, ptr->tfi_a, ptr->tfi_b, ptr->bsn_a,ptr->bsn_b,ptr->bsn_c,ptr->cps,ptr->spb);
+
+
+ this->cs = *cs;
+ this->hdr_size[0] = EGPRS_TYPE3_HDR_SIZE;
+}
+
+void gprs_rlc_data::fill_hdr_type2( GprsCodingScheme *cs, const uint16_t bsn, const uint16_t tfi,const uint16_t cps )
+{
+ /*Refer Header type from 10.3a.3.2 of 46.060*/
+ struct gprs_rlc_dl_header_egprs_2 *ptr = (struct gprs_rlc_dl_header_egprs_2 *)hdr_ptr[0];
+ ptr->usf = GPRS_RLCMAC_DATA_BLOCK;
+
+ ptr->tfi_a = tfi & 0x01;
+
+ ptr->tfi_b = tfi >> 1;
+ ptr->bsn_a = bsn & 0x3;
+
+ ptr->bsn_b = bsn >> 2 ;
+
+ ptr->bsn_c = bsn & 0x0400 ;
+
+ /* Need to check with cs */
+
+ ptr->cps = cps;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "usf=%d\n tfi_a=%d\n tfi_b=%d\n bsna %d \n bsnb %d\n bsnc %d\n cps %d\n",
+ ptr->usf, ptr->tfi_a, ptr->tfi_b, ptr->bsn_a,ptr->bsn_b,ptr->bsn_c,ptr->cps);
+
+ this->cs = *cs;
+ this->hdr_size[0] = EGPRS_TYPE2_HDR_SIZE;
+}
+
+void gprs_rlc_data::set_resend_fn_ts(const uint32_t fn, const uint8_t ts)
+{
+ this->resend_fn = fn;
+ this->resend_ts = ts;
+}
+
+void gprs_rlc_data::fill_hdr_type1(GprsCodingScheme *cs, const uint16_t bsn, const uint16_t tfi , const uint16_t cps)
+{
+ /*Refer Header type from 10.3a.3.1 of 46.060*/
+ struct gprs_rlc_dl_header_egprs_1 *ptr = (struct gprs_rlc_dl_header_egprs_1 *)hdr_ptr[0];
+ ptr->usf = GPRS_RLCMAC_DATA_BLOCK;
+
+ ptr->tfi_a = tfi & 0x01;
+
+ ptr->tfi_b = tfi >> 1;
+ ptr->bsn1_a = bsn & 0x3;
+
+ ptr->bsn1_b = bsn >> 2 ;
+
+ ptr->bsn1_c = bsn & 0x0400 ;
+ /*
+ Theres no scope of retx and Tx block clubbing present in our design
+ hence bsn2 is always assumed to be 1 i.e bsn2 = nextbsn(bsn1) = 1
+ */
+ ptr->bsn2_a = 1;
+ ptr->bsn2_b = 0 ;
+
+ ptr->cps = cps;
+ this->cs = *cs;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "usf :%d \n es :%d\n rrbp: %d \n tfi1:%d\n tfi2:%d\n bsn1a%d \n bsn1b %d \n bsn1c%d\n"
+ "bsn2a %d\n bsn2b %d\n ",ptr ->usf, ptr -> es_p, ptr -> rrbp, ptr -> tfi_a, ptr ->tfi_b, ptr->bsn1_a,
+ ptr->bsn1_b, ptr->bsn1_c, ptr->bsn2_a, ptr->bsn2_b);
+ LOGP(DRLCMACDL, LOGL_DEBUG, "pr: %d cps:%d ", ptr -> pr, ptr ->cps);
+
+ this->hdr_size[0] = EGPRS_TYPE1_HDR_SIZE;
+}
uint8_t *gprs_rlc_data::prepare(size_t block_data_len)
{
/* todo.. only set it once if it turns out to be a bottleneck */
- memset(block, 0x0, sizeof(block));
- memset(block, 0x2b, block_data_len);
+ memset(complete_blk, 0x0, sizeof(complete_blk));
+ memset(complete_blk, 0x2b, block_data_len);
+ memset(&hdr_ptr[0],0, RLC_MAX_HDR_SIZE);
+ memset(&hdr_ptr[1],0, RLC_MAX_HDR_SIZE);
+
+ this->mcs8_retx = false;
+ this->reseg_status = EGPRS_RESEG_SINGLE_BLOCK;
+ this->len_block2 = 0;
- return block;
+ return complete_blk;
}
void gprs_rlc_data::put_data(const uint8_t *data, size_t data_len)
{
- memcpy(block, data, data_len);
- len = data_len;
+ memcpy(complete_blk, data, data_len);
+ completed_block_len = data_len;
}
void gprs_rlc_v_b::reset()
@@ -55,9 +342,25 @@ void gprs_rlc_dl_window::reset()
m_v_b.reset();
}
+void gprs_rlc_dl_window::set_sns(uint16_t sns)
+{
+ OSMO_ASSERT(sns >= RLC_GPRS_SNS);
+ OSMO_ASSERT(sns <= RLC_MAX_SNS);
+ /* check for 2^n */
+ OSMO_ASSERT((sns & (-sns)) == sns);
+ m_sns = sns;
+}
+
+void gprs_rlc_dl_window::set_ws(uint16_t ws)
+{
+ OSMO_ASSERT(ws >= RLC_GPRS_SNS/2);
+ OSMO_ASSERT(ws <= RLC_MAX_SNS/2);
+ m_ws = ws;
+}
+
int gprs_rlc_dl_window::resend_needed()
{
- for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
+ for (uint16_t bsn = v_a(); bsn != v_s(); bsn = this->mod_sns(bsn + 1)) {
if (m_v_b.is_nacked(bsn) || m_v_b.is_resend(bsn))
return bsn;
}
@@ -69,7 +372,7 @@ int gprs_rlc_dl_window::mark_for_resend()
{
int resend = 0;
- for (uint16_t bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
+ for (uint16_t bsn = v_a(); bsn != v_s(); bsn = this->mod_sns(bsn + 1)) {
if (m_v_b.is_unacked(bsn)) {
/* mark to be re-send */
m_v_b.mark_resend(bsn);
@@ -85,7 +388,7 @@ int gprs_rlc_dl_window::count_unacked()
uint16_t unacked = 0;
uint16_t bsn;
- for (bsn = v_a(); bsn != v_s(); bsn = mod_sns(bsn + 1)) {
+ for (bsn = v_a(); bsn != v_s(); bsn = this->mod_sns(bsn + 1)) {
if (!m_v_b.is_acked(bsn))
unacked += 1;
}
@@ -98,24 +401,17 @@ 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)
+void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint16_t ssn,
+ uint16_t *lost, uint16_t *received)
{
- unsigned num_blocks = rbb->cur_bit;
- unsigned bsn;
-
- /* first_bsn is in range V(A)..V(S) */
+ /* SSN - 1 is in range V(A)..V(S)-1 */
+ for (int bitpos = 0; bitpos < ws(); bitpos++) {
+ uint16_t bsn = this->mod_sns(bitnum_to_bsn(bitpos, ssn));
- 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))
+ if (bsn == this->mod_sns(v_a() - 1))
break;
- is_ack = bitvec_get_bit_pos(rbb, bitpos) == 1;
-
- if (is_ack) {
+ if (show_rbb[ws() - 1 - bitpos] == 'R') {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn);
if (!m_v_b.is_acked(bsn))
*received += 1;
@@ -129,17 +425,218 @@ void gprs_rlc_dl_window::update(BTS *bts, const struct bitvec *rbb,
}
}
-void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint16_t ssn,
- uint16_t *lost, uint16_t *received)
+void extract_egprs_crbb_urbb(uint16_t uncomp_length, const uint8_t *uncomp_bitmap, char *show_rbb)
+{
+ for (int i = 0; i < uncomp_length; i++) {
+ uint8_t bit;
+
+ bit = !!(uncomp_bitmap[i/8] & (1<<(7-i%8)));
+ show_rbb[i] = bit ? 'R' : 'I';
+ }
+
+ show_rbb[uncomp_length] = '\0';
+}
+
+void extract_egprs_urbb(uint16_t uncomp_length, const uint8_t *uncomp_bitmap, char *show_rbb,uint16_t start_index)
+{
+ for (int i = 0; i < uncomp_length; i++) {
+ uint8_t bit;
+
+ bit = !!(uncomp_bitmap[i/8] & (1<<(7-i%8)));
+ show_rbb[start_index+uncomp_length-i] = bit ? 'R' : 'I';
+ }
+
+ show_rbb[uncomp_length] = '\0';
+}
+
+int search_runlen(
+ Node *root, /* root of Ones or Zeros tree */
+ uint8_t* bmbuf, /* Received compressed bitmap buf */
+ uint8_t bit_pos, /* the start bit pos to read codeword */
+ uint8_t* len_codewd, /* length of codeword */
+ uint16_t* rlen /* run length of Ones or Zeros */
+ )
{
+ Node* iter;
+ uint8_t dir;
+
+ iter = root;
+ *len_codewd = 0;
+
+ while (iter->run_length == 0) {
+ if ((iter->left == NULL)&& (iter->right == NULL))
+ return -1;
+
+ /* get the bit value at the bitpos and put it in right most of dir */
+ dir = (bmbuf[BITS_TO_BYTES(bit_pos)-1]>>(7-(MOD8(bit_pos))))&0x01;
+ (bit_pos)++;
+ (*len_codewd)++;
+
+ if (((dir&0x01) == 0) && (iter->left != NULL))
+ iter = iter->left;
+
+ else if (((dir&0x01) == 1) && (iter->right != NULL))
+ iter = iter->right;
+ else
+ return -1;
+ }
+ (*rlen) = *(iter->run_length);
+
+ return 1;
+} /* search_runlen */
+
+void gprs_rlc_dl_window::decompress_crbb(
+ BTS *bts,
+ int8_t compress_bmap_len, /* compressed bitmap length */
+ uint8_t clr_code_bit, /* run length of Ones or Zeros */
+ uint8_t* orig_buf, /* received block bitmap */
+ int16_t orig_bmaplen, /* bitmap length of Ack/Nack descr */
+ uint16_t* decompress_bmap_len, /* total bitmap length after decompression */
+ uint8_t* uncompress_bmbuf, /* bitmap after decompression */
+ bitvec *dest
+ )
+{
+ uint8_t bit_pos = 0;
+ uint8_t nbits = 0; /* number of bits of codeword */
+ uint16_t run_length = 0;
+ uint16_t cbmaplen = 0; /* compressed bitmap part after decompression */
+ unsigned wp = 0;
+ *decompress_bmap_len = 0;
+ int8_t Lc = compress_bmap_len;
+
+ while (compress_bmap_len >= 0) {
+
+ if (clr_code_bit == 1) {
+ search_runlen (bts->ones_list, orig_buf, bit_pos, &nbits, &run_length);
+ //If run length > 64, need makeup and terminating code
+ if (run_length < 64) {
+ clr_code_bit = 0;
+ }
+ cbmaplen= cbmaplen + run_length;
+ /* put run length of Ones in uncompressed bitmap */
+ while (run_length !=0) {
+ if (run_length > 8) {
+ bitvec_write_field(dest, wp, 0xff, 8);
+ run_length = run_length -8;
+ }
+ else {
+ bitvec_write_field(dest, wp, 0xff, run_length);
+ run_length = 0;
+ }
+ }
+ }
+ else {
+ search_runlen (bts->zeros_list, orig_buf, bit_pos, &nbits, &run_length);
+ //If run length > 64, need makeup and terminating code
+ if (run_length < 64) {
+ clr_code_bit = 1;
+ }
+ cbmaplen= cbmaplen + run_length;
+ /* put run length of Zeros in uncompressed bitmap */
+ while (run_length !=0) {
+ if (run_length > 8) {
+ bitvec_write_field(dest, wp, 0x00, 8);
+ run_length = run_length -8;
+ }
+ else {
+ bitvec_write_field(dest, wp, 0x00, run_length);
+ run_length = 0;
+ }
+ }
+ }
+ bit_pos = bit_pos + nbits;
+ compress_bmap_len = compress_bmap_len - nbits;
+ }
+
+ /* Decompress_bmap_len is the len of uncompressed bitmap
+ + Original bitmap len of ack/nack desc
+ - Original compressed bitmap len
+ ==> this is requird in extract rbb func*/
+ (*decompress_bmap_len) = cbmaplen + orig_bmaplen - Lc - 23;
+
+ return ;
+}/* Decompress_CRBB */
+
+void gprs_rlc_dl_window::egprs_update(BTS *bts, char *show_rbb,
+ EGPRS_AckNack_Desc_t *Egprs_Desc, uint16_t *lost,
+ uint16_t *received, int16_t len)
+{
+ int16_t ssn = Egprs_Desc->STARTING_SEQUENCE_NUMBER;
+ uint8_t bow = Egprs_Desc->BEGINNING_OF_WINDOW;
+ uint8_t eow = Egprs_Desc->END_OF_WINDOW;
+ uint16_t uncomp_len = 0; /* total bitmap length of compressed part after
+ decompcompress plus uncompressed part */
+ uint8_t uncomp_bitmap[128];
+ uint16_t crbb_urbb_len = 0; /* bitmap length of compressed part after decompression */
+ uint16_t urbb_len;
+ int8_t Lc = Egprs_Desc->CRBB_LENGTH;
+
+ bitvec dest;
+ dest.data = uncomp_bitmap;
+ dest.cur_bit = 0;
+ dest.data_len = 128;
+
+ if(len > 0) {
+ urbb_len = len - Lc;
+ }
+ else {
+ urbb_len = Egprs_Desc->URBB_LENGTH;
+ }
+ if(Egprs_Desc->Exist_CRBB) {
+ LOGP(DRLCMACDL, LOGL_DEBUG, "Compress bitmap exist, "
+ "CRBB LEN =%d and Starting color code =%d",
+ Lc, Egprs_Desc->CRBB_STARTING_COLOR_CODE);
+
+ decompress_crbb(bts,
+ Lc,
+ Egprs_Desc->CRBB_STARTING_COLOR_CODE,
+ Egprs_Desc->CRBB,
+ len, //Ack Nack desc length
+ &uncomp_len,
+ uncomp_bitmap,
+ &dest);
+
+ /* now attach unCompressed bitmap part to the decompressed bitmap
+ * in unCompBitmap array if there is any */
+/* if (Lc != 0) {
+ ubmaplen = acknack_len - Lc - 23;
+ }
+ else {
+ ubmaplen = acknack_len - 15;
+ }*/
+ crbb_urbb_len = dest.cur_bit;
+ extract_egprs_crbb_urbb(crbb_urbb_len, uncomp_bitmap, show_rbb);
+ LOGP(DRLCMACDL, LOGL_DEBUG, "crbb len %d uncomp len %d\n",Lc,crbb_urbb_len);
+ }
+
+ /* uncompressed part */
+ if ((urbb_len !=0) && (Egprs_Desc->URBB != (uint8_t *)NULL)) {
+ extract_egprs_urbb(urbb_len, Egprs_Desc->URBB, show_rbb, crbb_urbb_len);
+ LOGP(DRLCMACDL, LOGL_DEBUG, "urbb len %d\n" ,urbb_len);
+ }
+
+ /* if Beginning of window is set 1, Mark Acked between SSN-2 ( V(Q)-1) to V(A)*/
+ if (bow) {
+ for(int i = (v_a() -1); i < (ssn -2); i++ ) {
+ uint16_t bsn = this->mod_sns(i);
+ *received += 1;
+ m_v_b.mark_acked(bsn);
+ }
+ /* ssn -1 which is V(Q) should be nacked */
+ uint16_t bsn = ((2048 + (ssn-1)) & 0x07FF);/* MOD 2048 (MAX BSN NUM) */
+ m_v_b.mark_nacked(bsn);
+ bts->rlc_nacked();
+ *lost += 1;
+ }
+
/* SSN - 1 is in range V(A)..V(S)-1 */
- for (int bitpos = 0; bitpos < ws(); bitpos++) {
- uint16_t bsn = mod_sns(bitnum_to_bsn(bitpos, ssn));
+ for (int bitpos = 0; bitpos < crbb_urbb_len + urbb_len; bitpos++) {
+ uint16_t bsn = mod_sns(ssn + bitpos);
- if (bsn == mod_sns(v_a() - 1))
+ if (mod_sns(v_s() -bsn) >= distance())
break;
- if (show_rbb[ws() - 1 - bitpos] == 'R') {
+ if (show_rbb[bitpos] == 'R') {
LOGP(DRLCMACDL, LOGL_DEBUG, "- got ack for BSN=%d\n", bsn);
if (!m_v_b.is_acked(bsn))
*received += 1;
@@ -151,15 +648,26 @@ void gprs_rlc_dl_window::update(BTS *bts, char *show_rbb, uint16_t ssn,
*lost += 1;
}
}
-}
+ /* if EOW is set, nack data btw last BSN indicated in the bitmap and
+ * the end of tx window V(S) */
+ if(eow) {
+/* Currently EOW is not handled
+ for (int i = ssn + crbb_urbb_len + uncomp_len; bsn < v_s(); i++)
+ uint16_t bsn = mod_sns(ssn + i);
+ m_v_b.mark_nacked(bsn);
+ bts->rlc_nacked();
+ *lost += 1;
+*/
+ }
+}
int gprs_rlc_dl_window::move_window()
{
int i;
uint16_t bsn;
int moved = 0;
- for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) {
+ for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = this->mod_sns(bsn + 1)) {
if (m_v_b.is_acked(bsn)) {
m_v_b.mark_invalid(bsn);
moved += 1;
@@ -175,23 +683,23 @@ void gprs_rlc_dl_window::show_state(char *show_v_b)
int i;
uint16_t bsn;
- for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = mod_sns(bsn + 1)) {
+ for (i = 0, bsn = v_a(); bsn != v_s(); i++, bsn = this->mod_sns(bsn + 1)) {
uint16_t index = bsn & mod_sns_half();
switch(m_v_b.get_state(index)) {
- case GPRS_RLC_DL_BSN_INVALID:
- show_v_b[i] = 'I';
- break;
- case GPRS_RLC_DL_BSN_ACKED:
- show_v_b[i] = 'A';
- break;
- case GPRS_RLC_DL_BSN_RESEND:
- show_v_b[i] = 'X';
- break;
- case GPRS_RLC_DL_BSN_NACKED:
- show_v_b[i] = 'N';
- break;
- default:
- show_v_b[i] = '?';
+ case GPRS_RLC_DL_BSN_INVALID:
+ show_v_b[i] = 'I';
+ break;
+ case GPRS_RLC_DL_BSN_ACKED:
+ show_v_b[i] = 'A';
+ break;
+ case GPRS_RLC_DL_BSN_RESEND:
+ show_v_b[i] = 'X';
+ break;
+ case GPRS_RLC_DL_BSN_NACKED:
+ show_v_b[i] = 'N';
+ break;
+ default:
+ show_v_b[i] = '?';
}
}
show_v_b[i] = '\0';
@@ -203,7 +711,7 @@ void gprs_rlc_v_n::reset()
m_v_n[i] = GPRS_RLC_UL_BSN_INVALID;
}
-void gprs_rlc_window::set_sns(uint16_t sns)
+void gprs_rlc_ul_window::set_sns(uint16_t sns)
{
OSMO_ASSERT(sns >= RLC_GPRS_SNS);
OSMO_ASSERT(sns <= RLC_MAX_SNS);
@@ -212,7 +720,7 @@ void gprs_rlc_window::set_sns(uint16_t sns)
m_sns = sns;
}
-void gprs_rlc_window::set_ws(uint16_t ws)
+void gprs_rlc_ul_window::set_ws(uint16_t ws)
{
OSMO_ASSERT(ws >= RLC_GPRS_SNS/2);
OSMO_ASSERT(ws <= RLC_MAX_SNS/2);
@@ -231,11 +739,29 @@ void gprs_rlc_ul_window::update_rbb(char *rbb)
}
}
+/* Update the receive block bitmap */
+uint16_t gprs_rlc_ul_window::update_egprs_rbb(char *rbb)
+{
+ int i;
+ uint16_t bsn;
+ for (i = 0, bsn = (v_q()+1); ((bsn < (v_r())) && (i < ws())); i++, bsn = this->mod_sns(bsn + 1)) {
+ //if (m_v_n.is_received(ssn()-1-i))
+ if (m_v_n.is_received(bsn)) //bsn
+ //rbb[ws()-1-i] = 'R';
+ rbb[i] = 'R'; //i
+ else
+ rbb[i] = 'I';
+ }
+ LOGP(DRLCMACUL, LOGL_DEBUG, "V(N):in update_egprs_rbb \"%s\" R=Received "
+ "I=Invalid\n", rbb);
+ return i;
+}
+
/* Raise V(R) to highest received sequence number not received. */
void gprs_rlc_ul_window::raise_v_r(const uint16_t bsn)
{
uint16_t offset_v_r;
- offset_v_r = mod_sns(bsn + 1 - v_r());
+ offset_v_r = this->mod_sns(bsn + 1 - v_r());
/* Positive offset, so raise. */
if (offset_v_r < (sns() >> 1)) {
while (offset_v_r--) {
@@ -259,7 +785,7 @@ uint16_t gprs_rlc_ul_window::raise_v_q()
if (!m_v_n.is_received(v_q()))
break;
LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
- "V(Q) to %d\n", v_q(), mod_sns(v_q() + 1));
+ "V(Q) to %d\n", v_q(), this->mod_sns(v_q() + 1));
raise_v_q(1);
count += 1;
}
@@ -280,108 +806,3 @@ bool gprs_rlc_ul_window::invalidate_bsn(const uint16_t bsn)
return was_valid;
}
-
-static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc,
- GprsCodingScheme cs, bool with_padding, unsigned int header_bits)
-{
- unsigned int i;
- unsigned int padding_bits = with_padding ? cs.optionalPaddingBits() : 0;
-
- memset(rlc, 0, sizeof(*rlc));
-
- rlc->cs = cs;
- rlc->with_padding = with_padding;
- rlc->num_data_blocks = cs.numDataBlocks();
-
- OSMO_ASSERT(rlc->num_data_blocks <= ARRAY_SIZE(rlc->block_info));
-
- for (i = 0; i < rlc->num_data_blocks; i++) {
- gprs_rlc_data_block_info_init(&rlc->block_info[i], cs,
- with_padding);
-
- rlc->data_offs_bits[i] =
- header_bits + padding_bits +
- (i+1) * cs.numDataBlockHeaderBits() +
- i * 8 * rlc->block_info[0].data_len;
- }
-}
-
-void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc,
- GprsCodingScheme cs, bool with_padding)
-{
- return gprs_rlc_data_header_init(rlc, cs, with_padding,
- cs.numDataHeaderBitsDL());
-}
-
-void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc,
- GprsCodingScheme cs, bool with_padding)
-{
- return gprs_rlc_data_header_init(rlc, cs, with_padding,
- cs.numDataHeaderBitsUL());
-}
-
-void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi,
- GprsCodingScheme cs, bool with_padding)
-{
- unsigned int data_len = cs.maxDataBlockBytes();
- if (with_padding)
- data_len -= cs.optionalPaddingBits() / 8;
-
- rdbi->data_len = data_len;
- rdbi->bsn = 0;
- rdbi->ti = 0;
- rdbi->e = 1;
- rdbi->cv = 15;
- rdbi->pi = 0;
- rdbi->spb = 0;
-}
-
-unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, int punct, int punct2,
- int with_padding)
-{
- switch (GprsCodingScheme::Scheme(cs)) {
- case GprsCodingScheme::MCS1: return 0b1011 + punct % 2;
- case GprsCodingScheme::MCS2: return 0b1001 + punct % 2;
- case GprsCodingScheme::MCS3: return (with_padding ? 0b0110 : 0b0011) +
- punct % 3;
- case GprsCodingScheme::MCS4: return 0b0000 + punct % 3;
- case GprsCodingScheme::MCS5: return 0b100 + punct % 2;
- case GprsCodingScheme::MCS6: return (with_padding ? 0b010 : 0b000) +
- punct % 2;
- case GprsCodingScheme::MCS7: return 0b10100 + 3 * (punct % 3) + punct2 % 3;
- case GprsCodingScheme::MCS8: return 0b01011 + 3 * (punct % 3) + punct2 % 3;
- case GprsCodingScheme::MCS9: return 0b00000 + 4 * (punct % 3) + punct2 % 3;
- default: ;
- }
-
- return -1;
-}
-
-void gprs_rlc_mcs_cps_decode(unsigned int cps,
- GprsCodingScheme cs, int *punct, int *punct2, int *with_padding)
-{
- *punct2 = -1;
- *with_padding = 0;
-
- switch (GprsCodingScheme::Scheme(cs)) {
- case GprsCodingScheme::MCS1:
- cps -= 0b1011; *punct = cps % 2; break;
- case GprsCodingScheme::MCS2:
- cps -= 0b1001; *punct = cps % 2; break;
- case GprsCodingScheme::MCS3:
- cps -= 0b0011; *punct = cps % 3; *with_padding = cps >= 3; break;
- case GprsCodingScheme::MCS4:
- cps -= 0b0000; *punct = cps % 3; break;
- case GprsCodingScheme::MCS5:
- cps -= 0b100; *punct = cps % 2; break;
- case GprsCodingScheme::MCS6:
- cps -= 0b000; *punct = cps % 2; *with_padding = cps >= 2; break;
- case GprsCodingScheme::MCS7:
- cps -= 0b10100; *punct = cps / 3; *punct2 = cps % 3; break;
- case GprsCodingScheme::MCS8:
- cps -= 0b01011; *punct = cps / 3; *punct2 = cps % 3; break;
- case GprsCodingScheme::MCS9:
- cps -= 0b00000; *punct = cps / 4; *punct2 = cps % 3; break;
- default: ;
- }
-}