Commit fbe109a6 authored by fnabet's avatar fnabet

RLC/MAC UE interface changes for Tx and adapt to eNB

parent 1a591da2
......@@ -388,9 +388,9 @@ typedef struct {
struct PMCH_InfoList_r9 *pmch_InfoList
#endif
);
unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, char*);
unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, const unsigned int,char*);
void (*mac_rlc_data_ind)(module_id_t, logical_chan_id_t, char*, tb_size_t, num_tb_t, crc_t* );
mac_rlc_status_resp_t (*mac_rlc_status_ind) (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP,
mac_rlc_status_resp_t (*mac_rlc_status_ind) (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, sub_frame_t subframeP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP,
logical_chan_id_t channel_idP, tb_size_t tb_sizeP);
signed int (*rrc_rlc_data_req)(module_id_t, rb_id_t, mui_t, confirm_t, sdu_size_t, char *);
void (*rrc_rlc_register_rrc) (void (*rrc_data_indP)(module_id_t , rb_id_t , sdu_size_t , char* ),
......
......@@ -562,14 +562,16 @@ int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) {
int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0);
uint16_t subframe = (uint16_t) flexran_get_current_subframe(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,subframe,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0);
return rlc_status.bytes_in_buffer;
}
int flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0);
uint16_t subframe = (uint16_t) flexran_get_current_subframe(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0);
return rlc_status.head_sdu_creation_time;
}
......
......@@ -821,6 +821,7 @@ schedule_ue_spec(
rnti,
module_idP,
frameP,
subframeP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
DCCH,
......@@ -839,6 +840,7 @@ schedule_ue_spec(
ENB_FLAG_YES,
MBMS_FLAG_NO,
DCCH,
TBS, //not used
(char *)&dlsch_buffer[0]);
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
......@@ -872,6 +874,7 @@ schedule_ue_spec(
rnti,
module_idP,
frameP,
subframeP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
DCCH+1,
......@@ -890,6 +893,7 @@ schedule_ue_spec(
ENB_FLAG_YES,
MBMS_FLAG_NO,
DCCH+1,
TBS, //not used
(char *)&dlsch_buffer[sdu_length_total]);
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
......@@ -932,6 +936,7 @@ schedule_ue_spec(
rnti,
module_idP,
frameP,
subframeP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
......@@ -949,6 +954,7 @@ schedule_ue_spec(
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
TBS, //not used
(char*)&dlsch_buffer[sdu_length_total]);
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
T_INT(harq_pid), T_INT(lcid), T_INT(sdu_lengths[num_sdus]));
......
......@@ -504,7 +504,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
module_idP,CC_id,frameP,MTCH,TBS,
TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
rlc_status = mac_rlc_status_ind(module_idP,0,frameP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH,
rlc_status = mac_rlc_status_ind(module_idP,0,frameP,subframeP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH,
TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
LOG_D(MAC,"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d\n",
MTCH,frameP,subframeP, rlc_status.bytes_in_buffer);
......@@ -521,6 +521,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
ENB_FLAG_YES,
MBMS_FLAG_YES,
MTCH,
0, //not used
(char*)&mch_buffer[sdu_length_total]);
//sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]);
LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",module_idP,CC_id,sdu_lengths[num_sdus],MTCH);
......
......@@ -174,6 +174,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
rnti,
mod_id,
frame,
subframe,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
......@@ -193,6 +194,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
rnti,
mod_id,
frame,
subframe,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
......@@ -209,6 +211,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
rlc_size, //not used
(char *)&dlsch_buffer[sdu_length_total]);
LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[j]);
......
......@@ -160,7 +160,7 @@ void _store_dlsch_buffer (module_id_t Mod_id,
for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels
rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
......@@ -1241,6 +1241,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
rnti,
mod_id,
frame,
subframe,
ENB_FLAG_YES,
MBMS_FLAG_NO,
j,
......
......@@ -109,7 +109,7 @@ void store_dlsch_buffer (module_id_t Mod_id,
for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels
rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
......
......@@ -394,7 +394,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
} else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) {
// This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example)
dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element
rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
DCCH,
6);
......@@ -409,6 +409,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,
eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
DCCH,
6, //not used
(char *)&ulsch_buff[0]);
LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
......
......@@ -1265,13 +1265,13 @@ unsigned char generate_ulsch_header(uint8_t *mac_header,
void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen, uint8_t *access_mode)
{
mac_rlc_status_resp_t rlc_status;
uint8_t total_rlc_pdu_header_len=0, rlc_pdu_header_len_last=0 ;
uint16_t buflen_remain = 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 lcid=0,lcid_rlc_pdu_count=0;
boolean_t is_lcid_processed = FALSE;
boolean_t is_all_lcid_processed = FALSE;
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 payload_offset=0,num_sdus=0;
......@@ -1291,6 +1291,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
int lcg_id_bsr_trunc = 0;
int highest_priority = 16;
int num_lcg_id_with_data = 0;
rlc_buffer_occupancy_t lcid_buffer_occupancy_old=0, lcid_buffer_occupancy_new=0;
LOG_D(MAC,"[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n",
module_idP, frameP, subframe, buflen);
......@@ -1400,16 +1401,32 @@ 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 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++) {
// TO DO: Multiplex in the order defined by the logical channel prioritization
for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid++) {
if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
is_lcid_processed = FALSE;
lcid_rlc_pdu_count = 0;
is_lcid_processed = FALSE;
lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP,
UE_mac_inst[module_idP].crnti,
eNB_index,
frameP,
subframe,
ENB_FLAG_NO,
lcid);
lcid_buffer_occupancy_new = lcid_buffer_occupancy_old;
AssertFatal (lcid_buffer_occupancy_new == UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid], "LCID=%d RLC has BO %d bytes but MAC has stored %d bytes\n",
lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid]);
AssertFatal (lcid_buffer_occupancy_new <= UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]], "LCID=%d RLC has more BO %d bytes than BSR = %d bytes\n",
lcid,lcid_buffer_occupancy_new,UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]]);
//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 + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
while ((!is_lcid_processed) && (lcid_buffer_occupancy_new) && (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
// Workaround for issue in OAI eNB or EPC which are not able to process SRB2 message multiplexed with SRB1 on the same MAC PDU
if ((usim_test == 0) && (lcid == DCCH1) && (lcid_rlc_pdu_count == 0) && (num_sdus)) {
......@@ -1420,253 +1437,103 @@ for (lcid=DCCH; lcid < DTCH ; lcid++) {
buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
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
lcid,
buflen_remain);
// Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO
if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] < rlc_status.bytes_in_buffer) {
LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n",
module_idP,frameP,subframe,
lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count);
// Skip multiplexing for the LCID
break;
}
/*
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 RLC PDU nb=%d Frame %d Subrame %d\n",
lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe);
*/
if (rlc_status.bytes_in_buffer > 0) {
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",
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,
UE_mac_inst[module_idP].crnti,
eNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
(char *)&ulsch_buff[sdu_length_total]);
LOG_D(MAC, "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %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,lcid_buffer_occupancy_new,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]]);
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]);
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,
lcid,
buflen_remain,
(char *)&ulsch_buff[sdu_length_total]);
AssertFatal (buflen_remain >= sdu_lengths[num_sdus], "LCID=%d RLC has segmented %d bytes but MAC has max=%d\n",
lcid,sdu_lengths[num_sdus],buflen_remain);
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 SRB%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];
/* 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]){
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
}
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",
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.LCGID[lcid],
sdu_lengths[num_sdus],lcid);
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
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 --;
// 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;
}
}
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 ;
//Change to 1 byte if it does not fit in the TBS, ie last PDU
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;
}
}
//Update number of SDU
num_sdus ++;
//Update total MAC Header size for RLC PDUs and save last one
total_rlc_pdu_header_len += rlc_pdu_header_len_last;
if (sdu_lengths[num_sdus])
{
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);
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;
is_all_lcid_processed = TRUE;
}
else {
rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128 ) ? 3 : 2 ;
//Change to 1 byte if it does not fit in the TBS, ie last PDU
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;
is_all_lcid_processed = TRUE;
}
}
//Update number of SDU
num_sdus ++;
//Update total MAC Header size for RLC PDUs and save last one
total_rlc_pdu_header_len += rlc_pdu_header_len_last;
lcid_rlc_pdu_count ++;
}
else
{
/* avoid infinite loop ... */
is_lcid_processed = TRUE;
}
} //end if (rlc_status.bytes_in_buffer > 0)
else {
// Switch to next LCID or exit the whole loop
is_lcid_processed = TRUE;
}
lcid_rlc_pdu_count ++;
}
/* Get updated BO after multiplexing this PDU */
lcid_buffer_occupancy_new = mac_rlc_get_buffer_occupancy_ind(module_idP,
UE_mac_inst[module_idP].crnti,
eNB_index,
frameP,
subframe,
ENB_FLAG_NO,
lcid);
UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
is_lcid_processed = (is_lcid_processed) || (lcid_buffer_occupancy_new <= 0);
}
}
// Now Check for DTCH first
// TO DO: do it according to Logical Channel Prioritization if at least 2 DTCH
for (lcid=DTCH; lcid < MAX_NUM_LCID ; lcid++) {
if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) {
//Update Buffer remain and BSR bytes after transmission
is_lcid_processed = FALSE;
lcid_rlc_pdu_count = 0;
AssertFatal (lcid_buffer_occupancy_new <= lcid_buffer_occupancy_old, "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n",
lcid_buffer_occupancy_new,lcid_buffer_occupancy_old,lcid,lcid_rlc_pdu_count,frameP,subframe);
//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 + sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) {
UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] = lcid_buffer_occupancy_new;
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] += (lcid_buffer_occupancy_new - lcid_buffer_occupancy_old);
buflen_remain = buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + sdu_length_total + 1);
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
lcid,
buflen_remain);
// Workaround for BO issue in RLC AM ReTx : RLC BO can not be bigger than stored MAC BO
if (UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid] < rlc_status.bytes_in_buffer) {
LOG_I(MAC, "[UE %d] Frame %d Subframe%d: WARNING Inconsistent BO! for LCID=%d MAC=%d RLC=%d RLC PDU nb=%d\n",
module_idP,frameP,subframe,
lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count);
// Skip multiplexing for the LCID
break;
}
/*
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 RLC PDU nb=%d Frame %d Subrame %d\n",
lcid,UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid],rlc_status.bytes_in_buffer,lcid_rlc_pdu_count,frameP,subframe);
*/
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,
UE_mac_inst[module_idP].crnti,
eNB_index,
frameP,
ENB_FLAG_NO,
MBMS_FLAG_NO,
lcid,
(char *)&ulsch_buff[sdu_length_total]);
AssertFatal (sdu_lengths[num_sdus] < MAX_ULSCH_PAYLOAD_BYTES, "LCID=%d RLC PDU size = %d is too big\n",
lcid,sdu_lengths[num_sdus]);
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]);
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];
/* 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]){
UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] -= sdu_lengths[num_sdus] ;
}
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",
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.LCGID[lcid],
sdu_lengths[num_sdus],lcid);
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
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))
//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[lcid]] == 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))
{
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;
}
bsr_ce_len = sizeof(BSR_SHORT);
bsr_len = bsr_ce_len + bsr_header_len;
}
}
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 ;
//Change to 1 byte if it does not fit in the TBS, ie last PDU
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;
}
}
//Update number of SDU
num_sdus ++;
//Update total MAC Header size for RLC PDUs and save last one
total_rlc_pdu_header_len += rlc_pdu_header_len_last;
} //end if (rlc_status.bytes_in_buffer > 0)
else {
// Switch to next LCID or exit the whole loop
is_lcid_processed = TRUE;
}
lcid_rlc_pdu_count ++;
UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
}
}
UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] = LCID_EMPTY;
}
}
//lcgid= get_bsr_lcgid(module_idP);
// Compute BSR Values and update Nb LCGID with data after multiplexing
num_lcg_id_with_data = 0;
......@@ -2396,7 +2263,7 @@ boolean_t update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subfra
lcgid_buffer_remain[lcgid] += UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[lcid];
}
rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
lcid,
0);
......
......@@ -186,9 +186,9 @@ rlc_am_get_buffer_occupancy_in_bytes (
#if TRACE_RLC_AM_BO
if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
if ((rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : STATUS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->status_buffer_occupancy);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retransmission_buffer_occupancy);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retrans_num_bytes_to_retransmit);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : SDU BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->sdu_buffer_occupancy,
......@@ -669,13 +669,13 @@ rlc_am_mac_status_indication (
*/
if (rlc->input_sdus == NULL) return status_resp;
if (rlc->last_frame_status_indication != ctxt_pP->frame) {
if (rlc->last_absolute_subframe_status_indication != (PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP))) {
rlc_am_check_timer_poll_retransmit(ctxt_pP, rlc);
rlc_am_check_timer_reordering(ctxt_pP, rlc);
rlc_am_check_timer_status_prohibit(ctxt_pP, rlc);
}
rlc->last_frame_status_indication = ctxt_pP->frame;
rlc->last_absolute_subframe_status_indication = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
rlc->nb_bytes_requested_by_mac = tb_sizeP;
......@@ -701,31 +701,14 @@ rlc_am_mac_status_indication (
}
} else {
if (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc)) {
if ((status_resp.buffer_occupancy_in_bytes == 0) && (rlc->input_sdus[rlc->current_sdu_index].mem_block == NULL) && (rlc->nb_sdu > 0)) {
// force BO to be > 0
rlc_sn_t sn = (rlc->vt_s - 1) & RLC_AM_SN_MASK;
rlc_sn_t sn_end = (rlc->vt_a - 1) & RLC_AM_SN_MASK;
/* Look for the first retransmittable PDU starting from vtS - 1 */
while (sn != sn_end) {
AssertFatal (rlc->tx_data_pdu_buffer[sn].mem_block != NULL, "RLC AM Tpoll Retx expiry sn=%d is empty vtA=%d vtS=%d LcId=%d\n",
sn, rlc->vt_a,rlc->vt_s,rlc->channel_id);
if ((rlc->tx_data_pdu_buffer[sn].flags.ack == 0) && (rlc->tx_data_pdu_buffer[sn].flags.max_retransmit == 0)) {
rlc->retrans_num_bytes_to_retransmit = rlc->tx_data_pdu_buffer[sn].header_and_payload_size;
rlc->tx_data_pdu_buffer[sn].flags.retransmit = 1;
status_resp.buffer_occupancy_in_bytes = rlc->tx_data_pdu_buffer[sn].header_and_payload_size;
status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu;
status_resp.head_sdu_remaining_size_to_send = status_resp.buffer_occupancy_in_bytes;
// TODO head_sdu_is_segmented
break;
}
else
{
sn = RLC_AM_PREV_SN(sn);
}
}
}
/* Not so many possibilities ... */
/* either buffer_occupancy_in_bytes = 0 and that's it */
/* or we have segmented all received SDUs and buffer occupancy is then made of retransmissions and/or status pdu pending */
/* then consider only retransmission buffer for the specific BO values used by eNB scheduler (not used up to now...) */
if (rlc->retrans_num_bytes_to_retransmit) {
status_resp.buffer_occupancy_in_pdus = rlc->retrans_num_pdus;
status_resp.head_sdu_remaining_size_to_send = rlc->retrans_num_bytes_to_retransmit;
status_resp.head_sdu_is_segmented = 1;
}
}
#if MESSAGE_CHART_GENERATOR_RLC_MAC
......@@ -770,6 +753,17 @@ rlc_am_mac_status_indication (
#endif
return status_resp;
}
//-----------------------------------------------------------------------------
void
rlc_am_set_nb_bytes_requested_by_mac (
void * const rlc_pP,
const tb_size_t tb_sizeP
)
{
((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP;
}
//-----------------------------------------------------------------------------
struct mac_data_req
rlc_am_mac_data_request (
......
......@@ -277,6 +277,13 @@ protected_rlc_am( void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void *
*/
public_rlc_am( struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);)
/*! \fn void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP)
* \brief Set available TBS for RLC Tx just before am_mac_data_request. Used for UE only.
* \param[in] rlc_pP RLC AM protocol instance pointer.
* \param[in] tb_sizeP Available Tx Transport Block size in bytes.
*/
public_rlc_am( void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP);)
/*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP)
* \brief Gives PDUs to lower layer MAC.
* \param[in] ctxt_pP Running context.
......@@ -293,6 +300,13 @@ public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ct
*/
public_rlc_am( void rlc_am_mac_data_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indP);)
/*! \fn uint32_t rlc_am_get_buffer_occupancy_in_bytes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP)
* \brief Get Tx Buffer Occupancy.
* \param[in] ctxt_pP Running context.
* \param[in] rlc_pP RLC AM protocol instance pointer.
*/
public_rlc_am( uint32_t rlc_am_get_buffer_occupancy_in_bytes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP);)
/*! \fn void rlc_am_data_req (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, mem_block_t *sduP)
* \brief Interface with higher layers, buffer higher layer SDUS for transmission.
* \param[in] ctxt_pP Running context.
......
......@@ -57,7 +57,6 @@ typedef struct rlc_am_entity_s {
boolean_t is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */
rlc_buffer_occupancy_t sdu_buffer_occupancy; /*!< \brief Number of bytes of unsegmented SDUs. */
rlc_buffer_occupancy_t retransmission_buffer_occupancy; /*!< \brief Number of bytes of PDUs in retransmission buffer waiting for a ACK. */
rlc_buffer_occupancy_t status_buffer_occupancy; /*!< \brief Number of bytes of control PDUs waiting for transmission. */
rlc_am_control_pdu_info_t control_pdu_info;
......@@ -76,7 +75,7 @@ typedef struct rlc_am_entity_s {
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer; /*!< \brief Transmission PDU data buffer. Used also for retransmissions */
signed int retrans_num_pdus; /*!< \brief Number of PDUs in the retransmission buffer. */
signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. */
signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. Only payload is taken into account */
boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */
//---------------------------------------------------------------------
......@@ -181,7 +180,7 @@ typedef struct rlc_am_entity_s {
uint8_t status_requested; /*!< \brief Status bitmap requested by peer. */
rlc_sn_t sn_status_triggered_delayed; /*!< \brief SN of the last received poll for which Status is delayed until SN is out of Rx Window. */
frame_t last_frame_status_indication; /*!< \brief The last frame number a MAC status indication has been received by RLC. */
uint32_t last_absolute_subframe_status_indication; /*!< \brief The last absolute subframe number a MAC status indication has been received by RLC. */
//-----------------------------
// buffer occupancy measurements sent to MAC
//-----------------------------
......
......@@ -41,17 +41,23 @@ void rlc_am_free_in_sdu(
const unsigned int index_in_bufferP)
{
if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) {
/* BugFix: SDU shall have been already freed during initial PDU segmentation or concatenation !! */
AssertFatal(rlcP->input_sdus[index_in_bufferP].mem_block == NULL, "RLC AM Tx SDU Conf: Data Part is not empty index=%d LcId=%d\n",
index_in_bufferP,rlcP->channel_id);
/*
if (rlcP->input_sdus[index_in_bufferP].mem_block != NULL) {
free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__);
rlcP->input_sdus[index_in_bufferP].mem_block = NULL;
rlcP->nb_sdu_no_segmented -= 1;
rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0;
}
*/
rlcP->nb_sdu -= 1;
memset(&rlcP->input_sdus[index_in_bufferP], 0, sizeof(rlc_am_tx_sdu_management_t));
rlcP->input_sdus[index_in_bufferP].flags.transmitted_successfully = 1;
// TODO : understand why. This should not happen
if (rlcP->current_sdu_index == index_in_bufferP) {
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
}
......
......@@ -79,7 +79,7 @@ rlc_am_init(
//rlc_pP->vr_h = 0;
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->last_frame_status_indication = 123456; // any value > 1
rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE;
......@@ -135,7 +135,7 @@ rlc_am_reestablish(
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->status_requested = RLC_AM_STATUS_NOT_TRIGGERED;
rlc_pP->last_frame_status_indication = 123456; // any value > 1
rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE;
......
......@@ -51,8 +51,8 @@ void rlc_am_nack_pdu (
mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP].mem_block;
int pdu_sdu_index;
int sdu_index;
//int pdu_sdu_index;
//int sdu_index;
if (mb_p != NULL) {
assert(so_startP <= so_endP);
......@@ -84,10 +84,10 @@ void rlc_am_nack_pdu (
rlc_pP->tx_data_pdu_buffer[snP].flags.retransmit = 1;
/* TODO : before incrementing retx_count_next, this must be a new occurrence of retransmission */
/* TODO : before incrementing retx_count_next, one have to check this must be a new occurrence of retransmission */
if (rlc_pP->tx_data_pdu_buffer[snP].retx_count == rlc_pP->tx_data_pdu_buffer[snP].retx_count_next){
rlc_pP->tx_data_pdu_buffer[snP].retx_count_next ++;
rlc_pP->retrans_num_bytes_to_retransmit += rlc_pP->tx_data_pdu_buffer[snP].header_and_payload_size;
rlc_pP->retrans_num_bytes_to_retransmit += rlc_pP->tx_data_pdu_buffer[snP].payload_size;
}
/* TODO: Move this part in UL SCH processing */
......@@ -148,7 +148,7 @@ void rlc_am_ack_pdu (
rlc_pP->tx_data_pdu_buffer[snP].retx_count);
if (rlc_pP->tx_data_pdu_buffer[snP].retx_count >= 0) {
rlc_pP->retrans_num_bytes_to_retransmit -= rlc_pP->tx_data_pdu_buffer[snP].header_and_payload_size;
rlc_pP->retrans_num_bytes_to_retransmit -= rlc_pP->tx_data_pdu_buffer[snP].payload_size;
}
for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->tx_data_pdu_buffer[snP].nb_sdus; pdu_sdu_index++) {
......@@ -845,7 +845,6 @@ void rlc_am_retransmit_any_pdu(
//rlc_pP->c_pdu_without_poll = 0;
//rlc_pP->c_byte_without_poll = 0;
//rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK;
rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP);
rlc_pP->stat_tx_data_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu += 1;
rlc_pP->stat_tx_data_bytes += ((struct mac_tb_req*)(pdu_p->data))->tb_size;
......@@ -879,7 +878,6 @@ void rlc_am_retransmit_any_pdu(
rlc_pP->c_pdu_without_poll = 0;
rlc_pP->c_byte_without_poll = 0;
//rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK;
rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP);
rlc_pP->stat_tx_data_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu += 1;
rlc_pP->stat_tx_data_bytes += ((struct mac_tb_req*)(pdu_p->data))->tb_size;
......
......@@ -308,14 +308,12 @@ rlc_am_receive_process_control_pdu(
assert(ack_sn < RLC_AM_SN_MODULO);
assert(rlc_pP->control_pdu_info.num_nack < RLC_AM_MAX_NACK_IN_STATUS_PDU);
if (rlc_am_in_tx_window(ctxt_pP, rlc_pP, ack_sn) > 0) {
/* Nv1495998 : ackSn can be equal to current vtA only in case the status pdu contains a list of nack_sn with same value = vtA with SOStart/SOEnd */
/* and meaning the report is not complete due to not enough ressources to fill all SOStart/SOEnd of this NACK_SN */
if (RLC_AM_DIFF_SN(rlc_pP->vt_s,rlc_pP->vt_a) >= RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a))
{
if (rlc_pP->control_pdu_info.num_nack == 0) {
while (sn_cursor != ack_sn) {
if (sn_cursor == rlc_pP->poll_sn) {
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP);
}
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor);
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
}
......@@ -324,10 +322,6 @@ rlc_am_receive_process_control_pdu(
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
while (sn_cursor != ack_sn) {
if (sn_cursor == rlc_pP->poll_sn) {
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP);
}
if (sn_cursor != nack_sn) {
rlc_am_ack_pdu(ctxt_pP,
rlc_pP,
......@@ -357,6 +351,16 @@ rlc_am_receive_process_control_pdu(
}
}
}
/* Check for Stopping TpollReTx */
if ((rlc_pP->poll_sn != RLC_SN_UNDEFINED) &&
(RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a) > RLC_AM_DIFF_SN(rlc_pP->poll_sn,rlc_pP->vt_a))) {
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP);
rlc_pP->poll_sn = RLC_SN_UNDEFINED;
}
/* Update vtA */
} else {
LOG_N(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN OUT OF WINDOW\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
......
......@@ -110,6 +110,7 @@ typedef struct rlc_am_tx_data_pdu_management {
sdu_size_t hole_so_start [RLC_AM_MAX_HOLES_REPORT_PER_PDU]; /*!< \brief Array containing the start segment offsets for marking a hole (negative acknowledged area) in the PDU. */
sdu_size_t hole_so_stop [RLC_AM_MAX_HOLES_REPORT_PER_PDU]; /*!< \brief Array containing the stop segment offsets for marking a hole (negative acknowledged area) in the PDU. */
uint8_t num_holes; /*!< \brief Number of registereg holes in hole_so_start[], hole_so_stop[]. */
uint8_t retx_hole_index; /*!< \brief Next index of registered holes to retransmit. */
sdu_size_t header_and_payload_size; /*!< \brief Size of the PDU in bytes, including header and payload. */
sdu_size_t payload_size; /*!< \brief Size of the PDU payload in bytes. */
rlc_sn_t sn; /*!< \brief Sequence number of the PDU. */
......
......@@ -77,10 +77,32 @@ rlc_am_check_timer_poll_retransmit(
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
/* Check for any retransmittable PDU if Buffer Occupancy empty or window stall */
if (((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) ||
(rlc_pP->vt_s == rlc_pP->vt_ms)) {
// force BO to be > 0
rlc_sn_t sn = RLC_AM_PREV_SN(rlc_pP->vt_s);
rlc_sn_t sn_end = RLC_AM_PREV_SN(rlc_pP->vt_a);
/* Look for the first retransmittable PDU starting from vtS - 1 */
while (sn != sn_end) {
AssertFatal (rlc_pP->tx_data_pdu_buffer[sn].mem_block != NULL, "RLC AM Tpoll Retx expiry sn=%d is empty vtA=%d vtS=%d LcId=%d\n",
sn, rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
if ((rlc_pP->tx_data_pdu_buffer[sn].flags.ack == 0) && (rlc_pP->tx_data_pdu_buffer[sn].flags.max_retransmit == 0)) {
rlc_pP->tx_data_pdu_buffer[sn].flags.retransmit = 1;
rlc_pP->retrans_num_pdus += 1;
rlc_pP->retrans_num_bytes_to_retransmit += rlc_pP->tx_data_pdu_buffer[sn].payload_size;
}
else
{
sn = RLC_AM_PREV_SN(sn);
}
}
}
rlc_pP->force_poll= TRUE;
//#warning TO DO rlc_am_check_timer_poll_retransmit
rlc_pP->t_poll_retransmit.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_poll_retransmit.ms_duration;
//BugFix : new ms_time_out is computed when next poll is transmitter
}
}
}
......@@ -119,9 +141,9 @@ rlc_am_start_timer_poll_retransmit(
rlc_am_entity_t * const rlc_pP
)
{
rlc_pP->t_poll_retransmit.timed_out = 0;
/* Stop timer if it was previously running */
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP,rlc_pP);
if (rlc_pP->t_poll_retransmit.running == 0) {
if (rlc_pP->t_poll_retransmit.ms_duration > 0) {
rlc_pP->t_poll_retransmit.running = 1;
rlc_pP->t_poll_retransmit.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_poll_retransmit.ms_duration;
......@@ -138,14 +160,7 @@ rlc_am_start_timer_poll_retransmit(
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] NOT STARTED, CAUSE CONFIGURED 0 ms\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
}
} else {
#if MESSAGE_CHART_GENERATOR_RLC_MAC
MSC_LOG_EVENT((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,\
"0 "PROTOCOL_RLC_AM_MSC_FMT" t_poll_retransmit not restarted (TO %u ms)",\
PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP,rlc_pP), rlc_pP->t_poll_retransmit.ms_time_out);
#endif
}
}
//-----------------------------------------------------------------------------
void
......
......@@ -520,6 +520,16 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
return status_resp;
}
//-----------------------------------------------------------------------------
void
rlc_um_set_nb_bytes_requested_by_mac (
void * rlc_pP,
const tb_size_t tb_sizeP
)
{
((rlc_um_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP;
}
//-----------------------------------------------------------------------------
struct mac_data_req
rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP)
......
......@@ -188,6 +188,13 @@ protected_rlc_um( void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_
*/
public_rlc_um( struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP);)
/*! \fn void rlc_um_set_nb_bytes_requested_by_mac (rlc_um_entity_t * const rlc_pP, const tb_size_t tb_sizeP)
* \brief Set available TBS size for MAC Tx.
* \param[in] rlc_pP RLC UM protocol instance pointer.
* \param[in] tb_sizeP remaining TBS in bytes.
*/
public_rlc_um( void rlc_um_set_nb_bytes_requested_by_mac (rlc_um_entity_t * const rlc_pP, const tb_size_t tb_sizeP);)
/*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
* \brief Gives PDUs to lower layer MAC.
* \param[in] ctxt_pP Running context.
......@@ -205,6 +212,11 @@ public_rlc_um( struct mac_data_req rlc_um_mac_data_request (const protocol_ct
*/
public_rlc_um( void rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, struct mac_data_ind data_indP);)
/*! \fn uint32_t rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP)
* \brief Gets Tx Buffer Occupancy.
* \param[in] rlc_pP RLC UM protocol instance pointer.)
*/
public_rlc_um( uint32_t rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP);)
/*! \fn void rlc_um_data_req (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, mem_block_t *sduP)
* \brief Interface with higher layers, buffer higher layer SDUS for transmission.
......
......@@ -436,10 +436,11 @@ public_rlc_rrc(void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_d
* \param [in] eNB_flagP Flag to indicate eNB (1) or UE (0)
* \param [in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0)
* \param [in] rb_idP Radio bearer identifier.
* \param [in] tb_sizeP Available Tx TBS in bytes. For UE only.
* \param [in,out] bufferP Memory area to fill with the bytes requested by MAC.
* \return A status about the processing, OK or error code.
*/
public_rlc_mac(tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char*);)
public_rlc_mac(tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, const tb_size_t,char*);)
/*! \fn void mac_rlc_data_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, uint32_t frameP, char* bufferP, tb_size_t tb_sizeP, num_tb_t num_tbP, crc_t *crcs)
* \brief Interface with MAC layer, deserialize the transport blocks sent by MAC, then map data indication to the RLC instance corresponding to the radio bearer identifier.
......@@ -457,18 +458,31 @@ public_rlc_mac(tbs_size_t mac_rlc_data_req (const module_id_t, co
public_rlc_mac(void mac_rlc_data_ind (const module_id_t, const rnti_t, const eNB_index_t,const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char*, tb_size_t, num_tb_t,
crc_t* );)
/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, tb_size_t tb_sizeP)
/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, tb_size_t tb_sizeP)
* \brief Interface with MAC layer, request and set the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier.
* \param[in] mod_idP Virtualized module identifier.
* \param[in] rntiP UE identifier.
* \param[in] frameP Frame index.
* \param[in] subframeP SubFrame index.
* \param[in] eNB_flagP Flag to indicate eNB operation (1 true, 0 false)
* \param[in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0)
* \param[in] rb_idP Radio bearer identifier.
* \param[in] tb_sizeP Size of a transport block set in bytes.
* \return The maximum number of bytes that the RLC instance can send in the next transmission sequence.
*/
public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t );)
public_rlc_mac(mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t );)
/*! \fn rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(const module_id_t module_idP, const rnti_t rntiP, const eNB_index_t eNB_index, const frame_t frameP, const sub_frame_t subframeP,const eNB_flag_t enb_flagP, const logical_chan_id_t channel_idP)
* \brief Interface with MAC layer, UE only: request and get the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier.
* \param[in] mod_idP Virtualized module identifier.
* \param[in] rntiP UE identifier.
* \param[in] frameP Frame index.
* \param[in] subframeP SubFrame index.
* \param[in] eNB_flagP Flag to indicate eNB operation (1 true, 0 false)
* \param[in] channel_idP Logical Channel identifier.
* \return The maximum number of bytes that the RLC instance can send in the next transmission sequence.
*/
public_rlc_mac(rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const logical_chan_id_t );)
//-----------------------------------------------------------------------------
// RLC methods
//-----------------------------------------------------------------------------
......
......@@ -125,6 +125,7 @@ tbs_size_t mac_rlc_data_req(
const eNB_flag_t enb_flagP,
const MBMS_flag_t MBMS_flagP,
const logical_chan_id_t channel_idP,
const tb_size_t tb_sizeP,
char *buffer_pP)
{
//-----------------------------------------------------------------------------
......@@ -189,12 +190,14 @@ tbs_size_t mac_rlc_data_req(
break;
case RLC_MODE_AM:
data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am);
if (!enb_flagP) rlc_am_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.am,tb_sizeP);
data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am);
ret_tb_size =mac_rlc_serialize_tb(buffer_pP, data_request.data);
break;
case RLC_MODE_UM:
data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um);
if (!enb_flagP) rlc_um_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.um,tb_sizeP);
data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um);
ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data);
break;
......@@ -320,6 +323,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
const rnti_t rntiP,
const eNB_index_t eNB_index,
const frame_t frameP,
const sub_frame_t subframeP,
const eNB_flag_t enb_flagP,
const MBMS_flag_t MBMS_flagP,
const logical_chan_id_t channel_idP,
......@@ -337,7 +341,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
srb_flag_t srb_flag = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO;
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index);
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, subframeP, eNB_index);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_STATUS_IND,VCD_FUNCTION_IN);
memset (&mac_rlc_status_resp, 0, sizeof(mac_rlc_status_resp_t));
......@@ -430,3 +434,65 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
return mac_rlc_status_resp;
}
//-----------------------------------------------------------------------------
rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind(
const module_id_t module_idP,
const rnti_t rntiP,
const eNB_index_t eNB_index,
const frame_t frameP,
const sub_frame_t subframeP,
const eNB_flag_t enb_flagP,
const logical_chan_id_t channel_idP)
{
//-----------------------------------------------------------------------------
rlc_buffer_occupancy_t mac_rlc_buffer_occupancy_resp = 0;
rlc_mode_t rlc_mode = RLC_MODE_NONE;
rlc_union_t *rlc_union_p = NULL;
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
srb_flag_t srb_flag = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO;
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index);
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_GET_BUFFER_OCCUPANCY_IND,VCD_FUNCTION_IN);
/* Assumptions : for UE only */
/* At each TTI, Buffer Occupancy is first computed in mac_rlc_status_ind called by MAC ue_scheduler() function */
/* Then this function is called during MAC multiplexing ue_get_sdu(), and it may be call several times for the same bearer if it is in AM mode and there are several PDU types to transmit */
AssertFatal(enb_flagP == FALSE,"RLC Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%d\n", channel_idP);
key = RLC_COLL_KEY_LCID_VALUE(module_idP, rntiP, enb_flagP, channel_idP, srb_flag);
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
if (h_rc == HASH_TABLE_OK) {
rlc_mode = rlc_union_p->mode;
} else {
rlc_mode = RLC_MODE_NONE;
//LOG_W(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
//LOG_D(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
}
switch (rlc_mode) {
case RLC_MODE_AM:
mac_rlc_buffer_occupancy_resp = rlc_am_get_buffer_occupancy_in_bytes(&ctxt, &rlc_union_p->rlc.am);
break;
case RLC_MODE_UM:
mac_rlc_buffer_occupancy_resp = rlc_um_get_buffer_occupancy(&rlc_union_p->rlc.um);
break;
default:
mac_rlc_buffer_occupancy_resp = 0 ;
}
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_GET_BUFFER_OCCUPANCY_IND,VCD_FUNCTION_OUT);
return mac_rlc_buffer_occupancy_resp;
}
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