rlc_am_receiver.c 21 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21

22
23
#define RLC_AM_MODULE 1
#define RLC_AM_RECEIVER_C 1
24
25
#include "platform_types.h"
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
26
#include "assertions.h"
knopp's avatar
mutexes    
knopp committed
27
#include "msc.h"
28
29
30
31
32
33
#include "rlc.h"
#include "rlc_am.h"
#include "list.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"

fnabet's avatar
fnabet committed
34

35
//-----------------------------------------------------------------------------
36
37
signed int
rlc_am_get_data_pdu_infos(
38
  const protocol_ctxt_t* const ctxt_pP,
39
  const rlc_am_entity_t* const rlc_pP,
40
41
42
  rlc_am_pdu_sn_10_t* header_pP,
  int16_t total_sizeP,
  rlc_am_pdu_info_t* pdu_info_pP)
43
{
fnabet's avatar
fnabet committed
44
    memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t));
45

fnabet's avatar
fnabet committed
46
47
48
    int16_t          sum_li = 0;
    pdu_info_pP->d_c = header_pP->b1 >> 7;
    pdu_info_pP->num_li = 0;
49
50


fnabet's avatar
fnabet committed
51
52
    AssertFatal (pdu_info_pP->d_c != 0, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    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;
    pdu_info_pP->e   = (header_pP->b1 >> 2) & 0x01;
    pdu_info_pP->sn  = header_pP->b2 +  (((uint16_t)(header_pP->b1 & 0x03)) << 8);

    pdu_info_pP->header_size  = 2;

    if (pdu_info_pP->rf) {
      pdu_info_pP->lsf = (header_pP->data[0] >> 7) & 0x01;
      pdu_info_pP->so  = header_pP->data[1] +  (((uint16_t)(header_pP->data[0] & 0x7F)) << 8);
      pdu_info_pP->payload = &header_pP->data[2];
      pdu_info_pP->header_size  += 2;
    } else {
      pdu_info_pP->payload = &header_pP->data[0];
    }

    if (pdu_info_pP->e) {
      rlc_am_e_li_t      *e_li;
      unsigned int li_length_in_bytes  = 1;
      unsigned int li_to_read          = 1;

      if (pdu_info_pP->rf) {
        e_li = (rlc_am_e_li_t*)(&header_pP->data[2]);
      } else {
        e_li = (rlc_am_e_li_t*)(header_pP->data);
      }

      while (li_to_read)  {
        li_length_in_bytes = li_length_in_bytes ^ 3;

        if (li_length_in_bytes  == 2) {
          pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b1 << 4)) & 0x07F0;
          pdu_info_pP->li_list[pdu_info_pP->num_li] |= (((uint8_t)(e_li->b2 >> 4)) & 0x000F);
          li_to_read = e_li->b1 & 0x80;
          pdu_info_pP->header_size  += 2;
89
        } else {
90
91
92
93
94
          pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b2 << 8)) & 0x0700;
          pdu_info_pP->li_list[pdu_info_pP->num_li] |=  e_li->b3;
          li_to_read = e_li->b2 & 0x08;
          e_li++;
          pdu_info_pP->header_size  += 1;
95
96
        }

97
98
99
100
        sum_li += pdu_info_pP->li_list[pdu_info_pP->num_li];
        pdu_info_pP->num_li = pdu_info_pP->num_li + 1;

        if (pdu_info_pP->num_li > RLC_AM_MAX_SDU_IN_PDU) {
101
102
          LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[GET PDU INFO]  SN %04d TOO MANY LIs ",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
103
104
                pdu_info_pP->sn);
          return -2;
105
        }
106
107
108
109
110
111
112
113
114
115
116
117
118
      }

      if (li_length_in_bytes  == 2) {
        pdu_info_pP->payload = &e_li->b3;
      } else {
        pdu_info_pP->payload = &e_li->b1;
      }
    }

    pdu_info_pP->payload_size = total_sizeP - pdu_info_pP->header_size;

    if (pdu_info_pP->payload_size > sum_li) {
      pdu_info_pP->hidden_size = pdu_info_pP->payload_size - sum_li;
119
    }
120
121

    return 0;
122
123
}
//-----------------------------------------------------------------------------
124
125
void
rlc_am_display_data_pdu_infos(
126
127
128
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const rlc_pP,
  rlc_am_pdu_info_t* pdu_info_pP)
129
{
130
131
132
133
  int num_li;

  if (pdu_info_pP->d_c) {
    if (pdu_info_pP->rf) {
134
135
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d SO %05d LSF %01d POLL %1d ",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
136
137
138
139
            pdu_info_pP->sn,
            pdu_info_pP->fi,
            pdu_info_pP->so,
            pdu_info_pP->lsf, pdu_info_pP->p);
140
    } else {
141
142
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d POLL %1d ",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
143
144
145
146
147
148
149
150
151
152
153
            pdu_info_pP->sn,
            pdu_info_pP->fi,
            pdu_info_pP->p);
    }

    for (num_li = 0; num_li < pdu_info_pP->num_li; num_li++) {
      LOG_D(RLC, "LI %05d ",  pdu_info_pP->li_list[num_li]);
    }

    if (pdu_info_pP->hidden_size > 0) {
      LOG_D(RLC, "hidden size %05d ",  pdu_info_pP->hidden_size);
154
    }
155
156
157

    LOG_D(RLC, "\n");
  } else {
158
159
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] ERROR RX CONTROL PDU\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
160
  }
161
}
gauthier's avatar
gauthier committed
162
// assumed the sn of the tb_p is equal to VR(MS)
163
//-----------------------------------------------------------------------------
164
165
void
rlc_am_rx_update_vr_ms(
166
167
168
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const rlc_pP,
  mem_block_t* tb_pP)
169
{
170
171
172
173
174
175
176
177
178
179
  //rlc_am_pdu_info_t* pdu_info_p        = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
  rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
  mem_block_t*       cursor_p;

  cursor_p = tb_pP;

  if (cursor_p) {
    do {
      pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;

fnabet's avatar
fnabet committed
180
181
182
      if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
          (rlc_pP->vr_ms != pdu_info_cursor_p->sn)) {

183
#if TRACE_RLC_AM_RX
184
185
        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),
186
              rlc_pP->vr_ms, pdu_info_cursor_p->sn);
187
#endif
fnabet's avatar
fnabet committed
188

189
190
191
        return;
      }

fnabet's avatar
fnabet committed
192
      rlc_pP->vr_ms = RLC_AM_NEXT_SN(pdu_info_cursor_p->sn);
193
      cursor_p = cursor_p->next;
fnabet's avatar
fnabet committed
194
    } while ((cursor_p != NULL) && (rlc_pP->vr_ms != rlc_pP->vr_h));
195
196

  }
197
}
gauthier's avatar
gauthier committed
198
// assumed the sn of the tb_p is equal to VR(R)
199
//-----------------------------------------------------------------------------
200
201
void
rlc_am_rx_update_vr_r(
202
203
204
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const rlc_pP,
  mem_block_t* tb_pP)
205
{
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
  mem_block_t*       cursor_p;

  cursor_p = tb_pP;

  if (cursor_p) {
    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) ||
          (rlc_pP->vr_r != pdu_info_cursor_p->sn)) {
        return;
      }

220
#if TRACE_RLC_AM_RX
221
222
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(R)] UPDATED VR(R) %04d -> %04d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
223
224
            rlc_pP->vr_r,
            (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK);
225
#endif
226
227
228
229
230
231
232
233
234
235
236
237
238
239

      if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.rf == 1) {
        if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.lsf == 1) {
          rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
        }
      } else  {
        rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
      }

      cursor_p = cursor_p->next;
    } while (cursor_p != NULL);

    //rlc_pP->vr_r = (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK;
  }
240
241
242
}
//-----------------------------------------------------------------------------
void
243
rlc_am_receive_routing (
244
245
246
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const rlc_pP,
  struct mac_data_ind data_indP)
247
{
248
249
250
  mem_block_t           *tb_p             = NULL;
  uint8_t               *first_byte_p     = NULL;
  sdu_size_t             tb_size_in_bytes;
knopp's avatar
mutexes    
knopp committed
251
  RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

  while ((tb_p = list_remove_head (&data_indP.data))) {
    first_byte_p = ((struct mac_tb_ind *) (tb_p->data))->data_ptr;
    tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;

    if (tb_size_in_bytes > 0) {
      if ((*first_byte_p & 0x80) == 0x80) {
        rlc_pP->stat_rx_data_bytes += tb_size_in_bytes;
        rlc_pP->stat_rx_data_pdu   += 1;
        rlc_am_receive_process_data_pdu (ctxt_pP, rlc_pP, tb_p, first_byte_p, tb_size_in_bytes);
      } else {
        rlc_pP->stat_rx_control_bytes += tb_size_in_bytes;
        rlc_pP->stat_rx_control_pdu += 1;
        rlc_am_receive_process_control_pdu (ctxt_pP, rlc_pP, tb_p, &first_byte_p, &tb_size_in_bytes);
        // Test if remaining bytes not processed (up to know, highest probability is bug in MAC)
        AssertFatal( tb_size_in_bytes == 0,
                     "Remaining %d bytes following a control PDU",
                     tb_size_in_bytes);
      }

272
273
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RX ROUTING] VR(R)=%03d VR(MR)=%03d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
274
275
276
277
            rlc_pP->vr_r,
            rlc_pP->vr_mr);
    }
  } // end while
knopp's avatar
mutexes    
knopp committed
278
  RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
279
280
}
//-----------------------------------------------------------------------------
281
282
void
rlc_am_receive_process_data_pdu (
283
284
285
286
287
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const rlc_pP,
  mem_block_t* tb_pP,
  uint8_t* first_byte_pP,
  uint16_t tb_size_in_bytesP)
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
{
  // 5.1.3.2 Receive operations
  // 5.1.3.2.1 General
  // The receiving side of an AM RLC entity shall maintain a receiving window according to state variables VR(R) and
  // VR(MR) as follows:
  //     - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
  //     - a SN falls outside of the receiving window otherwise.
  //
  // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
  // - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
  // - if the received RLC data PDU was placed in the reception buffer:
  //     - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as
  //       needed (see sub clause 5.1.3.2.3).
  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
  //     - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).


  // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
  // When a RLC data PDU is received from lower layer, where the RLC data PDU contains byte segment numbers y to z of
  // an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
  //     - if x falls outside of the receiving window; or
  //     - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
  //         - discard the received RLC data PDU;
  //     - else:
  //         - place the received RLC data PDU in the reception buffer;
  //         - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
  //             - discard the duplicate byte segments.
gauthier's avatar
gauthier committed
315
316
  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;
fnabet's avatar
fnabet committed
317
318
  rlc_am_rx_pdu_status_t pdu_status		= RLC_AM_DATA_PDU_STATUS_OK;
  boolean_t		reassemble = false;
319

320
  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) {
321

322
323
    ((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received = 0;

fnabet's avatar
fnabet committed
324
      if (RLC_AM_SN_IN_WINDOW(pdu_info_p->sn, rlc_pP->vr_r)) {
325

326
327
      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),
328
329
330
331
332
333
            rlc_pP->vr_r,
            rlc_pP->vr_h,
            rlc_pP->vr_mr,
            rlc_pP->vr_ms,
            rlc_pP->vr_x);

fnabet's avatar
fnabet committed
334
335
      pdu_status = rlc_am_rx_list_check_duplicate_insert_pdu(ctxt_pP, rlc_pP,tb_pP);
      if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
336
337
        rlc_pP->stat_rx_data_pdu_dropped     += 1;
        rlc_pP->stat_rx_data_bytes_dropped   += tb_size_in_bytesP;
fnabet's avatar
fnabet committed
338
339
        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  PDU DISCARDED CAUSE=%d SN=%d\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_status,pdu_info_p->sn);
340
#if RLC_STOP_ON_LOST_PDU
341
        AssertFatal( 0 == 1,
342
343
                     PROTOCOL_RLC_AM_CTXT_FMT" LOST PDU DETECTED\n",
                     PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
344
#endif
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
      } else {
        // 5.1.3.2.3
        // Actions when a RLC data PDU is placed in the reception buffer
        //
        // When a RLC data PDU with SN = x is placed in the reception buffer, the receiving side of an AM RLC entity shall:
        //     - if x >= VR(H)
        //         - update VR(H) to x+ 1;
        //
        //     - if all byte segments of the AMD PDU with SN = VR(MS) are received:
        //         - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for which not all byte segments
        //           have been received;
        //
        //     - if x = VR(R):
        //         - if all byte segments of the AMD PDU with SN = VR(R) are received:
        //             - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which not all byte segments
        //               have been received;
        //             - update VR(MR) to the updated VR(R) + AM_Window_Size;
        //
        //         - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside of the receiving
        //           window and in-sequence byte segments of the AMD PDU with SN = VR(R), remove RLC headers when
        //           doing so and deliver the reassembled RLC SDUs to upper layer in sequence if not delivered before;
        //
        //     - if t-Reordering is running:
        //         - if VR(X) = VR(R); or
        //         - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
        //             - stop and reset t-Reordering;
        //
        //     - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
        //         - if VR (H) > VR(R):
        //             - start t-Reordering;
        //             - set VR(X) to VR(H).
376
377


378
#if TRACE_RLC_AM_RX
379
380
        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  RX LIST AFTER INSERTION:\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
381
        rlc_am_rx_list_display(rlc_pP, "rlc_am_receive_process_data_pdu AFTER INSERTION ");
382
#endif
383

fnabet's avatar
fnabet committed
384
385
386
387
        /* 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);
388
389
390
391
        }

        rlc_am_rx_check_all_byte_segments(ctxt_pP, rlc_pP, tb_pP);

fnabet's avatar
fnabet committed
392
        /* 2) Reordering Window Processing: Update vr_ms if sn = vr_ms and all bytes received for sn */
393
394
395
396
397
398
399
400
        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);
        }

        if (pdu_info_p->sn == rlc_pP->vr_r) {
          if (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) {
            rlc_am_rx_update_vr_r(ctxt_pP, rlc_pP, tb_pP);
            rlc_pP->vr_mr = (rlc_pP->vr_r + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
401
          }
402

fnabet's avatar
fnabet committed
403
          reassemble = rlc_am_rx_check_vr_reassemble(ctxt_pP, rlc_pP);
fnabet's avatar
fnabet committed
404
405
          //TODO : optimization : check whether a reassembly is needed by looking at LI, FI, SO, etc...

406
407
        }

fnabet's avatar
fnabet committed
408
        //FNA: fix check VrX out of receiving window
fnabet's avatar
fnabet committed
409
410
        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))) {
411
            rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
fnabet's avatar
fnabet committed
412
            rlc_pP->vr_x = RLC_SN_UNDEFINED;
413
414
415
416
417
418
          }
        }

        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_pP->vr_x = rlc_pP->vr_h;
fnabet's avatar
fnabet committed
419
420
421
422
423
424
425
426
427
428
429
430
431
            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;
            }
432
433
          }
        }
434
      }
435

436
437
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] VR(R) %04d VR(H) %04d  VR(MS) %04d  VR(MR) %04d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
438
439
440
441
442
443
444
            rlc_pP->vr_r,
            rlc_pP->vr_h,
            rlc_pP->vr_ms,
            rlc_pP->vr_mr);
    } else {
      rlc_pP->stat_rx_data_pdu_out_of_window     += 1;
      rlc_pP->stat_rx_data_bytes_out_of_window   += tb_size_in_bytesP;
fnabet's avatar
fnabet committed
445
      pdu_status = RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW;
fnabet's avatar
fnabet committed
446
447
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  PDU OUT OF RX WINDOW, DISCARDED, SN=%d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
448
    }
fnabet's avatar
fnabet committed
449
450

      /* 3) Check for triggering a Tx Status PDU if a poll is received or if a pending status was delayed */
fnabet's avatar
fnabet committed
451
      if ((pdu_info_p->p) && (pdu_status < RLC_AM_DATA_PDU_STATUS_BUFFER_FULL)) {
fnabet's avatar
fnabet committed
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
        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;
      }


496
  } else {
fnabet's avatar
fnabet committed
497
	  pdu_status = RLC_AM_DATA_PDU_STATUS_HEADER_ERROR;
fnabet's avatar
fnabet committed
498
499
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU]  PDU DISCARDED BAD HEADER FORMAT SN=%d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
fnabet's avatar
fnabet committed
500
501
502
503
504
505
506
507
508
  }

  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);
509
510
  }
}