Modified gprs_rlcmac_data_block_parse() function.

Changed the internal logic of the function. Fixed handling for case with several LLC PDU in one data block.
This commit is contained in:
Ivan Kluchnikov 2012-06-05 16:56:27 +04:00
parent b2b8100499
commit bceb3fbf29
2 changed files with 68 additions and 37 deletions

View File

@ -424,56 +424,86 @@ void gprs_rlcmac_tx_ul_ack(uint8_t tfi, uint32_t tlli, RlcMacUplinkDataBlock_t *
void gprs_rlcmac_data_block_parse(gprs_rlcmac_tbf* tbf, RlcMacUplinkDataBlock_t * ul_data_block)
{
unsigned block_data_len = 0;
unsigned data_octet_num = 0;
// 1. Count the number of octets in header and number of LLC PDU in uplink data block.
unsigned data_block_hdr_len = 3; // uplink data block header length: 3 mandatory octets
unsigned llc_pdu_num = 0; // number of LLC PDU in data block
if (ul_data_block->E_1 == 0) // Extension octet follows immediately
{
block_data_len = ul_data_block->LENGTH_INDICATOR[0];
unsigned i = -1;
do
{
i++;
data_block_hdr_len += 1;
llc_pdu_num++;
// New LLC PDU starts after the current LLC PDU and continues until
// the end of the RLC information field, no more extension octets.
if ((ul_data_block->M[0] == 1)&&(ul_data_block->E[0] == 1))
if ((ul_data_block->M[i] == 1)&&(ul_data_block->E[i] == 1))
{
for (unsigned i = tbf->data_index; i < tbf->data_index + block_data_len; i++)
{
tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
data_octet_num++;
}
tbf->data_index += block_data_len;
gsmtap_send_llc(tbf->rlc_data, tbf->data_index);
gprs_rlcmac_tx_ul_ud(tbf);
tbf->data_index = 0;
block_data_len = 19 - block_data_len;
if(ul_data_block->TI == 1) // TLLI field is present
block_data_len -= 4;
for (unsigned i = tbf->data_index; i < tbf->data_index + block_data_len; i++)
{
tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
data_octet_num++;
}
tbf->data_index += block_data_len;
return;
llc_pdu_num++;
}
} while(ul_data_block->E[i] == 0); // there is another extension octet, which delimits the new LLC PDU
}
else
{
block_data_len = 20; // RLC data length without 3 header octets.
llc_pdu_num++;
}
if(ul_data_block->TI == 1) // TLLI field is present
{
tbf->tlli = ul_data_block->TLLI;
block_data_len -= 4; // TLLI length
data_block_hdr_len += 4; // TLLI length : 4 octets
if (ul_data_block->PI == 1) // PFI is present if TI field indicates presence of TLLI
{
block_data_len -= 1; // PFI length
}
data_block_hdr_len += 1; // PFI length : 1 octet
}
}
for (unsigned i = tbf->data_index; i < tbf->data_index + block_data_len; i++)
// 2. Extract all LLC PDU from uplink data block and send them to SGSN.
unsigned llc_pdu_len = 0;
unsigned data_octet_num = 0;
for (unsigned num = 0; num < llc_pdu_num; num ++)
{
if (ul_data_block->E_1 == 0) // Extension octet follows immediately
{
llc_pdu_len = ul_data_block->LENGTH_INDICATOR[num];
}
else
{
llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len;
}
for (unsigned i = tbf->data_index; i < tbf->data_index + llc_pdu_len; i++)
{
tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
data_octet_num++;
}
tbf->data_index += block_data_len;
tbf->data_index += llc_pdu_len;
if (ul_data_block->E_1 == 0) // Extension octet follows immediately
{
// New LLC PDU starts after the current LLC PDU
if (ul_data_block->M[num] == 1)
{
gsmtap_send_llc(tbf->rlc_data, tbf->data_index);
gprs_rlcmac_tx_ul_ud(tbf);
tbf->data_index = 0;
// New LLC PDU continues until the end of the RLC information field, no more extension octets.
if ((ul_data_block->E[num] == 1))
{
llc_pdu_len = UL_RLC_DATA_BLOCK_LEN - data_block_hdr_len - data_octet_num;
for (unsigned i = tbf->data_index; i < tbf->data_index + llc_pdu_len; i++)
{
tbf->rlc_data[i] = ul_data_block->RLC_DATA[data_octet_num];
data_octet_num++;
}
tbf->data_index += llc_pdu_len;
num++;
}
}
}
}
}
/* Received Uplink RLC data block. */

View File

@ -30,6 +30,7 @@ extern "C" {
}
#define LLC_MAX_LEN 1543
#define UL_RLC_DATA_BLOCK_LEN 23
enum gprs_rlcmac_tbf_state {
GPRS_RLCMAC_WAIT_DATA_SEQ_START,