Commit b77694e8 authored by fnabet's avatar fnabet

main AM RX process PDU changes

parent dec41a2a
......@@ -51,7 +51,7 @@
# define RLC_AM_SDU_CONTROL_BUFFER_SIZE 128
/** Size of the retransmission buffer (number of PDUs). */
# define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_SN_MODULO
# define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_WINDOW_SIZE
/** PDU minimal header size in bytes. */
# define RLC_AM_HEADER_MIN_SIZE 2
......@@ -69,6 +69,36 @@
# define RLC_AM_MAX_NACK_IN_STATUS_PDU 1023
/** Max holes created by NACK_SN with segment offsets for a PDU in the retransmission buffer. */
# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 32
# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 16
/** @} */
# endif
/* 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_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))
#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_EVENT(x,event) ((x) |= (event))
#define RLC_GET_EVENT(x,event) ((x) & (event))
#define RLC_CLEAR_EVENT(x,event) ((x) &= (~(event)))
/* 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 */
#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 */
/* 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))
#define RLC_AM_GET_STATUS(x,event) (RLC_GET_EVENT(x,event))
#define RLC_AM_CLEAR_STATUS(x,event) (RLC_CLEAR_EVENT(x,event))
#define RLC_AM_CLEAR_ALL_STATUS(x) ((x) = (RLC_AM_STATUS_NOT_TRIGGERED))
#endif
......@@ -182,7 +182,8 @@ typedef struct rlc_am_entity_s {
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. */
boolean_t status_requested; /*!< \brief Status 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. */
frame_t last_frame_status_indication; /*!< \brief The last frame number a MAC status indication has been received by RLC. */
//-----------------------------
// buffer occupancy measurements sent to MAC
......
......@@ -74,9 +74,10 @@ rlc_am_init(
// RX state variables
//rlc_pP->vr_r = 0;
rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
//rlc_pP->vr_x = 0;
rlc_pP->vr_x = RLC_SN_UNDEFINED;
//rlc_pP->vr_ms = 0;
//rlc_pP->vr_h = 0;
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->last_frame_status_indication = 123456; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
......@@ -128,9 +129,11 @@ rlc_am_reestablish(
// RX state variables
rlc_pP->vr_r = 0;
rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
rlc_pP->vr_x = 0;
rlc_pP->vr_x = RLC_SN_UNDEFINED;
rlc_pP->vr_ms = 0;
rlc_pP->vr_h = 0;
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->status_requested = RLC_AM_STATUS_NOT_TRIGGERED;
rlc_pP->last_frame_status_indication = 123456; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
......
......@@ -47,7 +47,8 @@ rlc_am_get_data_pdu_infos(
pdu_info_pP->num_li = 0;
if (pdu_info_pP->d_c) {
AssertFatal (pdu_info_pP->d_c != 0, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
pdu_info_pP->rf = (header_pP->b1 >> 6) & 0x01;
pdu_info_pP->p = (header_pP->b1 >> 5) & 0x01;
pdu_info_pP->fi = (header_pP->b1 >> 3) & 0x03;
......@@ -117,12 +118,6 @@ rlc_am_get_data_pdu_infos(
}
return 0;
} else {
LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[GET DATA PDU INFO] SN %04d ERROR CONTROL PDU ",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
pdu_info_pP->sn);
return -1;
}
}
//-----------------------------------------------------------------------------
void
......@@ -181,26 +176,22 @@ rlc_am_rx_update_vr_ms(
do {
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) {
if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
(rlc_pP->vr_ms != pdu_info_cursor_p->sn)) {
#if TRACE_RLC_AM_RX
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->vr_ms, pdu_info_cursor_p->sn);
#endif
rlc_pP->vr_ms = pdu_info_cursor_p->sn;
return;
}
rlc_pP->vr_ms = RLC_AM_NEXT_SN(pdu_info_cursor_p->sn);
cursor_p = cursor_p->next;
} while (cursor_p != NULL);
} while ((cursor_p != NULL) && (rlc_pP->vr_ms != rlc_pP->vr_h));
#if TRACE_RLC_AM_RX
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->vr_ms,
(pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK);
#endif
rlc_pP->vr_ms = (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK;
}
}
// assumed the sn of the tb_p is equal to VR(R)
......@@ -322,18 +313,14 @@ rlc_am_receive_process_data_pdu (
// - discard the duplicate byte segments.
rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
rlc_am_pdu_sn_10_t* rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)first_byte_pP;
rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK;
boolean_t reassemble = false;
if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_pP, rlc_am_pdu_sn_10_p, tb_size_in_bytesP, pdu_info_p) >= 0) {
((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received = 0;
if (rlc_am_in_rx_window(ctxt_pP, rlc_pP, pdu_info_p->sn)) {
if (pdu_info_p->p) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] POLL BIT SET, STATUS REQUESTED:\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
rlc_pP->status_requested = 1;
}
if (RLC_AM_SN_IN_WINDOW(pdu_info_p->sn, rlc_pP->vr_r)) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] VR(R) %04d VR(H) %04d VR(MR) %04d VR(MS) %04d VR(X) %04d\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
......@@ -346,10 +333,8 @@ rlc_am_receive_process_data_pdu (
if (rlc_am_rx_list_insert_pdu(ctxt_pP, rlc_pP,tb_pP) < 0) {
rlc_pP->stat_rx_data_pdu_dropped += 1;
rlc_pP->stat_rx_data_bytes_dropped += tb_size_in_bytesP;
free_mem_block (tb_pP, __func__);
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED, STATUS REQUESTED:\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
rlc_pP->status_requested = 1;
#if RLC_STOP_ON_LOST_PDU
AssertFatal( 0 == 1,
PROTOCOL_RLC_AM_CTXT_FMT" LOST PDU DETECTED\n",
......@@ -394,12 +379,15 @@ rlc_am_receive_process_data_pdu (
rlc_am_rx_list_display(rlc_pP, "rlc_am_receive_process_data_pdu AFTER INSERTION ");
#endif
if (rlc_am_sn_gte_vr_h(ctxt_pP, rlc_pP, pdu_info_p->sn) > 0) {
rlc_pP->vr_h = (pdu_info_p->sn + 1) & RLC_AM_SN_MASK;
/* 1) Update vrH if sn >= vrH */
if (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(rlc_pP->vr_h,rlc_pP->vr_r))
{
rlc_pP->vr_h = RLC_AM_NEXT_SN(pdu_info_p->sn);
}
rlc_am_rx_check_all_byte_segments(ctxt_pP, rlc_pP, tb_pP);
/* 2) Reordering Window Processing: Update vr_ms if sn = vr_ms and all bytes received for sn */
if ((pdu_info_p->sn == rlc_pP->vr_ms) && (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received)) {
rlc_am_rx_update_vr_ms(ctxt_pP, rlc_pP, tb_pP);
}
......@@ -410,20 +398,35 @@ rlc_am_receive_process_data_pdu (
rlc_pP->vr_mr = (rlc_pP->vr_r + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
}
rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
reassemble = true;
//TODO : optimization : check whether a reassembly is needed by looking at LI, FI, SO, etc...
}
//FNA: fix check VrX out of receiving window
if (rlc_pP->t_reordering.running) {
if ((rlc_pP->vr_x == rlc_pP->vr_r) || ((rlc_am_in_rx_window(ctxt_pP, rlc_pP, rlc_pP->vr_x) == 0) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
if ((rlc_pP->t_reordering.running) || ((rlc_pP->t_reordering.ms_duration == 0) && (rlc_pP->vr_x != RLC_SN_UNDEFINED))) {
if ((rlc_pP->vr_x == rlc_pP->vr_r) || (!(RLC_AM_SN_IN_WINDOW(rlc_pP->vr_x, rlc_pP->vr_r)) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
rlc_pP->vr_x = RLC_SN_UNDEFINED;
}
}
if (!(rlc_pP->t_reordering.running)) {
if (rlc_pP->vr_h != rlc_pP->vr_r) { // - if VR (H) > VR(R) translated to - if VR (H) != VR(R)
rlc_am_start_timer_reordering(ctxt_pP, rlc_pP);
rlc_pP->vr_x = rlc_pP->vr_h;
if (rlc_pP->t_reordering.ms_duration != 0) {
rlc_am_start_timer_reordering(ctxt_pP, rlc_pP);
}
else {
/* specific case for no timer reordering configured */
/* reordering window directly advances with vrH */
rlc_pP->vr_ms = rlc_pP->vr_h;
/* Trigger a Status and clear any existing Delay Flag */
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING);
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
}
}
}
}
......@@ -437,12 +440,67 @@ rlc_am_receive_process_data_pdu (
} else {
rlc_pP->stat_rx_data_pdu_out_of_window += 1;
rlc_pP->stat_rx_data_bytes_out_of_window += tb_size_in_bytesP;
free_mem_block (tb_pP, __func__);
pdu_status = RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW;
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU OUT OF RX WINDOW, DISCARDED, STATUS REQUESTED:\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
rlc_pP->status_requested = 1;
}
/* 3) Check for triggering a Tx Status PDU if a poll is received or if a pending status was delayed */
if (pdu_info_p->p) {
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] POLL BIT SET, STATUS REQUESTED:\n",
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
/* Polling Info Saving for In and Out of Window PDU */
/* avoid multi status trigger */
if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) ||
!(RLC_AM_GET_STATUS(rlc_pP->status_requested,(RLC_AM_STATUS_TRIGGERED_POLL | RLC_AM_STATUS_TRIGGERED_T_REORDERING))))
{
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_POLL);
if ((pdu_status != RLC_AM_DATA_PDU_STATUS_OK) || ((pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
(!(RLC_AM_SN_IN_WINDOW(pdu_info_p->sn,rlc_pP->vr_r)) ||
(RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
)
)
{
/* Conditions are met for sending a Status Report */
/* Then clear Delay Flag and reset its corresponding sn */
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
}
else if (rlc_pP->sn_status_triggered_delayed == RLC_SN_UNDEFINED)
{
/* Delay status trigger if pdustatus OK and sn>= vr_ms */
/* Note: vr_r and vr_ms have been updated */
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
rlc_pP->sn_status_triggered_delayed = pdu_info_p->sn;
}
}
}
/* ReEnable a previously delayed Status Trigger if PDU discarded or */
/* sn no more in RxWindow due to RxWindow advance or sn < vr_ms */
if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) &&
(pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
(!(RLC_AM_SN_IN_WINDOW(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r)) ||
(RLC_AM_DIFF_SN(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
)
{
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
}
} else {
pdu_status = RLC_AM_DATA_PDU_STATUS_HEADER_ERROR;
}
if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
/* Discard received block if out of window, duplicate or header error */
free_mem_block (tb_pP, __func__);
}
else if (reassemble) {
/* Reassemble SDUs */
rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
}
}
......@@ -49,6 +49,10 @@ rlc_am_rx_list_insert_pdu(
cursor_p = rlc_pP->receiver_buffer.head;
// it is assumed this pdu is in rx window
//TODO : check for duplicate
// should be rewrite
/* look for previous SN */
if (cursor_p) {
if (rlc_pP->vr_mr < rlc_pP->vr_r) {
if (pdu_info_p->sn >= rlc_pP->vr_r) {
......
......@@ -474,7 +474,7 @@ rlc_am_send_status_pdu(
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
sn_cursor = pdu_info_cursor_p->sn;
while (rlc_am_in_rx_window(ctxt_pP, rlc_pP, sn_cursor) == 0) {
while (!(RLC_AM_SN_IN_WINDOW(sn_cursor, rlc_pP->vr_r))) {
cursor_p = cursor_p->next;
previous_sn_cursor = sn_cursor;
......
......@@ -236,6 +236,28 @@ typedef struct rlc_am_rx_pdu_management {
uint8_t all_segments_received; /*!< \brief Is all segments of PDU SN have been received. */
} rlc_am_rx_pdu_management_t;
/** @} */
typedef enum rlc_am_rx_pdu_status
{
/** PDU okay. */
RLC_AM_DATA_PDU_STATUS_OK = 0,
/** SN outside RX window */
RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW = 1,
/** SN already available */
RLC_AM_DATA_PDU_STATUS_SN_DUPLICATE = 2,
/** SN already available */
RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE = 3,
/** Buffer full */
RLC_AM_DATA_PDU_STATUS_BUFFER_FULL = 4,
/** Header Error (LI,SO...) */
RLC_AM_DATA_PDU_STATUS_HEADER_ERROR = 5,
/** Unknown bearer */
RLC_AM_DATA_PDU_STATUS_INVALID_BEARER = 6,
/** RLC in wrong state */
RLC_AM_DATA_PDU_STATUS_WRONG_STATE = 7
} rlc_am_rx_pdu_status_t;
/*! \cond PRIVATE */
//-----------------------------------------------------------------------------
// interlayers optimizations
......
......@@ -64,6 +64,7 @@ enum RLC_OPERATION_MODE { TRANSMITTER_ONLY = 0x00,
// dimensions
# define SN_12BITS_MASK 0x0FFF
# define RLC_SN_OVERFLOW 0xFFFF
# define RLC_SN_UNDEFINED RLC_SN_OVERFLOW
//----------------------------------------------------------
// DISCARD
//----------------------------------------------------------
......
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