rlc_am.c 60.2 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
              LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BO : CONTROL PDU %d bytes \n", ctxt_pP->frame, rlc_pP->module_id, rlc_pP->rb_id, ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3));
74 75
          }
#endif
gauthier's avatar
gauthier committed
76
          return ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
77 78 79 80
      }
  }

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


#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
94
  if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
95 96 97
    LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BO : STATUS  BUFFER %d bytes \n", ctxt_pP->frame, rlc_pP->module_id, rlc_pP->rb_id, rlc_pP->status_buffer_occupancy);
    LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BO : RETRANS BUFFER %d bytes \n", ctxt_pP->frame, rlc_pP->module_id,rlc_pP->rb_id, rlc_pP->retransmission_buffer_occupancy);
    LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BO : SDU     BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n", ctxt_pP->frame, rlc_pP->module_id,rlc_pP->rb_id, rlc_pP->sdu_buffer_occupancy, max_li_overhead, header_overhead, rlc_pP->nb_sdu_no_segmented);
98 99
  }
#endif
gauthier's avatar
gauthier committed
100
  return rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead;
101 102
}
//-----------------------------------------------------------------------------
103 104 105 106 107
void
rlc_am_release (
                const protocol_ctxt_t* const ctxt_pP,
                rlc_am_entity_t * const      rlc_pP
                )
108 109 110 111 112
//-----------------------------------------------------------------------------
{

}
//-----------------------------------------------------------------------------
113 114 115 116 117 118 119
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
                )
120 121
{
//-----------------------------------------------------------------------------
122
    rlc_union_t       *rlc_union_p = NULL;
gauthier's avatar
gauthier committed
123
    rlc_am_entity_t *l_rlc_p         = NULL;
124
    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);
125 126 127 128
    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
129
        l_rlc_p = &rlc_union_p->rlc.am;
130 131
        LOG_D(RLC,
            "[FRAME %5u][%s][RRC][MOD %u/%u][][--- 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][MOD %u/%u][RB %u]\n",
132 133 134 135
            ctxt_pP->frame,
            ( ctxt_pP->enb_flag > 0) ? "eNB":"UE",
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
136 137 138 139 140 141
            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,
142 143
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
144
            rb_idP);
145 146 147
        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,
148 149 150 151 152 153
               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
154
    } else {
155
        LOG_E(RLC, "[FRAME %5u][%s][RRC][MOD %u/%u][][--- CONFIG_REQ  --->][RLC_AM][MOD %u/%u][RB %u] RLC NOT FOUND\n",
156 157 158 159 160 161
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
162
            rb_idP);
gauthier's avatar
gauthier committed
163
    }
164
}
gauthier's avatar
gauthier committed
165 166 167 168 169 170
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};
171 172

//-----------------------------------------------------------------------------
173
void config_req_rlc_am_asn1 (
174 175 176 177
                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)
178 179
{
//-----------------------------------------------------------------------------
180
  rlc_union_t     *rlc_union_p   = NULL;
gauthier's avatar
gauthier committed
181
  rlc_am_entity_t *l_rlc_p         = NULL;
182
  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);
183 184 185 186
  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
187
      l_rlc_p = &rlc_union_p->rlc.am;
188 189 190 191 192 193 194 195
      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) ){

          LOG_D(RLC, "[FRAME %5u][%s][RRC][MOD %u/%u][][--- 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][MOD %u/%u][RB %u]\n",
196 197 198 199
              ctxt_pP->frame,
              (ctxt_pP->enb_flag) ? "eNB" : "UE",
              ctxt_pP->enb_module_id,
              ctxt_pP->ue_module_id,
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],
206 207
              ctxt_pP->enb_module_id,
              ctxt_pP->ue_module_id,
208 209
              rb_idP);

210 211 212
          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,
213 214 215 216 217 218 219 220 221
              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,
              "[FRAME %5u][%s][RRC][MOD %u/%u][][--- 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][MOD %u/%u][RB %u], RLC-AM NOT CONFIGURED\n",
222 223 224 225
              ctxt_pP->frame,
              (ctxt_pP->enb_flag) ? "eNB" : "UE",
              ctxt_pP->enb_module_id,
              ctxt_pP->ue_module_id,
226 227 228 229 230 231
              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,
232 233
              ctxt_pP->enb_module_id,
              ctxt_pP->ue_module_id,
234 235 236 237
              rb_idP);
      }
  } else {
      LOG_E(RLC, "[FRAME %5u][%s][RRC][MOD %u/%u][][--- CONFIG_REQ  --->][RLC_AM][MOD %u/%u][RB %u] RLC NOT FOUND\n",
238 239 240 241 242 243
          ctxt_pP->frame,
          (ctxt_pP->enb_flag) ? "eNB" : "UE",
          ctxt_pP->enb_module_id,
          ctxt_pP->ue_module_id,
          ctxt_pP->enb_module_id,
          ctxt_pP->ue_module_id,
244 245
          rb_idP);
  }
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 271 272 273 274 275 276 277 278
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)
279 280
//-----------------------------------------------------------------------------
{
gauthier's avatar
gauthier committed
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
    *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;
308 309 310 311

}
//-----------------------------------------------------------------------------
void
312 313 314 315
rlc_am_get_pdus (
                const protocol_ctxt_t* const ctxt_pP,
                rlc_am_entity_t * const      rlc_pP
                )
316 317 318 319 320 321 322 323 324 325 326
{
//-----------------------------------------------------------------------------
  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
327
    switch (rlc_pP->protocol_state) {
328 329 330 331 332 333

        case RLC_NULL_STATE:
            break;

        case RLC_DATA_TRANSFER_READY_STATE:
            // TRY TO SEND CONTROL PDU FIRST
gauthier's avatar
gauthier committed
334
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) {
335 336 337 338 339 340 341 342 343 344
                // 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
345
                if (rlc_pP->t_status_prohibit.running == 0) {
346
                    rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
gauthier's avatar
gauthier committed
347
                    mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);
348
                    if (pdu) {
gauthier's avatar
gauthier committed
349 350
                        list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
                        rlc_pP->status_requested = 0;
351
                        rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
352 353 354 355
                        return;
                    }
                }
                  else {
gauthier's avatar
gauthier committed
356
                      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",
357 358 359 360
                        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
361 362
                        rlc_pP->rb_id,
                        rlc_pP->t_status_prohibit.frame_time_out);
363 364
                }
            }
gauthier's avatar
gauthier committed
365 366
            /*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);
367
                if (pdu != NULL {
gauthier's avatar
gauthier committed
368 369
                    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);
370
#ifdef TRACE_RLC_AM_TX
371
                        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);
372
#endif
gauthier's avatar
gauthier committed
373 374
                        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;
375 376 377 378 379 380 381 382
                    } else {
                      stay_on_this_list = 0;
                    }
                } else {
                    stay_on_this_list = 0;
                }
            }*/
            // THEN TRY TO SEND RETRANS PDU
gauthier's avatar
gauthier committed
383
            if (rlc_pP->first_retrans_pdu_sn >= 0) {
384 385
                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
386 387 388
                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)) {
389

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

gauthier's avatar
gauthier committed
392
                    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)) {
393
                        mem_block_t* copy = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn);
gauthier's avatar
gauthier committed
394
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RE-SEND DATA PDU SN %04d   %d BYTES\n",
395 396 397 398
                            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
399 400 401
                            rlc_pP->rb_id,
                            rlc_pP->first_retrans_pdu_sn,
                            tx_data_pdu_management->header_and_payload_size);
gauthier's avatar
gauthier committed
402 403 404 405 406 407
                        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;
408

gauthier's avatar
gauthier committed
409 410
                        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;
411 412 413

                        tx_data_pdu_management->retx_count += 1;
                        return;
gauthier's avatar
gauthier committed
414
                    } 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
415
                        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",
416 417 418 419
                                ctxt_pP->frame,
                                (ctxt_pP->enb_module_id) ? "eNB" : "UE",
                                ctxt_pP->enb_module_id,
                                ctxt_pP->ue_module_id,
420 421 422 423 424 425 426 427 428
                                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(
429 430 431 432
                                        ctxt_pP,
                                        rlc_pP,
                                        rlc_pP->first_retrans_pdu_sn,
                                        &rlc_pP->nb_bytes_requested_by_mac);
gauthier's avatar
gauthier committed
433
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n",
434 435 436 437
                              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
438 439 440 441
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn,
                              tx_data_pdu_management->nack_so_start);

gauthier's avatar
gauthier committed
442 443 444
                        rlc_pP->stat_tx_data_pdu                   += 1;
                        rlc_pP->stat_tx_retransmit_pdu             += 1;
                        rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
445 446 447
                        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
448
                        list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
449 450 451 452
                    } else {
                        break;
                    }
                    // update first_retrans_pdu_sn
gauthier's avatar
gauthier committed
453 454 455
                    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
456
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] UPDATED first_retrans_pdu_sn SN %04d\n",
457 458 459 460
                              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
461 462
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn);
463 464 465
                    };

                    display_flag = 1;
gauthier's avatar
gauthier committed
466
                    if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
467
                        // no more pdu to be retransmited
gauthier's avatar
gauthier committed
468
                        rlc_pP->first_retrans_pdu_sn = -1;
469
                        display_flag = 0;
gauthier's avatar
gauthier committed
470
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] CLEAR first_retrans_pdu_sn\n",
471 472 473 474
                              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
475
                              rlc_pP->rb_id);
476 477
                    }
                    if (display_flag > 0) {
gauthier's avatar
gauthier committed
478
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] UPDATED first_retrans_pdu_sn %04d\n",
479 480 481 482
                              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
483 484
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn);
485 486 487 488
                    }
                    return;

/* ONLY ONE TB PER TTI
gauthier's avatar
gauthier committed
489
                    if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
490
#ifdef TRACE_RLC_AM_TX
491
                      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);
492 493 494 495 496
#endif
                      break;
                    }*/
                }
            }
gauthier's avatar
gauthier committed
497
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
498
                rlc_am_segment_10(ctxt_pP, rlc_pP);
gauthier's avatar
gauthier committed
499 500 501
                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;
502
                    rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size);
503 504 505
                    return;
                }
            }
506 507 508 509
            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);
510 511
                return;
            } else {
gauthier's avatar
gauthier committed
512
                LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] COULD NOT RETRANSMIT ANY PDU BECAUSE ",
513 514 515 516
                      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
517
                      rlc_pP->rb_id);
gauthier's avatar
gauthier committed
518
                if (rlc_pP->pdus_to_mac_layer.head != NULL) {
519 520
                    LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
                }
521
                if (!(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP))) {
gauthier's avatar
gauthier committed
522
                    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);
523
                }
gauthier's avatar
gauthier committed
524 525
                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);
526 527 528 529 530 531
                }
                LOG_D(RLC, "\n");
            }
            break;

        default:
gauthier's avatar
gauthier committed
532
            LOG_E(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n",
533 534 535 536
                  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
537 538
                  rlc_pP->rb_id,
                  rlc_pP->protocol_state);
539 540 541 542
    }
}
//-----------------------------------------------------------------------------
void
543 544 545 546 547
rlc_am_rx (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 arg_pP,
                struct mac_data_ind          data_indP
                )
548 549 550
{
//-----------------------------------------------------------------------------

gauthier's avatar
gauthier committed
551
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
552 553 554 555

  switch (rlc->protocol_state) {

      case RLC_NULL_STATE:
gauthier's avatar
gauthier committed
556
       LOG_N(RLC, "[RLC_AM %p] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", arg_pP);
557 558 559 560
        list_free (&data_indP.data);
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
561
        rlc_am_receive_routing (ctxt_pP, rlc, data_indP);
562 563 564 565 566 567 568 569 570
        break;

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

//-----------------------------------------------------------------------------
struct mac_status_resp
571 572 573 574 575
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)
576 577 578
{
//-----------------------------------------------------------------------------
  struct mac_status_resp  status_resp;
gauthier's avatar
gauthier committed
579 580 581
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
582
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
583

584 585 586 587 588
  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;
589 590
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

591 592 593 594
  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);
595
  }
596
  rlc->last_frame_status_indication = ctxt_pP->frame;
597 598 599

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

600
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc);
601

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

gauthier's avatar
gauthier committed
604 605
          //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;
606
          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
607

608
          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
609 610 611 612 613 614

          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)  {
615
              status_resp.head_sdu_is_segmented = 0;
gauthier's avatar
gauthier committed
616 617 618 619 620
          }
          else {
              status_resp.head_sdu_is_segmented = 1;
          }

621 622
  } else {
  }
623 624


625 626
#ifdef TRACE_RLC_AM_TX_STATUS
  if (tb_sizeP > 0) {
gauthier's avatar
gauthier committed
627
      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n",
628
            ctxt_pP->frame,
gauthier's avatar
gauthier committed
629 630 631 632 633 634
            (rlc->is_enb) ? "eNB" : "UE",
            rlc->enb_module_id,
            rlc->ue_module_id,
            rlc->rb_id,
            tb_sizeP,
            status_resp.buffer_occupancy_in_bytes);
635
      /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
636
          msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",rlc->module_id,
637
rlc->rb_id, ctxt_pP->frame, tx_statusP.no_pdu);
638 639
      }
      if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
640
          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,
641
ctxt_pP->frame, tx_statusP.no_pdu);
642 643 644 645 646 647 648
      }*/
  }
#endif
  return status_resp;
}
//-----------------------------------------------------------------------------
struct mac_data_req
649 650 651 652
rlc_am_mac_data_request (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 rlc_pP
                )
653 654 655
{
//-----------------------------------------------------------------------------
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
656 657 658 659 660 661
  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;
662
  tb_size_t           tb_size_in_bytes;
gauthier's avatar
gauthier committed
663 664 665
  int                 num_nack;
  char                message_string[9000];
  size_t              message_string_size = 0;
666
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
667
  MessageDef         *msg_p;
668
#   endif
gauthier's avatar
gauthier committed
669 670
  int                 octet_index, index;
#endif
671

672
  rlc_am_get_pdus (ctxt_pP, rlc_pP);
673 674

  list_init (&data_req.data, NULL);
gauthier's avatar
gauthier committed
675 676
  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;
677
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
gauthier's avatar
gauthier committed
678
      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n",
679 680 681 682
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
683
            l_rlc_p->rb_id,
gauthier's avatar
gauthier committed
684 685
            nb_bytes_requested_by_mac,
            data_req.data.nb_elements);
686
  }
687
  data_req.buffer_occupancy_in_bytes   = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, l_rlc_p);
gauthier's avatar
gauthier committed
688
  data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
689

gauthier's avatar
gauthier committed
690
#ifdef TRACE_RLC_AM_PDU
691
  if (data_req.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
692 693 694 695 696 697

      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;
698
          tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size;
gauthier's avatar
gauthier committed
699 700

          if ((((struct mac_tb_req *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
701
              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
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 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
#   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");

756
                  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
757 758 759
                  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);

760 761
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
762
                  } else {
763
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
764
                  }
gauthier's avatar
gauthier committed
765
# else
766
                  rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
gauthier's avatar
gauthier committed
767 768
# endif
              }
769
          } else {
gauthier's avatar
gauthier committed
770
              if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &g_rlc_am_control_pdu_info) >= 0) {
771
                  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
772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791

#   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);
                      }
                  }
792
                  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
793 794 795
                  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);

796 797
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
798
                  } else {
799
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
800
                  }
gauthier's avatar
gauthier committed
801
#   endif
802 803
              }
          }
gauthier's avatar
gauthier committed
804
          tb_p = tb_p->next;
805 806
      }
  }
gauthier's avatar
gauthier committed
807
#endif
808 809 810 811
  return data_req;
}
//-----------------------------------------------------------------------------
void
812 813 814 815 816
rlc_am_mac_data_indication (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                 rlc_pP,
                struct mac_data_ind          data_indP
                )
817 818
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
819 820
    rlc_am_entity_t           *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
    /*rlc_am_control_pdu_info_t control_pdu_info;
821
    int                       num_li;
gauthier's avatar
gauthier committed
822
    int16_t                     tb_size;*/
gauthier's avatar
gauthier committed
823 824 825 826
#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;
827
  sdu_size_t          tb_size_in_bytes;
gauthier's avatar
gauthier committed
828 829 830
  int                 num_nack;
  char                message_string[7000];
  size_t              message_string_size = 0;
831
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
832
  MessageDef         *msg_p;
833
#   endif
gauthier's avatar
gauthier committed
834 835
  int                 octet_index, index;
#endif
836

gauthier's avatar
gauthier committed
837 838 839 840 841 842 843 844 845 846 847
#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 ) {
848
              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
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 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
#   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");

903
                  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
904 905 906
                  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);

907 908
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
909
                  } else {
910
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
911
                  }
gauthier's avatar
gauthier committed
912
# else
913
                  rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
gauthier's avatar
gauthier committed
914 915 916 917 918 919 920
# 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
921
                  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
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
                  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);
                      }
                  }
938
                  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
939 940 941
                  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);

942 943
                  if (ctxt_pP->enb_flag) {
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
944
                  } else {
945
                      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
946
                  }
gauthier's avatar
gauthier committed
947 948 949 950 951 952 953
#   endif
              }
          }
          tb_p = tb_p->next;
      }
  }
#endif
954
    rlc_am_rx (ctxt_pP, rlc_pP, data_indP);
955 956 957 958
}

//-----------------------------------------------------------------------------
void
959 960 961 962
rlc_am_data_req (
                const protocol_ctxt_t* const ctxt_pP,
                void * const                rlc_pP,
                mem_block_t * const         sdu_pP)
963 964
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
965
  rlc_am_entity_t     *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
gauthier's avatar
gauthier committed
966 967 968 969
  uint32_t             mui;
  uint16_t             data_offset;
  uint16_t             data_size;
  uint8_t              conf;
gauthier's avatar
gauthier committed
970
#if defined(TRACE_RLC_AM_PDU)
gauthier's avatar
gauthier committed
971 972
  char                 message_string[7000];
  size_t               message_string_size = 0;
gauthier's avatar
gauthier committed
973
#if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
974
  MessageDef          *msg_p;
gauthier's avatar
gauthier committed
975
#endif
gauthier's avatar
gauthier committed
976 977
  int                  octet_index, index;
#endif
978

gauthier's avatar
gauthier committed
979
  pthread_mutex_lock(&l_rlc_p->lock_input_sdus);
gauthier's avatar
gauthier committed
980 981 982
  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)) {
983 984


gauthier's avatar
gauthier committed
985 986
      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;
987

gauthier's avatar
gauthier committed
988 989 990 991
      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;
992

gauthier's avatar
gauthier committed
993
#if defined(TRACE_RLC_AM_PDU)
gauthier's avatar
gauthier committed
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
      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
1013
          message_string_size += sprintf(&message_string[message_string_size], " %02x", ((uint8_t*)(&sdu_pP->data[data_offset]))[octet_index]);
gauthier's avatar
gauthier committed
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
          /*
           * 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
1026
#   if defined(ENABLE_ITTI)
1027
      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
1028 1029
      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);
1030

1031 1032
      if (ctxt_pP->enb_flag) {
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->enb_module_id, msg_p);
gauthier's avatar
gauthier committed
1033
      } else {
1034
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->ue_module_id + NB_eNB_INST, msg_p);
gauthier's avatar
gauthier committed
1035
      }
gauthier's avatar
gauthier committed
1036 1037
#   else
      LOG_T(RLC, "%s", message_string);