diff options
Diffstat (limited to 'src/rlc.cpp')
-rw-r--r-- | src/rlc.cpp | 733 |
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: ; - } -} |