rlc_um.c 36.1 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
gauthier's avatar
gauthier committed
51

52

53
54
55
#ifdef TRACE_RLC_UM_PDU
char  message_string[10000];
#endif
56
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
57
void rlc_um_stat_req     (rlc_um_entity_t *rlc_pP,
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
		  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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    *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;
93
94
}
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
95
uint32_t
gauthier's avatar
gauthier committed
96
rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP)
97
98
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
99
100
    if (rlc_pP->buffer_occupancy > 0) {
        return rlc_pP->buffer_occupancy;
101
102
103
104
105
106
    } else {
        return 0;
    }
}
//-----------------------------------------------------------------------------
void
107
rlc_um_get_pdus (const protocol_ctxt_t* const ctxt_pP, void *argP)
108
109
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
110
  rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) argP;
111

gauthier's avatar
gauthier committed
112
  switch (rlc_p->protocol_state) {
113
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

      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
142
    	  if (rlc_p->tx_sn_length == 10) {
143
              rlc_um_segment_10 (ctxt_pP, rlc_p);
144
    	  }
gauthier's avatar
gauthier committed
145
    	  if (rlc_p->tx_sn_length == 5) {
146
              rlc_um_segment_5 (ctxt_pP, rlc_p);
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    	  }
        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:
172
        LOG_E(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] MAC_DATA_REQ UNKNOWN PROTOCOL STATE %02X hex\n",
173
174
175
176
                ctxt_pP->frame,
                (ctxt_pP->enb_flag) ? "eNB" : "UE",
                ctxt_pP->enb_module_id,
                ctxt_pP->ue_module_id,
177
                (rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
178
179
                rlc_p->rb_id,
                rlc_p->protocol_state);
180
181
182
183
184
  }
}

//-----------------------------------------------------------------------------
void
185
rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, 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.
210
        LOG_N(RLC, "[RLC_UM][MOD %02u/%02u] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", ctxt_pP->enb_module_id, ctxt_pP->ue_module_id);
211

212
        /*if (data_indP.data.nb_elements > 0) {
213
            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, ctxt_pP->frame, data_indP.data.nb_elements);
gauthier's avatar
gauthier committed
214
            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) ",
215
216
                ctxt_pP->frame,
                (ctxt_pP->enb_flag) ? "eNB":"UE",
217
                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) {
260
            LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] MAC_DATA_IND %d TBs\n",
261
262
263
264
                    ctxt_pP->frame,
                    (ctxt_pP->enb_flag) ? "eNB" : "UE",
                    ctxt_pP->enb_module_id,
                    ctxt_pP->ue_module_id,
265
                    (l_rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
266
267
                    l_rlc_p->rb_id,
                    data_indP.data.nb_elements);
268
269
270
271
272

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

273
                rlc_um_get_pdu_infos(ctxt_pP->frame,(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);
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
318
                  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)
319
                  msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag ? TASK_RLC_ENB:TASK_RLC_UE , RLC_UM_DATA_PDU_IND, message_string_size + sizeof (IttiMsgText));
320
321
322
                  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);

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

                  tb_p = tb_p->next;
333
334
            }
        }
335
#endif
336
        rlc_um_receive (ctxt_pP, l_rlc_p, data_indP);
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
        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.
356
        LOG_N(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] RLC_LOCAL_SUSPEND_STATE\n",
357
358
359
360
                ctxt_pP->frame,
                (ctxt_pP->enb_flag) ? "eNB" : "UE",
                ctxt_pP->enb_module_id,
                ctxt_pP->ue_module_id,
361
                (l_rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
362
                l_rlc_p->rb_id);
363
        /*if (data_indP.data.nb_elements > 0) {
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, ctxt_pP->frame, data_indP.data.nb_elements);
gauthier's avatar
gauthier committed
365
            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) ",
366
367
                ctxt_pP->frame,
                (ctxt_pP->enb_flag) ? "eNB":"UE",
368
                l_rlc_p->module_id,
369
370
371
372
                data_indP.data.nb_elements);

            tb = data_indP.data.head;
            while (tb != NULL) {
gauthier's avatar
gauthier committed
373
                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
374
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[1]) +  (((uint16_t)((((struct mac_tb_ind *) (tb->data))->data_ptr[0]) & 0x03)) << 8),
375
376
377
378
379
380
                                                                    (((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
381
            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",
382
383
                l_rlc_p->module_id,
                l_rlc_p->rb_id);
384

gauthier's avatar
gauthier committed
385
386
            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);
387
        }*/
388
389
390
391
        list_free (&data_indP.data);
        break;

      default:
392
        LOG_E(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] TX UNKNOWN PROTOCOL STATE %02X hex\n",
393
394
395
396
                ctxt_pP->frame,
                (ctxt_pP->enb_flag) ? "eNB" : "UE",
                ctxt_pP->enb_module_id,
                ctxt_pP->ue_module_id,
397
                (l_rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
398
399
                l_rlc_p->rb_id,
                l_rlc_p->protocol_state);
400
401
402
403
404
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
405
rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP)
406
407
408
{
//-----------------------------------------------------------------------------
  struct mac_status_resp status_resp;
gauthier's avatar
gauthier committed
409
410
411
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
412
  rlc_um_entity_t   *rlc_p = NULL;
413
  mem_block_t       *mb_p = NULL;
414

415
416
417
418
419
  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;
420

gauthier's avatar
gauthier committed
421
  if (rlc_pP) {
422
423
      status_resp.rlc_info.rlc_protocol_state      = ((rlc_um_entity_t *) rlc_pP)->protocol_state;

gauthier's avatar
gauthier committed
424
      rlc_p = (rlc_um_entity_t *) rlc_pP;
425
      rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_p);
426

gauthier's avatar
gauthier committed
427
      rlc_p->nb_bytes_requested_by_mac = tbs_sizeP;
428

gauthier's avatar
gauthier committed
429
      status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p);
430
      if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
431

432
433
          status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes;
          status_resp.buffer_occupancy_in_pdus = rlc_p->input_sdus.nb_elements;
434

435
436
437
          diff_time =   ctxt_pP->frame - ((struct rlc_um_tx_sdu_management *)mb_p->data)->sdu_creation_time;
          status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time :  (uint32_t)(0xffffffff - diff_time + ctxt_pP->frame) ;
          //msg("rlc_p status for ctxt_pP->frame %d diff time %d resp %d\n", ctxt_pP->frame, diff_time,status_resp.head_sdu_creation_time) ;
438

439
440
          sdu_size            = ((struct rlc_um_tx_sdu_management *) mb_p->data)->sdu_size;
          sdu_remaining_size  = ((struct rlc_um_tx_sdu_management *) mb_p->data)->sdu_remaining_size;
441

442
443
          status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
          if (sdu_size == sdu_remaining_size)  {
444
           status_resp.head_sdu_is_segmented = 0;
445
446
447
448
          }
          else {
              status_resp.head_sdu_is_segmented = 1;
          }
449

450
      } else {
451
      }
gauthier's avatar
gauthier committed
452
      //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);
453

gauthier's avatar
gauthier committed
454
      status_resp.rlc_info.rlc_protocol_state = ((rlc_um_entity_t *) rlc_pP)->protocol_state;
455
      #ifdef DEBUG_RLC_UM_TX_STATUS
gauthier's avatar
gauthier committed
456
      if ((((rlc_um_entity_t *) rlc_pP)->rb_id > 0) && (status_resp.buffer_occupancy_in_bytes > 0)) {
457
          LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] MAC_STATUS_INDICATION (DATA) %d bytes requested -> %d bytes available\n",
458
459
460
461
                  ctxt_pP->frame,
                  (ctxt_pP->enb_flag) ? "eNB" : "UE",
                  ctxt_pP->enb_module_id,
                  ctxt_pP->ue_module_id,
462
                  (rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
463
464
465
466
                  rlc_p->rb_id,
                  tbs_sizeP,
                  status_resp.buffer_occupancy_in_bytes);

467
          if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
468
              LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",
469
470
471
472
                      ctxt_pP->frame,
                      (ctxt_pP->enb_flag) ? "eNB" : "UE",
                      ctxt_pP->enb_module_id,
                      ctxt_pP->ue_module_id,
473
                      (rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
474
475
                      rlc_p->rb_id,
                      tx_statusP.no_pdu);
476
477
          }
          if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
478
              LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] MAC_STATUS_INDICATION  TX STATUS UNSUCCESSFUL %d PDUs\n",
479
480
481
482
                      ctxt_pP->frame,
                      (ctxt_pP->enb_flag) ? "eNB" : "UE",
                      ctxt_pP->enb_module_id,
                      ctxt_pP->ue_module_id,
483
                      (rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
484
485
                      rlc_p->rb_id,
                      tx_statusP.no_pdu);
486
487
488
489
          }
      }
      #endif
  } else {
gauthier's avatar
mutex !    
gauthier committed
490
     LOG_E(RLC, "[RLC] rlc_um_mac_status_indication RLC NULL!!!\n");
491
492
493
494
495
496
  }
  return status_resp;
}

//-----------------------------------------------------------------------------
struct mac_data_req
497
rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP)
498
{
499
500
    //-----------------------------------------------------------------------------
    struct mac_data_req data_req;
gauthier's avatar
gauthier committed
501
    int16_t               tb_size_in_bytes;
502
503
504
505
506
507
508
509
510
    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
511
    rlc_um_entity_t *l_rlc_p = (rlc_um_entity_t *) rlc_pP;
512

513
    rlc_um_get_pdus (ctxt_pP, rlc_pP);
514

515
516
    list_init (&data_req.data, NULL);
    list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
517
518


519
520
521
522
523
524
525
526
527
528
    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;

529
            LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] MAC_DATA_REQUEST  TB SIZE %u\n",
530
531
532
533
                    ctxt_pP->frame,
                    (ctxt_pP->enb_flag) ? "eNB" : "UE",
                    ctxt_pP->enb_module_id,
                    ctxt_pP->ue_module_id,
534
                    (l_rlc_p->is_data_plane) ? "DRB" : "SRB",
535
536
537
538
539
540
541
542
                    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
543
            rlc_um_get_pdu_infos(ctxt_pP->frame,(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);
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
584
585
586
587
588
            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)
589
            msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_UM_DATA_PDU_REQ, message_string_size + sizeof (IttiMsgText));
590
591
592
            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);

593
594
            if (ctxt_pP->enb_flag) {
                itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
595
            } else {
596
                itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
597
            }
598
599
600
601
602
603
604
605
# else
            LOG_T(RLC, "%s", message_string);
# endif
#endif
            tb_p = tb_p->next;
        }
    }
    return data_req;
606
607
608
609
}

//-----------------------------------------------------------------------------
void
610
rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, struct mac_data_ind data_indP)
611
612
{
//-----------------------------------------------------------------------------
613
614
    rlc_um_rx (ctxt_pP, rlc_pP, data_indP);
    rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_pP);
615
616
617
618
}

//-----------------------------------------------------------------------------
void
619
rlc_um_data_req (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, mem_block_t *sdu_pP)
620
621
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
622
  rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) rlc_pP;
623
624
625
626
627

#ifndef USER_MODE
  unsigned long int rlc_um_time_us;
  int min, sec, usec;
#endif
gauthier's avatar
gauthier committed
628
629
630
631
632
633
634
635
#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
636

637
  LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][%s %02d] RLC_UM_DATA_REQ size %d Bytes, BO %d , NB SDU %d\n",
638
639
640
641
     ctxt_pP->frame,
     (ctxt_pP->enb_flag) ? "eNB" : "UE",
     ctxt_pP->enb_module_id,
     ctxt_pP->ue_module_id,
642
     (rlc_p->is_data_plane) ? "DRB" : "SRB",
gauthier's avatar
gauthier committed
643
644
645
     rlc_p->rb_id,
     ((struct rlc_um_data_req *) (sdu_pP->data))->data_size,
     rlc_p->buffer_occupancy,
646
647
648
     rlc_p->input_sdus.nb_elements);

  /*rlc_util_print_hex_octets(
649
650
      RLC,
      (uint8_t*)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)],
651
      ((struct rlc_um_data_req *) (sdu_pP->data))->data_size);*/
652
653

    // IMPORTANT : do not change order of affectations
gauthier's avatar
gauthier committed
654
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size = ((struct rlc_um_data_req *) (sdu_pP->data))->data_size;
655
    //rlc_p->nb_sdu += 1;
gauthier's avatar
gauthier committed
656
    ((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
657
658
659
    ((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;
660
    ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_creation_time = ctxt_pP->frame;
661
    //rlc_p->next_sdu_index = (rlc_p->next_sdu_index + 1) % rlc_p->size_input_sdus_buffer;
gauthier's avatar
gauthier committed
662
663
664

    rlc_p->stat_tx_pdcp_sdu   += 1;
    rlc_p->stat_tx_pdcp_bytes += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
665
#   if defined(TRACE_RLC_UM_PDU)
gauthier's avatar
gauthier committed
666
667
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
      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");

698
#   if defined(ENABLE_ITTI)
699
      msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_UM_SDU_REQ, message_string_size + sizeof (IttiMsgText));
gauthier's avatar
gauthier committed
700
701
702
      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);

703
704
      if (ctxt_pP->enb_flag) {
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
gauthier's avatar
gauthier committed
705
      } else {
706
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
gauthier's avatar
gauthier committed
707
      }
708
709
710
#else 
      LOG_T(RLC, "%s", message_string);
#endif 
gauthier's avatar
gauthier committed
711
#   endif
gauthier's avatar
mutex !    
gauthier committed
712
      pthread_mutex_lock(&rlc_p->lock_input_sdus);
gauthier's avatar
gauthier committed
713
      rlc_p->buffer_occupancy += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
714
      list_add_tail_eurecom(sdu_pP, &rlc_p->input_sdus);
gauthier's avatar
mutex !    
gauthier committed
715
      pthread_mutex_unlock(&rlc_p->lock_input_sdus);
716
}