Commit 79242aaf authored by fnabet's avatar fnabet

RLC AM Tx changes

parent 5551c5e5
......@@ -43,6 +43,109 @@
#include "DL-AM-RLC.h"
//-----------------------------------------------------------------------------
uint32_t
rlc_am_get_status_pdu_buffer_occupancy(
rlc_am_entity_t * const rlc_pP){
//Compute Max Status PDU size according to what has been received and not received in the window [vrR vrMS[
// minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1
uint32_t nb_bits_to_transmit = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
mem_block_t *cursor_p = rlc_pP->receiver_buffer.head;
rlc_am_pdu_info_t *pdu_info_cursor_p = NULL;
int waited_so = 0;
rlc_sn_t sn_cursor = rlc_pP->vr_r;
rlc_sn_t sn_prev = rlc_pP->vr_r;
rlc_sn_t sn_end = rlc_pP->vr_ms;
boolean_t segment_loop_end = false;
if (sn_prev != sn_end)
{
while ((RLC_AM_DIFF_SN(sn_prev,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)) && (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;
// Add holes between sn_prev and sn_cursor
while ((sn_prev != sn_cursor) && (sn_prev != sn_end))
{
/* Add 1 NACK_SN + E1 + E2 */
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
sn_prev = RLC_AM_NEXT_SN(sn_prev);
} //end while (sn_prev != sn_cursor)
/* Handle case sn_cursor is partially received */
/* Each gap will add NACK_SN + E1 + E2 + SOStart + SOEnd */
if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) && (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)))
{
/* Check lsf */
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
/* Fill for [0 SO[ if SO not null */
if (pdu_info_cursor_p->so) {
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
/* Go to next segment */
cursor_p = cursor_p->next;
if (cursor_p != NULL)
{
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
}
}
else {
waited_so = pdu_info_cursor_p->payload_size;
}
/* Fill following gaps if any */
while (!segment_loop_end)
{
if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor))
{
/* Check lsf */
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
if (waited_so < pdu_info_cursor_p->so) {
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
}
else {
/* contiguous segment: only update waited_so */
/* Assuming so and payload_size updated according to duplication removal done at reception ... */
waited_so += pdu_info_cursor_p->payload_size;
}
/* Go to next received PDU or PDU Segment */
cursor_p = cursor_p->next;
if (cursor_p != NULL)
{
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
}
}
else
{
/* Fill last gap assuming LSF is not received */
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
segment_loop_end = true;
}
} // end while (!segment_loop_end)
} // end if segments
else
{
/* Go to next received PDU or PDU Segment */
cursor_p = cursor_p->next;
}
sn_prev = RLC_AM_NEXT_SN(sn_cursor);
}
} // end if (sn_prev != sn_end)
// round up to the greatest byte
return ((nb_bits_to_transmit + 7) >> 3);
}
//-----------------------------------------------------------------------------
uint32_t
rlc_am_get_buffer_occupancy_in_bytes (
......@@ -54,26 +157,24 @@ rlc_am_get_buffer_occupancy_in_bytes (
// priority of control trafic
rlc_pP->status_buffer_occupancy = 0;
if (rlc_pP->status_requested) {
if (rlc_pP->t_status_prohibit.running == 0) {
if ((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK)) {
rlc_pP->status_buffer_occupancy = rlc_am_get_status_pdu_buffer_occupancy(rlc_pP);
#if TRACE_RLC_AM_BO
if (((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3) > 0) {
LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3));
}
LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->status_buffer_occupancy);
#endif
rlc_pP->status_buffer_occupancy = ((15 + rlc_pP->num_nack_sn*(10+1) + rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
}
}
// data traffic
if (rlc_pP->nb_sdu_no_segmented <= 1) {
max_li_overhead = 0;
} else {
max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2);
/* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/
uint32_t num_li = rlc_pP->nb_sdu_no_segmented - 1;
max_li_overhead = num_li + (num_li >> 1) + (num_li & 1);
}
if (rlc_pP->sdu_buffer_occupancy == 0) {
......@@ -372,6 +473,7 @@ rlc_am_get_pdus (
}
}*/
// 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;
......
......@@ -72,24 +72,11 @@
# 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
#define RLC_AM_POLL_PDU_INFINITE 0xFFFF
#define RLC_AM_POLL_BYTE_INFINITE 0xFFFFFFFF
/* 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))
......@@ -99,10 +86,52 @@
#define RLC_AM_DIFF_SN(sn,snref) (RLC_DIFF_SN(sn,snref,RLC_AM_SN_MODULO))
#define RLC_AM_SN_IN_WINDOW(sn,snref) (RLC_SN_IN_WINDOW(sn,snref,RLC_AM_SN_MODULO))
#define RLC_SET_BIT(x,offset) ((x) |= (1 << (offset)))
#define RLC_GET_BIT(x,offset) (((x) & (1 << (offset))) >> (offset))
#define RLC_CLEAR_BIT(x,offset) ((x) &= ~(1 << (offset)))
#define RLC_SET_EVENT(x,event) ((x) |= (event))
#define RLC_GET_EVENT(x,event) ((x) & (event))
#define RLC_CLEAR_EVENT(x,event) ((x) &= (~(event)))
/* 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
#define RLC_AM_PDU_FI_BITS 2
#define RLC_AM_PDU_POLL_BITS 1
#define RLC_AM_PDU_RF_BITS 1
#define EURL_AM_PDU_LSF_BITS 1
/* AM Data PDU */
#define RLC_AM_PDU_E_OFFSET 2
#define RLC_AM_PDU_FI_OFFSET (RLC_AM_PDU_E_OFFSET + RLC_AM_PDU_E_BITS)
#define RLC_AM_PDU_POLL_OFFSET (RLC_AM_PDU_FI_OFFSET + RLC_AM_PDU_FI_BITS)
#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_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))
/* 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
/* Uplink STATUS PDU trigger events */
#define RLC_AM_STATUS_NOT_TRIGGERED 0
#define RLC_AM_STATUS_TRIGGERED_POLL 0x01 /* Status Report is triggered by a received poll */
......
......@@ -69,17 +69,15 @@ typedef struct rlc_am_entity_s {
pthread_mutex_t lock_input_sdus;
rlc_am_tx_sdu_management_t *input_sdus; /*!< \brief Input SDU buffer (for SDUs coming from upper layers). */
signed int nb_sdu; /*!< \brief Total number of valid rlc_am_tx_sdu_management_t in input_sdus[]. */
signed int nb_sdu_no_segmented; /*!< \brief Total number of SDUs not segmented and partially segmented. */
signed int nb_sdu_no_segmented; /*!< \brief Total number of SDUs not segmented and partially segmented. nb_sdu_no_segmented = next_sdu_index - current_sdu_index */
signed int next_sdu_index; /*!< \brief Next SDU index in input_sdus array where for a new incoming SDU. */
signed int current_sdu_index; /*!< \brief Current SDU index in input_sdus array to be segmented. */
signed int current_sdu_index; /*!< \brief Current SDU index in input_sdus array to be segmented which is not segmented or partially segmented. */
rlc_am_tx_data_pdu_management_t *pdu_retrans_buffer; /*!< \brief Retransmission buffer. */
signed int retrans_num_pdus; /*!< \brief Number of PDUs in the retransmission buffer. */
signed int retrans_num_bytes; /*!< \brief Number of bytes in the retransmission buffer. */
signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. */
unsigned int num_nack_so; /*!< \brief Number of segment offsets asked to be retransmitted by peer RLC entity. */
unsigned int num_nack_sn; /*!< \brief Number of segment asked to be retransmitted by peer RLC entity. */
boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */
//---------------------------------------------------------------------
......@@ -137,7 +135,7 @@ typedef struct rlc_am_entity_s {
//-----------------------------
uint16_t max_retx_threshold; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to limit the number of retransmissions of an AMD PDU. */
uint16_t poll_pdu; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollPDU PDUs. */
uint16_t poll_byte; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollByte bytes. */
uint32_t poll_byte; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollByte bytes. */
//---------------------------------------------------------------------
// STATISTICS
......@@ -176,7 +174,7 @@ typedef struct rlc_am_entity_s {
//---------------------------------------------------------------------
// OUTPUTS
//---------------------------------------------------------------------
sdu_size_t nb_bytes_requested_by_mac; /*!< \brief Number of bytes requested by lower layer for next transmission. */
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. */
......
......@@ -56,6 +56,8 @@ void rlc_am_free_in_sdu(
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
}
// TODO : this loop is useless as UL SDUs are transmitted and acknowledged in sequence
// even with PDCP UL SDU discard functionality
while ((rlcP->current_sdu_index != rlcP->next_sdu_index) &&
(rlcP->input_sdus[rlcP->current_sdu_index].flags.transmitted_successfully == 1)) {
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
......
......@@ -55,7 +55,6 @@ void rlc_am_nack_pdu (
int sdu_index;
if (mb_p != NULL) {
rlc_pP->num_nack_sn += 1;
assert(so_startP <= so_endP);
//-----------------------------------------
......@@ -69,10 +68,6 @@ void rlc_am_nack_pdu (
rlc_am_clear_holes(ctxt_pP, rlc_pP, snP);
}
if (!((so_startP == 0) && (so_endP == 0x7FFF))) {
rlc_pP->num_nack_so += 1;
}
rlc_am_add_hole(ctxt_pP, rlc_pP, snP, so_startP, so_endP);
if (rlc_pP->first_retrans_pdu_sn < 0) {
......@@ -283,7 +278,7 @@ mem_block_t* rlc_am_retransmit_get_copy (
pdu_mngt->flags.retransmit = 0;
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt->payload_size);
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt->payload_size,false);
return mb_copy;
} else {
return NULL;
......@@ -745,7 +740,7 @@ mem_block_t* rlc_am_retransmit_get_subsegment(
return NULL;
}
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sub_segment_p, test_pdu_copy_size);
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sub_segment_p, test_pdu_copy_size,false);
return mb_sub_segment_p;
} else {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] RE-SEND DATA PDU SN %04d BUT NO PDU AVAILABLE -> RETURN NULL\n",
......@@ -843,10 +838,12 @@ void rlc_am_retransmit_any_pdu(
// no need for update rlc_pP->nb_bytes_requested_by_mac
pdu_p = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, sn);
pdu_sn_10_p = (rlc_am_pdu_sn_10_t*) (&pdu_p->data[sizeof(struct mac_tb_req)]);
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->pdu_retrans_buffer[sn].header_and_payload_size);
pdu_sn_10_p->b1 = pdu_sn_10_p->b1 | 0x20;
rlc_pP->c_pdu_without_poll = 0;
rlc_pP->c_byte_without_poll = 0;
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->pdu_retrans_buffer[sn].header_and_payload_size,false);
//BugFix: polling is checked and done in function above !
//pdu_sn_10_p->b1 = pdu_sn_10_p->b1 | 0x20;
//BugFix : pdu_without_poll and byte_without_poll are reset only if a Poll is transmitted
//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;
......@@ -877,7 +874,7 @@ void rlc_am_retransmit_any_pdu(
rlc_am_nack_pdu (ctxt_pP, rlc_pP, found_pdu_sn, 0, 0x7FFF);
pdu_p = rlc_am_retransmit_get_subsegment(ctxt_pP, rlc_pP, found_pdu_sn, &rlc_pP->nb_bytes_requested_by_mac);
pdu_sn_10_p = (rlc_am_pdu_sn_10_t*) (&pdu_p->data[sizeof(struct mac_tb_req)]);
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->pdu_retrans_buffer[found_pdu_sn].header_and_payload_size);
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_sn_10_p, rlc_pP->pdu_retrans_buffer[found_pdu_sn].header_and_payload_size,false);
pdu_sn_10_p->b1 = pdu_sn_10_p->b1 | 0x20;
rlc_pP->c_pdu_without_poll = 0;
rlc_pP->c_byte_without_poll = 0;
......
......@@ -39,7 +39,8 @@ void rlc_am_pdu_polling (
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t *const rlc_pP,
rlc_am_pdu_sn_10_t *const pdu_pP,
const int16_t payload_sizeP)
const int16_t payload_sizeP,
boolean_t is_new_pdu)
{
// 5.2.2 Polling
// An AM RLC entity can poll its peer AM RLC entity in order to trigger STATUS reporting at the peer AM RLC entity.
......@@ -68,41 +69,50 @@ void rlc_am_pdu_polling (
// - start t-PollRetransmit;
// - else:
// - restart t-PollRetransmit;
rlc_pP->c_pdu_without_poll += 1;
rlc_pP->c_byte_without_poll += payload_sizeP;
if (is_new_pdu) {
if (rlc_pP->poll_pdu != RLC_AM_POLL_PDU_INFINITE) {
rlc_pP->c_pdu_without_poll += 1;
}
if (rlc_pP->poll_byte != RLC_AM_POLL_BYTE_INFINITE) {
rlc_pP->c_byte_without_poll += payload_sizeP;
}
}
if (
(rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) ||
(rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte) ||
((is_new_pdu) && ((rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) ||
(rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte))) ||
((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) ||
(rlc_pP->vt_s == rlc_pP->vt_ms) ||
(rlc_pP->force_poll == TRUE)
(rlc_pP->force_poll == true)
) {
rlc_pP->force_poll = FALSE;
rlc_pP->force_poll = false;
if (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) {
if ((is_new_pdu) && (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu)) {
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX NUM PDU THRESHOLD %d HAS BEEN REACHED\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->poll_pdu);
} else
if (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte) {
}
if ((is_new_pdu) && (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte)) {
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX NUM BYTES THRESHOLD %d HAS BEEN REACHED\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->poll_byte);
} else
}
if ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) {
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX BUFFERS ARE EMPTY\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
} else
}
if (rlc_pP->vt_s == rlc_pP->vt_ms) {
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE OF WINDOW STALLING\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
}
pdu_pP->b1 = pdu_pP->b1 | 0x20;
RLC_AM_PDU_SET_POLL(pdu_pP->b1);
rlc_pP->c_pdu_without_poll = 0;
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;
//optimisation if (!rlc_pP->t_poll_retransmit.running) {
rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP);
......@@ -110,7 +120,8 @@ void rlc_am_pdu_polling (
//optimisation rlc_pP->t_poll_retransmit.frame_time_out = ctxt_pP->frame + rlc_pP->t_poll_retransmit.time_out;
//optimisation }
} else {
pdu_pP->b1 = pdu_pP->b1 & 0xDF;
// Not sure this is necessary
RLC_AM_PDU_CLEAR_POLL(pdu_pP->b1);
}
}
//-----------------------------------------------------------------------------
......@@ -178,7 +189,9 @@ void rlc_am_segment_10 (
if (rlc_pP->nb_sdu_no_segmented <= 1) {
max_li_overhead = 0;
} else {
max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2);
/* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/
test_num_li = rlc_pP->nb_sdu_no_segmented - 1;
max_li_overhead = test_num_li + (test_num_li >> 1) + (test_num_li & 1);
}
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] max_li_overhead %d\n",
......@@ -485,11 +498,11 @@ void rlc_am_segment_10 (
fi = fi + 1;
}
pdu_p->b1 = pdu_p->b1 | (fi << 3);
pdu_p->b1 = pdu_p->b1 | (fi << RLC_AM_PDU_FI_OFFSET);
// set fist e bit
if (fill_num_li > 0) {
pdu_p->b1 = pdu_p->b1 | 0x04;
RLC_AM_PDU_SET_E(pdu_p->b1);
}
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] SEND PDU SN %04d SIZE %d BYTES PAYLOAD SIZE %d BYTES\n",
......@@ -501,8 +514,9 @@ void rlc_am_segment_10 (
rlc_pP->stat_tx_data_pdu += 1;
rlc_pP->stat_tx_data_bytes += (data_pdu_size - pdu_remaining_size);
//pdu_p->sn = rlc_pP->vt_s;
pdu_p->b1 = pdu_p->b1 | 0x80; // DATA/CONTROL field is DATA PDU
// set DATA/CONTROL field is DATA PDU(1)
RLC_AM_PDU_SET_D_C(pdu_p->b1);
// set sn = rlc_pP->vt_s;
pdu_p->b1 = pdu_p->b1 | (rlc_pP->vt_s >> 8);
pdu_p->b2 = rlc_pP->vt_s & 0xFF;
rlc_pP->vt_s = (rlc_pP->vt_s+1) & RLC_AM_SN_MASK;
......@@ -511,13 +525,14 @@ void rlc_am_segment_10 (
pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size;
//#warning "why 3000: changed to RLC_SDU_MAX_SIZE "
assert(pdu_tb_req_p->tb_size < RLC_SDU_MAX_SIZE );
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt_p->payload_size);
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt_p->payload_size,true);
//list_add_tail_eurecom (pdu_mem_p, &rlc_pP->segmentation_pdu_list);
pdu_mngt_p->mem_block = pdu_mem_p;
pdu_mngt_p->first_byte = (unsigned char*)pdu_p;
pdu_mngt_p->header_and_payload_size = data_pdu_size - pdu_remaining_size;
pdu_mngt_p->retx_count = -1;
pdu_mngt_p->flags.transmitted = 1;
rlc_pP->retrans_num_pdus += 1;
rlc_pP->retrans_num_bytes += pdu_mngt_p->header_and_payload_size;
......
......@@ -51,14 +51,14 @@
# endif
# endif
/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP)
/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP,boolean_t is_new_pdu)
* \brief Set or not the poll bit in the PDU header depending on RLC AM protocol variables.
* \param[in] ctxt_pP Running context.
* \param[in] rlcP RLC AM protocol instance pointer.
* \param[in] pduP Pointer on the header of the PDU in order to be able to set the poll bit if necessary.
* \param[in] payload_sizeP Size of the payload of the PDU.
*/
protected_rlc_am_segment(void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP);)
protected_rlc_am_segment(void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP,boolean_t is_new_pdu);)
/*! \fn void rlc_am_segment_10 (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP)
* \brief Segment a PDU with 10 bits sequence number, based on segmentation information given by MAC (size to transmit).
......
......@@ -88,9 +88,12 @@ typedef struct rlc_am_tx_sdu_management {
* \brief Structure containing PDU variables related to its retransmission.
*/
typedef struct pdu_management_flags {
uint8_t transmitted:1; /*!< \brief Boolean telling that this PDU is not empty and has been at least transmitted once. */
uint8_t ack:1; /*!< \brief Boolean telling that this PDU has been acknowledged. */
uint8_t nack:1; /*!< \brief Boolean telling that this PDU has been acknowledged negatively. */
uint8_t retransmit:1; /*!< \brief Boolean telling a retransmission is scheduled for this PDU. */
uint8_t dummy:6; /*!< \brief Free bits. */
uint8_t max_retransmit:1; /*!< \brief Boolean telling max retransmission has been hit for this PDU. */
uint8_t dummy:3; /*!< \brief Free bits. */
} pdu_management_flags_t;
......
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