rlc_am.c 60.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
gauthier's avatar
gauthier committed
21

22 23
#define RLC_AM_MODULE 1
#define RLC_AM_C 1
24 25 26 27
//-----------------------------------------------------------------------------
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
28
#if ENABLE_ITTI
gauthier's avatar
gauthier committed
29 30
# include "intertask_interface.h"
#endif
31
#include "assertions.h"
knopp's avatar
mutexes  
knopp committed
32
#include "msc.h"
33
#include "hashtable.h"
34 35 36 37 38 39 40 41 42 43
#include "rlc_am.h"
#include "rlc_am_segment.h"
#include "rlc_am_timer_poll_retransmit.h"
#include "mac_primitives.h"
#include "rlc_primitives.h"
#include "list.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UL-AM-RLC.h"
#include "DL-AM-RLC.h"
44

gauthier's avatar
gauthier committed
45

46
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
47
uint32_t
48
rlc_am_get_buffer_occupancy_in_bytes (
49 50
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const      rlc_pP)
51
{
gauthier's avatar
gauthier committed
52 53
  uint32_t max_li_overhead;
  uint32_t header_overhead;
54 55

  // priority of control trafic
gauthier's avatar
gauthier committed
56
  if (rlc_pP->status_requested) {
57
    if (rlc_pP->t_status_prohibit.running == 0) {
58
#if TRACE_RLC_AM_BO
59 60 61

      if (((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3) > 0) {
        LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n",
62
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
63
              ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3));
64
      }
65 66 67 68

#endif
      return ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
    }
69 70 71
  }

  // data traffic
gauthier's avatar
gauthier committed
72
  if (rlc_pP->nb_sdu_no_segmented <= 1) {
73
    max_li_overhead = 0;
74
  } else {
75
    max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2);
76
  }
77

gauthier's avatar
gauthier committed
78
  if (rlc_pP->sdu_buffer_occupancy == 0) {
79
    header_overhead = 0;
80
  } else {
81
    header_overhead = 2;
82 83 84
  }


85
#if TRACE_RLC_AM_BO
86

gauthier's avatar
gauthier committed
87
  if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
88 89 90 91
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : STATUS  BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->status_buffer_occupancy);
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retransmission_buffer_occupancy);
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : SDU     BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
92 93 94 95
          rlc_pP->sdu_buffer_occupancy,
          max_li_overhead,
          header_overhead,
          rlc_pP->nb_sdu_no_segmented);
96
  }
97

98
#endif
99
  return rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead;
100 101
}
//-----------------------------------------------------------------------------
102 103
void
rlc_am_release (
104 105 106
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const      rlc_pP
)
107
{
108
  // empty
109 110
}
//-----------------------------------------------------------------------------
111 112
void
config_req_rlc_am (
113 114 115
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t             srb_flagP,
  rlc_am_info_t  * const       config_am_pP,
116
  const rb_id_t                rb_idP,
117
  const logical_chan_id_t      chan_idP 
118
)
119
{
120 121
  rlc_union_t       *rlc_union_p = NULL;
  rlc_am_entity_t *l_rlc_p         = NULL;
122
  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
123 124 125 126 127 128 129
  hashtable_rc_t   h_rc;

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);

  if (h_rc == HASH_TABLE_OK) {
    l_rlc_p = &rlc_union_p->rlc.am;
    LOG_D(RLC,
130 131
          PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d)\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
132 133 134 135 136 137 138
          config_am_pP->max_retx_threshold,
          config_am_pP->poll_pdu,
          config_am_pP->poll_byte,
          config_am_pP->t_poll_retransmit,
          config_am_pP->t_reordering,
          config_am_pP->t_status_prohibit);
    rlc_am_init(ctxt_pP, l_rlc_p);
139
    rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
140 141 142 143 144 145 146 147
    rlc_am_configure(ctxt_pP, l_rlc_p,
                     config_am_pP->max_retx_threshold,
                     config_am_pP->poll_pdu,
                     config_am_pP->poll_byte,
                     config_am_pP->t_poll_retransmit,
                     config_am_pP->t_reordering,
                     config_am_pP->t_status_prohibit);
  } else {
148 149
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ RLC NOT FOUND\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
150
  }
151
}
152 153 154 155 156 157
uint32_t pollPDU_tab[PollPDU_pInfinity+1]= {4,8,16,32,64,128,256,1024}; // What is PollPDU_pInfinity??? 1024 for now
uint32_t maxRetxThreshold_tab[UL_AM_RLC__maxRetxThreshold_t32+1]= {1,2,3,4,6,8,16,32};
uint32_t pollByte_tab[PollByte_spare1]= {25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,10000}; // What is PollByte_kBinfinity??? 10000 for now
uint32_t PollRetransmit_tab[T_PollRetransmit_spare9]= {5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500};
uint32_t am_t_Reordering_tab[T_Reordering_spare1]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200};
uint32_t t_StatusProhibit_tab[T_StatusProhibit_spare8]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500};
158 159

//-----------------------------------------------------------------------------
160
void config_req_rlc_am_asn1 (
161 162 163
  const protocol_ctxt_t* const         ctxt_pP,
  const srb_flag_t                     srb_flagP,
  const struct RLC_Config__am  * const config_am_pP,
164
  const rb_id_t                        rb_idP,
165
  const logical_chan_id_t              chan_idP)
166
{
167
  rlc_union_t     *rlc_union_p   = NULL;
gauthier's avatar
gauthier committed
168
  rlc_am_entity_t *l_rlc_p         = NULL;
169
  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
170 171 172
  hashtable_rc_t   h_rc;

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
173

174
  if (h_rc == HASH_TABLE_OK) {
175 176 177 178 179 180 181 182 183
    l_rlc_p = &rlc_union_p->rlc.am;

    if ((config_am_pP->ul_AM_RLC.maxRetxThreshold <= UL_AM_RLC__maxRetxThreshold_t32) &&
        (config_am_pP->ul_AM_RLC.pollPDU<=PollPDU_pInfinity) &&
        (config_am_pP->ul_AM_RLC.pollByte<PollByte_spare1) &&
        (config_am_pP->ul_AM_RLC.t_PollRetransmit<T_PollRetransmit_spare9) &&
        (config_am_pP->dl_AM_RLC.t_Reordering<T_Reordering_spare1) &&
        (config_am_pP->dl_AM_RLC.t_StatusProhibit<T_StatusProhibit_spare8) ) {

gauthier's avatar
gauthier committed
184
      MSC_LOG_RX_MESSAGE(
185 186 187 188 189 190 191 192 193 194
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
        NULL,
        0,
        MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ t_PollRetx %u t_Reord %u t_StatusPro %u",
        MSC_AS_TIME_ARGS(ctxt_pP),
        PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
        PollRetransmit_tab[config_am_pP->ul_AM_RLC.t_PollRetransmit],
        am_t_Reordering_tab[config_am_pP->dl_AM_RLC.t_Reordering],
        t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
gauthier's avatar
gauthier committed
195

196 197
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d)\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
198 199 200 201 202 203 204 205
            maxRetxThreshold_tab[config_am_pP->ul_AM_RLC.maxRetxThreshold],
            pollPDU_tab[config_am_pP->ul_AM_RLC.pollPDU],
            pollByte_tab[config_am_pP->ul_AM_RLC.pollByte],
            PollRetransmit_tab[config_am_pP->ul_AM_RLC.t_PollRetransmit],
            am_t_Reordering_tab[config_am_pP->dl_AM_RLC.t_Reordering],
            t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);

      rlc_am_init(ctxt_pP, l_rlc_p);
206
      rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
207 208 209 210 211 212 213 214
      rlc_am_configure(ctxt_pP, l_rlc_p,
                       maxRetxThreshold_tab[config_am_pP->ul_AM_RLC.maxRetxThreshold],
                       pollPDU_tab[config_am_pP->ul_AM_RLC.pollPDU],
                       pollByte_tab[config_am_pP->ul_AM_RLC.pollByte],
                       PollRetransmit_tab[config_am_pP->ul_AM_RLC.t_PollRetransmit],
                       am_t_Reordering_tab[config_am_pP->dl_AM_RLC.t_Reordering],
                       t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
    } else {
gauthier's avatar
gauthier committed
215
      MSC_LOG_RX_DISCARDED_MESSAGE(
216 217 218 219 220 221 222
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
        NULL,
        0,
        MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ",
        MSC_AS_TIME_ARGS(ctxt_pP),
        PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p));
gauthier's avatar
gauthier committed
223

224
      LOG_D(RLC,
225 226
            PROTOCOL_RLC_AM_CTXT_FMT"ILLEGAL CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d), RLC-AM NOT CONFIGURED\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
227 228 229 230 231 232 233
            config_am_pP->ul_AM_RLC.maxRetxThreshold,
            config_am_pP->ul_AM_RLC.pollPDU,
            config_am_pP->ul_AM_RLC.pollByte,
            config_am_pP->ul_AM_RLC.t_PollRetransmit,
            config_am_pP->dl_AM_RLC.t_Reordering,
            config_am_pP->dl_AM_RLC.t_StatusProhibit);
    }
234
  } else {
235 236
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"CONFIG_REQ RLC NOT FOUND\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
237
  }
238 239
}

240
//-----------------------------------------------------------------------------
241
void rlc_am_stat_req (
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  const protocol_ctxt_t* const         ctxt_pP,
  rlc_am_entity_t * const              rlc_pP,
  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_tx_retransmit_pdu_by_status,
  unsigned int* stat_tx_retransmit_bytes_by_status,
  unsigned int* stat_tx_retransmit_pdu,
  unsigned int* stat_tx_retransmit_bytes,
  unsigned int* stat_tx_control_pdu,
  unsigned int* stat_tx_control_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_rx_control_pdu,
  unsigned int* stat_rx_control_bytes,
  unsigned int* stat_timer_reordering_timed_out,
  unsigned int* stat_timer_poll_retransmit_timed_out,
  unsigned int* stat_timer_status_prohibit_timed_out)
271
{
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
  *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_tx_retransmit_pdu_by_status     = rlc_pP->stat_tx_retransmit_pdu_by_status;
  *stat_tx_retransmit_bytes_by_status   = rlc_pP->stat_tx_retransmit_bytes_by_status;
  *stat_tx_retransmit_pdu               = rlc_pP->stat_tx_retransmit_pdu;
  *stat_tx_retransmit_bytes             = rlc_pP->stat_tx_retransmit_bytes;
  *stat_tx_control_pdu                  = rlc_pP->stat_tx_control_pdu;
  *stat_tx_control_bytes                = rlc_pP->stat_tx_control_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_rx_control_pdu                  = rlc_pP->stat_rx_control_pdu;
  *stat_rx_control_bytes                = rlc_pP->stat_rx_control_bytes;
  *stat_timer_reordering_timed_out      = rlc_pP->stat_timer_reordering_timed_out;
  *stat_timer_poll_retransmit_timed_out = rlc_pP->stat_timer_poll_retransmit_timed_out;
  *stat_timer_status_prohibit_timed_out = rlc_pP->stat_timer_status_prohibit_timed_out;
299 300 301 302

}
//-----------------------------------------------------------------------------
void
303
rlc_am_get_pdus (
304 305 306
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const      rlc_pP
)
307 308 309 310 311 312 313 314 315 316
{
  int display_flag = 0;
  // 5.1.3.1 Transmit operations
  // 5.1.3.1.1
  // General
  // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control PDUs over RLC data PDUs.
  // The transmitting side of an AM RLC entity shall prioritize retransmission of RLC data PDUs over transmission of new
  // AMD PDUs.


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
  switch (rlc_pP->protocol_state) {

  case RLC_NULL_STATE:
    break;

  case RLC_DATA_TRANSFER_READY_STATE:

    // TRY TO SEND CONTROL PDU FIRST
    if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) {
      // When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall:
      // - if t-StatusProhibit is not running:
      //     - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer;
      // - else:
      //     - at the first transmission opportunity indicated by lower layer after t-StatusProhibit expires, construct a single
      //       STATUS PDU even if status reporting was triggered several times while t-StatusProhibit was running and
      //       deliver it to lower layer;
      //
      // When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall:
      //     - start t-StatusProhibit.
      if (rlc_pP->t_status_prohibit.running == 0) {
        rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
        mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);

        if (pdu) {
          list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
          rlc_pP->status_requested = 0;
          rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
          return;
        }
      } else {
347 348 349
        LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU BECAUSE T-STATUS-PROHIBIT RUNNING (TIME-OUT %u)\n",
              PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
              rlc_pP->t_status_prohibit.ms_time_out);
350 351 352 353 354 355 356 357
      }
    }

    /*while ((rlc_pP->nb_bytes_requested_by_mac > 0) && (stay_on_this_list)) {
        mem_block_t* pdu = list_get_head(&rlc_pP->control_pdu_list);
        if (pdu != NULL {
            if ( ((rlc_am_tx_control_pdu_management_t*)(pdu->data))->size <= rlc_pP->nb_bytes_requested_by_mac) {
                pdu = list_remove_head(&rlc_pP->control_pdu_list);
358
    #if TRACE_RLC_AM_TX
359 360 361 362
                msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND CONTROL PDU\n", ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, ctxt_pP->frame);
    #endif
                list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
                rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - ((rlc_am_tx_control_pdu_management_t*)(pdu->data))->size;
363
            } else {
364
              stay_on_this_list = 0;
365
            }
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
        } else {
            stay_on_this_list = 0;
        }
    }*/
    // THEN TRY TO SEND RETRANS PDU
    if (rlc_pP->first_retrans_pdu_sn >= 0) {
      rlc_am_tx_data_pdu_management_t* tx_data_pdu_management;

      // tx min 3 bytes because of the size of the RLC header
      while ((rlc_pP->nb_bytes_requested_by_mac > 2) &&
             (rlc_pP->first_retrans_pdu_sn  >= 0) &&
             (rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s)) {

        tx_data_pdu_management = &rlc_pP->pdu_retrans_buffer[rlc_pP->first_retrans_pdu_sn];

381 382
        if ((tx_data_pdu_management->header_and_payload_size <= rlc_pP->nb_bytes_requested_by_mac) && (tx_data_pdu_management->retx_count >= 0)
            && (tx_data_pdu_management->nack_so_start == 0) && (tx_data_pdu_management->nack_so_stop == 0x7FFF)) {
383
          mem_block_t* copy = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn);
384 385
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RE-SEND DATA PDU SN %04d   %d BYTES\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
                rlc_pP->first_retrans_pdu_sn,
                tx_data_pdu_management->header_and_payload_size);
          rlc_pP->stat_tx_data_pdu                   += 1;
          rlc_pP->stat_tx_retransmit_pdu             += 1;
          rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
          rlc_pP->stat_tx_data_bytes                 += tx_data_pdu_management->header_and_payload_size;
          rlc_pP->stat_tx_retransmit_bytes           += tx_data_pdu_management->header_and_payload_size;
          rlc_pP->stat_tx_retransmit_bytes_by_status += tx_data_pdu_management->header_and_payload_size;

          list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
          rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - tx_data_pdu_management->header_and_payload_size;

          tx_data_pdu_management->retx_count += 1;
          return;
        } else if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac >= RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
401 402
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d MAC BYTES %d SIZE %d RTX COUNT %d  nack_so_start %d nack_so_stop %04X(hex)\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
403 404 405 406 407 408 409 410 411 412 413 414
                rlc_pP->first_retrans_pdu_sn,
                rlc_pP->nb_bytes_requested_by_mac,
                tx_data_pdu_management->header_and_payload_size,
                tx_data_pdu_management->retx_count,
                tx_data_pdu_management->nack_so_start,
                tx_data_pdu_management->nack_so_stop);

          mem_block_t* copy = rlc_am_retransmit_get_subsegment(
                                ctxt_pP,
                                rlc_pP,
                                rlc_pP->first_retrans_pdu_sn,
                                &rlc_pP->nb_bytes_requested_by_mac);
415 416
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
                rlc_pP->first_retrans_pdu_sn,
                tx_data_pdu_management->nack_so_start);

          rlc_pP->stat_tx_data_pdu                   += 1;
          rlc_pP->stat_tx_retransmit_pdu             += 1;
          rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
          rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(copy->data))->tb_size);
          rlc_pP->stat_tx_retransmit_bytes           += (((struct mac_tb_req*)(copy->data))->tb_size);
          rlc_pP->stat_tx_retransmit_bytes_by_status += (((struct mac_tb_req*)(copy->data))->tb_size);
          list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
        } else {
          break;
        }

        // update first_retrans_pdu_sn
        while ((rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s) &&
               (!(rlc_pP->pdu_retrans_buffer[rlc_pP->first_retrans_pdu_sn].flags.retransmit))) {
          rlc_pP->first_retrans_pdu_sn = (rlc_pP->first_retrans_pdu_sn+1) & RLC_AM_SN_MASK;
435 436
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn SN %04d\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
437 438 439 440 441 442 443 444 445
                rlc_pP->first_retrans_pdu_sn);
        };

        display_flag = 1;

        if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
          // no more pdu to be retransmited
          rlc_pP->first_retrans_pdu_sn = -1;
          display_flag = 0;
446 447
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CLEAR first_retrans_pdu_sn\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
448 449 450
        }

        if (display_flag > 0) {
451 452
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn %04d\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
453 454 455 456 457 458 459
                rlc_pP->first_retrans_pdu_sn);
        }

        return;

        /* ONLY ONE TB PER TTI
                            if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
460
        #if TRACE_RLC_AM_TX
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
                              msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BREAK LOOP ON RETRANSMISSION BECAUSE ONLY %d BYTES ALLOWED TO TRANSMIT BY MAC\n",ctxt_pP->frame,  ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, rlc_pP->nb_bytes_requested_by_mac);
        #endif
                              break;
                            }*/
      }
    }

    if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
      rlc_am_segment_10(ctxt_pP, rlc_pP);
      list_add_list (&rlc_pP->segmentation_pdu_list, &rlc_pP->pdus_to_mac_layer);

      if (rlc_pP->pdus_to_mac_layer.head != NULL) {
        rlc_pP->stat_tx_data_pdu                   += 1;
        rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size);
        return;
      }
    }

    if ((rlc_pP->pdus_to_mac_layer.head == NULL) &&
        (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP)) &&
        (rlc_pP->nb_bytes_requested_by_mac > 2)) {
      rlc_am_retransmit_any_pdu(ctxt_pP, rlc_pP);
      return;
    } else {
485 486
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" COULD NOT RETRANSMIT ANY PDU BECAUSE ",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
487 488 489 490 491 492

      if (rlc_pP->pdus_to_mac_layer.head != NULL) {
        LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
      }

      if (!(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP))) {
493 494
        LOG_D(RLC, "TIMER POLL DID NOT TIMED OUT (RUNNING = %d NUM PDUS TO RETRANS = %d  NUM BYTES TO RETRANS = %d) ", rlc_pP->t_poll_retransmit.running,
              rlc_pP->retrans_num_pdus, rlc_pP->retrans_num_bytes_to_retransmit);
495 496 497 498 499 500
      }

      if (rlc_pP->nb_bytes_requested_by_mac <= 2) {
        LOG_D(RLC, "NUM BYTES REQUESTED BY MAC = %d", rlc_pP->nb_bytes_requested_by_mac);
      }
      LOG_D(RLC, "\n");
501
    }
502 503 504 505

    break;

  default:
506 507
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
508 509
          rlc_pP->protocol_state);
  }
510 511 512
}
//-----------------------------------------------------------------------------
void
513
rlc_am_rx (
514 515 516 517
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 arg_pP,
  struct mac_data_ind          data_indP
)
518
{
gauthier's avatar
gauthier committed
519
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
520 521 522

  switch (rlc->protocol_state) {

523
  case RLC_NULL_STATE:
524
    LOG_N(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", arg_pP);
525 526
    list_free (&data_indP.data);
    break;
527

528 529 530
  case RLC_DATA_TRANSFER_READY_STATE:
    rlc_am_receive_routing (ctxt_pP, rlc, data_indP);
    break;
531

532
  default:
533
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" TX UNKNOWN PROTOCOL STATE 0x%02X\n", rlc, rlc->protocol_state);
534 535 536 537 538
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
539
rlc_am_mac_status_indication (
540 541 542 543
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 rlc_pP,
  const uint16_t               tb_sizeP,
  struct mac_status_ind        tx_statusP)
544 545
{
  struct mac_status_resp  status_resp;
gauthier's avatar
gauthier committed
546 547 548
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
549
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
550

551 552 553 554 555
  status_resp.buffer_occupancy_in_bytes        = 0;
  status_resp.buffer_occupancy_in_pdus         = 0;
  status_resp.head_sdu_remaining_size_to_send  = 0;
  status_resp.head_sdu_creation_time           = 0;
  status_resp.head_sdu_is_segmented            = 0;
556 557
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

558 559 560 561
  if (rlc->last_frame_status_indication != ctxt_pP->frame) {
    rlc_am_check_timer_poll_retransmit(ctxt_pP, rlc);
    rlc_am_check_timer_reordering(ctxt_pP, rlc);
    rlc_am_check_timer_status_prohibit(ctxt_pP, rlc);
562
  }
563

564
  rlc->last_frame_status_indication = ctxt_pP->frame;
565 566 567

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

568
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc);
569

570
  if ((rlc->input_sdus[rlc->current_sdu_index].mem_block != NULL) && (status_resp.buffer_occupancy_in_bytes)) {
571

572 573 574
    //status_resp.buffer_occupancy_in_bytes += ((rlc_am_entity_t *) rlc)->tx_header_min_length_in_bytes;
    status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu;
    diff_time =   ctxt_pP->frame - ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_creation_time;
gauthier's avatar
gauthier committed
575

576
    status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time :  (uint32_t)(0xffffffff - diff_time + ctxt_pP->frame) ;
gauthier's avatar
gauthier committed
577

578 579
    sdu_size            = ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_size;
    sdu_remaining_size  = ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_remaining_size;
gauthier's avatar
gauthier committed
580

581 582 583 584 585 586 587
    status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;

    if (sdu_size == sdu_remaining_size)  {
      status_resp.head_sdu_is_segmented = 0;
    } else {
      status_resp.head_sdu_is_segmented = 1;
    }
gauthier's avatar
gauthier committed
588

589
  } else {
590 591 592 593 594 595 596
	  if (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc)) {
		  if ((status_resp.buffer_occupancy_in_bytes == 0) && (rlc->input_sdus[rlc->current_sdu_index].mem_block == NULL) && (rlc->nb_sdu > 0)) {
			  // force BO to be > 0
			  rlc_sn_t             sn           = (rlc->vt_s - 1) & RLC_AM_SN_MASK;
			  rlc_sn_t             sn_end       = (rlc->vt_a - 1) & RLC_AM_SN_MASK;
			  int                  found_pdu    = 0;
			  rlc_sn_t             found_pdu_sn = 0; // avoid warning
597
                          (void)found_pdu_sn; /* avoid gcc warning "set but not used" */
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614


			  while (sn != sn_end) {
			    if (rlc->pdu_retrans_buffer[sn].mem_block != NULL) {
			      if (!found_pdu) {
			        found_pdu = 1;
			        found_pdu_sn = sn;
			      }
			      status_resp.buffer_occupancy_in_bytes = rlc->pdu_retrans_buffer[sn].header_and_payload_size;
			      status_resp.buffer_occupancy_in_pdus  = rlc->nb_sdu;
			      status_resp.head_sdu_remaining_size_to_send  = status_resp.buffer_occupancy_in_bytes;
			      // TODO head_sdu_is_segmented
			      break;
			    }
			  }
		  }
	  }
615
  }
616
#if MESSAGE_CHART_GENERATOR_RLC_MAC
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
  MSC_LOG_RX_MESSAGE(
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_MAC_ENB:MSC_MAC_UE,
    NULL,0,
    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS-IND %u",
    MSC_AS_TIME_ARGS(ctxt_pP),
    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc),
    tb_sizeP);
  MSC_LOG_TX_MESSAGE(
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_MAC_ENB:MSC_MAC_UE,
    NULL,0,
    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS-RESP BO:%u/n%u(%u)  %s sdu remain %u",
    MSC_AS_TIME_ARGS(ctxt_pP),
    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc),
    status_resp.buffer_occupancy_in_bytes,
    status_resp.buffer_occupancy_in_pdus,rlc->nb_sdu,
    (status_resp.head_sdu_is_segmented)?"sdu seg":"sdu not seg",
    status_resp.head_sdu_remaining_size_to_send);
#endif
637

638
#if TRACE_RLC_AM_TX_STATUS
639

640
  if (tb_sizeP > 0) {
641 642
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
643 644 645 646 647 648 649 650 651 652
          tb_sizeP,
          status_resp.buffer_occupancy_in_bytes);
    /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
        msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",rlc->module_id,
    rlc->rb_id, ctxt_pP->frame, tx_statusP.no_pdu);
    }
    if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
        msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION  TX STATUS UNSUCCESSFUL %d PDUs\n",rlc->module_id, rlc->rb_id,
    ctxt_pP->frame, tx_statusP.no_pdu);
    }*/
653
  }
654

655 656 657 658 659
#endif
  return status_resp;
}
//-----------------------------------------------------------------------------
struct mac_data_req
660
rlc_am_mac_data_request (
661 662 663
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 rlc_pP
)
664 665
{
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
666 667
  rlc_am_entity_t *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
  unsigned int nb_bytes_requested_by_mac = ((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac;
668
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
gauthier's avatar
gauthier committed
669 670 671
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
672
  tb_size_t           tb_size_in_bytes;
gauthier's avatar
gauthier committed
673 674 675
  int                 num_nack;
  char                message_string[9000];
  size_t              message_string_size = 0;
676
#   if ENABLE_ITTI
gauthier's avatar
gauthier committed
677
  MessageDef         *msg_p;
678
#   endif
gauthier's avatar
gauthier committed
679
  int                 octet_index, index;
Cedric Roux's avatar
Cedric Roux committed
680 681 682 683 684 685
  /* for no gcc warnings */
  (void)num_nack;
  (void)message_string;
  (void)message_string_size;
  (void)octet_index;
  (void)index;
gauthier's avatar
gauthier committed
686
#endif
687 688

  list_init (&data_req.data, NULL);
689
  rlc_am_get_pdus (ctxt_pP, l_rlc_p);
gauthier's avatar
gauthier committed
690
  list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
691

gauthier's avatar
gauthier committed
692
  //((rlc_am_entity_t *) rlc_pP)->tx_pdus += data_req.data.nb_elements;
693
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
694 695
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
696 697
          nb_bytes_requested_by_mac,
          data_req.data.nb_elements);
698
  }
699

700
  data_req.buffer_occupancy_in_bytes   = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, l_rlc_p);
gauthier's avatar
gauthier committed
701
  data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
702

703
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
704

705
  if (data_req.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
706

707
    tb_p = data_req.data.head;
gauthier's avatar
gauthier committed
708

709
    while (tb_p != NULL) {
gauthier's avatar
gauthier committed
710

711 712
      rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)((struct mac_tb_req *) (tb_p->data))->data_ptr;
      tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size;
gauthier's avatar
gauthier committed
713

714
      if ((((struct mac_tb_req *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
715
        if (rlc_am_get_data_pdu_infos(ctxt_pP,l_rlc_p,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
716
#if MESSAGE_CHART_GENERATOR
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
          message_string_size = 0;
          message_string_size += sprintf(&message_string[message_string_size],
                                         MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" DATA SN %u size %u RF %u P %u FI %u",
                                         MSC_AS_TIME_ARGS(ctxt_pP),
                                         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
                                         pdu_info.sn,
                                         tb_size_in_bytes,
                                         pdu_info.rf,
                                         pdu_info.p,
                                         pdu_info.fi);

          if (pdu_info.rf) {
            message_string_size += sprintf(&message_string[message_string_size], " LSF %u\n", pdu_info.lsf);
            message_string_size += sprintf(&message_string[message_string_size], " SO %u\n", pdu_info.so);
          }

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

            for (index=0; index < pdu_info.num_li; index++) {
gauthier's avatar
gauthier committed
737
              message_string_size += sprintf(&message_string[message_string_size], " LI %u", pdu_info.li_list[index]);
738 739 740
            }
          }

gauthier's avatar
gauthier committed
741
          MSC_LOG_TX_MESSAGE(
742 743 744 745 746 747 748
            (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*)rlc_am_pdu_sn_10_p,
            tb_size_in_bytes,
            message_string);

#endif
749
#   if ENABLE_ITTI
750
          message_string_size = 0;
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
          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);

          if (pdu_info.rf) {
            message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA REQ: AMD PDU segment\n\n");
          } else {
            message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA REQ: AMD PDU\n\n");
          }

          message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
          message_string_size += sprintf(&message_string[message_string_size], "  D/C       : %u\n", pdu_info.d_c);
          message_string_size += sprintf(&message_string[message_string_size], "  RF        : %u\n", pdu_info.rf);
          message_string_size += sprintf(&message_string[message_string_size], "  P         : %u\n", pdu_info.p);
          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.rf) {
            message_string_size += sprintf(&message_string[message_string_size], "  LSF       : %u\n", pdu_info.lsf);
            message_string_size += sprintf(&message_string[message_string_size], "  SO        : %u\n", pdu_info.so);
          }

          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");
gauthier's avatar
gauthier committed
792
              }
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818

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

          msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_DATA_PDU_REQ, message_string_size + sizeof (IttiMsgText));
          msg_p->ittiMsg.rlc_am_data_pdu_req.size = message_string_size;
          memcpy(&msg_p->ittiMsg.rlc_am_data_pdu_req.text, message_string, message_string_size);

819
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
820 821 822 823 824 825

# else
          rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
# endif
        }
      } else {
826
        if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &l_rlc_p->control_pdu_info) >= 0) {
827
          tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size; //tb_size_in_bytes modified by rlc_am_get_control_pdu_infos!
828
#if MESSAGE_CHART_GENERATOR
829 830
          message_string_size = 0;
          message_string_size += sprintf(&message_string[message_string_size],
gauthier's avatar
gauthier committed
831
                                         MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS ACK_SN %u",
832 833
                                         MSC_AS_TIME_ARGS(ctxt_pP),
                                         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
834
                                         l_rlc_p->control_pdu_info.ack_sn);
gauthier's avatar
gauthier committed
835

836 837
          for (num_nack = 0; num_nack < l_rlc_p->control_pdu_info.num_nack; num_nack++) {
            if (l_rlc_p->control_pdu_info.nack_list[num_nack].e2) {
838
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %u SO START %u SO END %u",
839 840 841
            		  l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_start,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_end);
842 843 844

            } else {
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %u",
845
            		  l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn);
846 847 848
            }
          }

gauthier's avatar
gauthier committed
849
          MSC_LOG_TX_MESSAGE(
850 851 852 853 854 855 856
            (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*)rlc_am_pdu_sn_10_p,
            tb_size_in_bytes,
            message_string);

#endif
857
#   if ENABLE_ITTI
858
          message_string_size = 0;
859 860 861 862
          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], "PDU type    : RLC AM DATA REQ: STATUS PDU\n\n");
          message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
863 864 865 866
          message_string_size += sprintf(&message_string[message_string_size], "  D/C       : %u\n", l_rlc_p->control_pdu_info.d_c);
          message_string_size += sprintf(&message_string[message_string_size], "  CPT       : %u\n", l_rlc_p->control_pdu_info.cpt);
          message_string_size += sprintf(&message_string[message_string_size], "  ACK_SN    : %u\n", l_rlc_p->control_pdu_info.ack_sn);
          message_string_size += sprintf(&message_string[message_string_size], "  E1        : %u\n", l_rlc_p->control_pdu_info.e1);
867

868 869
          for (num_nack = 0; num_nack < l_rlc_p->control_pdu_info.num_nack; num_nack++) {
            if (l_rlc_p->control_pdu_info.nack_list[num_nack].e2) {
870
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d SO START %05d SO END %05d",
871 872 873
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_start,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_end);
874
            } else {
875
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d",  l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn);
876
            }
877
          }
878 879 880 881 882

          msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_STATUS_PDU_REQ, message_string_size + sizeof (IttiMsgText));
          msg_p->ittiMsg.rlc_am_status_pdu_req.size = message_string_size;
          memcpy(&msg_p->ittiMsg.rlc_am_status_pdu_req.text, message_string, message_string_size);

883
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
884 885 886

#   endif
        }
887
      }
888 889 890

      tb_p = tb_p->next;
    }
891
  }
892

gauthier's avatar
gauthier committed
893
#endif
894 895 896 897
  return data_req;
}
//-----------------------------------------------------------------------------
void
898
rlc_am_mac_data_indication (
899 900 901 902
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 rlc_pP,
  struct mac_data_ind          data_indP
)
903
{
904
  rlc_am_entity_t*           l_rlc_p = (rlc_am_entity_t*) rlc_pP;
905 906 907
  /*rlc_am_control_pdu_info_t control_pdu_info;
  int                       num_li;
  int16_t                     tb_size;*/
908
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
gauthier's avatar
gauthier committed
909 910 911
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
912
  sdu_size_t          tb_size_in_bytes;
gauthier's avatar
gauthier committed
913 914 915
  int                 num_nack;
  char                message_string[7000];
  size_t              message_string_size = 0;
916
#   if ENABLE_ITTI
gauthier's avatar
gauthier committed
917
  MessageDef         *msg_p;
918
#   endif
gauthier's avatar
gauthier committed
919
  int                 octet_index, index;
Cedric Roux's avatar
Cedric Roux committed
920 921 922 923 924 925
  /* for no gcc warnings */
  (void)num_nack;
  (void)message_string;
  (void)message_string_size;
  (void)octet_index;
  (void)index;
gauthier's avatar
gauthier committed
926
#endif
927

928 929
  (void)l_rlc_p; /* avoid gcc warning "unused variable" */

930
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
931

gauthier's avatar
gauthier committed
932 933
  if (data_indP.data.nb_elements > 0) {

934
    tb_p = data_indP.data.head;
gauthier's avatar
gauthier committed
935

936
    while (tb_p != NULL) {
gauthier's avatar
gauthier committed
937

938 939
      rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)((struct mac_tb_ind *) (tb_p->data))->data_ptr;
      tb_size_in_bytes   = ((struct mac_tb_ind *) (tb_p->data))->size;
gauthier's avatar
gauthier committed
940

941
      if ((((struct mac_tb_ind *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
942
        if (rlc_am_get_data_pdu_infos(ctxt_pP,l_rlc_p,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
943
#if MESSAGE_CHART_GENERATOR
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
          message_string_size = 0;
          message_string_size += sprintf(&message_string[message_string_size],
                                         MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" DATA SN %u size %u RF %u P %u FI %u",
                                         MSC_AS_TIME_ARGS(ctxt_pP),
                                         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
                                         pdu_info.sn,
                                         tb_size_in_bytes,
                                         pdu_info.rf,
                                         pdu_info.p,
                                         pdu_info.fi);

          if (pdu_info.rf) {
            message_string_size += sprintf(&message_string[message_string_size], " LSF %u\n", pdu_info.lsf);
            message_string_size += sprintf(&message_string[message_string_size], " SO %u\n", pdu_info.so);
          }

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

            for (index=0; index < pdu_info.num_li; index++) {
gauthier's avatar
gauthier committed
964
              message_string_size += sprintf(&message_string[message_string_size], " LI %u", pdu_info.li_list[index]);
965 966 967
            }
          }

gauthier's avatar
gauthier committed
968
          MSC_LOG_RX_MESSAGE(
969 970 971 972 973 974 975 976
            (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*)rlc_am_pdu_sn_10_p,
            tb_size_in_bytes,
            message_string);

#endif

977
#   if ENABLE_ITTI && TRACE_RLC_AM_PDU
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
          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);

          if (pdu_info.rf) {
            message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA IND: AMD PDU segment\n\n");
          } else {
            message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA IND: AMD PDU\n\n");
          }

          message_string_size += sprintf(&message_string[message_string_size], "Header      :\n");
          message_string_size += sprintf(&message_string[message_string_size], "  D/C       : %u\n", pdu_info.d_c);
          message_string_size += sprintf(&message_string[message_string_size], "  RF        : %u\n", pdu_info.rf);
          message_string_size += sprintf(&message_string[message_string_size], "  P         : %u\n", pdu_info.p);
          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.rf) {
            message_string_size += sprintf(&message_string[message_string_size], "  LSF       : %u\n", pdu_info.lsf);
            message_string_size += sprintf(&message_string[message_string_size], "  SO        : %u\n", pdu_info.so);
          }

          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");
gauthier's avatar
gauthier committed
1019
              }
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045

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

          msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_DATA_PDU_IND, message_string_size + sizeof (IttiMsgText));
          msg_p->ittiMsg.rlc_am_data_pdu_ind.size = message_string_size;
          memcpy(&msg_p->ittiMsg.rlc_am_data_pdu_ind.text, message_string, message_string_size);

1046
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
1047 1048 1049 1050 1051 1052

# else
          rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
# endif
        }
      } else {
1053
        if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &l_rlc_p->control_pdu_info) >= 0) {
1054
#if MESSAGE_CHART_GENERATOR
1055 1056
          message_string_size = 0;
          message_string_size += sprintf(&message_string[message_string_size],
gauthier's avatar
gauthier committed
1057
                                         MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS size ACK_SN %u",
1058 1059
                                         MSC_AS_TIME_ARGS(ctxt_pP),
                                         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),