rlc_am_segment.c 24.7 KB
Newer Older
1
/*******************************************************************************
gauthier's avatar
gauthier committed
2
3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

gauthier's avatar
gauthier committed
5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


gauthier's avatar
gauthier committed
11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

gauthier's avatar
gauthier committed
16
17
18
19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.
20

gauthier's avatar
gauthier committed
21
22
23
24
25
  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
gauthier's avatar
gauthier committed
27
28

 *******************************************************************************/
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#define RLC_AM_MODULE
#define RLC_AM_SEGMENT_C
//-----------------------------------------------------------------------------
#ifdef USER_MODE
#include <assert.h>
#endif
//-----------------------------------------------------------------------------
//#include "rtos_header.h"
#include "platform_types.h"
//-----------------------------------------------------------------------------
#include "list.h"
#include "rlc_am.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"

//-----------------------------------------------------------------------------
45
void rlc_am_pdu_polling (
46
47
48
49
  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)
50
51
//-----------------------------------------------------------------------------
{
52
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
89
  // 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.
  // 5.2.2.1 Transmission of a AMD PDU or AMD PDU segment
  // Upon assembly of a new AMD PDU, the transmitting side of an AM RLC entity shall:
  //     - increment PDU_WITHOUT_POLL by one;
  //     - increment BYTE_WITHOUT_POLL by every new byte of Data field element that it maps to the Data field of
  //       the RLC data PDU;
  //     - if PDU_WITHOUT_POLL >= pollPDU; or
  //     - if BYTE_WITHOUT_POLL >= pollByte;
  //         -include a poll in the RLC data PDU as described below.
  // Upon assembly of an AMD PDU or AMD PDU segment, the transmitting side of an AM RLC entity shall:
  //     - if both the transmission buffer and the retransmission buffer becomes empty (excluding transmitted RLC data
  //       PDU awaiting for acknowledgements) after the transmission of the RLC data PDU; or
  //     - if no new RLC data PDU can be transmitted after the transmission of the RLC data PDU (e.g. due to window
  //       stalling);
  //         - include a poll in the RLC data PDU as described below.
  // To include a poll in a RLC data PDU, the transmitting side of an AM RLC entity shall:
  //     - set the P field of the RLC data PDU to "1";
  //     - set PDU_WITHOUT_POLL to 0;
  //     - set BYTE_WITHOUT_POLL to 0;
  // After delivering a RLC data PDU including a poll to lower layer and after incrementing of VT(S) if necessary, the
  // transmitting side of an AM RLC entity shall:
  //     - set POLL_SN to VT(S) – 1;
  //     - if t-PollRetransmit is not running:
  //         - start t-PollRetransmit;
  //     - else:
  //         - restart t-PollRetransmit;
  rlc_pP->c_pdu_without_poll     += 1;
  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) ||
    ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) ||
    (rlc_pP->vt_s == rlc_pP->vt_ms)
  ) {

    if (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) {
90
91
      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),
92
93
94
95
            rlc_pP->poll_pdu);
    }

    if (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte) {
96
97
      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),
98
99
100
101
            rlc_pP->poll_byte);
    }

    if ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) {
102
103
      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));
104
105
106
    }

    if (rlc_pP->vt_s == rlc_pP->vt_ms) {
107
108
      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));
109
    }
110
111
112
113
114
115
116
117
118
119
120
121
122
123

    pdu_pP->b1 = pdu_pP->b1 | 0x20;
    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;
    //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 {
    pdu_pP->b1 = pdu_pP->b1 & 0xDF;
  }
124
125
}
//-----------------------------------------------------------------------------
126
void rlc_am_segment_10 (
127
128
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_am_entity_t *const rlc_pP)
129
{
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  //-----------------------------------------------------------------------------
  list_t              pdus;
  sdu_size_t          pdu_remaining_size      = 0;
  sdu_size_t          test_pdu_remaining_size = 0;

  sdu_size_t                       nb_bytes_to_transmit = rlc_pP->nb_bytes_requested_by_mac;
  rlc_am_pdu_sn_10_t              *pdu_p        = NULL;
  struct mac_tb_req               *pdu_tb_req_p = NULL;
  mem_block_t                     *pdu_mem_p    = NULL;
  unsigned char                   *data         = NULL;
  unsigned char                   *data_sdu_p   = NULL;
  rlc_am_e_li_t                   *e_li_p       = NULL;
  rlc_am_tx_sdu_management_t      *sdu_mngt_p   = NULL;
  rlc_am_tx_data_pdu_management_t *pdu_mngt_p   = NULL;

  sdu_size_t         li_length_in_bytes         = 0;
  sdu_size_t         test_li_length_in_bytes    = 0;
  sdu_size_t         test_remaining_size_to_substract= 0;
  unsigned int       test_remaining_num_li_to_substract = 0;
  unsigned int       continue_fill_pdu_with_sdu         = 0;
  unsigned int       num_fill_sdu                       = 0;
  unsigned int       test_num_li                        = 0;
  unsigned int       fill_num_li                        = 0;
  unsigned int       sdu_buffer_index                   = 0;
  sdu_size_t         data_pdu_size                      = 0;

  unsigned int       fi_first_byte_pdu_is_first_byte_sdu = 0;
  unsigned int       fi_last_byte_pdu_is_last_byte_sdu   = 0;
  unsigned int       fi                                  = 0;
  signed int         max_li_overhead                     = 0;

  LOG_T(RLC,
162
163
        PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] rlc_pP->current_sdu_index %d rlc_pP->next_sdu_index %d rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block %p sdu_buffer_occupancy %d\n",
        PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
        rlc_pP->current_sdu_index,
        rlc_pP->next_sdu_index,
        rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block,
        rlc_pP->sdu_buffer_occupancy);

  if (rlc_pP->sdu_buffer_occupancy <= 0) {
    return;
  }

  //msg ("[FRAME %05d][%s][RLC_AM][MOD %u/%u][RB %u][SEGMENT]\n", rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame);
  list_init (&pdus, NULL);    // param string identifying the list is NULL
  pdu_mem_p = NULL;


  pthread_mutex_lock(&rlc_pP->lock_input_sdus);

  while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block) && (nb_bytes_to_transmit > 0) ) {
181
182
    LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] nb_bytes_to_transmit %d BO %d\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
183
          nb_bytes_to_transmit,
gauthier's avatar
gauthier committed
184
          rlc_pP->sdu_buffer_occupancy);
185
186
187
188
189
190
191
192
193

    // pdu_p management
    if (!pdu_mem_p) {
      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);
      }

194
195
      LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] max_li_overhead %d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
196
197
198
199
            max_li_overhead);

      if  (nb_bytes_to_transmit >= (rlc_pP->sdu_buffer_occupancy + RLC_AM_HEADER_MIN_SIZE + max_li_overhead)) {
        data_pdu_size = rlc_pP->sdu_buffer_occupancy + RLC_AM_HEADER_MIN_SIZE + max_li_overhead;
200
201
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] alloc PDU size %d bytes to contain not all bytes requested by MAC but all BO of RLC@1\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
202
203
204
              data_pdu_size);
      } else {
        data_pdu_size = nb_bytes_to_transmit;
205
206
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] alloc PDU size %d bytes to contain all bytes requested by MAC@1\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
207
208
209
210
              data_pdu_size);
      }

      if (!(pdu_mem_p = get_free_mem_block (data_pdu_size + sizeof(struct mac_tb_req)))) {
211
212
        LOG_C(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] ERROR COULD NOT GET NEW PDU, EXIT\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
213
        pthread_mutex_unlock(&rlc_pP->lock_input_sdus);
214
        return;
215
216
      }

217
218
      LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] get new PDU %d bytes\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
219
220
221
222
223
224
225
226
227
            data_pdu_size);
      pdu_remaining_size = data_pdu_size - RLC_AM_HEADER_MIN_SIZE;
      pdu_p        = (rlc_am_pdu_sn_10_t*) (&pdu_mem_p->data[sizeof(struct mac_tb_req)]);
      pdu_tb_req_p = (struct mac_tb_req*) (pdu_mem_p->data);
      pdu_mngt_p   = &rlc_pP->pdu_retrans_buffer[rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE];
      memset(pdu_mngt_p, 0, sizeof (rlc_am_tx_data_pdu_management_t));

      memset (pdu_mem_p->data, 0, sizeof (rlc_am_pdu_sn_10_t)+sizeof(struct mac_tb_req));
      li_length_in_bytes = 1;
228
229
    }

230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
    //----------------------------------------
    // compute how many SDUS can fill the PDU
    //----------------------------------------
    continue_fill_pdu_with_sdu = 1;
    num_fill_sdu               = 0;
    test_num_li                = 0;
    sdu_buffer_index           = rlc_pP->current_sdu_index;
    test_pdu_remaining_size    = pdu_remaining_size;
    test_li_length_in_bytes    = 1;
    test_remaining_size_to_substract   = 0;
    test_remaining_num_li_to_substract = 0;


    while ((rlc_pP->input_sdus[sdu_buffer_index].mem_block) && (continue_fill_pdu_with_sdu > 0)) {
      sdu_mngt_p = &rlc_pP->input_sdus[sdu_buffer_index];

      if (sdu_mngt_p->sdu_remaining_size > test_pdu_remaining_size) {
        // no LI
        continue_fill_pdu_with_sdu = 0;
        num_fill_sdu += 1;
        test_pdu_remaining_size = 0;
        test_remaining_size_to_substract = 0;
        test_remaining_num_li_to_substract = 0;
      } else if (sdu_mngt_p->sdu_remaining_size == test_pdu_remaining_size) {
        // fi will indicate end of PDU is end of SDU, no need for LI
        continue_fill_pdu_with_sdu = 0;
        num_fill_sdu += 1;
        test_pdu_remaining_size = 0;
        test_remaining_size_to_substract = 0;
        test_remaining_num_li_to_substract = 0;
      } else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) == test_pdu_remaining_size ) {
        // no LI
        continue_fill_pdu_with_sdu = 0;
        num_fill_sdu += 1;
        test_pdu_remaining_size = 0;
        test_remaining_size_to_substract = 0;
        test_remaining_num_li_to_substract = 0;
        pdu_remaining_size = pdu_remaining_size - (test_li_length_in_bytes ^ 3);
      } else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) < test_pdu_remaining_size ) {
        if (pdu_mngt_p->nb_sdus >= (RLC_AM_MAX_SDU_IN_PDU-1)) {
          continue_fill_pdu_with_sdu = 0;
          //num_fill_sdu += 1;
          test_pdu_remaining_size = 0;
          test_remaining_size_to_substract = 0;
          test_remaining_num_li_to_substract = 0;
          pdu_remaining_size = pdu_remaining_size - 1;
        } else {
          test_num_li += 1;
          num_fill_sdu += 1;
          test_pdu_remaining_size = test_pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3));
          test_remaining_size_to_substract = test_li_length_in_bytes ^ 3;
          test_remaining_num_li_to_substract = 1;
          test_li_length_in_bytes = test_li_length_in_bytes ^ 3;
        }
      } else {
285
286
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] sdu_mngt_p->sdu_remaining_size=%d test_pdu_remaining_size=%d test_li_length_in_bytes=%d\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
287
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
              sdu_mngt_p->sdu_remaining_size,
              test_pdu_remaining_size,
              test_li_length_in_bytes ^ 3);
        // reduce the size of the PDU
        continue_fill_pdu_with_sdu = 0;
        num_fill_sdu += 1;
        test_pdu_remaining_size = 0;
        test_remaining_size_to_substract = 0;
        test_remaining_num_li_to_substract = 0;
        pdu_remaining_size = pdu_remaining_size - 1;
      }

      pdu_mngt_p->sdus_index[pdu_mngt_p->nb_sdus++] = sdu_buffer_index;
      sdu_mngt_p->pdus_index[sdu_mngt_p->nb_pdus++] = rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE;
      assert(sdu_mngt_p->nb_pdus < RLC_AM_MAX_SDU_FRAGMENTS);
      sdu_buffer_index = (sdu_buffer_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
    }

    if (test_remaining_num_li_to_substract > 0) {
      // there is a LI that is not necessary
      test_num_li = test_num_li - 1;
      pdu_remaining_size = pdu_remaining_size - test_remaining_size_to_substract;
    }

    //----------------------------------------
    // Do the real filling of the pdu_p
    //----------------------------------------
314
315
    LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT" data shift %d Bytes num_li %d\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
          ((test_num_li*3) +1) >> 1,
          test_num_li);
    data = ((unsigned char*)(&pdu_p->data[((test_num_li*3) +1) >> 1]));
    pdu_mngt_p->payload = data;
    e_li_p = (rlc_am_e_li_t*)(pdu_p->data);
    continue_fill_pdu_with_sdu          = 1;
    li_length_in_bytes                  = 1;
    fill_num_li                         = 0;
    fi_first_byte_pdu_is_first_byte_sdu = 0;
    fi_last_byte_pdu_is_last_byte_sdu   = 0;

    if (rlc_pP->input_sdus[rlc_pP->current_sdu_index].sdu_remaining_size ==
        rlc_pP->input_sdus[rlc_pP->current_sdu_index].sdu_size) {
      fi_first_byte_pdu_is_first_byte_sdu = 1;
    }
gauthier's avatar
gauthier committed
331

332
333
    while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block) && (continue_fill_pdu_with_sdu > 0)) {
      sdu_mngt_p = &rlc_pP->input_sdus[rlc_pP->current_sdu_index];
gauthier's avatar
gauthier committed
334

335
      if (sdu_mngt_p->sdu_segmented_size == 0) {
336
337
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] GET NEW SDU %p AVAILABLE SIZE %d Bytes\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
338
339
340
              sdu_mngt_p,
              sdu_mngt_p->sdu_remaining_size);
      } else {
341
342
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] GET AGAIN SDU %p REMAINING AVAILABLE SIZE %d Bytes / %d Bytes LENGTH \n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
343
344
345
346
347
348
349
350
              sdu_mngt_p,
              sdu_mngt_p->sdu_remaining_size,
              sdu_mngt_p->sdu_size);
      }

      data_sdu_p = &sdu_mngt_p->first_byte[sdu_mngt_p->sdu_segmented_size];

      if (sdu_mngt_p->sdu_remaining_size > pdu_remaining_size) {
351
352
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling all remaining PDU with %d bytes\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
353
354
355
356
357
358
359
360
361
362
363
364
              pdu_remaining_size);
        //msg ("[FRAME %05d][%s][RLC_AM][MOD %u/%u][RB %u][SEGMENT] pdu_mem_p %p pdu_p %p pdu_p->data %p data %p data_sdu_p %p pdu_remaining_size %d\n", rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame, pdu_mem_p, pdu_p, pdu_p->data, data, data_sdu_p,pdu_remaining_size);

        memcpy(data, data_sdu_p, pdu_remaining_size);
        pdu_mngt_p->payload_size += pdu_remaining_size;
        sdu_mngt_p->sdu_remaining_size = sdu_mngt_p->sdu_remaining_size - pdu_remaining_size;
        sdu_mngt_p->sdu_segmented_size = sdu_mngt_p->sdu_segmented_size + pdu_remaining_size;
        fi_last_byte_pdu_is_last_byte_sdu = 0;
        // no LI
        rlc_pP->sdu_buffer_occupancy -= pdu_remaining_size;
        continue_fill_pdu_with_sdu = 0;
        pdu_remaining_size = 0;
365
366
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] sdu_remaining_size %d bytes sdu_segmented_size %d bytes\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
367
368
369
              sdu_mngt_p->sdu_remaining_size,
              sdu_mngt_p->sdu_segmented_size);
      } else if (sdu_mngt_p->sdu_remaining_size == pdu_remaining_size) {
370
371
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Exactly Filling remaining PDU with %d remaining bytes of SDU\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
              pdu_remaining_size);
        memcpy(data, data_sdu_p, pdu_remaining_size);
        pdu_mngt_p->payload_size += pdu_remaining_size;

        // free SDU
        rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
        rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
        //free_mem_block (rlc_pP->input_sdus[rlc_pP->current_sdu_index]);
        //rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
        //rlc_pP->nb_sdu -= 1;
        rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;

        fi_last_byte_pdu_is_last_byte_sdu = 1;
        // fi will indicate end of PDU is end of SDU, no need for LI
        continue_fill_pdu_with_sdu = 0;
        pdu_remaining_size = 0;
      } else if ((sdu_mngt_p->sdu_remaining_size + (li_length_in_bytes ^ 3)) < pdu_remaining_size ) {
        if (fill_num_li == (RLC_AM_MAX_SDU_IN_PDU - 1)) {
390
391
          LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] [SIZE %d] REACHING RLC_AM_MAX_SDU_IN_PDU LIs -> STOP SEGMENTATION FOR THIS PDU SDU\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
                sdu_mngt_p->sdu_remaining_size);
          memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
          pdu_mngt_p->payload_size += sdu_mngt_p->sdu_remaining_size;
          pdu_remaining_size = 0; //Forced to 0 pdu_remaining_size - sdu_mngt_p->sdu_remaining_size;
          // free SDU
          rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
          rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
          //rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
          //rlc_pP->nb_sdu -= 1;
          rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;

          // reduce the size of the PDU
          continue_fill_pdu_with_sdu = 0;
          fi_last_byte_pdu_is_last_byte_sdu = 1;
        } else {
407
408
          LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling  PDU with %d all remaining bytes of SDU\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
409
410
411
412
413
414
415
416
417
418
419
                sdu_mngt_p->sdu_remaining_size);
          memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
          pdu_mngt_p->payload_size += sdu_mngt_p->sdu_remaining_size;
          data = &data[sdu_mngt_p->sdu_remaining_size];
          li_length_in_bytes = li_length_in_bytes ^ 3;
          fill_num_li += 1;

          if (li_length_in_bytes  == 2) {
            if (fill_num_li == test_num_li) {
              //e_li_p->e1  = 0;
              e_li_p->b1 = 0;
420
            } else {
421
422
              //e_li_p->e1  = 1;
              e_li_p->b1 =  0x80;
423
            }
424
425
426
427

            //e_li_p->li1 = sdu_mngt_p->sdu_remaining_size;
            e_li_p->b1 = e_li_p->b1 | (sdu_mngt_p->sdu_remaining_size >> 4);
            e_li_p->b2 = sdu_mngt_p->sdu_remaining_size << 4;
428
429
            LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] set e_li_p->b1=0x%02X set e_li_p->b2=0x%02X fill_num_li=%d test_num_li=%d\n",
                  PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
430
431
432
433
434
435
436
437
                  e_li_p->b1,
                  e_li_p->b2,
                  fill_num_li,
                  test_num_li);
          } else {
            if (fill_num_li != test_num_li) {
              //e_li_p->e2  = 1;
              e_li_p->b2  = e_li_p->b2 | 0x08;
438
            }
439
440
441
442

            //e_li_p->li2 = sdu_mngt_p->sdu_remaining_size;
            e_li_p->b2 = e_li_p->b2 | (sdu_mngt_p->sdu_remaining_size >> 8);
            e_li_p->b3 = sdu_mngt_p->sdu_remaining_size & 0xFF;
443
444
            LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] set e_li_p->b2=0x%02X set e_li_p->b3=0x%02X fill_num_li=%d test_num_li=%d\n",
                  PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
                  e_li_p->b2,
                  e_li_p->b3,
                  fill_num_li,
                  test_num_li);
            e_li_p++;
          }

          pdu_remaining_size = pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + li_length_in_bytes);
          // free SDU
          rlc_pP->sdu_buffer_occupancy  -= sdu_mngt_p->sdu_remaining_size;
          sdu_mngt_p->sdu_remaining_size = 0;

          rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
          //free_mem_block (rlc_pP->input_sdus[rlc_pP->current_sdu_index]);
          //rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
          //rlc_pP->nb_sdu -= 1;
          rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
462
        }
463
      } else {
464
465
        LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling  PDU with %d all remaining bytes of SDU and reduce TB size by %d bytes\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
466
467
              sdu_mngt_p->sdu_remaining_size,
              pdu_remaining_size - sdu_mngt_p->sdu_remaining_size);
468
#ifdef USER_MODE
469
        assert(1!=1);
470
#endif
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
        memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
        pdu_mngt_p->payload_size += sdu_mngt_p->sdu_remaining_size;
        pdu_remaining_size = pdu_remaining_size - sdu_mngt_p->sdu_remaining_size;
        // free SDU
        rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
        rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
        //rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
        //rlc_pP->nb_sdu -= 1;
        rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;

        // reduce the size of the PDU
        continue_fill_pdu_with_sdu = 0;
        fi_last_byte_pdu_is_last_byte_sdu = 1;
      }
    }
486

487
488
489
490
491
492
    // set framing info
    if (fi_first_byte_pdu_is_first_byte_sdu) {
      fi = 0;
    } else {
      fi = 2;
    }
493

494
495
496
497
498
499
500
501
502
503
504
    if (!fi_last_byte_pdu_is_last_byte_sdu) {
      fi = fi + 1;
    }

    pdu_p->b1 = pdu_p->b1 | (fi << 3);

    // set fist e bit
    if (fill_num_li > 0) {
      pdu_p->b1 = pdu_p->b1 | 0x04;
    }

505
506
    LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] SEND PDU SN %04d  SIZE %d BYTES PAYLOAD SIZE %d BYTES\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
          rlc_pP->vt_s,
          data_pdu_size - pdu_remaining_size,
          pdu_mngt_p->payload_size);

    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
    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;

    pdu_tb_req_p->data_ptr        = (unsigned char*)pdu_p;
    pdu_tb_req_p->tb_size         = data_pdu_size - pdu_remaining_size;
522
#warning "why 3000: changed to RLC_SDU_MAX_SIZE "
523
524
525
526
527
528
529
530
    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);

    //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;
531

532
533
    rlc_pP->retrans_num_pdus  += 1;
    rlc_pP->retrans_num_bytes += pdu_mngt_p->header_and_payload_size;
534

535
536
    pdu_p = NULL;
    pdu_mem_p = NULL;
537

538
539
    //nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
    nb_bytes_to_transmit = 0; // 1 PDU only
540

541
542
    mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, (rlc_pP->vt_s-1) & RLC_AM_SN_MASK);
    list_add_tail_eurecom (copy, &rlc_pP->segmentation_pdu_list);
543

544
  }
545

546
  pthread_mutex_unlock(&rlc_pP->lock_input_sdus);
547
}