rlc_am_segment.c 24.6 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
  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
gauthier's avatar
gauthier committed
25

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
#define RLC_AM_MODULE 1
#define RLC_AM_SEGMENT_C 1
31
//-----------------------------------------------------------------------------
32
#if USER_MODE
33
34
35
36
37
#include <assert.h>
#endif
//-----------------------------------------------------------------------------
#include "platform_types.h"
//-----------------------------------------------------------------------------
knopp's avatar
mutexes    
knopp committed
38
#include "msc.h"
39
40
41
42
43
44
#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
  // 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)) ||
85
86
    (rlc_pP->vt_s == rlc_pP->vt_ms) ||
    (rlc_pP->force_poll == TRUE)
87
  ) {
88
	rlc_pP->force_poll = FALSE;
89
90

    if (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) {
91
92
      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),
93
            rlc_pP->poll_pdu);
94
    } else
95
    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
            rlc_pP->poll_byte);
99
    } else
100
    if ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) {
101
102
      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));
103
    } else
104
    if (rlc_pP->vt_s == rlc_pP->vt_ms) {
105
106
      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));
107
    }
108
109
110
111
112
113
114
115
116
117
118
119
120
121

    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;
  }
122
123
}
//-----------------------------------------------------------------------------
124
void rlc_am_segment_10 (
125
126
  const protocol_ctxt_t* const  ctxt_pP,
  rlc_am_entity_t *const rlc_pP)
127
{
128
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
  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,
159
160
        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),
161
162
163
164
165
166
167
168
169
170
171
172
173
174
        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;


knopp's avatar
mutexes    
knopp committed
175
  RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
176
177

  while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block) && (nb_bytes_to_transmit > 0) ) {
178
179
    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),
180
          nb_bytes_to_transmit,
gauthier's avatar
gauthier committed
181
          rlc_pP->sdu_buffer_occupancy);
182
183
184
185
186
187
188
189
190

    // 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);
      }

191
192
      LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] max_li_overhead %d\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
193
194
195
196
            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;
197
198
        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),
199
200
201
              data_pdu_size);
      } else {
        data_pdu_size = nb_bytes_to_transmit;
202
203
        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),
204
205
206
207
              data_pdu_size);
      }

      if (!(pdu_mem_p = get_free_mem_block (data_pdu_size + sizeof(struct mac_tb_req)))) {
208
209
        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));
knopp's avatar
mutexes    
knopp committed
210
        RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
211
        return;
212
213
      }

214
215
      LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] get new PDU %d bytes\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
216
217
218
219
220
221
222
223
224
            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;
225
226
    }

227
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
    //----------------------------------------
    // 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 {
282
283
        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),
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
              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
    //----------------------------------------
311
312
    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),
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
          ((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
328

329
330
    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
331

332
      if (sdu_mngt_p->sdu_segmented_size == 0) {
333
334
        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),
335
336
337
              sdu_mngt_p,
              sdu_mngt_p->sdu_remaining_size);
      } else {
338
339
        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),
340
341
342
343
344
345
346
347
              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) {
348
349
        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),
350
351
352
353
354
355
356
357
358
359
360
361
              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;
362
363
        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),
364
365
366
              sdu_mngt_p->sdu_remaining_size,
              sdu_mngt_p->sdu_segmented_size);
      } else if (sdu_mngt_p->sdu_remaining_size == pdu_remaining_size) {
367
368
        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),
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
              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)) {
387
388
          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),
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
                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 {
404
405
          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),
406
407
408
409
410
411
412
413
414
415
416
                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;
417
            } else {
418
419
              //e_li_p->e1  = 1;
              e_li_p->b1 =  0x80;
420
            }
421
422
423
424

            //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;
425
426
            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),
427
428
429
430
431
432
433
434
                  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;
435
            }
436
437
438
439

            //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;
440
441
            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),
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
                  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;
459
        }
460
      } else {
461
462
        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),
463
464
              sdu_mngt_p->sdu_remaining_size,
              pdu_remaining_size - sdu_mngt_p->sdu_remaining_size);
465
#if USER_MODE
466
        assert(1!=1);
467
#endif
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
        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;
      }
    }
483

484
485
486
487
488
489
    // set framing info
    if (fi_first_byte_pdu_is_first_byte_sdu) {
      fi = 0;
    } else {
      fi = 2;
    }
490

491
492
493
494
495
496
497
498
499
500
501
    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;
    }

502
503
    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),
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
          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;
519
//#warning "why 3000: changed to RLC_SDU_MAX_SIZE "
520
521
522
523
524
525
526
527
    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;
528

529
530
    rlc_pP->retrans_num_pdus  += 1;
    rlc_pP->retrans_num_bytes += pdu_mngt_p->header_and_payload_size;
531

532
533
    pdu_p = NULL;
    pdu_mem_p = NULL;
534

535
536
    //nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
    nb_bytes_to_transmit = 0; // 1 PDU only
537

538
539
    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);
540

541
  }
542

knopp's avatar
mutexes    
knopp committed
543
  RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
544
}