Commit 26d99fae authored by fnabet's avatar fnabet

add changes for Tx Status PDU report

parent b77694e8
......@@ -323,7 +323,8 @@ rlc_am_get_pdus (
case RLC_DATA_TRANSFER_READY_STATE:
// TRY TO SEND CONTROL PDU FIRST
if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) {
if ((rlc_pP->nb_bytes_requested_by_mac >= 2) &&
((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK))) {
// When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall:
// - if t-StatusProhibit is not running:
// - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer;
......@@ -334,22 +335,23 @@ rlc_am_get_pdus (
//
// When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall:
// - start t-StatusProhibit.
if (rlc_pP->t_status_prohibit.running == 0) {
rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);
if (pdu) {
rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);
if (pdu) {
list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
rlc_pP->status_requested = 0;
RLC_AM_CLEAR_ALL_STATUS(rlc_pP->status_requested);
rlc_pP->status_buffer_occupancy = 0;
rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_PROHIBIT);
return;
}
} else {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU BECAUSE T-STATUS-PROHIBIT RUNNING (TIME-OUT %u)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->t_status_prohibit.ms_time_out);
}
else {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU (Available MAC Data %u)(T-PROHIBIT %u) (DELAY FLAG %u)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->nb_bytes_requested_by_mac,rlc_pP->t_status_prohibit.ms_time_out,(rlc_pP->status_requested & RLC_AM_STATUS_TRIGGERED_DELAYED));
}
/*while ((rlc_pP->nb_bytes_requested_by_mac > 0) && (stay_on_this_list)) {
......
......@@ -72,6 +72,22 @@
# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 16
/** @} */
/* Common to Data and Status PDU */
#define RLC_AM_SN_BITS 10
#define RLC_AM_PDU_D_C_BITS 1
#define RLC_AM_PDU_E_BITS 1
/* STATUS PDU */
#define RLC_AM_STATUS_PDU_CPT_STATUS 0
#define RLC_AM_STATUS_PDU_CPT_OFFSET 4
#define RLC_AM_STATUS_PDU_CPT_LENGTH 3
#define RLC_AM_STATUS_PDU_ACK_SN_OFFSET 2
#define RLC_AM_STATUS_PDU_SO_LENGTH 15
#define RLC_AM_STATUS_PDU_SO_END_ALL_BYTES 0x7FFF
/* MACRO DEFINITIONS */
#define RLC_AM_NEXT_SN(sn) (((sn)+1) & ((RLC_AM_SN_MODULO)-1))
......@@ -93,6 +109,7 @@
#define RLC_AM_STATUS_TRIGGERED_T_REORDERING 0x02 /* Status Report is triggered by Timer Reordering Expiry */
#define RLC_AM_STATUS_TRIGGERED_DELAYED 0x10 /* Status is delayed until SN(receivedPoll) < VR(MS) */
#define RLC_AM_STATUS_PROHIBIT 0x20 /* TimerStatusProhibit still running */
#define RLC_AM_STATUS_NO_TX_MASK (RLC_AM_STATUS_PROHIBIT | RLC_AM_STATUS_TRIGGERED_DELAYED)
/* Status triggered (bit 5-7) will be concatenated with Poll triggered (bit 0-4) for RLCdec. RLC_AM_STATUS_TRIGGERED_DELAYED is not recorded. */
#define RLC_AM_SET_STATUS(x,event) (RLC_SET_EVENT(x,event))
......
......@@ -449,6 +449,353 @@ rlc_am_send_status_pdu(
// - set the ACK_SN to the SN of the next not received RLC Data PDU which is not indicated as missing in the
// resulting STATUS PDU.
signed int nb_bits_to_transmit = rlc_pP->nb_bytes_requested_by_mac << 3;
// minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1
signed int nb_bits_transmitted = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
rlc_am_control_pdu_info_t control_pdu_info;
rlc_am_pdu_info_t *pdu_info_cursor_p = NULL;
rlc_sn_t sn_cursor = 0;
rlc_sn_t sn_nack = rlc_pP->vr_r;
mem_block_t *cursor_p = rlc_pP->receiver_buffer.head;
int all_segments_received = 0;
int waited_so = 0;
mem_block_t *tb_p = NULL;
sdu_size_t pdu_size = 0;
boolean_t status_report_completed = false;
boolean_t lsf_received = false;
boolean_t segment_loop_end = false;
memset(&control_pdu_info, 0, sizeof(rlc_am_control_pdu_info_t));
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] nb_bits_to_transmit %d (15 already allocated for header)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
nb_bits_to_transmit);
rlc_am_rx_list_display(rlc_pP, " DISPLAY BEFORE CONSTRUCTION OF STATUS REPORT");
#endif
/* Handle no NACK first */
if (rlc_pP->vr_r == rlc_pP->vr_ms) {
control_pdu_info.ack_sn = rlc_pP->vr_ms;
status_report_completed = true;
}
else if (cursor_p != NULL) {
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
sn_cursor = pdu_info_cursor_p->sn;
// Not very clear why this is needed
// commenting
#if 0
while (!(RLC_AM_SN_IN_WINDOW(sn_cursor, rlc_pP->vr_r))) {
cursor_p = cursor_p->next;
previous_sn_cursor = sn_cursor;
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
sn_cursor = pdu_info_cursor_p->sn;
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d FIND VR(R) <= SN sn_cursor %04d -> %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
__LINE__,
previous_sn_cursor,
sn_cursor);
#endif
}
#endif
// 12 bits = size of NACK_SN field + E1, E2 bits
// 42 bits = size of NACK_SN field + SO_START, SO_END fields, E1, E2 bits
while ((!status_report_completed) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))
&& (cursor_p != NULL) && (nb_bits_transmitted <= nb_bits_to_transmit)) {
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
sn_cursor = pdu_info_cursor_p->sn;
all_segments_received = ((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received;
// E1 bit is set at the end
/* First fill NACK_SN with each missing PDU between current sn_nack and sn_cursor */
while ((sn_nack != sn_cursor) && (sn_nack != rlc_pP->vr_ms)) {
if (nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) <= nb_bits_to_transmit) {
/* Fill NACK_SN infos */
if (control_pdu_info.num_nack) {
/* Set E1 of previous NACK_SN */
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 1;
}
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_nack;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 0;
control_pdu_info.num_nack += 1;
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
__LINE__,
sn_nack);
#endif
sn_nack = RLC_AM_NEXT_SN(sn_nack);
}
else {
/* Not enough UL TBS*/
/* latest value of sn_nack shall be used as ACK_SN */
control_pdu_info.ack_sn = sn_nack;
status_report_completed = true;
break;
}
}
/* Now process all Segments of sn_cursor if PDU not fully received */
if ((!status_report_completed) && (all_segments_received == 0) && (sn_nack != rlc_pP->vr_ms)) {
AssertFatal (sn_nack == sn_cursor, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
/* First ensure there is enough TBS for at least 1 SOStart/SOEnd, else break */
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
/* Set E1 of previous NACK_SN */
if (control_pdu_info.num_nack) {
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 1;
}
/* Init loop flags */
lsf_received = false;
segment_loop_end = false;
/* Init first SO Start according to first segment */
if (pdu_info_cursor_p->so) {
waited_so = 0;
/* Fill the first SO */
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1;
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
control_pdu_info.num_nack += 1;
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
__LINE__,
previous_sn_cursor,
waited_so,
0x7FFF);
#endif
waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
/* Go to next segment */
cursor_p = cursor_p->next;
}
else {
waited_so = pdu_info_cursor_p->payload_size;
}
/* Find the first discontinuity and then fill SOStart/SOEnd */
while (!segment_loop_end) {
if (cursor_p != NULL) {
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
if (pdu_info_cursor_p->sn == sn_cursor) {
/* PDU segment is for the same SN*/
if (waited_so < pdu_info_cursor_p->so) {
/* SO is greater than previous received portion : gap identified to fill */
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
/* Set E1 of previous NACK_SN */
if (control_pdu_info.num_nack) {
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 1;
}
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so;
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
control_pdu_info.num_nack += 1;
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
}
else {
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
control_pdu_info.ack_sn = sn_cursor;
status_report_completed = true;
segment_loop_end = true;
break;
}
}
else {
/* Assuming so and payload_size updated according to duplication removal done at reception ... */
waited_so += pdu_info_cursor_p->payload_size;
}
} //end if (pdu_info_cursor_p->sn == sn_cursor)
else if (!lsf_received) {
/* We just switched to next SN, fill last gap if not end received */
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
/* Set E1 of previously received NACK */
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 1;
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
control_pdu_info.num_nack += 1;
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
}
else {
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
control_pdu_info.ack_sn = sn_cursor;
status_report_completed = true;
}
segment_loop_end = true;
continue; //in order not to go to next cursor
} // end if (!lsf_received)
/* Go to next received PDU or PDU Segment */
cursor_p = cursor_p->next;
} //end if (cursor_p != NULL)
else if (!lsf_received) {
/* Previous PDU segment was the last one and had lsf indication : fill the latest gap */
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
/* Set E1 of previously received NACK */
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 1;
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
control_pdu_info.num_nack += 1;
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
}
else {
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
control_pdu_info.ack_sn = sn_cursor;
status_report_completed = true;
}
segment_loop_end = true;
}
} //end while (!segment_loop_end)
} // end if enough resource for transmitting at least one SOStart/SOEnd
else {
/* Not enough UL TBS to set at least one SOStart/SOEnd */
/* latest value of sn_nack shall be used as ACK_SN */
control_pdu_info.ack_sn = sn_nack;
status_report_completed = true;
}
}
/* Increment sn_nack except if sn_nack = vrMS and if current SN was not fully received */
if ((sn_nack != rlc_pP->vr_ms) && (all_segments_received)) {
sn_nack = RLC_AM_NEXT_SN(sn_nack);
cursor_p = cursor_p->next;
}
}
/* Set ACK_SN unless it was set before */
if (!status_report_completed){
control_pdu_info.ack_sn = sn_nack;
}
if (control_pdu_info.num_nack) {
control_pdu_info.e1 = 1;
}
} else {
control_pdu_info.ack_sn = rlc_pP->vr_r;
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d = VR(R)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
__LINE__,
control_pdu_info.ack_sn);
#endif
}
//msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] nb_bits_to_transmit %d\n",
// rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame,nb_bits_to_transmit);
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d NUM NACK %d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
__LINE__,
control_pdu_info.ack_sn,
control_pdu_info.num_nack);
#endif
/* encode the control pdu */
pdu_size = (nb_bits_transmitted + 7) >> 3;
AssertFatal (pdu_size <= rlc_pP->nb_bytes_requested_by_mac, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d forecast pdu_size %d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
__LINE__,
pdu_size);
#endif
tb_p = get_free_mem_block(sizeof(struct mac_tb_req) + pdu_size, __func__);
memset(tb_p->data, 0, sizeof(struct mac_tb_req) + pdu_size);
//estimation only ((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size;
((struct mac_tb_req*)(tb_p->data))->data_ptr = (uint8_t*)&(tb_p->data[sizeof(struct mac_tb_req)]);
// warning reuse of pdu_size
// TODO : rlc_am_write_status_pdu should be rewritten as not very tested ...
pdu_size = rlc_am_write_status_pdu(ctxt_pP, rlc_pP,(rlc_am_pdu_sn_10_t*)(((struct mac_tb_req*)(tb_p->data))->data_ptr), &control_pdu_info);
((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size;
//assert((((struct mac_tb_req*)(tb_p->data))->tb_size) < 3000);
#if TRACE_RLC_AM_STATUS_CREATION
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] SEND STATUS PDU SIZE %d, rlc_pP->nb_bytes_requested_by_mac %d, nb_bits_to_transmit>>3 %d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_size,
rlc_pP->nb_bytes_requested_by_mac,
nb_bits_to_transmit >> 3);
#endif
AssertFatal (pdu_size == ((nb_bits_transmitted + 7) >> 3), "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
// remaining bytes to transmit for RLC (retrans pdus and new data pdus)
rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - pdu_size;
// put pdu in trans
list_add_head(tb_p, &rlc_pP->control_pdu_list);
rlc_pP->stat_tx_control_pdu += 1;
rlc_pP->stat_tx_control_bytes += pdu_size;
}
#if 0
//-----------------------------------------------------------------------------
void
rlc_am_send_status_pdu_backup(
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t *const rlc_pP
)
{
// When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall:
// - if t-StatusProhibit is not running:
// - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer;
// - else:
// - at the first transmission opportunity indicated by lower layer after t-StatusProhibit expires, construct a single
// STATUS PDU even if status reporting was triggered several times while t-StatusProhibit was running and
// deliver it to lower layer;
//
// When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall:
// - start t-StatusProhibit.
//
// When constructing a STATUS PDU, the AM RLC entity shall:
// - for the AMD PDUs with SN such that VR(R) <= SN < VR(MR) that has not been completely received yet, in
// increasing SN of PDUs and increasing byte segment order within PDUs, starting with SN = VR(R) up to
// the point where the resulting STATUS PDU still fits to the total size of RLC PDU(s) indicated by lower layer:
// - for an AMD PDU for which no byte segments have been received yet::
// - include in the STATUS PDU a NACK_SN which is set to the SN of the AMD PDU;
// - for a continuous sequence of byte segments of a partly received AMD PDU that have not been received yet:
// - include in the STATUS PDU a set of NACK_SN, SOstart and SOend
// - set the ACK_SN to the SN of the next not received RLC Data PDU which is not indicated as missing in the
// resulting STATUS PDU.
signed int nb_bits_to_transmit = rlc_pP->nb_bytes_requested_by_mac << 3;
rlc_am_control_pdu_info_t control_pdu_info;
rlc_am_pdu_info_t *pdu_info_cursor_p = NULL;
......@@ -470,6 +817,7 @@ rlc_am_send_status_pdu(
rlc_am_rx_list_display(rlc_pP, " DISPLAY BEFORE CONSTRUCTION OF STATUS REPORT");
#endif
if (cursor_p != NULL) {
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
sn_cursor = pdu_info_cursor_p->sn;
......@@ -757,3 +1105,5 @@ end_push_nack:
rlc_pP->stat_tx_control_bytes += pdu_size;
}
#endif
......@@ -70,6 +70,8 @@ rlc_am_check_timer_reordering(
PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP,rlc_pP));
#endif
AssertFatal (rlc_pP->vr_x != RLC_SN_UNDEFINED, "RLC AM TReordering Expiry vrX not defined LcId=%d\n", rlc_pP->channel_id);
rlc_pP->t_reordering.running = 0;
rlc_pP->t_reordering.timed_out = 1;
rlc_pP->stat_timer_reordering_timed_out += 1;
......@@ -77,38 +79,54 @@ rlc_am_check_timer_reordering(
rlc_am_pdu_info_t* pdu_info;
mem_block_t* cursor;
cursor = rlc_pP->receiver_buffer.head;
rlc_usn_t vr_ms_new = rlc_pP->vr_x;
if (cursor) {
do {
pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info;
AssertFatal (cursor != NULL, "RLC AM TReordering Expiry Rx PDU list empty LcId=%d\n", rlc_pP->channel_id);
// NOT VERY SURE ABOUT THAT, THINK ABOUT IT
rlc_pP->vr_ms = (pdu_info->sn + 1) & RLC_AM_SN_MASK;
while ((cursor != NULL) && (vr_ms_new != rlc_pP->vr_h)) {
pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info;
if (rlc_am_sn_gte_vr_x(ctxt_pP, rlc_pP, pdu_info->sn)) {
if (((rlc_am_rx_pdu_management_t*)(cursor->data))->all_segments_received == 0) {
rlc_pP->vr_ms = pdu_info->sn;
break;
}
}
cursor = cursor->next;
} while (cursor != NULL);
// First find an element with SN greater or equal than vrX
if (RLC_AM_DIFF_SN(pdu_info->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(rlc_pP->vr_x,rlc_pP->vr_r)) {
if (((rlc_am_rx_pdu_management_t*)(cursor->data))->all_segments_received == 0) {
// Stop at first found discontinuity
// vr_ms_new holds SN following the latest in sequence fully received PDU >= old vrX
break;
}
else {
vr_ms_new = RLC_AM_NEXT_SN(vr_ms_new);
}
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT UPDATED VR(MS) %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->vr_ms);
}
cursor = cursor->next;
}
if (rlc_am_sn_gt_vr_ms(ctxt_pP, rlc_pP, rlc_pP->vr_h)) {
/* Update vr_ms */
rlc_pP->vr_ms = vr_ms_new;
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT UPDATED VR(MS) %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->vr_ms);
/* if new vrMS is lower than vrH, update vrX and restart timerReordering */
if (rlc_pP->vr_ms != rlc_pP->vr_h) {
rlc_pP->vr_x = rlc_pP->vr_h;
rlc_pP->t_reordering.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_reordering.ms_duration;
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT, RESTARTED T-REORDERING, UPDATED VR(X) to VR(R) %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->vr_x);
}
rlc_pP->status_requested = 1;
/* Trigger a STATUS report */
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING);
// Clear Delay flag if it was setup as it is useless due to Status PDU to be sent for TReordering expiry
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
}
}
}
......
......@@ -70,6 +70,8 @@ rlc_am_check_timer_status_prohibit(
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
//#warning TO DO rlc_am_check_timer_status_prohibit
rlc_am_stop_and_reset_timer_status_prohibit(ctxt_pP, rlc_pP);
/* Clear StatusProhibit flag */
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_PROHIBIT);
//rlc_pP->t_status_prohibit.frame_time_out = ctxt_pP->frame + rlc_pP->t_status_prohibit.time_out;
}
}
......
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