Commit ca2aeacc authored by hbilel's avatar hbilel

BSR and MAC multiplexing fixes

parent 7637ed26
...@@ -133,12 +133,18 @@ ...@@ -133,12 +133,18 @@
/*!\brief maximum value for channel quality indicator */ /*!\brief maximum value for channel quality indicator */
#define MAX_CQI_VALUE 15 #define MAX_CQI_VALUE 15
//if value equal oxFFFF means counters are NOT active /*!\brief value for indicating BSR Timer is not running */
#define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) #define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF)
#define LCID_EMPTY 0 #define LCID_EMPTY 0
#define LCID_NOT_EMPTY 1 #define LCID_NOT_EMPTY 1
/*!\brief minimum RLC PDU size to be transmitted = min RLC Status PDU or RLC UM PDU SN 5 bits */
#define MIN_RLC_PDU_SIZE (2)
/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */
#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE)
/* /*
* eNB part * eNB part
*/ */
......
...@@ -1245,13 +1245,12 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1245,13 +1245,12 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
{ {
mac_rlc_status_resp_t rlc_status; mac_rlc_status_resp_t rlc_status;
uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0,dtch_header_len_last=0; uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ;
uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0; uint16_t buflen_remain = 0;
//TO DO
// uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ;
uint8_t bsr_len=0,bsr_ce_len=0,bsr_header_len=0; uint8_t bsr_len=0,bsr_ce_len=0,bsr_header_len=0;
uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0; uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
uint8_t lcid=0; uint8_t lcid=0;
boolean_t is_lcid_processed = FALSE;
uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t payload_offset=0,num_sdus=0; uint8_t payload_offset=0,num_sdus=0;
...@@ -1267,7 +1266,6 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1267,7 +1266,6 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
unsigned short short_padding=0, post_padding=0, padding_len=0; unsigned short short_padding=0, post_padding=0, padding_len=0;
int j; // used for padding int j; // used for padding
// Compute header length // Compute header length
int all_pdu_len;
int lcg_id = 0; int lcg_id = 0;
int lcg_id_bsr_trunc = 0; int lcg_id_bsr_trunc = 0;
int highest_priority = 16; int highest_priority = 16;
...@@ -1304,10 +1302,6 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1304,10 +1302,6 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
} }
#endif #endif
dcch_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
dcch1_header_len=2;//sizeof(SCH_SUBHEADER_SHORT);
// hypo length,in case of long header skip the padding byte
dtch_header_len=(buflen > 128 ) ? 3 : 2 ; //sizeof(SCH_SUBHEADER_LONG)-1 : sizeof(SCH_SUBHEADER_SHORT);
bsr_header_len = 0; bsr_header_len = 0;
phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED); phr_header_len = 1;//sizeof(SCH_SUBHEADER_FIXED);
...@@ -1385,64 +1379,74 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1385,64 +1379,74 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
// check for UL bandwidth requests and add SR control element // check for UL bandwidth requests and add SR control element
// Check for DCCH first // Check for DCCH first
// TO DO: Unrool the loop to do it at least once to avoid the if num_sdu
for (lcid=DCCH; lcid < DTCH ; lcid++) {
if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH] == LCID_NOT_EMPTY) { is_lcid_processed = FALSE;
//Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
//Adjust at the end of the loop
while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total + 1);
//It is not necessary to get RLC status again, it was done in ue_scheduler and stored
//for sanity keep it and check, to be removed if OK
rlc_status = mac_rlc_status_ind(module_idP, rlc_status = mac_rlc_status_ind(module_idP,
UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].crnti,
eNB_index, eNB_index,
frameP, frameP,
ENB_FLAG_NO, ENB_FLAG_NO,
MBMS_FLAG_NO, // eNB_index MBMS_FLAG_NO, // eNB_index
DCCH, lcid,
(buflen-dcch_header_len-bsr_len-phr_len)); buflen_remain);
AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d\n",
lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer);
if (rlc_status.bytes_in_buffer > 0) {
AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d\n",
DCCH,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH],rlc_status.bytes_in_buffer);
LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RLC SRB1 has %d bytes to " LOG_D(MAC, "[UE %d] Frame %d : UL-DCCH -> ULSCH, RLC SRB%d has %d bytes to "
"send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
module_idP,frameP, UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH],buflen,bsr_len,phr_len,sdu_length_total,dcch_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]]); module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
sdu_lengths[0] += mac_rlc_data_req(module_idP, sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].crnti,
eNB_index, eNB_index,
frameP, frameP,
ENB_FLAG_NO, ENB_FLAG_NO,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH, lcid,
(char *)&ulsch_buff[sdu_lengths[0]]); (char *)&ulsch_buff[sdu_length_total]);
AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH] >= sdu_lengths[0], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
DCCH,sdu_lengths[0],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH]); lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
sdu_length_total += sdu_lengths[0]; sdu_length_total += sdu_lengths[num_sdus];
sdu_lcids[0] = DCCH; sdu_lcids[num_sdus] = lcid;
LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for SRB1\n",module_idP,sdu_lengths[0]); LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for SRB%d\n",module_idP,sdu_lengths[num_sdus],lcid);
num_sdus = 1;
//header_len +=2; //header_len +=2;
// update LCID remain buffer // update LCID remain buffer
UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH] -= sdu_lengths[0]; UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus];
/* Update BSR : substract transmitted data */ /* Update BSR : substract transmitted data */
if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] >= sdu_lengths[0]){ if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] -= sdu_lengths[0] ; UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
} }
else { else {
LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n", LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n",
module_idP,frameP,subframe, module_idP,frameP,subframe,
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]], UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH], UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
sdu_lengths[0],DCCH); sdu_lengths[num_sdus],lcid);
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] = 0; UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] = 0;
} }
//Update the number of LCGID with data as BSR shall reflect status after BSR transmission //Update the number of LCGID with data as BSR shall reflect status after BSR transmission
if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] == 0)) if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0))
{ {
num_lcg_id_with_data --; num_lcg_id_with_data --;
// Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1 // Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
...@@ -1454,113 +1458,54 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1454,113 +1458,54 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
} }
UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH] = LCID_EMPTY; //Update total MAC Header size for RLC PDUs and save last one
total_rlc_pdu_header_len += rlc_pdu_header_len_last;
if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
//No more remaining TBS after this PDU
//exit the function
rlc_pdu_header_len_last = 1;
is_lcid_processed = TRUE;
} }
else { else {
dcch_header_len=0; rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
num_sdus = 0;
}
// if the RLC AM is used, then RLC will only provide 2 bytes for ACK
// in this case, we sould add bsr
// DCCH1
if (UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH1] == LCID_NOT_EMPTY) {
//It is not necessary to get RLC status again, it was done in ue_scheduler and stored
//for sanity keep it and check, to be removed if OK
rlc_status = mac_rlc_status_ind(module_idP,
UE_mac_inst[module_idP].crnti,
eNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO, // eNB_index
DCCH1,
(buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-sdu_length_total));
AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH1] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d\n", //Change to 1 byte if it does not fit in the TBS, ie last PDU
DCCH1,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH1],rlc_status.bytes_in_buffer); if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
rlc_pdu_header_len_last = 1;
LOG_D(MAC,"[UE %d] Frame %d subframe %d: UL-DCCH1 -> ULSCH, RLC SRB2 has %d bytes to" is_lcid_processed = TRUE;
" send (Transport Block size %d BSR size=%d PHR=%d SRB1 Hdr %d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", }
module_idP,frameP, subframe, UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH1],buflen,bsr_len,phr_len,dcch_header_len,sdu_length_total,dcch1_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1]]);
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
UE_mac_inst[module_idP].crnti,
eNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
DCCH1,
(char *)&ulsch_buff[sdu_lengths[num_sdus]]);
AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH1] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", //Update number of SDU
DCCH1,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH1]); num_sdus ++;
}
sdu_length_total += sdu_lengths[num_sdus]; } //end if (rlc_status.bytes_in_buffer > 0)
sdu_lcids[num_sdus] = DCCH1;
LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU Got %d bytes for SRB2\n",module_idP,sdu_lengths[num_sdus]);
//dcch_header_len +=2; // include dcch1
UE_mac_inst[module_idP].scheduling_info.LCID_status[DCCH1] = LCID_EMPTY;
UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[DCCH1] -= sdu_lengths[num_sdus];
/* Update BSR : substract transmitted data */
if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1]] >= sdu_lengths[num_sdus]){
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1]] -= sdu_lengths[num_sdus];
}
else { else {
LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n", // Switch to next LCID or exit the whole loop
module_idP,frameP,subframe, is_lcid_processed = TRUE;
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1]],
UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1],
sdu_lengths[num_sdus],DCCH1);
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1]] = 0;
}
//Update the number of LCGID with data as BSR shall reflect status after BSR transmission
if ((num_lcg_id_with_data > 1) && (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH1]] == 0))
{
num_lcg_id_with_data --;
// Change BSR size to BSR SHORT if num_lcg_id_with_data becomes to 1
if ((bsr_len) && (num_lcg_id_with_data == 1))
{
bsr_ce_len = sizeof(BSR_SHORT);
bsr_len = bsr_ce_len + bsr_header_len;
} }
} }
num_sdus++; UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
} else {
dcch1_header_len =0;
} }
}
dtch_header_len=0; // Now Check for DTCH first
dtch_header_len_last=0; // TO DO: do it according to Logical Channel Prioritization if at least 2 DTCH
for (lcid=DTCH; lcid < MAX_NUM_LCID ; lcid++){ for (lcid=DTCH; lcid < MAX_NUM_LCID ; lcid++) {
dtch_header_len+=3; if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
dtch_header_len_last=3;
all_pdu_len = bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len+sdu_length_total; is_lcid_processed = FALSE;
if ((UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) &&
(all_pdu_len <= buflen)) {
AssertFatal (UE_mac_inst[module_idP].logicalChannelConfig[lcid] != NULL, "LCID (%d) is not active!\n", lcid); //Multiplex all available DTCH RLC PDUs considering to multiplex the last PDU each time for maximize the data
//Adjust at the end of the loop
while ((!is_lcid_processed) && (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total + 1);
// optimize the dtch header lenght
//if ((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] > 128) &&
/* if (((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH] >= 128) &&
((UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DTCH]+bsr_len+phr_len+dcch_header_len+dcch1_header_len+dtch_header_len) > buflen)&&
buflen >=128 ))
dtch_header_len = 3;//sizeof(SCH_SUBHEADER_LONG);
else
dtch_header_len = 2;//sizeof(SCH_SUBHEADER_SHORT);
*/
//It is not necessary to get RLC status again, it was done in ue_scheduler and stored
//for sanity keep it and check, to be removed if OK
rlc_status = mac_rlc_status_ind(module_idP, rlc_status = mac_rlc_status_ind(module_idP,
UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].crnti,
eNB_index, eNB_index,
...@@ -1568,45 +1513,46 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1568,45 +1513,46 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
ENB_FLAG_NO, ENB_FLAG_NO,
MBMS_FLAG_NO, // eNB_index MBMS_FLAG_NO, // eNB_index
lcid, lcid,
buflen-all_pdu_len); buflen_remain);
AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d\n", AssertFatal ( UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= rlc_status.bytes_in_buffer, "Inconsistent BO! for LCID=%d MAC=%d RLC=%d\n",
lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer); lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer);
LOG_D(MAC,"[UE %d] Frame %d subframe %d: UL-DTCH -> ULSCH%d, %d bytes to send (Transport Block size %d, mac header len %d, BSR byte before Tx=%d)\n",
module_idP,frameP, subframe,lcid, rlc_status.bytes_in_buffer,buflen,dtch_header_len, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
if (rlc_status.bytes_in_buffer > 0) { if (rlc_status.bytes_in_buffer > 0) {
LOG_D(MAC, "[UE %d] Frame %d : UL-DTCH -> ULSCH, RLC LCID%d has %d bytes to "
"send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n",
module_idP,frameP, lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],buflen,bsr_len,phr_len,sdu_length_total,total_rlc_pdu_header_len,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].crnti,
eNB_index, eNB_index,
frameP, frameP,
ENB_FLAG_NO, ENB_FLAG_NO,
MBMS_FLAG_NO, // eNB_index MBMS_FLAG_NO,
lcid, lcid,
(char *)&ulsch_buff[sdu_length_total]); (char *)&ulsch_buff[sdu_length_total]);
AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n", AssertFatal (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]); lcid,sdu_lengths[num_sdus],UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
//adjust dtch header
LOG_D(MAC,"[UE %d] Frame %d Subframe %d TX Got %d bytes for DTCH%d New BSR bytes=%d\n",module_idP,frameP,subframe,sdu_lengths[num_sdus],lcid,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
sdu_lcids[num_sdus] = lcid;
sdu_length_total += sdu_lengths[num_sdus];
if (sdu_lengths[num_sdus] < 128) {
dtch_header_len --;
dtch_header_len_last --;
}
/* Update BSR : substract transmitted data */ sdu_length_total += sdu_lengths[num_sdus];
sdu_lcids[num_sdus] = lcid;
LOG_D(MAC,"[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LCID%d\n",module_idP,sdu_lengths[num_sdus],lcid);
//header_len +=2;
// update LCID remain buffer
UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus]; UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] -= sdu_lengths[num_sdus];
/* Update BSR : substract transmitted data */
if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){ if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] >= sdu_lengths[num_sdus]){
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus]; UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
} }
else { else {
LOG_I(MAC, "[UE %d] Frame %d Subframe %d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n", LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Buffer occupancy =%d for LCGID%d is lower than data transmitted=%d for LCID%d\n",
module_idP,frameP,subframe, module_idP,frameP,subframe,
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]],
UE_mac_inst[module_idP].scheduling_info.LCGID[lcid], UE_mac_inst[module_idP].scheduling_info.LCGID[lcid],
...@@ -1624,20 +1570,43 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1624,20 +1570,43 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
bsr_ce_len = sizeof(BSR_SHORT); bsr_ce_len = sizeof(BSR_SHORT);
bsr_len = bsr_ce_len + bsr_header_len; bsr_len = bsr_ce_len + bsr_header_len;
} }
} }
//Update total MAC Header size for RLC PDUs and save last one
total_rlc_pdu_header_len += rlc_pdu_header_len_last;
num_sdus++; if (buflen == (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1)) {
//No more remaining TBS after this PDU
//exit the function
rlc_pdu_header_len_last = 1;
is_lcid_processed = TRUE;
}
else {
rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
} else { //Change to 1 byte if it does not fit in the TBS, ie last PDU
dtch_header_len -= 3; if (buflen <= (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) {
rlc_pdu_header_len_last = 1;
is_lcid_processed = TRUE;
} }
UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
} else { // no rlc pdu : generate the dummy header //Update number of SDU
dtch_header_len -= 3; num_sdus ++;
}
} //end if (rlc_status.bytes_in_buffer > 0)
else {
// Switch to next LCID or exit the whole loop
is_lcid_processed = TRUE;
} }
} }
UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
}
}
//lcgid= get_bsr_lcgid(module_idP); //lcgid= get_bsr_lcgid(module_idP);
// Compute BSR Values and update Nb LCGID with data after multiplexing // Compute BSR Values and update Nb LCGID with data after multiplexing
...@@ -1687,28 +1656,22 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1687,28 +1656,22 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", module_idP,frameP,bsr_s, bsr_l, phr_p); LOG_T(MAC,"[UE %d] Frame %d: bsr s %p bsr_l %p, phr_p %p\n", module_idP,frameP,bsr_s, bsr_l, phr_p);
if (dtch_header_len == 0 )
dtch_header_len_last =0;
// adjust the header length
dcch_header_len_tmp = dcch_header_len;
dtch_header_len_tmp = dtch_header_len;
if (dtch_header_len==0) {
dcch_header_len = (dcch_header_len>0)? 1: dcch_header_len;
} else {
dtch_header_len_last-=1;
dtch_header_len= (dtch_header_len >0)? dtch_header_len - dtch_header_len_last : dtch_header_len;
}
// Check BSR padding: it is done after PHR according to Logical Channel Prioritization order // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order
// Check for max padding size, ie MAC Hdr for last RLC PDU = 1
/* For Padding BSR: /* For Padding BSR:
- if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader: - if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader:
- if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission; - if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission;
- else report Short BSR. - else report Short BSR.
- else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR. - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR.
*/ */
padding_len = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total; if (sdu_length_total) {
padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
}
else {
padding_len = buflen - (bsr_len + phr_len);
}
if ((padding_len) && (bsr_len == 0)) if ((padding_len) && (bsr_len == 0))
{ {
...@@ -1766,7 +1729,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1766,7 +1729,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2]; bsr_l->Buffer_size2 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID2];
bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3]; bsr_l->Buffer_size3 = UE_mac_inst[module_idP].scheduling_info.BSR[LCGID3];
LOG_D(MAC, "[UE %d] Frame %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP, LOG_I(MAC, "[UE %d] Frame %d BSR Trig=%d report long BSR (level LCGID0 %d,level LCGID1 %d,level LCGID2 %d,level LCGID3 %d)\n", module_idP,frameP,
UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].BSR_reporting_active,
UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0], UE_mac_inst[module_idP].scheduling_info.BSR[LCGID0],
UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1], UE_mac_inst[module_idP].scheduling_info.BSR[LCGID1],
...@@ -1781,7 +1744,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1781,7 +1744,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
bsr_t->LCGID = lcg_id_bsr_trunc; bsr_t->LCGID = lcg_id_bsr_trunc;
bsr_t->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc]; bsr_t->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];
LOG_D(MAC,"[UE %d] Frame %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n", LOG_I(MAC,"[UE %d] Frame %d BSR Trig=%d report TRUNCATED BSR with level %d for LCGID %d\n",
module_idP, frameP, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc); module_idP, frameP, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
} }
...@@ -1791,31 +1754,49 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1791,31 +1754,49 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
bsr_s->LCGID = lcg_id_bsr_trunc; bsr_s->LCGID = lcg_id_bsr_trunc;
bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc]; bsr_s->Buffer_size = UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc];
LOG_D(MAC,"[UE %d] Frame %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n", LOG_I(MAC,"[UE %d] Frame %d BSR Trig=%d report SHORT BSR with level %d for LCGID %d\n",
module_idP, frameP, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc); module_idP, frameP, UE_mac_inst[module_idP].BSR_reporting_active, UE_mac_inst[module_idP].scheduling_info.BSR[lcg_id_bsr_trunc],lcg_id_bsr_trunc);
} }
} }
// 1-bit padding or 2-bit padding special padding subheader // 1-bit padding or 2-bit padding special padding subheader
padding_len = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total; // Check for max padding size, ie MAC Hdr for last RLC PDU = 1
if (sdu_length_total) {
padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
}
else {
padding_len = buflen - (bsr_len + phr_len);
}
if (padding_len <= 2) { if (padding_len <= 2) {
short_padding = padding_len; short_padding = padding_len;
// only add padding header // only add padding header
post_padding = 0; post_padding = 0;
} else { //update total MAC Hdr size for RLC data
if (sdu_length_total) {
rlc_pdu_header_len_last = 1;
total_rlc_pdu_header_len ++;
}
}
else if (sdu_length_total) {
total_rlc_pdu_header_len += rlc_pdu_header_len_last;
post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
// If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding
if (post_padding == 0) {
total_rlc_pdu_header_len -= rlc_pdu_header_len_last;
padding_len = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
short_padding = padding_len;
total_rlc_pdu_header_len ++;
}
}
else {
if (padding_len == buflen) {// nona mac pdu if (padding_len == buflen) {// nona mac pdu
*access_mode=CANCELED_ACCESS; *access_mode=CANCELED_ACCESS;
} }
short_padding = 0; short_padding = 0;
if (dtch_header_len==0) { post_padding = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
dcch_header_len = dcch_header_len_tmp;
} else {
dtch_header_len= dtch_header_len_tmp;
}
post_padding = buflen-bsr_len-phr_len-dcch_header_len-dcch1_header_len-dtch_header_len-sdu_length_total -1 ;
} }
// Generate header // Generate header
...@@ -1834,11 +1815,13 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1834,11 +1815,13 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
post_padding); // long_bsr post_padding); // long_bsr
LOG_D(MAC, LOG_D(MAC,
"[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, dcch_header_len %d, dtch_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n", "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, total_rlc_pdu_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n",
module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, dcch_header_len, dtch_header_len, module_idP,buflen, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],payload_offset, total_rlc_pdu_header_len,
short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset); short_padding,post_padding, bsr_len, phr_len,buflen-sdu_length_total-payload_offset);
// cycle through SDUs and place in ulsch_buffer // cycle through SDUs and place in ulsch_buffer
if (sdu_length_total) {
memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total); memcpy(&ulsch_buffer[payload_offset],ulsch_buff,sdu_length_total);
}
// fill remainder of DLSCH with random data // fill remainder of DLSCH with random data
for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) { for (j=0; j<(buflen-sdu_length_total-payload_offset); j++) {
...@@ -1852,10 +1835,13 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1852,10 +1835,13 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
/* Actions when a BSR is sent */ /* Actions when a BSR is sent */
if (bsr_ce_len) if (bsr_ce_len)
{ {
LOG_D(MAC,"[UE %d] MAC BSR Sent !! bsr (ce%d,hdr%d) buff_len %d\n",
module_idP, bsr_ce_len, bsr_header_len, buflen);
// Reset ReTx BSR Timer // Reset ReTx BSR Timer
UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer); UE_mac_inst[module_idP].scheduling_info.retxBSR_SF = get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
LOG_I(MAC,"[UE %d] MAC ReTx BSR Timer Reset =%d\n", LOG_D(MAC,"[UE %d] MAC ReTx BSR Timer Reset =%d\n",
UE_mac_inst[module_idP].scheduling_info.retxBSR_SF); UE_mac_inst[module_idP].scheduling_info.retxBSR_SF);
// Reset Periodic Timer except when BSR is truncated // Reset Periodic Timer except when BSR is truncated
...@@ -1863,15 +1849,11 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf ...@@ -1863,15 +1849,11 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
{ {
UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer); UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF = get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
LOG_I(MAC,"[UE %d] MAC Periodic BSR Timer Reset =%d\n", LOG_D(MAC,"[UE %d] MAC Periodic BSR Timer Reset =%d\n",
UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF); UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF);
} }
LOG_I(MAC,"[UE %d] MAC BSR Triggered !! bsr (ce%d,hdr%d) buff_len %d\n",
module_idP, bsr_ce_len, bsr_header_len, buflen);
// Reset BSR Trigger flags // Reset BSR Trigger flags
UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE; UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
} }
......
...@@ -341,6 +341,7 @@ rlc_am_get_pdus ( ...@@ -341,6 +341,7 @@ rlc_am_get_pdus (
if (pdu) { if (pdu) {
list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer); list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
rlc_pP->status_requested = 0; rlc_pP->status_requested = 0;
rlc_pP->status_buffer_occupancy = 0;
rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP); rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment