rlc_um.c 34.3 KB
Newer Older
1
/*******************************************************************************
Lionel Gauthier's avatar
Lionel Gauthier committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

Lionel Gauthier's avatar
Lionel 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


Lionel Gauthier's avatar
Lionel 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

Lionel Gauthier's avatar
Lionel 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
18 19
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20

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

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

 *******************************************************************************/
29 30
#define RLC_UM_MODULE 1
#define RLC_UM_C 1
31 32 33 34 35
//-----------------------------------------------------------------------------
//#include "rtos_header.h"
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
36
#if ENABLE_ITTI
37 38 39
# include "intertask_interface.h"
#endif
#include "assertions.h"
Raymond Knopp's avatar
Raymond Knopp committed
40
#include "msc.h"
41 42 43 44 45 46 47 48 49 50 51
#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"

//-----------------------------------------------------------------------------
52
void rlc_um_stat_req     (rlc_um_entity_t *rlc_pP,
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
                          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)
{
  *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;
88 89
}
//-----------------------------------------------------------------------------
90
uint32_t
91
rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP)
92
{
93 94 95 96 97
  if (rlc_pP->buffer_occupancy > 0) {
    return rlc_pP->buffer_occupancy;
  } else {
    return 0;
  }
98 99 100
}
//-----------------------------------------------------------------------------
void
101
rlc_um_get_pdus (const protocol_ctxt_t* const ctxt_pP, void *argP)
102
{
103
  rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) argP;
104

105
  switch (rlc_p->protocol_state) {
106

107 108 109 110 111 112 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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  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
    if (rlc_p->tx_sn_length == 10) {
      rlc_um_segment_10 (ctxt_pP, rlc_p);
    }

    if (rlc_p->tx_sn_length == 5) {
      rlc_um_segment_5 (ctxt_pP, rlc_p);
    }

    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:
168 169
    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_DATA_REQ UNKNOWN PROTOCOL STATE %02X hex\n",
          PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
170
          rlc_p->protocol_state);
171 172 173 174 175
  }
}

//-----------------------------------------------------------------------------
void
176
rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind data_indP)
177
{
178
  rlc_um_entity_t    *l_rlc_p = (rlc_um_entity_t *) argP;
179
#if TRACE_RLC_UM_PDU || MESSAGE_CHART_GENERATOR
180
  char  message_string[10000];
181
  mem_block_t        *tb_p;
182
  int16_t               tb_size_in_bytes;
183
  size_t              message_string_size = 0;
184 185 186
  rlc_um_pdu_info_t   pdu_info;
  int index;
#endif
187
#if TRACE_RLC_UM_PDU
188
  int                 octet_index;
189
#   if ENABLE_ITTI
190 191 192
  MessageDef         *msg_p;
#   endif
#endif
193

194
  switch (l_rlc_p->protocol_state) {
195

196 197 198 199 200 201 202 203
  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.
204 205
    LOG_N(RLC, PROTOCOL_RLC_UM_CTXT_FMT" ERROR MAC_DATA_IND IN RLC_NULL_STATE\n",
          PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p));
206
#if MESSAGE_CHART_GENERATOR
207

208 209
    if (data_indP.data.nb_elements > 0) {
      tb_p = data_indP.data.head;
210

211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
      while (tb_p != NULL) {
        tb_size_in_bytes   = ((struct mac_tb_ind*) (tb_p->data))->size;
        rlc_um_get_pdu_infos(ctxt_pP,l_rlc_p,(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);
        message_string_size = 0;
        message_string_size += sprintf(&message_string[message_string_size],
                                       MSC_AS_TIME_FMT" "PROTOCOL_RLC_UM_MSC_FMT"DATA SN %u size %u FI %u",
                                       MSC_AS_TIME_ARGS(ctxt_pP),
                                       PROTOCOL_RLC_UM_MSC_ARGS(ctxt_pP, l_rlc_p),
                                       pdu_info.sn,
                                       tb_size_in_bytes,
                                       pdu_info.fi);

        if (pdu_info.e) {
          message_string_size += sprintf(&message_string[message_string_size], "| HE:");

          for (index=0; index < pdu_info.num_li; index++) {
Lionel Gauthier's avatar
Lionel Gauthier committed
227
            message_string_size += sprintf(&message_string[message_string_size], " LI %u", pdu_info.li_list[index]);
228
        }
229 230
        }

231
        MSC_LOG_RX_DISCARDED_MESSAGE(
232 233 234 235 236 237 238 239 240 241 242
          (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
          (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_UE:MSC_RLC_ENB,
          (const char*)pdu_info.payload,
          tb_size_in_bytes,
          message_string);

        tb_p = tb_p->next;
      }
    }

#endif
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    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;
263

264
#if TRACE_RLC_UM_PDU || MESSAGE_CHART_GENERATOR
265 266

    if (data_indP.data.nb_elements > 0) {
267 268
      LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_DATA_IND %d TBs\n",
            PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p),
269 270 271 272 273 274
            data_indP.data.nb_elements);

      tb_p = data_indP.data.head;

      while (tb_p != NULL) {
        tb_size_in_bytes   = ((struct mac_tb_ind *) (tb_p->data))->size;
275 276 277 278 279 280
        rlc_um_get_pdu_infos(ctxt_pP,
                             l_rlc_p,(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);

281
#if MESSAGE_CHART_GENERATOR
282 283 284 285 286 287 288 289 290 291 292 293 294
        message_string_size = 0;
        message_string_size += sprintf(&message_string[message_string_size],
                                       MSC_AS_TIME_FMT" "PROTOCOL_RLC_UM_MSC_FMT"DATA SN %u size %u FI %u",
                                       MSC_AS_TIME_ARGS(ctxt_pP),
                                       PROTOCOL_RLC_UM_MSC_ARGS(ctxt_pP, l_rlc_p),
                                       pdu_info.sn,
                                       tb_size_in_bytes,
                                       pdu_info.fi);

        if (pdu_info.e) {
          message_string_size += sprintf(&message_string[message_string_size], "| HE:");

          for (index=0; index < pdu_info.num_li; index++) {
Lionel Gauthier's avatar
Lionel Gauthier committed
295
            message_string_size += sprintf(&message_string[message_string_size], " LI  %u", pdu_info.li_list[index]);
296 297 298
          }
        }

299
        MSC_LOG_RX_MESSAGE(
300 301 302 303 304
          (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
          (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_UE:MSC_RLC_ENB,
          (char*)pdu_info.payload,
          tb_size_in_bytes,
          message_string);
305

306
#endif
307
#if TRACE_RLC_UM_PDU
308
        message_string_size = 0;
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
        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");
359

360
#   if ENABLE_ITTI
361 362 363 364
        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));
        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);

365
        itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
366

367
# else
368
        LOG_T(RLC, "%s", message_string);
369 370
# endif // ENABLE_ITTI
#endif // TRACE_RLC_UM_PDU
371

372 373 374 375
        tb_p = tb_p->next;
      }
    }

376
#endif
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
    rlc_um_receive (ctxt_pP, l_rlc_p, data_indP);
    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.
397 398
    LOG_N(RLC, PROTOCOL_RLC_UM_CTXT_FMT" RLC_LOCAL_SUSPEND_STATE\n",
          PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p));
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
    /*if (data_indP.data.nb_elements > 0) {
        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);
        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) ",
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB":"UE",
            l_rlc_p->module_id,
            data_indP.data.nb_elements);

        tb = data_indP.data.head;
        while (tb != NULL) {
            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 ",
                                                                (((struct mac_tb_ind *) (tb->data))->data_ptr[1]) +  (((uint16_t)((((struct mac_tb_ind *) (tb->data))->data_ptr[0]) & 0x03)) << 8),
                                                                (((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;
        }
        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",
            l_rlc_p->module_id,
            l_rlc_p->rb_id);

        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);
    }*/
    list_free (&data_indP.data);
    break;

  default:
428 429
    LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" TX UNKNOWN PROTOCOL STATE %02X hex\n",
          PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p),
430
          l_rlc_p->protocol_state);
431 432 433 434 435
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
436
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)
437 438
{
  struct mac_status_resp status_resp;
439 440 441
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
442
  rlc_um_entity_t   *rlc_p = NULL;
443
  mem_block_t       *mb_p = NULL;
444

445 446 447 448 449
  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;
450

451
  if (rlc_pP) {
452

453
    rlc_p = (rlc_um_entity_t *) rlc_pP;
454
    status_resp.rlc_info.rlc_protocol_state      = rlc_p->protocol_state;
455
    rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_p);
456

457
    rlc_p->nb_bytes_requested_by_mac = tbs_sizeP;
458

459
    status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p);
460

461
    if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
462

463 464
      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;
465

466 467 468
      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) ;
469

470 471 472 473
      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;

      status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
474

475 476
      if (sdu_size == sdu_remaining_size)  {
        status_resp.head_sdu_is_segmented = 0;
477
      } else {
478
        status_resp.head_sdu_is_segmented = 1;
479
      }
480 481 482 483 484 485 486

    } else {
    }

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

    status_resp.rlc_info.rlc_protocol_state = ((rlc_um_entity_t *) rlc_pP)->protocol_state;
487
#if TRACE_RLC_UM_TX_STATUS
488 489

    if ((((rlc_um_entity_t *) rlc_pP)->rb_id > 0) && (status_resp.buffer_occupancy_in_bytes > 0)) {
490 491
      LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) %d bytes requested -> %d bytes available\n",
            PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
492 493 494 495
            tbs_sizeP,
            status_resp.buffer_occupancy_in_bytes);

      if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
496 497
        LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",
              PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
498
              tx_statusP.no_pdu);
499
      }
500 501

      if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
502 503
        LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_STATUS_INDICATION  TX STATUS UNSUCCESSFUL %d PDUs\n",
              PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
504 505 506 507 508
              tx_statusP.no_pdu);
      }
    }

#endif
509
  } else {
510
    LOG_E(RLC, "[RLC] rlc_um_mac_status_indication RLC NULL!!!\n");
511
  }
512

513 514 515 516 517
  return status_resp;
}

//-----------------------------------------------------------------------------
struct mac_data_req
518
rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP)
519
{
520 521 522
  struct mac_data_req data_req;
  int16_t               tb_size_in_bytes;
  mem_block_t        *tb_p;
523
#if TRACE_RLC_UM_PDU || MESSAGE_CHART_GENERATOR
524
  char  message_string[10000];
525
  size_t              message_string_size = 0;
526
#   if ENABLE_ITTI
527
  MessageDef         *msg_p;
528
#   endif
529 530
  rlc_um_pdu_info_t   pdu_info;
  int                 octet_index, index;
531
#endif
532
  rlc_um_entity_t *l_rlc_p = (rlc_um_entity_t *) rlc_pP;
533

534
  rlc_um_get_pdus(ctxt_pP, l_rlc_p);
535

536 537
  list_init (&data_req.data, NULL);
  list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
538 539


540 541 542 543 544 545 546 547 548 549 550 551 552 553
  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;

554 555
      LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_DATA_REQUEST  TB SIZE %u\n",
            PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p),
556 557 558 559 560
            ((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);
561
#if TRACE_RLC_UM_PDU || MESSAGE_CHART_GENERATOR
562 563
      rlc_um_get_pdu_infos(ctxt_pP, l_rlc_p,(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);
#endif
564
#if MESSAGE_CHART_GENERATOR
565 566 567 568 569 570 571 572
      message_string_size = 0;
      message_string_size += sprintf(&message_string[message_string_size],
                                     MSC_AS_TIME_FMT" "PROTOCOL_RLC_UM_MSC_FMT" DATA SN %u size %u FI %u",
                                     MSC_AS_TIME_ARGS(ctxt_pP),
                                     PROTOCOL_RLC_UM_MSC_ARGS(ctxt_pP, l_rlc_p),
                                     pdu_info.sn,
                                     tb_size_in_bytes,
                                     pdu_info.fi);
573

574 575 576 577
      if (pdu_info.e) {
        message_string_size += sprintf(&message_string[message_string_size], "|HE:");

        for (index=0; index < pdu_info.num_li; index++) {
Lionel Gauthier's avatar
Lionel Gauthier committed
578
          message_string_size += sprintf(&message_string[message_string_size], " LI %u", pdu_info.li_list[index]);
579 580 581
        }
      }

582
      MSC_LOG_TX_MESSAGE(
583 584 585 586 587 588 589
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_UE:MSC_RLC_ENB,
        (const char*)pdu_info.payload,
        pdu_info.payload_size,
        message_string);

#endif
590
#if TRACE_RLC_UM_PDU
591
      message_string_size = 0;
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
      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) {
619
            message_string_size += sprintf(&message_string[message_string_size], " |\n");
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
          }

          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");
642

643
#   if ENABLE_ITTI
644 645 646 647
      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));
      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);

648
      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
649

650
# else
651
      LOG_T(RLC, "%s", message_string);
652 653
# endif
#endif
654
      tb_p = tb_p->next;
655
    }
656 657 658
  }

  return data_req;
659 660 661 662
}

//-----------------------------------------------------------------------------
void
663
rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, struct mac_data_ind data_indP)
664
{
665 666
  rlc_um_rx (ctxt_pP, rlc_pP, data_indP);
  rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_pP);
667 668 669 670
}

//-----------------------------------------------------------------------------
void
671
rlc_um_data_req (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, mem_block_t *sdu_pP)
672
{
673
  rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) rlc_pP;
674

675
#if ! USER_MODE
676 677 678
  unsigned long int rlc_um_time_us;
  int min, sec, usec;
#endif
679 680
#if TRACE_RLC_UM_PDU
#if ENABLE_ITTI
Lionel Gauthier's avatar
Lionel Gauthier committed
681
  MessageDef          *msg_p;
682
#   endif
Lionel Gauthier's avatar
Lionel Gauthier committed
683 684
  uint16_t             data_offset;
  uint16_t             data_size;
685 686 687
  size_t               message_string_size = 0;
  int                  octet_index, index;
  char                 message_string[7000];
Lionel Gauthier's avatar
Lionel Gauthier committed
688
#endif
689

690 691
  LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" RLC_UM_DATA_REQ size %d Bytes, BO %d , NB SDU %d\n",
        PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
692 693 694
        ((struct rlc_um_data_req *) (sdu_pP->data))->data_size,
        rlc_p->buffer_occupancy,
        rlc_p->input_sdus.nb_elements);
695 696

  /*rlc_util_print_hex_octets(
697 698
      RLC,
      (uint8_t*)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)],
699
      ((struct rlc_um_data_req *) (sdu_pP->data))->data_size);*/
700

701 702 703 704 705 706 707 708 709 710 711 712
  // IMPORTANT : do not change order of affectations
  ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size = ((struct rlc_um_data_req *) (sdu_pP->data))->data_size;
  //rlc_p->nb_sdu += 1;
  ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->first_byte = (uint8_t*)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)];
  ((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 = ctxt_pP->frame;
  //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;
713 714

  MSC_LOG_RX_MESSAGE(
715 716
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
Lionel Gauthier's avatar
Lionel Gauthier committed
717 718
    NULL,
    0,
719 720 721 722
    MSC_AS_TIME_FMT" "PROTOCOL_RLC_UM_MSC_FMT" DATA-REQ size %u",
    MSC_AS_TIME_ARGS(ctxt_pP),
    PROTOCOL_RLC_UM_MSC_ARGS(ctxt_pP, rlc_p),
    ((struct rlc_um_tx_sdu_management*) (sdu_pP->data))->sdu_size);
723 724


725
#   if TRACE_RLC_UM_PDU
726 727 728 729 730 731 732 733 734 735 736 737 738 739
  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");
Lionel Gauthier's avatar
Lionel Gauthier committed
740
      }
741 742 743 744 745 746 747

      message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
    }

    /*
     * Print every single octet in hexadecimal form
     */
Cedric Roux's avatar
Cedric Roux committed
748
    message_string_size += sprintf(&message_string[message_string_size], " %02x", ((uint8_t*)(&sdu_pP->data[data_offset]))[octet_index]);
749 750 751 752 753 754 755 756 757 758 759 760 761
    /*
     * 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");
Lionel Gauthier's avatar
Lionel Gauthier committed
762

763
#   if ENABLE_ITTI
764 765 766
  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));
  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);
Lionel Gauthier's avatar
Lionel Gauthier committed
767

768
  itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
769 770 771 772

#else
  LOG_T(RLC, "%s", message_string);
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
773
#   endif
Raymond Knopp's avatar
Raymond Knopp committed
774
  RLC_UM_MUTEX_LOCK(&rlc_p->lock_input_sdus, ctxt_pP, rlc_p);
775 776
  rlc_p->buffer_occupancy += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
  list_add_tail_eurecom(sdu_pP, &rlc_p->input_sdus);
Raymond Knopp's avatar
Raymond Knopp committed
777
  RLC_UM_MUTEX_UNLOCK(&rlc_p->lock_input_sdus);
778 779 780 781 782 783 784 785 786 787 788 789 790 791
#if DEBUG_RLC_CONGESTION
#if MESSAGE_CHART_GENERATOR
  if (rlc_p->buffer_occupancy > 4096) {
      MSC_LOG_EVENT((ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,\
                             "0 "PROTOCOL_RLC_AM_MSC_FMT" BO %u bytes",\
                             PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP,rlc_pP), rlc_p->buffer_occupancy);
  }
#else
  LOG_W(RLC, PROTOCOL_RLC_UM_CTXT_FMT" BO %d , NB SDU %d\n",
        PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
        rlc_p->buffer_occupancy,
        rlc_p->input_sdus.nb_elements);
#endif
#endif
792
}