rlc_um.c 36.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
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
nikaeinn's avatar
nikaeinn committed
18
19
    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
#define RLC_UM_MODULE
#define RLC_UM_C
//-----------------------------------------------------------------------------
//#include "rtos_header.h"
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
36
37
38
39
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
#include "assertions.h"
40
41
42
43
44
45
46
47
48
49
#include "rlc_um.h"
#include "list.h"
#include "rlc_primitives.h"
#include "mac_primitives.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"


#include "rlc_um_very_simple_test.h"

gauthier's avatar
gauthier committed
50
#define DEBUG_RLC_UM_TX_STATUS 1
51
52
// NN --> LG: this could become a perf bottleneck, I added this to the makefile.
//#define TRACE_RLC_UM_PDU 1
53

54
55
56
#ifdef TRACE_RLC_UM_PDU
char  message_string[10000];
#endif
57
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
58
void rlc_um_stat_req     (rlc_um_entity_t *rlc_pP,
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
		  unsigned int* stat_tx_pdcp_sdu,
		  unsigned int* stat_tx_pdcp_bytes,
		  unsigned int* stat_tx_pdcp_sdu_discarded,
		  unsigned int* stat_tx_pdcp_bytes_discarded,
		  unsigned int* stat_tx_data_pdu,
		  unsigned int* stat_tx_data_bytes,
		  unsigned int* stat_rx_pdcp_sdu,
		  unsigned int* stat_rx_pdcp_bytes,
		  unsigned int* stat_rx_data_pdus_duplicate,
		  unsigned int* stat_rx_data_bytes_duplicate,
		  unsigned int* stat_rx_data_pdu,
		  unsigned int* stat_rx_data_bytes,
		  unsigned int* stat_rx_data_pdu_dropped,
		  unsigned int* stat_rx_data_bytes_dropped,
		  unsigned int* stat_rx_data_pdu_out_of_window,
		  unsigned int* stat_rx_data_bytes_out_of_window,
		  unsigned int* stat_timer_reordering_timed_out) {
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    *stat_tx_pdcp_sdu                     = rlc_pP->stat_tx_pdcp_sdu;
    *stat_tx_pdcp_bytes                   = rlc_pP->stat_tx_pdcp_bytes;
    *stat_tx_pdcp_sdu_discarded           = rlc_pP->stat_tx_pdcp_sdu_discarded;
    *stat_tx_pdcp_bytes_discarded         = rlc_pP->stat_tx_pdcp_bytes_discarded;
    *stat_tx_data_pdu                     = rlc_pP->stat_tx_data_pdu;
    *stat_tx_data_bytes                   = rlc_pP->stat_tx_data_bytes;
    *stat_rx_pdcp_sdu                     = rlc_pP->stat_rx_pdcp_sdu;
    *stat_rx_pdcp_bytes                   = rlc_pP->stat_rx_pdcp_bytes;
    *stat_rx_data_pdus_duplicate          = rlc_pP->stat_rx_data_pdus_duplicate;
    *stat_rx_data_bytes_duplicate         = rlc_pP->stat_rx_data_bytes_duplicate;
    *stat_rx_data_pdu                     = rlc_pP->stat_rx_data_pdu;
    *stat_rx_data_bytes                   = rlc_pP->stat_rx_data_bytes;
    *stat_rx_data_pdu_dropped             = rlc_pP->stat_rx_data_pdu_dropped;
    *stat_rx_data_bytes_dropped           = rlc_pP->stat_rx_data_bytes_dropped;
    *stat_rx_data_pdu_out_of_window       = rlc_pP->stat_rx_data_pdu_out_of_window;
    *stat_rx_data_bytes_out_of_window     = rlc_pP->stat_rx_data_bytes_out_of_window;
    *stat_timer_reordering_timed_out      = rlc_pP->stat_timer_reordering_timed_out;
94
95
}
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
96
uint32_t
gauthier's avatar
gauthier committed
97
rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP)
98
99
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
100
101
    if (rlc_pP->buffer_occupancy > 0) {
        return rlc_pP->buffer_occupancy;
102
103
104
105
106
107
    } else {
        return 0;
    }
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
108
rlc_um_get_pdus (void *argP, frame_t frameP)
109
110
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
111
  rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) argP;
112

gauthier's avatar
gauthier committed
113
  switch (rlc_p->protocol_state) {
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

      case RLC_NULL_STATE:
        // from 3GPP TS 25.322 V9.2.0 p43
        // In the NULL state the RLC entity does not exist and therefore it is
        // not possible to transfer any data through it.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // establishment, the RLC entity:
        //   - is created; and
        //   - enters the DATA_TRANSFER_READY state.
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
        // from 3GPP TS 25.322 V9.2.0 p43-44
        // In the DATA_TRANSFER_READY state, unacknowledged mode data can be
        // exchanged between the entities according to subclause 11.2.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // release, the RLC entity:
        // -enters the NULL state; and
        // -is considered as being terminated.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // modification, the RLC entity:
        // - stays in the DATA_TRANSFER_READY state;
        // - modifies only the protocol parameters and timers as indicated by
        // upper layers.
        // Upon reception of a CRLC-SUSPEND-Req from upper layers, the RLC
        // entity:
        // - enters the LOCAL_SUSPEND state.

        // SEND DATA TO MAC
gauthier's avatar
gauthier committed
143
144
    	  if (rlc_p->tx_sn_length == 10) {
              rlc_um_segment_10 (rlc_p,frameP);
145
    	  }
gauthier's avatar
gauthier committed
146
147
    	  if (rlc_p->tx_sn_length == 5) {
              rlc_um_segment_5 (rlc_p,frameP);
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    	  }
        break;

      case RLC_LOCAL_SUSPEND_STATE:
        // from 3GPP TS 25.322 V9.2.0 p44
        // In the LOCAL_SUSPEND state, the RLC entity is suspended, i.e. it does
        // not send UMD PDUs with "Sequence Number" greater than or equal to a
        // certain specified value (see subclause 9.7.5).
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // release, the RLC entity:
        // - enters the NULL state; and
        // - is considered as being terminated.
        // Upon reception of a CRLC-RESUME-Req from upper layers, the RLC entity:
        // - enters the DATA_TRANSFER_READY state; and
        // - resumes the data transmission.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // modification, the RLC entity:
        // - stays in the LOCAL_SUSPEND state;
        // - modifies only the protocol parameters and timers as indicated by
        //   upper layers.

        // TO DO TAKE CARE OF SN : THE IMPLEMENTATION OF THIS FUNCTIONNALITY IS NOT CRITICAL
        break;

      default:
gauthier's avatar
gauthier committed
173
174
175
176
177
178
179
        LOG_E(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_DATA_REQ UNKNOWN PROTOCOL STATE %02X hex\n",
                frameP,
                (rlc_p->is_enb) ? "eNB" : "UE",
                rlc_p->enb_module_id,
                rlc_p->ue_module_id,
                rlc_p->rb_id,
                rlc_p->protocol_state);
180
181
182
183
184
  }
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
185
rlc_um_rx (void *argP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
186
187
{
//-----------------------------------------------------------------------------
188
189
190
  rlc_um_entity_t    *l_rlc_p = (rlc_um_entity_t *) argP;
#ifdef TRACE_RLC_UM_PDU
  mem_block_t        *tb_p;
gauthier's avatar
gauthier committed
191
  int16_t               tb_size_in_bytes;
192
193
194
195
196
197
198
  size_t              message_string_size = 0;
#   if defined(ENABLE_ITTI)
  MessageDef         *msg_p;
#   endif
  rlc_um_pdu_info_t   pdu_info;
  int                 octet_index, index;
#endif
199

200
  switch (l_rlc_p->protocol_state) {
201
202
203
204
205
206
207
208
209

      case RLC_NULL_STATE:
        // from 3GPP TS 25.322 V9.2.0 p43
        // In the NULL state the RLC entity does not exist and therefore it is
        // not possible to transfer any data through it.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // establishment, the RLC entity:
        //   - is created; and
        //   - enters the DATA_TRANSFER_READY state.
gauthier's avatar
gauthier committed
210
        LOG_N(RLC, "[RLC_UM][MOD %02u/%02u] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", l_rlc_p->enb_module_id, l_rlc_p->ue_module_id);
211

212
        /*if (data_indP.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
213
214
215
            LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_DATA_IND %d TBs\n", l_rlc_p->module_id, l_rlc_p->rb_id, frameP, data_indP.data.nb_elements);
            rlc_p[l_rlc_p->module_id].m_mscgen_trace_length = sprintf(rlc_p[l_rlc_p->module_id].m_mscgen_trace, "[MSC_MSG][FRAME %05d][MAC_%s][MOD %02d][][--- MAC_DATA_IND/ %d TB(s) ",
                frameP,
216
217
                (l_rlc_p->is_enb) ? "eNB":"UE",
                l_rlc_p->module_id,
218
219
220
221
                data_indP.data.nb_elements);

            tb = data_indP.data.head;
            while (tb != NULL) {
gauthier's avatar
gauthier committed
222
                rlc_p[l_rlc_p->module_id].m_mscgen_trace_length += sprintf(&rlc_p[l_rlc_p->module_id].m_mscgen_trace[rlc_p[l_rlc_p->module_id].m_mscgen_trace_length], " SN %d %c%c%c %d Bytes ",
gauthier's avatar
gauthier committed
223
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[1]) +  (((uint16_t)((((struct mac_tb_ind *) (tb->data))->data_ptr[0]) & 0x03)) << 8),
224
225
226
227
228
229
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[0] & 0x10) ?  '}':'{',
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[0] & 0x08) ?  '{':'}',
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[0] & 0x04) ?  'E':'_',
                                                                    ((struct mac_tb_ind *) (tb->data))->size);
                tb = tb->next;
            }
gauthier's avatar
gauthier committed
230
            rlc_p[l_rlc_p->module_id].m_mscgen_trace_length += sprintf(&rlc_p[l_rlc_p->module_id].m_mscgen_trace[rlc_p[l_rlc_p->module_id].m_mscgen_trace_length], " DROPPED RLC NULL STATE ---X][RLC_UM][MOD %02d][RB %02d]\n",
231
232
                l_rlc_p->module_id,
                l_rlc_p->rb_id);
233

gauthier's avatar
gauthier committed
234
235
            rlc_p[l_rlc_p->module_id].m_mscgen_trace[rlc_p[l_rlc_p->module_id].m_mscgen_trace_length] = 0;
            LOG_D(RLC, "%s", rlc_p[l_rlc_p->module_id].m_mscgen_trace);
236
        }*/
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
        list_free (&data_indP.data);
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
        // from 3GPP TS 25.322 V9.2.0 p43-44
        // In the DATA_TRANSFER_READY state, unacknowledged mode data can be
        // exchanged between the entities according to subclause 11.2.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // release, the RLC entity:
        // -enters the NULL state; and
        // -is considered as being terminated.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // modification, the RLC entity:
        // - stays in the DATA_TRANSFER_READY state;
        // - modifies only the protocol parameters and timers as indicated by
        // upper layers.
        // Upon reception of a CRLC-SUSPEND-Req from upper layers, the RLC
        // entity:
        // - enters the LOCAL_SUSPEND state.
        data_indP.tb_size = data_indP.tb_size >> 3;

258
259
#ifdef TRACE_RLC_UM_PDU
        if (data_indP.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
260
261
262
263
264
265
266
            LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_DATA_IND %d TBs\n",
                    frameP,
                    (l_rlc_p->is_enb) ? "eNB" : "UE",
                    l_rlc_p->enb_module_id,
                    l_rlc_p->ue_module_id,
                    l_rlc_p->rb_id,
                    data_indP.data.nb_elements);
267
268
269
270
271

            tb_p = data_indP.data.head;
            while (tb_p != NULL) {
                tb_size_in_bytes   = ((struct mac_tb_ind *) (tb_p->data))->size;

gauthier's avatar
gauthier committed
272
                rlc_um_get_pdu_infos(frameP,(rlc_um_pdu_sn_10_t*) ((struct mac_tb_ind *) (tb_p->data))->data_ptr, tb_size_in_bytes, &pdu_info, l_rlc_p->rx_sn_length);
273
274
275
276
277
278
279
280
281
282
283
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
311
312
313
314
315
316
317
                  message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
                  message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", tb_size_in_bytes);
                  message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
                  message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
                  message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC UM DATA IND: UMD PDU\n\n");

                  message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
                  message_string_size += sprintf(&message_string[message_string_size], "  FI        : %u\n", pdu_info.fi);
                  message_string_size += sprintf(&message_string[message_string_size], "  E         : %u\n", pdu_info.e);
                  message_string_size += sprintf(&message_string[message_string_size], "  SN        : %u\n", pdu_info.sn);

                  if (pdu_info.e) {
                      message_string_size += sprintf(&message_string[message_string_size], "\nHeader extension  : \n");
                      for (index=0; index < pdu_info.num_li; index++) {
                          message_string_size += sprintf(&message_string[message_string_size], "  LI        : %u\n", pdu_info.li_list[index]);
                      }
                  }
                  message_string_size += sprintf(&message_string[message_string_size], "\nPayload  : \n");
                  message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
                  message_string_size += sprintf(&message_string[message_string_size], "      |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |\n");
                  message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
                  for (octet_index = 0; octet_index < pdu_info.payload_size; octet_index++) {
                      if ((octet_index % 16) == 0){
                          if (octet_index != 0) {
                              message_string_size += sprintf(&message_string[message_string_size], " |\n");
                          }
                          message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
                      }
                      /*
                       * Print every single octet in hexadecimal form
                       */
                      message_string_size += sprintf(&message_string[message_string_size], " %02x", pdu_info.payload[octet_index]);
                      /*
                       * Align newline and pipes according to the octets in groups of 2
                       */
                  }
                  /*
                   * Append enough spaces and put final pipe
                   */
                  for (index = octet_index; index < 16; ++index) {
                      message_string_size += sprintf(&message_string[message_string_size], "   ");
                  }
                  message_string_size += sprintf(&message_string[message_string_size], " |\n");

#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
318
                  msg_p = itti_alloc_new_message_sized (l_rlc_p->is_enb ? TASK_RLC_ENB:TASK_RLC_UE , RLC_UM_DATA_PDU_IND, message_string_size + sizeof (IttiMsgText));
319
320
321
                  msg_p->ittiMsg.rlc_um_data_pdu_ind.size = message_string_size;
                  memcpy(&msg_p->ittiMsg.rlc_um_data_pdu_ind.text, message_string, message_string_size);

322
323
324
325
326
                  if (l_rlc_p->is_enb) {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->enb_module_id, msg_p);
                  } else {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->ue_module_id + NB_eNB_INST, msg_p);
                  }
327
328
329
330
331
# else
                  LOG_T(RLC, "%s", message_string);
# endif

                  tb_p = tb_p->next;
332
333
            }
        }
334
#endif
gauthier's avatar
gauthier committed
335
        rlc_um_receive (l_rlc_p, frameP, eNB_flagP, data_indP);
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
        break;

      case RLC_LOCAL_SUSPEND_STATE:
        // from 3GPP TS 25.322 V9.2.0 p44
        // In the LOCAL_SUSPEND state, the RLC entity is suspended, i.e. it does
        // not send UMD PDUs with "Sequence Number" greater than or equal to a
        // certain specified value (see subclause 9.7.5).
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // release, the RLC entity:
        // - enters the NULL state; and
        // - is considered as being terminated.
        // Upon reception of a CRLC-RESUME-Req from upper layers, the RLC entity:
        // - enters the DATA_TRANSFER_READY state; and
        // - resumes the data transmission.
        // Upon reception of a CRLC-CONFIG-Req from upper layer indicating
        // modification, the RLC entity:
        // - stays in the LOCAL_SUSPEND state;
        // - modifies only the protocol parameters and timers as indicated by
        //   upper layers.
gauthier's avatar
gauthier committed
355
356
357
358
359
360
        LOG_N(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] RLC_LOCAL_SUSPEND_STATE\n",
                frameP,
                (l_rlc_p->is_enb) ? "eNB" : "UE",
                l_rlc_p->enb_module_id,
                l_rlc_p->ue_module_id,
                l_rlc_p->rb_id);
361
        /*if (data_indP.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
362
363
364
            LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_DATA_IND %d TBs\n", l_rlc_p->module_id, l_rlc_p->rb_id, frameP, data_indP.data.nb_elements);
            rlc_p[l_rlc_p->module_id].m_mscgen_trace_length = sprintf(rlc_p[l_rlc_p->module_id].m_mscgen_trace, "[MSC_MSG][FRAME %05d][MAC_%s][MOD %02d][][--- MAC_DATA_IND/ %d TB(s) ",
                frameP,
365
366
                (l_rlc_p->is_enb) ? "eNB":"UE",
                l_rlc_p->module_id,
367
368
369
370
                data_indP.data.nb_elements);

            tb = data_indP.data.head;
            while (tb != NULL) {
gauthier's avatar
gauthier committed
371
                rlc_p[l_rlc_p->module_id].m_mscgen_trace_length += sprintf(&rlc_p[l_rlc_p->module_id].m_mscgen_trace[rlc_p[l_rlc_p->module_id].m_mscgen_trace_length], " SN %d %c%c%c %d Bytes ",
gauthier's avatar
gauthier committed
372
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[1]) +  (((uint16_t)((((struct mac_tb_ind *) (tb->data))->data_ptr[0]) & 0x03)) << 8),
373
374
375
376
377
378
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[0] & 0x10) ?  '}':'{',
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[0] & 0x08) ?  '{':'}',
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[0] & 0x04) ?  'E':'_',
                                                                    ((struct mac_tb_ind *) (tb->data))->size);
                tb = tb->next;
            }
gauthier's avatar
gauthier committed
379
            rlc_p[l_rlc_p->module_id].m_mscgen_trace_length += sprintf(&rlc_p[l_rlc_p->module_id].m_mscgen_trace[rlc_p[l_rlc_p->module_id].m_mscgen_trace_length], " DROPPED RLC LOCAL SUSPEND STATE ---X][RLC_UM][MOD %02d][RB %02d]\n",
380
381
                l_rlc_p->module_id,
                l_rlc_p->rb_id);
382

gauthier's avatar
gauthier committed
383
384
            rlc_p[l_rlc_p->module_id].m_mscgen_trace[rlc_p[l_rlc_p->module_id].m_mscgen_trace_length] = 0;
            LOG_D(RLC, "%s", rlc_p[l_rlc_p->module_id].m_mscgen_trace);
385
        }*/
386
387
388
389
        list_free (&data_indP.data);
        break;

      default:
gauthier's avatar
gauthier committed
390
391
392
393
394
395
396
        LOG_E(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] TX UNKNOWN PROTOCOL STATE %02X hex\n",
                frameP,
                (l_rlc_p->is_enb) ? "eNB" : "UE",
                l_rlc_p->enb_module_id,
                l_rlc_p->ue_module_id,
                l_rlc_p->rb_id,
                l_rlc_p->protocol_state);
397
398
399
400
401
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
gauthier's avatar
gauthier committed
402
rlc_um_mac_status_indication (void *rlc_pP, frame_t frameP, eNB_flag_t eNB_flagP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP)
403
404
405
{
//-----------------------------------------------------------------------------
  struct mac_status_resp status_resp;
gauthier's avatar
gauthier committed
406
407
408
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
409
  rlc_um_entity_t   *rlc_p = NULL;
410

411
412
413
414
415
  status_resp.buffer_occupancy_in_pdus         = 0;
  status_resp.buffer_occupancy_in_bytes        = 0;
  status_resp.head_sdu_remaining_size_to_send  = 0;
  status_resp.head_sdu_creation_time           = 0;
  status_resp.head_sdu_is_segmented            = 0;
gauthier's avatar
gauthier committed
416
  status_resp.rlc_info.rlc_protocol_state      = ((rlc_um_entity_t *) rlc_pP)->protocol_state;
417

gauthier's avatar
gauthier committed
418
419
420
  if (rlc_pP) {
      rlc_p = (rlc_um_entity_t *) rlc_pP;
      rlc_um_check_timer_dar_time_out(rlc_p,frameP,eNB_flagP);
421

gauthier's avatar
gauthier committed
422
      rlc_p->nb_bytes_requested_by_mac = tbs_sizeP;
423

gauthier's avatar
gauthier committed
424
      status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p);
425
      if (status_resp.buffer_occupancy_in_bytes > 0) {
426

gauthier's avatar
gauthier committed
427
428
	  status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes;
	  status_resp.buffer_occupancy_in_pdus = rlc_p->nb_sdu;
429

gauthier's avatar
gauthier committed
430
	  diff_time =   frameP - ((struct rlc_um_tx_sdu_management *) (rlc_p->input_sdus[rlc_p->current_sdu_index])->data)->sdu_creation_time;
gauthier's avatar
gauthier committed
431
	  status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time :  (uint32_t)(0xffffffff - diff_time + frameP) ;
gauthier's avatar
gauthier committed
432
	  //msg("rlc_p status for frameP %d diff time %d resp %d\n", frameP, diff_time,status_resp.head_sdu_creation_time) ;
433

gauthier's avatar
gauthier committed
434
435
	  sdu_size            = ((struct rlc_um_tx_sdu_management *) (rlc_p->input_sdus[rlc_p->current_sdu_index])->data)->sdu_size;
	  sdu_remaining_size  = ((struct rlc_um_tx_sdu_management *) (rlc_p->input_sdus[rlc_p->current_sdu_index])->data)->sdu_remaining_size;
436
437

	  status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
438
439
440
441
442
443
	  if (sdu_size == sdu_remaining_size)  {
           status_resp.head_sdu_is_segmented = 0;
	  }
	  else {
	   status_resp.head_sdu_is_segmented = 1;
	  }
444

445
      } else {
446
      }
gauthier's avatar
gauthier committed
447
      //msg("[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_STATUS_INDICATION BO = %d\n", ((rlc_um_entity_t *) rlc_pP)->module_id, ((rlc_um_entity_t *) rlc_pP)->rb_id, status_resp.buffer_occupancy_in_bytes);
448

gauthier's avatar
gauthier committed
449
      status_resp.rlc_info.rlc_protocol_state = ((rlc_um_entity_t *) rlc_pP)->protocol_state;
450
      #ifdef DEBUG_RLC_UM_TX_STATUS
gauthier's avatar
gauthier committed
451
452
453
454
455
456
457
458
459
460
      if ((((rlc_um_entity_t *) rlc_pP)->rb_id > 0) && (status_resp.buffer_occupancy_in_bytes > 0)) {
          LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n",
                  frameP,
                  (rlc_p->is_enb) ? "eNB" : "UE",
                  rlc_p->enb_module_id,
                  rlc_p->ue_module_id,
                  rlc_p->rb_id,
                  tbs_sizeP,
                  status_resp.buffer_occupancy_in_bytes);

461
          if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
462
463
464
465
466
467
468
              LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",
                      frameP,
                      (rlc_p->is_enb) ? "eNB" : "UE",
                      rlc_p->enb_module_id,
                      rlc_p->ue_module_id,
                      rlc_p->rb_id,
                      tx_statusP.no_pdu);
469
470
          }
          if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
471
472
473
474
475
476
477
              LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_STATUS_INDICATION  TX STATUS UNSUCCESSFUL %d PDUs\n",
                      frameP,
                      (rlc_p->is_enb) ? "eNB" : "UE",
                      rlc_p->enb_module_id,
                      rlc_p->ue_module_id,
                      rlc_p->rb_id,
                      tx_statusP.no_pdu);
478
479
480
481
482
483
484
485
486
487
488
          }
      }
      #endif
  } else {
     LOG_E(RLC, "[RLC] RLCp not defined!!!\n");
  }
  return status_resp;
}

//-----------------------------------------------------------------------------
struct mac_data_req
gauthier's avatar
gauthier committed
489
rlc_um_mac_data_request (void *rlc_pP,frame_t frameP)
490
{
491
492
    //-----------------------------------------------------------------------------
    struct mac_data_req data_req;
gauthier's avatar
gauthier committed
493
    int16_t               tb_size_in_bytes;
494
495
496
497
498
499
500
501
502
    mem_block_t        *tb_p;
#ifdef TRACE_RLC_UM_PDU
    size_t              message_string_size = 0;
#   if defined(ENABLE_ITTI)
    MessageDef         *msg_p;
#   endif
    rlc_um_pdu_info_t   pdu_info;
    int                 octet_index, index;
#endif
gauthier's avatar
gauthier committed
503
    rlc_um_entity_t *l_rlc_p = (rlc_um_entity_t *) rlc_pP;
504

gauthier's avatar
gauthier committed
505
    rlc_um_get_pdus (rlc_pP,frameP);
506

507
508
    list_init (&data_req.data, NULL);
    list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
509
510


511
512
513
514
515
516
517
518
519
520
    data_req.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (l_rlc_p);
    if (data_req.buffer_occupancy_in_bytes > 0) {
        data_req.buffer_occupancy_in_bytes += l_rlc_p->tx_header_min_length_in_bytes;
    }
    data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
    if (data_req.data.nb_elements > 0) {
        tb_p = data_req.data.head;
        while (tb_p != NULL) {
            tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size;

gauthier's avatar
gauthier committed
521
522
523
524
525
            LOG_I(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_DATA_REQUEST  TB SIZE %u\n",
                    frameP,
                    (l_rlc_p->is_enb) ? "eNB" : "UE",
                    l_rlc_p->enb_module_id,
                    l_rlc_p->ue_module_id,
526
527
528
529
530
531
532
533
                    l_rlc_p->rb_id,
                    ((struct mac_tb_req *) (tb_p->data))->tb_size);
            l_rlc_p->stat_tx_data_pdu   += 1;
            l_rlc_p->stat_tx_data_bytes += tb_size_in_bytes;

            AssertFatal( tb_size_in_bytes > 0 , "RLC UM PDU LENGTH %d", tb_size_in_bytes);

#ifdef TRACE_RLC_UM_PDU
gauthier's avatar
gauthier committed
534
            rlc_um_get_pdu_infos(frameP,(rlc_um_pdu_sn_10_t*) ((struct mac_tb_req *) (tb_p->data))->data_ptr, tb_size_in_bytes, &pdu_info, l_rlc_p->rx_sn_length);
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
            message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
            message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", tb_size_in_bytes);
            message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
            message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
            message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC UM DATA IND: UMD PDU\n\n");

            message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
            message_string_size += sprintf(&message_string[message_string_size], "  FI        : %u\n", pdu_info.fi);
            message_string_size += sprintf(&message_string[message_string_size], "  E         : %u\n", pdu_info.e);
            message_string_size += sprintf(&message_string[message_string_size], "  SN        : %u\n", pdu_info.sn);

            if (pdu_info.e) {
                message_string_size += sprintf(&message_string[message_string_size], "\nHeader extension  : \n");
                for (index=0; index < pdu_info.num_li; index++) {
                    message_string_size += sprintf(&message_string[message_string_size], "  LI        : %u\n", pdu_info.li_list[index]);
                }
            }
            message_string_size += sprintf(&message_string[message_string_size], "\nPayload  : \n");
            message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
            message_string_size += sprintf(&message_string[message_string_size], "      |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |\n");
            message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
            for (octet_index = 0; octet_index < pdu_info.payload_size; octet_index++) {
                if ((octet_index % 16) == 0){
                    if (octet_index != 0) {
                        message_string_size += sprintf(&message_string[message_string_size], " |\n");
                    }
                    message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
                }
                /*
                 * Print every single octet in hexadecimal form
                 */
                message_string_size += sprintf(&message_string[message_string_size], " %02x", pdu_info.payload[octet_index]);
                /*
                 * Align newline and pipes according to the octets in groups of 2
                 */
            }
            /*
             * Append enough spaces and put final pipe
             */
            for (index = octet_index; index < 16; ++index) {
                message_string_size += sprintf(&message_string[message_string_size], "   ");
            }
            message_string_size += sprintf(&message_string[message_string_size], " |\n");

#   if defined(ENABLE_ITTI)
            msg_p = itti_alloc_new_message_sized (l_rlc_p->is_enb > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_UM_DATA_PDU_REQ, message_string_size + sizeof (IttiMsgText));
            msg_p->ittiMsg.rlc_um_data_pdu_req.size = message_string_size;
            memcpy(&msg_p->ittiMsg.rlc_um_data_pdu_req.text, message_string, message_string_size);

584
585
586
587
588
            if (l_rlc_p->is_enb) {
                itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->enb_module_id, msg_p);
            } else {
                itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->ue_module_id + NB_eNB_INST, msg_p);
            }
589
590
591
592
593
594
595
596
# else
            LOG_T(RLC, "%s", message_string);
# endif
#endif
            tb_p = tb_p->next;
        }
    }
    return data_req;
597
598
599
600
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
601
rlc_um_mac_data_indication (void *rlc_pP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
602
603
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
604
605
    rlc_um_rx (rlc_pP, frameP, eNB_flagP, data_indP);
    rlc_um_check_timer_dar_time_out(rlc_pP,frameP,eNB_flagP);
606
607
608
609
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
610
rlc_um_data_req (void *rlc_pP, frame_t frameP, mem_block_t *sdu_pP)
611
612
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
613
  rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) rlc_pP;
614
615
616
617
618

#ifndef USER_MODE
  unsigned long int rlc_um_time_us;
  int min, sec, usec;
#endif
gauthier's avatar
gauthier committed
619
620
621
622
623
624
625
626
#if defined(ENABLE_ITTI)
  char                 message_string[7000];
  size_t               message_string_size = 0;
  MessageDef          *msg_p;
  int                  octet_index, index;
  uint16_t             data_offset;
  uint16_t             data_size;
#endif
627

gauthier's avatar
gauthier committed
628
629
630
631
632
633
634
635
636
637
638
  LOG_I(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] RLC_UM_DATA_REQ size %d Bytes, BO %d , NB SDU %d current_sdu_index=%d next_sdu_index=%d\n",
     frameP,
     (rlc_p->is_enb) ? "eNB" : "UE",
     rlc_p->enb_module_id,
     rlc_p->ue_module_id,
     rlc_p->rb_id,
     ((struct rlc_um_data_req *) (sdu_pP->data))->data_size,
     rlc_p->buffer_occupancy,
     rlc_p->nb_sdu,
     rlc_p->current_sdu_index,
     rlc_p->next_sdu_index);
639
640
641
642
  rlc_util_print_hex_octets(
      RLC,
      (uint8_t*)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)],
      ((struct rlc_um_data_req *) (sdu_pP->data))->data_size);
643
644
645
646
647
648
649

  /*#ifndef USER_MODE
  rlc_um_time_us = (unsigned long int)(rt_get_time_ns ()/(RTIME)1000);
  sec = (rlc_um_time_us/ 1000000);
  min = (sec / 60) % 60;
  sec = sec % 60;
  usec =  rlc_um_time_us % 1000000;
gauthier's avatar
gauthier committed
650
  msg ("[RLC_UM_LITE][RB  %d] at time %2d:%2d.%6d\n", rlc_p->rb_id, min, sec , usec);
651
#endif*/
gauthier's avatar
gauthier committed
652
653
  if (rlc_p->input_sdus[rlc_p->next_sdu_index] == NULL) {
    rlc_p->input_sdus[rlc_p->next_sdu_index] = sdu_pP;
654
    // IMPORTANT : do not change order of affectations
gauthier's avatar
gauthier committed
655
656
657
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size = ((struct rlc_um_data_req *) (sdu_pP->data))->data_size;
    rlc_p->buffer_occupancy += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
    rlc_p->nb_sdu += 1;
gauthier's avatar
gauthier committed
658
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->first_byte = (uint8_t*)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)];
gauthier's avatar
gauthier committed
659
660
661
662
663
664
665
666
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_remaining_size = ((struct rlc_um_tx_sdu_management *)
                                                                              (sdu_pP->data))->sdu_size;
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_segmented_size = 0;
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_creation_time = frameP;
    rlc_p->next_sdu_index = (rlc_p->next_sdu_index + 1) % rlc_p->size_input_sdus_buffer;

    rlc_p->stat_tx_pdcp_sdu   += 1;
    rlc_p->stat_tx_pdcp_bytes += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
667
#   if defined(TRACE_RLC_UM_PDU)
gauthier's avatar
gauthier committed
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
      data_offset = sizeof (struct rlc_um_data_req_alloc);
      data_size   = ((struct rlc_um_tx_sdu_management *)(sdu_pP->data))->sdu_size;
      message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", rlc_p->rb_id);
      message_string_size += sprintf(&message_string[message_string_size], "SDU size    : %u\n", data_size);

      message_string_size += sprintf(&message_string[message_string_size], "\nPayload  : \n");
      message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
      message_string_size += sprintf(&message_string[message_string_size], "      |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |\n");
      message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
      for (octet_index = 0; octet_index < data_size; octet_index++) {
          if ((octet_index % 16) == 0){
              if (octet_index != 0) {
                  message_string_size += sprintf(&message_string[message_string_size], " |\n");
              }
              message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
          }
          /*
           * Print every single octet in hexadecimal form
           */
          message_string_size += sprintf(&message_string[message_string_size], " %02x", (uint8_t*)(&sdu_pP->data[data_offset])[octet_index]);
          /*
           * Align newline and pipes according to the octets in groups of 2
           */
      }
      /*
       * Append enough spaces and put final pipe
       */
      for (index = octet_index; index < 16; ++index) {
          message_string_size += sprintf(&message_string[message_string_size], "   ");
      }
      message_string_size += sprintf(&message_string[message_string_size], " |\n");

700
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
701
702
703
704
705
706
707
708
709
      msg_p = itti_alloc_new_message_sized (rlc_p->is_enb > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_UM_SDU_REQ, message_string_size + sizeof (IttiMsgText));
      msg_p->ittiMsg.rlc_um_sdu_req.size = message_string_size;
      memcpy(&msg_p->ittiMsg.rlc_um_sdu_req.text, message_string, message_string_size);

      if (rlc_p->is_enb) {
          itti_send_msg_to_task(TASK_UNKNOWN, rlc_p->enb_module_id, msg_p);
      } else {
          itti_send_msg_to_task(TASK_UNKNOWN, rlc_p->ue_module_id + NB_eNB_INST, msg_p);
      }
710
711
712
#else 
      LOG_T(RLC, "%s", message_string);
#endif 
gauthier's avatar
gauthier committed
713
#   endif
714
715

  } else {
gauthier's avatar
gauthier committed
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
    LOG_W(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] RLC-UM_DATA_REQ input buffer full SDU garbaged\n",
          frameP,
          (rlc_p->is_enb) ? "eNB" : "UE",
          rlc_p->enb_module_id,
          rlc_p->ue_module_id,
          rlc_p->rb_id);
    rlc_p->stat_tx_pdcp_sdu             += 1;
    rlc_p->stat_tx_pdcp_bytes           += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
    rlc_p->stat_tx_pdcp_sdu_discarded   += 1;
    rlc_p->stat_tx_pdcp_bytes_discarded += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
    free_mem_block (sdu_pP);
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
      AssertFatal(0, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RLC_UM_DATA_REQ, SDU DROPPED, INPUT BUFFER OVERFLOW\n",
          frameP,
          (rlc_p->is_enb) ? "eNB" : "UE",
          rlc_p->enb_module_id,
          rlc_p->ue_module_id,
          rlc_p->rb_id);
#endif
735
736
  }
}