rlc_um.c 36.4 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
gauthier's avatar
gauthier committed
107
rlc_um_get_pdus (void *argP, frame_t frameP)
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
143
    	  if (rlc_p->tx_sn_length == 10) {
              rlc_um_segment_10 (rlc_p,frameP);
144
    	  }
gauthier's avatar
gauthier committed
145
146
    	  if (rlc_p->tx_sn_length == 5) {
              rlc_um_segment_5 (rlc_p,frameP);
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:
gauthier's avatar
gauthier committed
172
173
174
175
176
177
178
        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);
179
180
181
182
183
  }
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
184
rlc_um_rx (void *argP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
185
186
{
//-----------------------------------------------------------------------------
187
188
189
  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
190
  int16_t               tb_size_in_bytes;
191
192
193
194
195
196
197
  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
198

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

      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
209
        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);
210

211
        /*if (data_indP.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
212
213
214
            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,
215
216
                (l_rlc_p->is_enb) ? "eNB":"UE",
                l_rlc_p->module_id,
217
218
219
220
                data_indP.data.nb_elements);

            tb = data_indP.data.head;
            while (tb != NULL) {
gauthier's avatar
gauthier committed
221
                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
222
                                                                    (((struct mac_tb_ind *) (tb->data))->data_ptr[1]) +  (((uint16_t)((((struct mac_tb_ind *) (tb->data))->data_ptr[0]) & 0x03)) << 8),
223
224
225
226
227
228
                                                                    (((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
229
            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",
230
231
                l_rlc_p->module_id,
                l_rlc_p->rb_id);
232

gauthier's avatar
gauthier committed
233
234
            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);
235
        }*/
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
        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;

257
258
#ifdef TRACE_RLC_UM_PDU
        if (data_indP.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
259
260
261
262
263
264
265
            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);
266
267
268
269
270

            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
271
                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);
272
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
                  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
317
                  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));
318
319
320
                  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);

321
322
323
324
325
                  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);
                  }
326
327
328
329
330
# else
                  LOG_T(RLC, "%s", message_string);
# endif

                  tb_p = tb_p->next;
331
332
            }
        }
333
#endif
gauthier's avatar
gauthier committed
334
        rlc_um_receive (l_rlc_p, frameP, eNB_flagP, data_indP);
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
        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
354
355
356
357
358
359
        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);
360
        /*if (data_indP.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
361
362
363
            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,
364
365
                (l_rlc_p->is_enb) ? "eNB":"UE",
                l_rlc_p->module_id,
366
367
368
369
                data_indP.data.nb_elements);

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

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

      default:
gauthier's avatar
gauthier committed
389
390
391
392
393
394
395
        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);
396
397
398
399
400
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
gauthier's avatar
gauthier committed
401
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)
402
403
404
{
//-----------------------------------------------------------------------------
  struct mac_status_resp status_resp;
gauthier's avatar
gauthier committed
405
406
407
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
408
  rlc_um_entity_t   *rlc_p = NULL;
409
  mem_block_t       *mb_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) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
426

427
428
          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;
429

430
431
432
          diff_time =   frameP - ((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 + frameP) ;
          //msg("rlc_p status for frameP %d diff time %d resp %d\n", frameP, diff_time,status_resp.head_sdu_creation_time) ;
433

434
435
          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;
436

437
438
          status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
          if (sdu_size == sdu_remaining_size)  {
439
           status_resp.head_sdu_is_segmented = 0;
440
441
442
443
          }
          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;

knopp's avatar
   
knopp committed
521
            LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] MAC_DATA_REQUEST  TB SIZE %u\n",
gauthier's avatar
gauthier committed
522
523
524
525
                    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

628
  LOG_D(RLC, "[FRAME %05d][%s][RLC_UM][MOD %02u/%02u][RB %02d] RLC_UM_DATA_REQ size %d Bytes, BO %d , NB SDU %d\n",
gauthier's avatar
gauthier committed
629
630
631
632
633
634
635
     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,
636
637
638
     rlc_p->input_sdus.nb_elements);

  /*rlc_util_print_hex_octets(
639
640
      RLC,
      (uint8_t*)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)],
641
      ((struct rlc_um_data_req *) (sdu_pP->data))->data_size);*/
642
643
644
645
646
647
648

  /*#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
649
  msg ("[RLC_UM_LITE][RB  %d] at time %2d:%2d.%6d\n", rlc_p->rb_id, min, sec , usec);
650
#endif*/
651

652
    // IMPORTANT : do not change order of affectations
gauthier's avatar
gauthier committed
653
654
    ((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;
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
660
    ((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;
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)
gauthier's avatar
gauthier committed
699
700
701
702
703
704
705
706
707
      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);
      }
708
709
710
#else 
      LOG_T(RLC, "%s", message_string);
#endif 
gauthier's avatar
gauthier committed
711
#   endif
712
      list_add_tail_eurecom(sdu_pP, &rlc_p->input_sdus);
713

714
  /*} else {
gauthier's avatar
gauthier committed
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
    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
734
  }*/
735
}