Commit b0d468c0 authored by fnabet's avatar fnabet

RLC AM: add retransmission and Rx status pdu

parent e7e48144
......@@ -389,7 +389,7 @@ rlc_am_get_pdus (
rlc_am_entity_t * const rlc_pP
)
{
int display_flag = 0;
//int display_flag = 0;
// 5.1.3.1 Transmit operations
// 5.1.3.1.1
// General
......@@ -436,123 +436,21 @@ rlc_am_get_pdus (
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)) {
mem_block_t* pdu = list_get_head(&rlc_pP->control_pdu_list);
if (pdu != NULL {
if ( ((rlc_am_tx_control_pdu_management_t*)(pdu->data))->size <= rlc_pP->nb_bytes_requested_by_mac) {
pdu = list_remove_head(&rlc_pP->control_pdu_list);
#if TRACE_RLC_AM_TX
msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND CONTROL PDU\n", ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, ctxt_pP->frame);
#endif
list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - ((rlc_am_tx_control_pdu_management_t*)(pdu->data))->size;
} else {
stay_on_this_list = 0;
}
} else {
stay_on_this_list = 0;
}
}*/
// THEN TRY TO SEND RETRANS PDU
// BUG FIX : they can be PDU to ReTx due to received NACK or 1 PDU (SN = vtS - 1) to ReTx due TPoll Expiry if Buffer Occupancy is null
if (rlc_pP->first_retrans_pdu_sn >= 0) {
rlc_am_tx_data_pdu_management_t* tx_data_pdu_management;
// tx min 3 bytes because of the size of the RLC header
while ((rlc_pP->nb_bytes_requested_by_mac > 2) &&
(rlc_pP->first_retrans_pdu_sn >= 0) &&
(rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s)) {
tx_data_pdu_management = &rlc_pP->tx_data_pdu_buffer[rlc_pP->first_retrans_pdu_sn];
if ((tx_data_pdu_management->header_and_payload_size <= rlc_pP->nb_bytes_requested_by_mac) && (tx_data_pdu_management->retx_count >= 0)
&& (tx_data_pdu_management->nack_so_start == 0) && (tx_data_pdu_management->nack_so_stop == 0x7FFF)) {
mem_block_t* copy = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RE-SEND DATA PDU SN %04d %d BYTES\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->first_retrans_pdu_sn,
tx_data_pdu_management->header_and_payload_size);
rlc_pP->stat_tx_data_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu_by_status += 1;
rlc_pP->stat_tx_data_bytes += tx_data_pdu_management->header_and_payload_size;
rlc_pP->stat_tx_retransmit_bytes += tx_data_pdu_management->header_and_payload_size;
rlc_pP->stat_tx_retransmit_bytes_by_status += tx_data_pdu_management->header_and_payload_size;
list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - tx_data_pdu_management->header_and_payload_size;
tx_data_pdu_management->retx_count = tx_data_pdu_management->retx_count_next;
return;
} else if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac >= RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d MAC BYTES %d SIZE %d RTX COUNT %d nack_so_start %d nack_so_stop %04X(hex)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->first_retrans_pdu_sn,
rlc_pP->nb_bytes_requested_by_mac,
tx_data_pdu_management->header_and_payload_size,
tx_data_pdu_management->retx_count,
tx_data_pdu_management->nack_so_start,
tx_data_pdu_management->nack_so_stop);
mem_block_t* copy = rlc_am_retransmit_get_subsegment(
ctxt_pP,
rlc_pP,
rlc_pP->first_retrans_pdu_sn,
&rlc_pP->nb_bytes_requested_by_mac);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->first_retrans_pdu_sn,
tx_data_pdu_management->nack_so_start);
rlc_pP->stat_tx_data_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu += 1;
rlc_pP->stat_tx_retransmit_pdu_by_status += 1;
rlc_pP->stat_tx_data_bytes += (((struct mac_tb_req*)(copy->data))->tb_size);
rlc_pP->stat_tx_retransmit_bytes += (((struct mac_tb_req*)(copy->data))->tb_size);
rlc_pP->stat_tx_retransmit_bytes_by_status += (((struct mac_tb_req*)(copy->data))->tb_size);
list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
} else {
break;
}
// update first_retrans_pdu_sn
while ((rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s) &&
(!(rlc_pP->tx_data_pdu_buffer[rlc_pP->first_retrans_pdu_sn].flags.retransmit))) {
rlc_pP->first_retrans_pdu_sn = (rlc_pP->first_retrans_pdu_sn+1) & RLC_AM_SN_MASK;
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn SN %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->first_retrans_pdu_sn);
};
if ((rlc_pP->retrans_num_bytes_to_retransmit) && (rlc_pP->nb_bytes_requested_by_mac > 2)) {
display_flag = 1;
if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
// no more pdu to be retransmited
rlc_pP->first_retrans_pdu_sn = -1;
display_flag = 0;
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CLEAR first_retrans_pdu_sn\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
}
/* Get 1 AM data PDU or PDU segment to retransmit */
mem_block_t* pdu_retx = rlc_am_get_pdu_to_retransmit(ctxt_pP, rlc_pP);
if (display_flag > 0) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->first_retrans_pdu_sn);
}
if (pdu_retx != NULL) {
list_add_tail_eurecom (pdu_retx, &rlc_pP->pdus_to_mac_layer);
return;
/* ONLY ONE TB PER TTI
if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
#if TRACE_RLC_AM_TX
msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BREAK LOOP ON RETRANSMISSION BECAUSE ONLY %d BYTES ALLOWED TO TRANSMIT BY MAC\n",ctxt_pP->frame, ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, rlc_pP->nb_bytes_requested_by_mac);
#endif
break;
}*/
}
}
if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
// THEN TRY TO SEND NEW DATA PDU
if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->sdu_buffer_occupancy) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
rlc_am_segment_10(ctxt_pP, rlc_pP);
list_add_list (&rlc_pP->segmentation_pdu_list, &rlc_pP->pdus_to_mac_layer);
......@@ -563,29 +461,6 @@ rlc_am_get_pdus (
}
}
if ((rlc_pP->pdus_to_mac_layer.head == NULL) &&
(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP)) &&
(rlc_pP->nb_bytes_requested_by_mac > 2)) {
rlc_am_retransmit_any_pdu(ctxt_pP, rlc_pP);
return;
} else {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" COULD NOT RETRANSMIT ANY PDU BECAUSE ",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
if (rlc_pP->pdus_to_mac_layer.head != NULL) {
LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
}
if (!(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP))) {
LOG_D(RLC, "TIMER POLL DID NOT TIMED OUT (RUNNING = %d NUM PDUS TO RETRANS = %d NUM BYTES TO RETRANS = %d) ", rlc_pP->t_poll_retransmit.running,
rlc_pP->retrans_num_pdus, rlc_pP->retrans_num_bytes_to_retransmit);
}
if (rlc_pP->nb_bytes_requested_by_mac <= 2) {
LOG_D(RLC, "NUM BYTES REQUESTED BY MAC = %d", rlc_pP->nb_bytes_requested_by_mac);
}
LOG_D(RLC, "\n");
}
break;
......
......@@ -56,6 +56,9 @@
/** PDU minimal header size in bytes. */
# define RLC_AM_HEADER_MIN_SIZE 2
/** PDU Segment minimal header size in bytes = PDU header + SOStart + SOEnd. */
# define RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE 4
/** If we want to send a segment of a PDU, then the min transport block size requested by MAC should be this amount. */
# define RLC_AM_MIN_SEGMENT_SIZE_REQUEST 8
......@@ -77,8 +80,8 @@
/* MACRO DEFINITIONS */
#define RLC_AM_NEXT_SN(sn) (((sn)+1) & ((RLC_AM_SN_MODULO)-1))
#define RLC_AM_PREV_SN(sn) (((sn)+(RLC_AM_SN_MODULO)-1) & ((RLC_AM_SN_MODULO)-1))
#define RLC_AM_NEXT_SN(sn) (((sn)+1) & (RLC_AM_SN_MASK))
#define RLC_AM_PREV_SN(sn) (((sn)+(RLC_AM_SN_MODULO)-1) & (RLC_AM_SN_MASK))
#define RLC_DIFF_SN(sn,snref,modulus) ((sn+(modulus)-snref) & ((modulus)-1))
#define RLC_SN_IN_WINDOW(sn,snref,modulus) ((RLC_DIFF_SN(sn,snref,modulus)) < ((modulus) >> 1))
......@@ -103,7 +106,8 @@
#define RLC_AM_PDU_RF_BITS 1
#define EURL_AM_PDU_LSF_BITS 1
#define RLC_AM_LI_BITS 11
#define RLC_AM_LI_MASK 0x7FF
/* AM Data PDU */
......@@ -113,12 +117,28 @@
#define RLC_AM_PDU_RF_OFFSET (RLC_AM_PDU_POLL_OFFSET + RLC_AM_PDU_POLL_BITS)
#define RLC_AM_PDU_D_C_OFFSET (RLC_AM_PDU_RF_OFFSET + RLC_AM_PDU_RF_BITS)
#define RLC_AM_PDU_GET_FI_START(px) (RLC_GET_BIT((px),RLC_AM_PDU_FI_OFFSET + 1))
#define RLC_AM_PDU_GET_FI_END(px) (RLC_GET_BIT((px),RLC_AM_PDU_FI_OFFSET))
#define RLC_AM_PDU_GET_LI(x,offset) (((x) >> (offset)) & RLC_AM_LI_MASK)
#define RLC_AM_PDU_SET_LI(x,li,offset) ((x) |= (((li) & RLC_AM_LI_MASK) << (offset)))
#define RLC_AM_PDU_SET_E(px) (RLC_SET_BIT((px),RLC_AM_PDU_E_OFFSET))
#define RLC_AM_PDU_SET_D_C(px) (RLC_SET_BIT((px),RLC_AM_PDU_D_C_OFFSET))
#define RLC_AM_PDU_SET_RF(px) (RLC_SET_BIT((px),RLC_AM_PDU_RF_OFFSET))
#define RLC_AM_PDU_SET_POLL(px) (RLC_SET_BIT((px),RLC_AM_PDU_POLL_OFFSET))
#define RLC_AM_PDU_CLEAR_POLL(px) (RLC_CLEAR_BIT((px),RLC_AM_PDU_POLL_OFFSET))
#define RLC_AM_PDU_SEGMENT_SO_LENGTH 15
#define RLC_AM_PDU_SEGMENT_SO_BYTES 2
#define RLC_AM_PDU_SEGMENT_SO_OFFSET 0
#define RLC_AM_PDU_LSF_OFFSET (RLC_AM_PDU_SEGMENT_SO_OFFSET + RLC_AM_PDU_SEGMENT_SO_LENGTH)
#define RLC_AM_PDU_SET_LSF(px) (RLC_SET_BIT((px),RLC_AM_PDU_LSF_OFFSET))
#define RLC_AM_HEADER_LI_LENGTH(li) ((li) + ((li)>>1) + ((li)&1))
#define RLC_AM_PDU_SEGMENT_HEADER_SIZE(numLis) (RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + RLC_AM_HEADER_LI_LENGTH(numLis))
/* STATUS PDU */
#define RLC_AM_STATUS_PDU_CPT_STATUS 0
......
......@@ -175,7 +175,6 @@ typedef struct rlc_am_entity_s {
sdu_size_t nb_bytes_requested_by_mac; /*!< \brief Number of remaining bytes available for transmission of any RLC PDU indicated by lower layer */
list_t pdus_to_mac_layer; /*!< \brief PDUs buffered for transmission to MAC layer. */
list_t control_pdu_list; /*!< \brief Control PDUs buffered for transmission to MAC layer. */
rlc_sn_t first_retrans_pdu_sn; /*!< \brief Lowest sequence number of PDU to be retransmitted. */
list_t segmentation_pdu_list; /*!< \brief List of "freshly" segmented PDUs. */
uint8_t status_requested; /*!< \brief Status bitmap requested by peer. */
......
......@@ -108,3 +108,41 @@ rlc_am_in_sdu_is_empty(
return 0;
}
// called when PDU is ACKED
//-----------------------------------------------------------------------------
void
rlc_am_pdu_sdu_data_cnf(
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t* const rlc_pP,
const rlc_sn_t snP)
{
int pdu_sdu_index;
int sdu_index;
for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->tx_data_pdu_buffer[snP].nb_sdus; pdu_sdu_index++) {
sdu_index = rlc_pP->tx_data_pdu_buffer[snP].sdus_index[pdu_sdu_index];
assert(sdu_index >= 0);
assert(sdu_index < RLC_AM_SDU_CONTROL_BUFFER_SIZE);
rlc_pP->input_sdus[sdu_index].nb_pdus_ack += 1;
if ((rlc_pP->input_sdus[sdu_index].nb_pdus_ack == rlc_pP->input_sdus[sdu_index].nb_pdus) &&
(rlc_pP->input_sdus[sdu_index].sdu_remaining_size == 0)) {
#if TEST_RLC_AM
rlc_am_v9_3_0_test_data_conf (
rlc_pP->module_id,
rlc_pP->rb_id,
rlc_pP->input_sdus[sdu_index].mui,
RLC_SDU_CONFIRM_YES);
#else
rlc_data_conf(
ctxt_pP,
rlc_pP->rb_id,
rlc_pP->input_sdus[sdu_index].mui,
RLC_SDU_CONFIRM_YES,
rlc_pP->is_data_plane);
#endif
rlc_am_free_in_sdu(ctxt_pP, rlc_pP, sdu_index);
}
}
}
......@@ -77,5 +77,13 @@ protected_rlc_am_in_sdu(void rlc_am_free_in_sdu_data (const protocol_ctxt_t* con
* \return 1 if the buffer is empty, else 0.
*/
protected_rlc_am_in_sdu(signed int rlc_am_in_sdu_is_empty(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP);)
/*! \fn void rlc_am_pdu_sdu_data_cnf(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,const rlc_sn_t snP)
* \brief Process SDU cnf of a ACKED PDU for all SDUs concatenated in this PDU.
* \param[in] ctxtP Running context.
* \param[in] rlcP RLC AM protocol instance pointer.
* \param[in] snP Sequence number of the PDU.
*/
protected_rlc_am_in_sdu(void rlc_am_pdu_sdu_data_cnf(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,const rlc_sn_t snP);)
/** @} */
# endif
......@@ -80,7 +80,6 @@ rlc_am_init(
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE;
}
......@@ -136,7 +135,6 @@ rlc_am_reestablish(
rlc_pP->status_requested = RLC_AM_STATUS_NOT_TRIGGERED;
rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE;
......
......@@ -50,21 +50,24 @@
# define public_rlc_am_retransmit(x) extern x
# endif
# endif
/*! \fn void rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, uint16_t snP, sdu_size_t so_startP, sdu_size_t so_endP)
/*! \fn boolean_t rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, int16_t snP, int16_t prev_nack_snP,sdu_size_t so_startP, sdu_size_t so_endP)
* \brief The RLC AM PDU which have the sequence number snP is marked NACKed with segment offset fields.
* \param[in] ctxtP Running context.
* \param[in] rlcP RLC AM protocol instance pointer.
* \param[in] snP Sequence number of the PDU that is negative acknowledged.
* \param[in] prev_nack_snP Sequence number of previous PDU that is negative acknowledged.
* \param[in] so_startP Start of the segment offset of the PDU that .
* \param[in] so_endP Transport blocks received from MAC layer.
* \return OK/KO
* \note It may appear a new hole in the retransmission buffer depending on the segment offset informations. Depending on the state of the retransmission buffer, negative confirmation can be sent to higher layers about the drop by the RLC AM instance of a particular SDU.
*/
protected_rlc_am_retransmit(void rlc_am_nack_pdu (
protected_rlc_am_retransmit(boolean_t rlc_am_nack_pdu (
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t *const rlcP,
const rlc_sn_t snP,
const sdu_size_t so_startP,
const sdu_size_t so_endP);)
const rlc_sn_t prev_nack_snP,
sdu_size_t so_startP,
sdu_size_t so_endP);)
/*! \fn void rlc_am_ack_pdu (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP, rlc_sn_t snP)
* \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
......@@ -90,6 +93,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_copy (
rlc_am_entity_t *const rlcP,
const rlc_sn_t snP));
#if 0
/*! \fn mem_block_t* rlc_am_retransmit_get_subsegment (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP,rlc_sn_t snP, sdu_size_t *sizeP)
* \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
* \param[in] ctxtP Running context.
......@@ -103,7 +107,18 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment (
rlc_am_entity_t *const rlcP,
const rlc_sn_t snP,
sdu_size_t *const sizeP));
#endif
/*! \fn mem_block_t* rlc_am_get_pdu_to_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* rlcP)
* \brief Find a PDU or PDU segment to retransmit.
* \param[in] ctxtP Running context.
* \param[in] rlcP RLC AM protocol instance pointer.
* \return A copy of the retransmitted PDU or PDU segment or NULL if TBS was not big enough
*/
protected_rlc_am_retransmit(mem_block_t* rlc_am_get_pdu_to_retransmit(
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t* const rlcP);)
#if 0
/*! \fn void rlc_am_retransmit_any_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* rlcP)
* \brief Retransmit any PDU in order to unblock peer entity, if no suitable PDU is found (depending on requested MAC size) to be retransmitted, then try to retransmit a subsegment of any PDU.
* \param[in] ctxtP Running context.
......@@ -112,6 +127,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment (
protected_rlc_am_retransmit(void rlc_am_retransmit_any_pdu(
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t* const rlcP);)
#endif
/*! \fn void rlc_am_tx_buffer_display (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* rlcP, char* message_pP)
* \brief Display the dump of the retransmission buffer.
......
......@@ -113,14 +113,14 @@ void rlc_am_pdu_polling (
rlc_pP->c_byte_without_poll = 0;
// vt_s shall have been updated before in case of new transmission
rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK;
rlc_pP->poll_sn = RLC_AM_PREV_SN(rlc_pP->vt_s);
//optimisation if (!rlc_pP->t_poll_retransmit.running) {
rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP);
//optimisation } else {
//optimisation rlc_pP->t_poll_retransmit.frame_time_out = ctxt_pP->frame + rlc_pP->t_poll_retransmit.time_out;
//optimisation }
} else {
// Not sure this is necessary
// Need to clear poll bit as it may be a copy(retransmission case) of the original RLC PDU which was containing a poll
RLC_AM_PDU_CLEAR_POLL(pdu_pP->b1);
}
}
......@@ -533,16 +533,19 @@ void rlc_am_segment_10 (
pdu_mngt_p->header_and_payload_size = data_pdu_size - pdu_remaining_size;
pdu_mngt_p->retx_count = 0;
pdu_mngt_p->retx_count_next = 0;
pdu_mngt_p->flags.retransmit = 0;
pdu_mngt_p->flags.transmitted = 1;
//TBC: What for resetting local pointers at the end ??
pdu_p = NULL;
pdu_mem_p = NULL;
//nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
nb_bytes_to_transmit = 0; // 1 PDU only
mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, (rlc_pP->vt_s-1) & RLC_AM_SN_MASK);
/* We need to copy the PDU to pass to MAC in order to keep it in the buffer for potential retransmissions */
mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, RLC_AM_PREV_SN(rlc_pP->vt_s));
list_add_tail_eurecom (copy, &rlc_pP->segmentation_pdu_list);
}
......
......@@ -268,6 +268,14 @@ rlc_am_receive_process_control_pdu(
{
rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)*first_byte_ppP;
sdu_size_t initial_pdu_size = *tb_size_in_bytes_pP;
rlc_sn_t ack_sn = rlc_pP->control_pdu_info.ack_sn;
rlc_sn_t sn_cursor = rlc_pP->vt_a;
rlc_sn_t vt_a_new = rlc_pP->vt_a;
rlc_sn_t sn_data_cnf;
rlc_sn_t nack_sn,prev_nack_sn;
sdu_size_t data_cnf_so_stop = 0x7FFF;
unsigned int nack_index;
boolean_t status = TRUE;
if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, tb_size_in_bytes_pP, &rlc_pP->control_pdu_info) >= 0) {
......@@ -280,10 +288,6 @@ rlc_am_receive_process_control_pdu(
rlc_pP->control_pdu_info.ack_sn);
rlc_am_display_control_pdu_infos(&rlc_pP->control_pdu_info);
rlc_sn_t ack_sn = rlc_pP->control_pdu_info.ack_sn;
rlc_sn_t sn_cursor = rlc_pP->vt_a;
rlc_sn_t nack_sn;
unsigned int nack_index;
// 5.2.1 Retransmission
//
......@@ -308,50 +312,89 @@ 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);
/* 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 */
/* Note : 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) {
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor);
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
}
vt_a_new = ack_sn;
sn_data_cnf = RLC_AM_PREV_SN(vt_a_new);
} else {
nack_index = 0;
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
prev_nack_sn = 0x3FFF;
while (sn_cursor != ack_sn) {
while (sn_cursor != nack_sn) {
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor);
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
}
vt_a_new = nack_sn;
// catch DataCfn
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[nack_sn];
if (tx_data_pdu_buffer_p->retx_payload_size == tx_data_pdu_buffer_p->payload_size) {
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
}
else if (tx_data_pdu_buffer_p->nack_so_start != 0) {
sn_data_cnf = nack_sn;
data_cnf_so_stop = tx_data_pdu_buffer_p->nack_so_start - 1;
}
else {
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
}
while ((sn_cursor != ack_sn) && (status)) {
if (sn_cursor != nack_sn) {
rlc_am_ack_pdu(ctxt_pP,
rlc_pP,
sn_cursor);
} else {
rlc_am_nack_pdu (ctxt_pP,
status = rlc_am_nack_pdu (ctxt_pP,
rlc_pP,
sn_cursor,
nack_sn,
prev_nack_sn,
rlc_pP->control_pdu_info.nack_list[nack_index].so_start,
rlc_pP->control_pdu_info.nack_list[nack_index].so_end);
nack_index = nack_index + 1;
prev_nack_sn = nack_sn;
if (nack_index == rlc_pP->control_pdu_info.num_nack) {
nack_sn = 0xFFFF; // value never reached by sn
} else {
if (nack_index < rlc_pP->control_pdu_info.num_nack) {
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
}
else if (nack_sn != ack_sn) {
/* general case*/
nack_sn = ack_sn;
}
else {
/*specific case when the sender did not have enough TBS to fill all SOStart SOEnd for this NACK_SN */
break;
}
if ((nack_index < rlc_pP->control_pdu_info.num_nack) && (nack_index > 0)) {
if (rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn != rlc_pP->control_pdu_info.nack_list[nack_index-1].nack_sn) {
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
}
} else {
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
}
}
} 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));
status = FALSE;
}
} else {
LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR IN DECODING CONTROL PDU\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
status = FALSE;
}
if (status) {
/* 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))) {
......@@ -359,15 +402,23 @@ rlc_am_receive_process_control_pdu(
rlc_pP->poll_sn = RLC_SN_UNDEFINED;
}
/* Update vtA */
//TODO : this part does not cover all cases of Data Cnf and move it at the end of Status PDU processing
sn_cursor = rlc_pP->vt_a;
} 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));
/* Handle all acked PDU up to and excluding sn_data_cnf */
while (sn_cursor != sn_data_cnf) {
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_cursor);
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
}
} else {
LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR IN DECODING CONTROL PDU\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
// Handle last SN. TO DO : case of PDU partially ACKED with SDU to be data conf
if (data_cnf_so_stop == 0x7FFF) {
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_data_cnf);
}
/* Update vtA and vtMS */
rlc_pP->vt_a = vt_a_new;
rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
}
*first_byte_ppP = (uint8_t*)((uint64_t)*first_byte_ppP + initial_pdu_size - *tb_size_in_bytes_pP);
......
......@@ -113,9 +113,10 @@ typedef struct rlc_am_tx_data_pdu_management {
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. */
sdu_size_t retx_payload_size; /*!< \brief Size of the PDU payload to be retransmitted in bytes including all Segment portions. */
rlc_sn_t sn; /*!< \brief Sequence number of the PDU. */
sdu_size_t nack_so_start; /*!< \brief Lowest NACK start segment offset, must be set to 0 if global NACK. */
sdu_size_t nack_so_stop; /*!< \brief Highest NACK stop segment offset, must be set to data_size if global NACK */
sdu_size_t nack_so_stop; /*!< \brief Highest NACK stop segment offset, must be set to data_size - 1 if global NACK */
int8_t nb_sdus; /*!< \brief Number of sdu having segments in this pdu. */
int8_t retx_count; /*!< \brief Counts the number of already occurred retransmissions of an AMD PDU (see subclause 5.2.1). */
......
......@@ -90,8 +90,12 @@ rlc_am_check_timer_poll_retransmit(
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;
if (rlc_pP->tx_data_pdu_buffer[sn].retx_count == rlc_pP->tx_data_pdu_buffer[sn].retx_count_next) {
rlc_pP->tx_data_pdu_buffer[sn].retx_count_next ++;
}
rlc_pP->retrans_num_pdus += 1;
rlc_pP->retrans_num_bytes_to_retransmit += rlc_pP->tx_data_pdu_buffer[sn].payload_size;
break;
}
else
{
......
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