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 { ...@@ -388,9 +388,9 @@ typedef struct {
struct PMCH_InfoList_r9 *pmch_InfoList struct PMCH_InfoList_r9 *pmch_InfoList
#endif #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* ); 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); 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 *); 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* ), 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) { ...@@ -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) { 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); rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_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; 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) { 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); rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_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; return rlc_status.head_sdu_creation_time;
} }
......
...@@ -821,6 +821,7 @@ schedule_ue_spec( ...@@ -821,6 +821,7 @@ schedule_ue_spec(
rnti, rnti,
module_idP, module_idP,
frameP, frameP,
subframeP,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH, DCCH,
...@@ -839,6 +840,7 @@ schedule_ue_spec( ...@@ -839,6 +840,7 @@ schedule_ue_spec(
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH, DCCH,
TBS, //not used
(char *)&dlsch_buffer[0]); (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), 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( ...@@ -872,6 +874,7 @@ schedule_ue_spec(
rnti, rnti,
module_idP, module_idP,
frameP, frameP,
subframeP,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH+1, DCCH+1,
...@@ -890,6 +893,7 @@ schedule_ue_spec( ...@@ -890,6 +893,7 @@ schedule_ue_spec(
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH+1, DCCH+1,
TBS, //not used
(char *)&dlsch_buffer[sdu_length_total]); (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(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( ...@@ -932,6 +936,7 @@ schedule_ue_spec(
rnti, rnti,
module_idP, module_idP,
frameP, frameP,
subframeP,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -949,6 +954,7 @@ schedule_ue_spec( ...@@ -949,6 +954,7 @@ schedule_ue_spec(
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
TBS, //not used
(char*)&dlsch_buffer[sdu_length_total]); (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(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])); 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 ...@@ -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, module_idP,CC_id,frameP,MTCH,TBS,
TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); 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); 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", 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); 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 ...@@ -521,6 +521,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_YES, MBMS_FLAG_YES,
MTCH, MTCH,
0, //not used
(char*)&mch_buffer[sdu_length_total]); (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]); //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); 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, ...@@ -174,6 +174,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
rnti, rnti,
mod_id, mod_id,
frame, frame,
subframe,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -193,6 +194,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, ...@@ -193,6 +194,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
rnti, rnti,
mod_id, mod_id,
frame, frame,
subframe,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -209,6 +211,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, ...@@ -209,6 +211,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
rlc_size, //not used
(char *)&dlsch_buffer[sdu_length_total]); (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]); 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, ...@@ -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 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_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_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; 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, ...@@ -1241,6 +1241,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
rnti, rnti,
mod_id, mod_id,
frame, frame,
subframe,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
j, j,
......
...@@ -109,7 +109,7 @@ void store_dlsch_buffer (module_id_t Mod_id, ...@@ -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 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_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_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; 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, ...@@ -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) { } 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) // 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 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, DCCH,
6); 6);
...@@ -409,6 +409,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, ...@@ -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, sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,
eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO, eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
DCCH, DCCH,
6, //not used
(char *)&ulsch_buff[0]); (char *)&ulsch_buff[0]);
LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]); LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
......
This diff is collapsed.
...@@ -186,9 +186,9 @@ rlc_am_get_buffer_occupancy_in_bytes ( ...@@ -186,9 +186,9 @@ rlc_am_get_buffer_occupancy_in_bytes (
#if TRACE_RLC_AM_BO #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 : 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", 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), PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->sdu_buffer_occupancy, rlc_pP->sdu_buffer_occupancy,
...@@ -669,13 +669,13 @@ rlc_am_mac_status_indication ( ...@@ -669,13 +669,13 @@ rlc_am_mac_status_indication (
*/ */
if (rlc->input_sdus == NULL) return status_resp; 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_poll_retransmit(ctxt_pP, rlc);
rlc_am_check_timer_reordering(ctxt_pP, rlc); rlc_am_check_timer_reordering(ctxt_pP, rlc);
rlc_am_check_timer_status_prohibit(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; rlc->nb_bytes_requested_by_mac = tb_sizeP;
...@@ -701,31 +701,14 @@ rlc_am_mac_status_indication ( ...@@ -701,31 +701,14 @@ rlc_am_mac_status_indication (
} }
} else { } else {
if (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc)) { /* Not so many possibilities ... */
if ((status_resp.buffer_occupancy_in_bytes == 0) && (rlc->input_sdus[rlc->current_sdu_index].mem_block == NULL) && (rlc->nb_sdu > 0)) { /* either buffer_occupancy_in_bytes = 0 and that's it */
// force BO to be > 0 /* or we have segmented all received SDUs and buffer occupancy is then made of retransmissions and/or status pdu pending */
rlc_sn_t sn = (rlc->vt_s - 1) & RLC_AM_SN_MASK; /* then consider only retransmission buffer for the specific BO values used by eNB scheduler (not used up to now...) */
rlc_sn_t sn_end = (rlc->vt_a - 1) & RLC_AM_SN_MASK; if (rlc->retrans_num_bytes_to_retransmit) {
status_resp.buffer_occupancy_in_pdus = rlc->retrans_num_pdus;
/* Look for the first retransmittable PDU starting from vtS - 1 */ status_resp.head_sdu_remaining_size_to_send = rlc->retrans_num_bytes_to_retransmit;
while (sn != sn_end) { status_resp.head_sdu_is_segmented = 1;
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);
}
}
}
} }
} }
#if MESSAGE_CHART_GENERATOR_RLC_MAC #if MESSAGE_CHART_GENERATOR_RLC_MAC
...@@ -770,6 +753,17 @@ rlc_am_mac_status_indication ( ...@@ -770,6 +753,17 @@ rlc_am_mac_status_indication (
#endif #endif
return status_resp; 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 struct mac_data_req
rlc_am_mac_data_request ( rlc_am_mac_data_request (
......
...@@ -277,6 +277,13 @@ protected_rlc_am( void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * ...@@ -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);) 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) /*! \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. * \brief Gives PDUs to lower layer MAC.
* \param[in] ctxt_pP Running context. * \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 ...@@ -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);) 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) /*! \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. * \brief Interface with higher layers, buffer higher layer SDUS for transmission.
* \param[in] ctxt_pP Running context. * \param[in] ctxt_pP Running context.
......
...@@ -57,7 +57,6 @@ typedef struct rlc_am_entity_s { ...@@ -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. */ 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 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_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; rlc_am_control_pdu_info_t control_pdu_info;
...@@ -76,7 +75,7 @@ typedef struct rlc_am_entity_s { ...@@ -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 */ 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_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. */ boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */
//--------------------------------------------------------------------- //---------------------------------------------------------------------
...@@ -181,7 +180,7 @@ typedef struct rlc_am_entity_s { ...@@ -181,7 +180,7 @@ typedef struct rlc_am_entity_s {
uint8_t status_requested; /*!< \brief Status bitmap requested by peer. */ 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. */ 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 // buffer occupancy measurements sent to MAC
//----------------------------- //-----------------------------
......
...@@ -41,17 +41,23 @@ void rlc_am_free_in_sdu( ...@@ -41,17 +41,23 @@ void rlc_am_free_in_sdu(
const unsigned int index_in_bufferP) const unsigned int index_in_bufferP)
{ {
if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) { 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) { if (rlcP->input_sdus[index_in_bufferP].mem_block != NULL) {
free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__); free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__);
rlcP->input_sdus[index_in_bufferP].mem_block = NULL; rlcP->input_sdus[index_in_bufferP].mem_block = NULL;
rlcP->nb_sdu_no_segmented -= 1; rlcP->nb_sdu_no_segmented -= 1;
rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0; rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0;
} }
*/
rlcP->nb_sdu -= 1; rlcP->nb_sdu -= 1;
memset(&rlcP->input_sdus[index_in_bufferP], 0, sizeof(rlc_am_tx_sdu_management_t)); 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; 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) { if (rlcP->current_sdu_index == index_in_bufferP) {
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE; rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
} }
......
...@@ -79,7 +79,7 @@ rlc_am_init( ...@@ -79,7 +79,7 @@ rlc_am_init(
//rlc_pP->vr_h = 0; //rlc_pP->vr_h = 0;
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; 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->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE; rlc_pP->initialized = TRUE;
...@@ -135,7 +135,7 @@ rlc_am_reestablish( ...@@ -135,7 +135,7 @@ rlc_am_reestablish(
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED; rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->status_requested = RLC_AM_STATUS_NOT_TRIGGERED; 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->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE; rlc_pP->initialized = TRUE;
......
...@@ -51,8 +51,8 @@ void rlc_am_nack_pdu ( ...@@ -51,8 +51,8 @@ void rlc_am_nack_pdu (
mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP].mem_block; mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP].mem_block;
int pdu_sdu_index; //int pdu_sdu_index;
int sdu_index; //int sdu_index;
if (mb_p != NULL) { if (mb_p != NULL) {
assert(so_startP <= so_endP); assert(so_startP <= so_endP);
...@@ -84,10 +84,10 @@ void rlc_am_nack_pdu ( ...@@ -84,10 +84,10 @@ void rlc_am_nack_pdu (
rlc_pP->tx_data_pdu_buffer[snP].flags.retransmit = 1; 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){ 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->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 */ /* TODO: Move this part in UL SCH processing */
...@@ -148,7 +148,7 @@ void rlc_am_ack_pdu ( ...@@ -148,7 +148,7 @@ void rlc_am_ack_pdu (
rlc_pP->tx_data_pdu_buffer[snP].retx_count); rlc_pP->tx_data_pdu_buffer[snP].retx_count);
if (rlc_pP->tx_data_pdu_buffer[snP].retx_count >= 0) { 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++) { 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( ...@@ -845,7 +845,6 @@ void rlc_am_retransmit_any_pdu(
//rlc_pP->c_pdu_without_poll = 0; //rlc_pP->c_pdu_without_poll = 0;
//rlc_pP->c_byte_without_poll = 0; //rlc_pP->c_byte_without_poll = 0;
//rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK; //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_data_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu += 1; rlc_pP->stat_tx_retransmit_pdu += 1;
rlc_pP->stat_tx_data_bytes += ((struct mac_tb_req*)(pdu_p->data))->tb_size; 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( ...@@ -879,7 +878,6 @@ void rlc_am_retransmit_any_pdu(
rlc_pP->c_pdu_without_poll = 0; rlc_pP->c_pdu_without_poll = 0;
rlc_pP->c_byte_without_poll = 0; rlc_pP->c_byte_without_poll = 0;
//rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK; //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_data_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu += 1; rlc_pP->stat_tx_retransmit_pdu += 1;
rlc_pP->stat_tx_data_bytes += ((struct mac_tb_req*)(pdu_p->data))->tb_size; 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( ...@@ -308,14 +308,12 @@ rlc_am_receive_process_control_pdu(
assert(ack_sn < RLC_AM_SN_MODULO); assert(ack_sn < RLC_AM_SN_MODULO);
assert(rlc_pP->control_pdu_info.num_nack < RLC_AM_MAX_NACK_IN_STATUS_PDU); 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) { if (rlc_pP->control_pdu_info.num_nack == 0) {
while (sn_cursor != ack_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);
}
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor); rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor);
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK; sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
} }
...@@ -324,10 +322,6 @@ rlc_am_receive_process_control_pdu( ...@@ -324,10 +322,6 @@ rlc_am_receive_process_control_pdu(
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn; nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
while (sn_cursor != ack_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) { if (sn_cursor != nack_sn) {
rlc_am_ack_pdu(ctxt_pP, rlc_am_ack_pdu(ctxt_pP,
rlc_pP, rlc_pP,
...@@ -357,6 +351,16 @@ rlc_am_receive_process_control_pdu( ...@@ -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 { } else {
LOG_N(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN OUT OF WINDOW\n", 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)); PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
......
...@@ -110,6 +110,7 @@ typedef struct rlc_am_tx_data_pdu_management { ...@@ -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_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. */ 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 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 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. */ sdu_size_t payload_size; /*!< \brief Size of the PDU payload in bytes. */
rlc_sn_t sn; /*!< \brief Sequence number of the PDU. */ rlc_sn_t sn; /*!< \brief Sequence number of the PDU. */
......
...@@ -77,10 +77,32 @@ rlc_am_check_timer_poll_retransmit( ...@@ -77,10 +77,32 @@ rlc_am_check_timer_poll_retransmit(
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT\n", LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); 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);
}
}
}