Modified gprs_rlcmac_segment_llc_pdu() and gprs_rlcmac_tx_dl_data_block() functions.

Changed the internal logic of the functions. Implemented singular case of using Length Indicator field, which described in 10.4.14 TS 44.060.
This commit is contained in:
Ivan Kluchnikov 2012-06-07 01:12:29 +04:00
parent bceb3fbf29
commit e3594236ff
1 changed files with 62 additions and 25 deletions

View File

@ -673,23 +673,41 @@ void gprs_rlcmac_tx_dl_data_block(uint32_t tlli, uint8_t tfi, uint8_t *pdu, int
data_block->TFI = tfi; data_block->TFI = tfi;
data_block->FBI = fbi; data_block->FBI = fbi;
data_block->BSN = bsn; data_block->BSN = bsn;
if ((end_index - start_index) < 19) {
// Last RLC data block of current LLC PDU
if (fbi == 1)
{
data_block->E_1 = 0; data_block->E_1 = 0;
data_block->LENGTH_INDICATOR[0] = end_index-start_index;
data_block->M[0] = 0; data_block->M[0] = 0;
data_block->E[0] = 1; data_block->E[0] = 1;
spare_len = 19 - data_block->LENGTH_INDICATOR[0]; // Singular case, TS 44.060 10.4.14
} else { if ((end_index - start_index) == (BLOCK_LEN - 3))
{
data_block->FBI = 0;
data_block->LENGTH_INDICATOR[0] = 0;
spare_len = 0;
end_index--;
}
else
{
data_block->LENGTH_INDICATOR[0] = end_index-start_index;
spare_len = BLOCK_LEN - 4 - data_block->LENGTH_INDICATOR[0];
}
}
else
{
data_block->E_1 = 1; data_block->E_1 = 1;
} }
int j = 0;
int data_oct_num = 0;
int i = 0; int i = 0;
// Pack LLC PDU into RLC data field
for(i = start_index; i < end_index; i++) { for(i = start_index; i < end_index; i++) {
data_block->RLC_DATA[j] = pdu[i]; data_block->RLC_DATA[data_oct_num] = pdu[i];
j++; data_oct_num++;
} }
// Fill spare bits
for(i = j; i < j + spare_len; i++) { for(i = data_oct_num; i < data_oct_num + spare_len; i++) {
data_block->RLC_DATA[i] = 0x2b; data_block->RLC_DATA[i] = 0x2b;
} }
LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Downlink Data Block\n"); LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Downlink Data Block\n");
@ -699,28 +717,51 @@ void gprs_rlcmac_tx_dl_data_block(uint32_t tlli, uint8_t tfi, uint8_t *pdu, int
free(data_block); free(data_block);
pcu_l1if_tx(data_block_vector, GsmL1_Sapi_Pdtch); pcu_l1if_tx(data_block_vector, GsmL1_Sapi_Pdtch);
bitvec_free(data_block_vector); bitvec_free(data_block_vector);
// Singular case, TS 44.060 10.4.14
if ((fbi == 1)&&((end_index + 1 - start_index) == (BLOCK_LEN - 3)))
{
gprs_rlcmac_tx_dl_data_block(tlli, tfi, pdu, end_index, end_index+1, bsn+1, fbi);
}
} }
int gprs_rlcmac_segment_llc_pdu(struct gprs_rlcmac_tbf *tbf) int gprs_rlcmac_segment_llc_pdu(struct gprs_rlcmac_tbf *tbf)
{ {
int fbi = 0; int fbi = 0;
int num_blocks = 0; int bsn = 0;
int i; int num_blocks = 0; // number of RLC data blocks necessary for LLC PDU transmission
if (tbf->data_index > BLOCK_DATA_LEN + 1)
// LLC PDU fits into one RLC data block with optional LI field.
if (tbf->data_index < BLOCK_LEN - 4)
{ {
int block_data_len = BLOCK_DATA_LEN; fbi = 1;
num_blocks = tbf->data_index/BLOCK_DATA_LEN; gprs_rlcmac_tx_dl_data_block(tbf->tlli, tbf->tfi, tbf->rlc_data, 0, tbf->data_index, bsn, fbi);
int rest_len = tbf->data_index%BLOCK_DATA_LEN; }
int start_index = 0; // Necessary several RLC data blocks for transmit LLC PDU.
int end_index = 0; else
if (tbf->data_index%BLOCK_DATA_LEN > 0) {
// length of RLC data field in block (no optional octets)
int block_data_len = BLOCK_LEN - 3;
// number of blocks with 20 octets length RLC data field
num_blocks = tbf->data_index/block_data_len;
// rest of LLC PDU, which doesn't fit into data blocks with 20 octets RLC data field
int rest_len = tbf->data_index%BLOCK_DATA_LEN;
if (rest_len > 0)
{ {
// add one block for transmission rest of LLC PDU
num_blocks++; num_blocks++;
} }
for (i = 0; i < num_blocks; i++)
int start_index = 0;
int end_index = 0;
// Transmit all RLC data blocks of current LLC PDU to MS
for (bsn = 0; bsn < num_blocks; bsn++)
{ {
if (i == num_blocks-1) if (bsn == num_blocks-1)
{ {
if (rest_len > 0) if (rest_len > 0)
{ {
@ -729,14 +770,10 @@ int gprs_rlcmac_segment_llc_pdu(struct gprs_rlcmac_tbf *tbf)
fbi = 1; fbi = 1;
} }
end_index = start_index + block_data_len; end_index = start_index + block_data_len;
gprs_rlcmac_tx_dl_data_block(tbf->tlli, tbf->tfi, tbf->rlc_data, start_index, end_index, i, fbi); gprs_rlcmac_tx_dl_data_block(tbf->tlli, tbf->tfi, tbf->rlc_data, start_index, end_index, bsn, fbi);
start_index += block_data_len; start_index += block_data_len;
} }
} }
else
{
gprs_rlcmac_tx_dl_data_block(tbf->tlli, tbf->tfi, tbf->rlc_data, 0, tbf->data_index, 0, 1);
}
} }
/* Send Uplink unit-data to SGSN. */ /* Send Uplink unit-data to SGSN. */