Skip to content
Snippets Groups Projects
Commit b77694e8 authored by fnabet's avatar fnabet
Browse files

main AM RX process PDU changes

parent dec41a2a
No related branches found
No related tags found
2 merge requests!168Develop integration w13,!167Bugfix 189 rlc am fixes
......@@ -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;
......
......@@ -40,14 +40,15 @@ rlc_am_get_data_pdu_infos(
int16_t total_sizeP,
rlc_am_pdu_info_t* pdu_info_pP)
{
memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t));
memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t));
int16_t sum_li = 0;
pdu_info_pP->d_c = header_pP->b1 >> 7;
pdu_info_pP->num_li = 0;
int16_t sum_li = 0;
pdu_info_pP->d_c = header_pP->b1 >> 7;
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 {
free_mem_block (tb_pP, __func__);
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
//----------------------------------------------------------
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment