rlc_am.c 59.3 KB
Newer Older
1
/*******************************************************************************
gauthier's avatar
gauthier committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom

    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.


    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.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

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

 *******************************************************************************/
29 30 31 32 33 34
#define RLC_AM_MODULE
#define RLC_AM_C
//-----------------------------------------------------------------------------
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
35 36 37
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
38 39
#include "assertions.h"
#include "hashtable.h"
40 41 42 43 44 45 46 47 48 49 50 51 52
#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"
//#define TRACE_RLC_AM_DATA_REQUEST
//#define TRACE_RLC_AM_TX_STATUS
//#define TRACE_RLC_AM_TX
53
//#define TRACE_RLC_AM_RX
54
//#define TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
55 56 57

extern rlc_am_control_pdu_info_t  g_rlc_am_control_pdu_info;

58
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
59
uint32_t
60 61 62
rlc_am_get_buffer_occupancy_in_bytes (
                const protocol_ctxt_t* const ctxt_pP,
                rlc_am_entity_t * const      rlc_pP)
63 64
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
65 66
  uint32_t max_li_overhead;
  uint32_t header_overhead;
67 68

  // priority of control trafic
gauthier's avatar
gauthier committed
69 70
  if (rlc_pP->status_requested) {
      if (rlc_pP->t_status_prohibit.running == 0) {
71
#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
72
          if (((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3) > 0) {
73 74 75 76
              LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n",
                    PROTOCOL_CTXT_ARGS(ctxt_pP),
                    RB_AM_ARGS(rlc_pP),
                    ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3));
77 78
          }
#endif
gauthier's avatar
gauthier committed
79
          return ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
80 81 82 83
      }
  }

  // data traffic
gauthier's avatar
gauthier committed
84
  if (rlc_pP->nb_sdu_no_segmented <= 1) {
85 86
      max_li_overhead = 0;
  } else {
gauthier's avatar
gauthier committed
87
      max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2);
88
  }
gauthier's avatar
gauthier committed
89
  if (rlc_pP->sdu_buffer_occupancy == 0) {
90 91 92 93 94 95 96
      header_overhead = 0;
  } else {
      header_overhead = 2;
  }


#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
97
  if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
98 99 100 101 102 103 104 105 106
    LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : STATUS  BUFFER %d bytes \n", PROTOCOL_CTXT_ARGS(ctxt_pP), RB_AM_ARGS(rlc_pP), rlc_pP->status_buffer_occupancy);
    LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_CTXT_ARGS(ctxt_pP), RB_AM_ARGS(rlc_pP), rlc_pP->retransmission_buffer_occupancy);
    LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : SDU     BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          RB_AM_ARGS(rlc_pP),
          rlc_pP->sdu_buffer_occupancy,
          max_li_overhead,
          header_overhead,
          rlc_pP->nb_sdu_no_segmented);
107 108
  }
#endif
gauthier's avatar
gauthier committed
109
  return rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead;
110 111
}
//-----------------------------------------------------------------------------
112 113 114 115 116
void
rlc_am_release (
                const protocol_ctxt_t* const ctxt_pP,
                rlc_am_entity_t * const      rlc_pP
                )
117 118 119 120 121
//-----------------------------------------------------------------------------
{

}
//-----------------------------------------------------------------------------
122 123 124 125 126 127 128
void
config_req_rlc_am (
                const protocol_ctxt_t* const ctxt_pP,
                const srb_flag_t             srb_flagP,
                rlc_am_info_t  * const       config_am_pP,
                const rb_id_t                rb_idP
                )
129 130
{
//-----------------------------------------------------------------------------
131
    rlc_union_t       *rlc_union_p = NULL;
gauthier's avatar
gauthier committed
132
    rlc_am_entity_t *l_rlc_p         = NULL;
133
    hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->enb_module_id, ctxt_pP->ue_module_id, ctxt_pP->enb_flag, rb_idP, srb_flagP);
134 135 136 137
    hashtable_rc_t   h_rc;

    h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
    if (h_rc == HASH_TABLE_OK) {
gauthier's avatar
gauthier committed
138
        l_rlc_p = &rlc_union_p->rlc.am;
139
        LOG_D(RLC,
140 141 142 143 144 145 146 147 148
              PROTOCOL_CTXT_FMT RB_AM_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_CTXT_ARGS(ctxt_pP),
              RB_AM_ARGS(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);
149 150 151
        rlc_am_init(ctxt_pP, l_rlc_p);
        rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP);
        rlc_am_configure(ctxt_pP, l_rlc_p,
152 153 154 155 156 157
               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);
gauthier's avatar
gauthier committed
158
    } else {
159
        LOG_E(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" CONFIG_REQ RLC NOT FOUND\n",
160
              PROTOCOL_CTXT_ARGS(ctxt_pP) );
gauthier's avatar
gauthier committed
161
    }
162
}
gauthier's avatar
gauthier committed
163 164 165 166 167 168
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};
169 170

//-----------------------------------------------------------------------------
171
void config_req_rlc_am_asn1 (
172 173 174 175
                const protocol_ctxt_t* const         ctxt_pP,
                const srb_flag_t                     srb_flagP,
                const struct RLC_Config__am  * const config_am_pP,
                const rb_id_t                        rb_idP)
176 177
{
//-----------------------------------------------------------------------------
178
  rlc_union_t     *rlc_union_p   = NULL;
gauthier's avatar
gauthier committed
179
  rlc_am_entity_t *l_rlc_p         = NULL;
180
  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->enb_module_id, ctxt_pP->ue_module_id, ctxt_pP->enb_flag, rb_idP, srb_flagP);
181 182 183 184
  hashtable_rc_t   h_rc;

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
  if (h_rc == HASH_TABLE_OK) {
gauthier's avatar
gauthier committed
185
      l_rlc_p = &rlc_union_p->rlc.am;
186 187 188 189 190 191 192
      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) ){

193 194 195
          LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_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_CTXT_ARGS(ctxt_pP),
                RB_AM_ARGS(l_rlc_p),
196 197 198 199 200
              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],
201
              t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
202

203 204 205
          rlc_am_init(ctxt_pP, l_rlc_p);
          rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP);
          rlc_am_configure(ctxt_pP, l_rlc_p,
206 207 208 209 210 211 212 213
              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 {
          LOG_D(RLC,
214 215 216 217 218 219 220 221 222
                PROTOCOL_CTXT_FMT RB_AM_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_CTXT_ARGS(ctxt_pP),
                RB_AM_ARGS(l_rlc_p),
                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);
223 224
      }
  } else {
225
      LOG_E(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT "CONFIG_REQ RLC NOT FOUND\n",
226
            PROTOCOL_CTXT_ARGS(ctxt_pP) );
227
  }
228 229 230
}

  //-----------------------------------------------------------------------------
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
void rlc_am_stat_req (
                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)
261 262
//-----------------------------------------------------------------------------
{
gauthier's avatar
gauthier committed
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
    *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;
290 291 292 293

}
//-----------------------------------------------------------------------------
void
294 295 296 297
rlc_am_get_pdus (
                const protocol_ctxt_t* const ctxt_pP,
                rlc_am_entity_t * const      rlc_pP
                )
298 299 300 301 302 303 304 305 306 307 308
{
//-----------------------------------------------------------------------------
  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.


gauthier's avatar
gauthier committed
309
    switch (rlc_pP->protocol_state) {
310 311 312 313 314 315

        case RLC_NULL_STATE:
            break;

        case RLC_DATA_TRANSFER_READY_STATE:
            // TRY TO SEND CONTROL PDU FIRST
gauthier's avatar
gauthier committed
316
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) {
317 318 319 320 321 322 323 324 325 326
                // 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.
gauthier's avatar
gauthier committed
327
                if (rlc_pP->t_status_prohibit.running == 0) {
328
                    rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
gauthier's avatar
gauthier committed
329
                    mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);
330
                    if (pdu) {
gauthier's avatar
gauthier committed
331 332
                        list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
                        rlc_pP->status_requested = 0;
333
                        rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
334 335 336 337
                        return;
                    }
                }
                  else {
gauthier's avatar
gauthier committed
338
                      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] DELAYED SENT STATUS PDU BECAUSE T-STATUS-PROHIBIT RUNNING (TIME-OUT FRAME %5u)\n",
339 340 341 342
                        ctxt_pP->frame,
                        (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                        ctxt_pP->enb_module_id,
                        ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
343 344
                        rlc_pP->rb_id,
                        rlc_pP->t_status_prohibit.frame_time_out);
345 346
                }
            }
gauthier's avatar
gauthier committed
347 348
            /*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);
349
                if (pdu != NULL {
gauthier's avatar
gauthier committed
350 351
                    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);
352
#ifdef TRACE_RLC_AM_TX
353
                        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);
354
#endif
gauthier's avatar
gauthier committed
355 356
                        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;
357 358 359 360 361 362 363 364
                    } else {
                      stay_on_this_list = 0;
                    }
                } else {
                    stay_on_this_list = 0;
                }
            }*/
            // THEN TRY TO SEND RETRANS PDU
gauthier's avatar
gauthier committed
365
            if (rlc_pP->first_retrans_pdu_sn >= 0) {
366 367
                rlc_am_tx_data_pdu_management_t* tx_data_pdu_management;
                // tx min 3 bytes because of the size of the RLC header
gauthier's avatar
gauthier committed
368 369 370
                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)) {
371

gauthier's avatar
gauthier committed
372
                    tx_data_pdu_management = &rlc_pP->pdu_retrans_buffer[rlc_pP->first_retrans_pdu_sn];
373

gauthier's avatar
gauthier committed
374
                    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)) {
375
                        mem_block_t* copy = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn);
gauthier's avatar
gauthier committed
376
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RE-SEND DATA PDU SN %04d   %d BYTES\n",
377 378 379 380
                            ctxt_pP->frame,
                            (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                            ctxt_pP->enb_module_id,
                            ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
381 382 383
                            rlc_pP->rb_id,
                            rlc_pP->first_retrans_pdu_sn,
                            tx_data_pdu_management->header_and_payload_size);
gauthier's avatar
gauthier committed
384 385 386 387 388 389
                        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;
390

gauthier's avatar
gauthier committed
391 392
                        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;
393 394 395

                        tx_data_pdu_management->retx_count += 1;
                        return;
gauthier's avatar
gauthier committed
396
                    } else if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac >= RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
gauthier's avatar
gauthier committed
397
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] 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",
398 399 400 401
                                ctxt_pP->frame,
                                (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                                ctxt_pP->enb_module_id,
                                ctxt_pP->ue_module_id,
402 403 404 405 406 407 408 409 410
                                rlc_pP->rb_id,
                                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(
411 412 413 414
                                        ctxt_pP,
                                        rlc_pP,
                                        rlc_pP->first_retrans_pdu_sn,
                                        &rlc_pP->nb_bytes_requested_by_mac);
gauthier's avatar
gauthier committed
415
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n",
416 417 418 419
                              ctxt_pP->frame,
                              (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                              ctxt_pP->enb_module_id,
                              ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
420 421 422 423
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn,
                              tx_data_pdu_management->nack_so_start);

gauthier's avatar
gauthier committed
424 425 426
                        rlc_pP->stat_tx_data_pdu                   += 1;
                        rlc_pP->stat_tx_retransmit_pdu             += 1;
                        rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
427 428 429
                        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);
gauthier's avatar
gauthier committed
430
                        list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
431 432 433 434
                    } else {
                        break;
                    }
                    // update first_retrans_pdu_sn
gauthier's avatar
gauthier committed
435 436 437
                    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;
gauthier's avatar
gauthier committed
438
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] UPDATED first_retrans_pdu_sn SN %04d\n",
439 440 441 442
                              ctxt_pP->frame,
                              (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                              ctxt_pP->enb_module_id,
                              ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
443 444
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn);
445 446 447
                    };

                    display_flag = 1;
gauthier's avatar
gauthier committed
448
                    if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
449
                        // no more pdu to be retransmited
gauthier's avatar
gauthier committed
450
                        rlc_pP->first_retrans_pdu_sn = -1;
451
                        display_flag = 0;
gauthier's avatar
gauthier committed
452
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] CLEAR first_retrans_pdu_sn\n",
453 454 455 456
                              ctxt_pP->frame,
                              (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                              ctxt_pP->enb_module_id,
                              ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
457
                              rlc_pP->rb_id);
458 459
                    }
                    if (display_flag > 0) {
gauthier's avatar
gauthier committed
460
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] UPDATED first_retrans_pdu_sn %04d\n",
461 462 463 464
                              ctxt_pP->frame,
                              (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                              ctxt_pP->enb_module_id,
                              ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
465 466
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn);
467 468 469 470
                    }
                    return;

/* ONLY ONE TB PER TTI
gauthier's avatar
gauthier committed
471
                    if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
472
#ifdef TRACE_RLC_AM_TX
473
                      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);
474 475 476 477 478
#endif
                      break;
                    }*/
                }
            }
gauthier's avatar
gauthier committed
479
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
480
                rlc_am_segment_10(ctxt_pP, rlc_pP);
gauthier's avatar
gauthier committed
481 482 483
                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;
484
                    rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size);
485 486 487
                    return;
                }
            }
488 489 490 491
            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);
492 493
                return;
            } else {
gauthier's avatar
gauthier committed
494
                LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] COULD NOT RETRANSMIT ANY PDU BECAUSE ",
495 496 497 498
                      ctxt_pP->frame,
                      (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                      ctxt_pP->enb_module_id,
                      ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
499
                      rlc_pP->rb_id);
gauthier's avatar
gauthier committed
500
                if (rlc_pP->pdus_to_mac_layer.head != NULL) {
501 502
                    LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
                }
503
                if (!(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP))) {
gauthier's avatar
gauthier committed
504
                    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);
505
                }
gauthier's avatar
gauthier committed
506 507
                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);
508 509 510 511 512 513
                }
                LOG_D(RLC, "\n");
            }
            break;

        default:
gauthier's avatar
gauthier committed
514
            LOG_E(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n",
515 516 517 518
                  ctxt_pP->frame,
                  (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                  ctxt_pP->enb_module_id,
                  ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
519 520
                  rlc_pP->rb_id,
                  rlc_pP->protocol_state);
521 522 523 524
    }
}
//-----------------------------------------------------------------------------
void
525 526 527 528 529
rlc_am_rx (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 arg_pP,
                struct mac_data_ind          data_indP
                )
530 531 532
{
//-----------------------------------------------------------------------------

gauthier's avatar
gauthier committed
533
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
534 535 536 537

  switch (rlc->protocol_state) {

      case RLC_NULL_STATE:
gauthier's avatar
gauthier committed
538
       LOG_N(RLC, "[RLC_AM %p] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", arg_pP);
539 540 541 542
        list_free (&data_indP.data);
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
543
        rlc_am_receive_routing (ctxt_pP, rlc, data_indP);
544 545 546 547 548 549 550 551 552
        break;

      default:
        LOG_E(RLC, "[RLC_AM %p] TX UNKNOWN PROTOCOL STATE 0x%02X\n", rlc, rlc->protocol_state);
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
553 554 555 556 557
rlc_am_mac_status_indication (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 rlc_pP,
                const uint16_t               tb_sizeP,
                struct mac_status_ind        tx_statusP)
558 559 560
{
//-----------------------------------------------------------------------------
  struct mac_status_resp  status_resp;
gauthier's avatar
gauthier committed
561 562 563
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
564
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
565

566 567 568 569 570
  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;
571 572
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

573 574 575 576
  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);
577
  }
578
  rlc->last_frame_status_indication = ctxt_pP->frame;
579 580 581

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

582
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc);
583

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

gauthier's avatar
gauthier committed
586 587
          //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;
588
          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
589

590
          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
591 592 593 594 595 596

          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;

          status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
          if (sdu_size == sdu_remaining_size)  {
597
              status_resp.head_sdu_is_segmented = 0;
gauthier's avatar
gauthier committed
598 599 600 601 602
          }
          else {
              status_resp.head_sdu_is_segmented = 1;
          }

603 604
  } else {
  }
605 606


607 608
#ifdef TRACE_RLC_AM_TX_STATUS
  if (tb_sizeP > 0) {
gauthier's avatar
gauthier committed
609
      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n",
610
            ctxt_pP->frame,
gauthier's avatar
gauthier committed
611 612 613 614 615 616
            (rlc->is_enb) ? "eNB" : "UE",
            rlc->enb_module_id,
            rlc->ue_module_id,
            rlc->rb_id,
            tb_sizeP,
            status_resp.buffer_occupancy_in_bytes);
617
      /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
618
          msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",rlc->module_id,
619
rlc->rb_id, ctxt_pP->frame, tx_statusP.no_pdu);
620 621
      }
      if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
622
          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,
623
ctxt_pP->frame, tx_statusP.no_pdu);
624 625 626 627 628 629 630
      }*/
  }
#endif
  return status_resp;
}
//-----------------------------------------------------------------------------
struct mac_data_req
631 632 633 634
rlc_am_mac_data_request (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 rlc_pP
                )
635 636 637
{
//-----------------------------------------------------------------------------
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
638 639 640 641 642 643
  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;
#ifdef TRACE_RLC_AM_PDU
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
644
  tb_size_t           tb_size_in_bytes;
gauthier's avatar
gauthier committed
645 646 647
  int                 num_nack;
  char                message_string[9000];
  size_t              message_string_size = 0;
648
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
649
  MessageDef         *msg_p;
650
#   endif
gauthier's avatar
gauthier committed
651 652
  int                 octet_index, index;
#endif
653

654
  rlc_am_get_pdus (ctxt_pP, rlc_pP);
655 656

  list_init (&data_req.data, NULL);
gauthier's avatar
gauthier committed
657 658
  list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
  //((rlc_am_entity_t *) rlc_pP)->tx_pdus += data_req.data.nb_elements;
659
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
gauthier's avatar
gauthier committed
660
      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n",
661 662 663 664
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
665
            l_rlc_p->rb_id,
gauthier's avatar
gauthier committed
666 667
            nb_bytes_requested_by_mac,
            data_req.data.nb_elements);
668
  }
669
  data_req.buffer_occupancy_in_bytes   = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, l_rlc_p);
gauthier's avatar
gauthier committed
670
  data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
671

gauthier's avatar
gauthier committed
672
#ifdef TRACE_RLC_AM_PDU
673
  if (data_req.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
674 675 676 677 678 679

      tb_p = data_req.data.head;

      while (tb_p != NULL) {

          rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)((struct mac_tb_req *) (tb_p->data))->data_ptr;
680
          tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size;
gauthier's avatar
gauthier committed
681 682

          if ((((struct mac_tb_req *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
683
              if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
gauthier's avatar
gauthier committed
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
#   if defined(ENABLE_ITTI)
                  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");
                          }
                          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");

738
                  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));
gauthier's avatar
gauthier committed
739 740 741
                  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);

742 743
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
744
                  } else {
745
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
746
                  }
gauthier's avatar
gauthier committed
747
# else
748
                  rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
gauthier's avatar
gauthier committed
749 750
# endif
              }
751
          } else {
gauthier's avatar
gauthier committed
752
              if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &g_rlc_am_control_pdu_info) >= 0) {
753
                  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!
gauthier's avatar
gauthier committed
754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773

#   if defined(ENABLE_ITTI)
                  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");
                  message_string_size += sprintf(&message_string[message_string_size], "  D/C       : %u\n", g_rlc_am_control_pdu_info.d_c);
                  message_string_size += sprintf(&message_string[message_string_size], "  CPT       : %u\n", g_rlc_am_control_pdu_info.cpt);
                  message_string_size += sprintf(&message_string[message_string_size], "  ACK_SN    : %u\n", g_rlc_am_control_pdu_info.ack_sn);
                  message_string_size += sprintf(&message_string[message_string_size], "  E1        : %u\n", g_rlc_am_control_pdu_info.e1);
                  for (num_nack = 0; num_nack < g_rlc_am_control_pdu_info.num_nack; num_nack++) {
                      if (g_rlc_am_control_pdu_info.nack_list[num_nack].e2) {
                          message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d SO START %05d SO END %05d",
                                  g_rlc_am_control_pdu_info.nack_list[num_nack].nack_sn,
                                  g_rlc_am_control_pdu_info.nack_list[num_nack].so_start,
                                  g_rlc_am_control_pdu_info.nack_list[num_nack].so_end);
                      } else {
                              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d",  g_rlc_am_control_pdu_info.nack_list[num_nack].nack_sn);
                      }
                  }
774
                  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));
gauthier's avatar
gauthier committed
775 776 777
                  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);

778 779
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
780
                  } else {
781
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
782
                  }
gauthier's avatar
gauthier committed
783
#   endif
784 785
              }
          }
gauthier's avatar
gauthier committed
786
          tb_p = tb_p->next;
787 788
      }
  }
gauthier's avatar
gauthier committed
789
#endif
790 791 792 793
  return data_req;
}
//-----------------------------------------------------------------------------
void
794 795 796 797 798
rlc_am_mac_data_indication (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 rlc_pP,
                struct mac_data_ind          data_indP
                )
799 800
{
//-----------------------------------------------------------------------------
801
//    rlc_am_entity_t           *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
gauthier's avatar
gauthier committed
802
    /*rlc_am_control_pdu_info_t control_pdu_info;
803
    int                       num_li;
gauthier's avatar
gauthier committed
804
    int16_t                     tb_size;*/
gauthier's avatar
gauthier committed
805 806 807 808
#ifdef TRACE_RLC_AM_PDU
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
809
  sdu_size_t          tb_size_in_bytes;
gauthier's avatar
gauthier committed
810 811 812
  int                 num_nack;
  char                message_string[7000];
  size_t              message_string_size = 0;
813
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
814
  MessageDef         *msg_p;
815
#   endif
gauthier's avatar
gauthier committed
816 817
  int                 octet_index, index;
#endif
818

gauthier's avatar
gauthier committed
819 820 821 822 823 824 825 826 827 828 829
#ifdef TRACE_RLC_AM_PDU
  if (data_indP.data.nb_elements > 0) {

      tb_p = data_indP.data.head;

      while (tb_p != NULL) {

          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;

          if ((((struct mac_tb_ind *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
830
              if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
gauthier's avatar
gauthier committed
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
#   if defined(ENABLE_ITTI)
                  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");
                          }
                          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");

885
                  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));
gauthier's avatar
gauthier committed
886 887 888
                  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);

889 890
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
891
                  } else {
892
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
893
                  }
gauthier's avatar
gauthier committed
894
# else
895
                  rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
gauthier's avatar
gauthier committed
896 897 898 899 900 901 902
# endif
              }
          } else {
              if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &g_rlc_am_control_pdu_info) >= 0) {

#   if defined(ENABLE_ITTI)
                  message_string_size += sprintf(&message_string[message_string_size], "Bearer      : %u\n", l_rlc_p->rb_id);
gauthier's avatar
 
gauthier committed
903
                  message_string_size += sprintf(&message_string[message_string_size], "PDU size    : %u\n", ((struct mac_tb_ind *) (tb_p->data))->size);
gauthier's avatar
gauthier committed
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
                  message_string_size += sprintf(&message_string[message_string_size], "PDU type    : RLC AM DATA IND: STATUS 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", g_rlc_am_control_pdu_info.d_c);
                  message_string_size += sprintf(&message_string[message_string_size], "  CPT       : %u\n", g_rlc_am_control_pdu_info.cpt);
                  message_string_size += sprintf(&message_string[message_string_size], "  ACK_SN    : %u\n", g_rlc_am_control_pdu_info.ack_sn);
                  message_string_size += sprintf(&message_string[message_string_size], "  E1        : %u\n", g_rlc_am_control_pdu_info.e1);
                  for (num_nack = 0; num_nack < g_rlc_am_control_pdu_info.num_nack; num_nack++) {
                      if (g_rlc_am_control_pdu_info.nack_list[num_nack].e2) {
                          message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d SO START %05d SO END %05d",
                                  g_rlc_am_control_pdu_info.nack_list[num_nack].nack_sn,
                                  g_rlc_am_control_pdu_info.nack_list[num_nack].so_start,
                                  g_rlc_am_control_pdu_info.nack_list[num_nack].so_end);
                      } else {
                              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d",  g_rlc_am_control_pdu_info.nack_list[num_nack].nack_sn);
                      }
                  }
920
                  msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_STATUS_PDU_IND, message_string_size + sizeof (IttiMsgText));
gauthier's avatar
gauthier committed
921 922 923
                  msg_p->ittiMsg.rlc_am_status_pdu_ind.size = message_string_size;
                  memcpy(&msg_p->ittiMsg.rlc_am_status_pdu_ind.text, message_string, message_string_size);

924 925
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
926
                  } else {
927
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
928
                  }
gauthier's avatar
gauthier committed
929 930 931 932 933 934 935
#   endif
              }
          }
          tb_p = tb_p->next;
      }
  }
#endif
936
    rlc_am_rx (ctxt_pP, rlc_pP, data_indP);
937 938 939 940
}

//-----------------------------------------------------------------------------
void
941 942 943 944
rlc_am_data_req (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                rlc_pP,
                mem_block_t * const         sdu_pP)
945 946
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
947
  rlc_am_entity_t     *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
gauthier's avatar
gauthier committed
948 949 950 951
  uint32_t             mui;
  uint16_t             data_offset;
  uint16_t             data_size;
  uint8_t              conf;
gauthier's avatar
gauthier committed
952
#if defined(TRACE_RLC_AM_PDU)
gauthier's avatar
gauthier committed
953 954
  char                 message_string[7000];
  size_t               message_string_size = 0;
gauthier's avatar
gauthier committed
955
#if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
956
  MessageDef          *msg_p;
gauthier's avatar
gauthier committed
957
#endif
gauthier's avatar
gauthier committed
958 959
  int                  octet_index, index;
#endif
960

gauthier's avatar
gauthier committed
961
  pthread_mutex_lock(&l_rlc_p->lock_input_sdus);
gauthier's avatar
gauthier committed
962 963 964
  if ((l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mem_block == NULL) &&
      (l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.segmented == 0) &&
      (((l_rlc_p->next_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE) != l_rlc_p->current_sdu_index)) {
965 966


gauthier's avatar
gauthier committed
967 968
      memset(&l_rlc_p->input_sdus[l_rlc_p->next_sdu_index], 0, sizeof(rlc_am_tx_sdu_management_t));
      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mem_block = sdu_pP;
969

gauthier's avatar
gauthier committed
970 971 972 973
      mui         = ((struct rlc_am_data_req *) (sdu_pP->data))->mui;
      data_offset = ((struct rlc_am_data_req *) (sdu_pP->data))->data_offset;
      data_size   = ((struct rlc_am_data_req *) (sdu_pP->data))->data_size;
      conf        = ((struct rlc_am_data_req *) (sdu_pP->data))->conf;
974

gauthier's avatar
gauthier committed
975
#if defined(TRACE_RLC_AM_PDU)
gauthier's avatar
gauthier committed
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
      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], "SDU size    : %u\n", data_size);
      message_string_size += sprintf(&message_string[message_string_size], "MUI         : %u\n", mui);
      message_string_size += sprintf(&message_string[message_string_size], "CONF        : %u\n", conf);

      message_string_size += sprintf(&message_string[message_string_size], "\nPayload  : \n");
      message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
      message_string_size += sprintf(&message_string[message_string_size], "      |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |\n");
      message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
      for (octet_index = 0; octet_index < data_size; octet_index++) {
          if ((octet_index % 16) == 0){
              if (octet_index != 0) {
                  message_string_size += sprintf(&message_string[message_string_size], " |\n");
              }
              message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
          }
          /*
           * Print every single octet in hexadecimal form
           */
gauthier's avatar
 
gauthier committed
995
          message_string_size += sprintf(&message_string[message_string_size], " %02x", ((uint8_t*)(&sdu_pP->data[data_offset]))[octet_index]);
gauthier's avatar
gauthier committed
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
          /*
           * 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");

gauthier's avatar
gauthier committed
1008
#   if defined(ENABLE_ITTI)
1009
      msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_SDU_REQ, message_string_size + sizeof (IttiMsgText));
gauthier's avatar
gauthier committed
1010 1011
      msg_p->ittiMsg.rlc_am_sdu_req.size = message_string_size;
      memcpy(&msg_p->ittiMsg.rlc_am_sdu_req.text, message_string, message_string_size);
1012

1013 1014
      if (ctxt_pP->enb_flag) {
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
gauthier's avatar
gauthier committed
1015
      } else {
1016
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
gauthier's avatar
gauthier committed
1017
      }
gauthier's avatar
gauthier committed
1018 1019
#   else
      LOG_T(RLC, "%s", message_string);
gauthier's avatar
gauthier committed
1020
#   endif
gauthier's avatar
gauthier committed
1021
#endif
gauthier's avatar
gauthier committed
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036

     l_rlc_p->stat_tx_pdcp_sdu   += 1;
     l_rlc_p->stat_tx_pdcp_bytes += data_size;

      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mui      = mui;
      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_size = data_size;
      //l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].confirm  = conf;

      l_rlc_p->sdu_buffer_occupancy += data_size;
      l_rlc_p->nb_sdu += 1;
      l_rlc_p->nb_sdu_no_segmented += 1;

      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].first_byte = (uint8_t*)(&sdu_pP->data[data_offset]);
      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_remaining_size = l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_size;
      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_segmented_size = 0;
1037
      l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_creation_time  = ctxt_pP->frame;
gauthier's avatar
gauthier committed
1038 1039 104