rlc_am.c 55.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*******************************************************************************

Eurecom OpenAirInterface 2
Copyright(c) 1999 - 2010 Eurecom

This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.

This program is distributed in the hope 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
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

The full GNU General Public License is included in this distribution in
the file called "COPYING".

Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums       : http://forums.eurecom.fsr/openairinterface
Address      : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France

*******************************************************************************/
#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
gauthier's avatar
gauthier committed
38
# include "assertions.h"
39 40 41 42 43 44 45 46 47 48 49 50 51
#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
52
//#define TRACE_RLC_AM_RX
53
//#define TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
54 55 56 57
#define TRACE_RLC_AM_PDU 1

extern rlc_am_control_pdu_info_t  g_rlc_am_control_pdu_info;

58 59
//-----------------------------------------------------------------------------
u32_t
gauthier's avatar
gauthier committed
60
rlc_am_get_buffer_occupancy_in_bytes (rlc_am_entity_t *rlc_pP,frame_t frameP)
61 62 63 64 65 66
{
//-----------------------------------------------------------------------------
  u32_t max_li_overhead;
  u32_t header_overhead;

  // priority of control trafic
gauthier's avatar
gauthier committed
67 68
  if (rlc_pP->status_requested) {
      if (rlc_pP->t_status_prohibit.running == 0) {
69
#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
70
          if (((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3) > 0) {
gauthier's avatar
gauthier committed
71
              LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BO : CONTROL PDU %d bytes \n", frameP, 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));
72 73
          }
#endif
gauthier's avatar
gauthier committed
74
          return ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
75 76 77 78
      }
  }

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


#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
92
  if ((rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
gauthier's avatar
gauthier committed
93 94 95
    LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BO : STATUS  BUFFER %d bytes \n", frameP, 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", frameP, 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", frameP, rlc_pP->module_id,rlc_pP->rb_id, rlc_pP->sdu_buffer_occupancy, max_li_overhead, header_overhead, rlc_pP->nb_sdu_no_segmented);
96 97
  }
#endif
gauthier's avatar
gauthier committed
98
  return rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead;
99 100
}
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
101
void rlc_am_release (rlc_am_entity_t *rlc_pP)
102 103 104 105 106
//-----------------------------------------------------------------------------
{

}
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
107 108 109 110 111 112 113
void config_req_rlc_am (frame_t         frameP,
                        eNB_flag_t      eNB_flagP,
                        module_id_t     enb_module_idP,
                        module_id_t     ue_module_idP,
                        rlc_am_info_t  *config_am_pP,
                        rb_id_t         rb_idP,
                        rb_type_t       rb_typeP)
114 115
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
116 117 118
    rlc_am_entity_t *rlc = NULL;

    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",
gauthier's avatar
gauthier committed
119
                                                                                                       frameP,
gauthier's avatar
gauthier committed
120 121 122 123 124 125 126 127 128 129 130
                                                                                                       ( eNB_flagP > 0) ? "eNB":"UE",
                                                                                                       enb_module_idP,
                                                                                                       ue_module_idP,
                                                                                                       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,
                                                                                                       enb_module_idP,
                                                                                                       ue_module_idP,
131 132
                                                                                                       rb_idP);

gauthier's avatar
gauthier committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146
    if (eNB_flagP) {
        rlc = &rlc_array_eNB[enb_module_idP][ue_module_idP][rb_idP].rlc.am;
    } else {
        rlc = &rlc_array_ue[ue_module_idP][rb_idP].rlc.am;
    }
    rlc_am_init(rlc,frameP);
    rlc_am_set_debug_infos(rlc, frameP, eNB_flagP, enb_module_idP, ue_module_idP, rb_idP, rb_typeP);
    rlc_am_configure(rlc,frameP,
           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);
147 148 149 150 151 152 153 154 155 156

}
u32_t pollPDU_tab[PollPDU_pInfinity+1]={4,8,16,32,64,128,256,1024};  // What is PollPDU_pInfinity??? 1024 for now
u32_t maxRetxThreshold_tab[UL_AM_RLC__maxRetxThreshold_t32+1]={1,2,3,4,6,8,16,32};
u32_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
u32_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};
u32_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};
u32_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};

//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
157 158 159 160 161 162 163
void config_req_rlc_am_asn1 (frame_t                 frameP,
                             eNB_flag_t              eNB_flagP,
                             module_id_t             enb_module_idP,
                             module_id_t             ue_module_idP,
                             struct RLC_Config__am  *config_am_pP,
                             rb_id_t                 rb_idP,
                             rb_type_t               rb_typeP)
164 165
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
    rlc_am_entity_t *rlc = NULL;

    if (eNB_flagP) {
        rlc = &rlc_array_eNB[enb_module_idP][ue_module_idP][rb_idP].rlc.am;
    } else {
        rlc = &rlc_array_ue[ue_module_idP][rb_idP].rlc.am;
    }
    if ((config_am_pP->ul_AM_RLC.maxRetxThreshold <= UL_AM_RLC__maxRetxThreshold_t32) &&
        (config_am_pP->ul_AM_RLC.pollPDU<=PollPDU_pInfinity) &&
        (config_am_pP->ul_AM_RLC.pollByte<PollByte_spare1) &&
        (config_am_pP->ul_AM_RLC.t_PollRetransmit<T_PollRetransmit_spare9) &&
        (config_am_pP->dl_AM_RLC.t_Reordering<T_Reordering_spare1) &&
        (config_am_pP->dl_AM_RLC.t_StatusProhibit<T_StatusProhibit_spare8) ){

            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",
                     frameP,
                     (eNB_flagP) ? "eNB" : "UE",
                      enb_module_idP,
                      ue_module_idP,
                      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],
                      enb_module_idP,
                      ue_module_idP,
                      rb_idP);
194
    
gauthier's avatar
gauthier committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
            rlc_am_init(rlc,frameP);
            rlc_am_set_debug_infos(rlc, frameP, eNB_flagP, enb_module_idP, ue_module_idP, rb_idP, rb_typeP);
            rlc_am_configure(rlc,
                         frameP,
                         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",
                frameP,
                (eNB_flagP) ? "eNB" : "UE",
                enb_module_idP,
                ue_module_idP,
                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,
                enb_module_idP,
                ue_module_idP,
                rb_idP);
    }
221 222 223
}

  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
224
void rlc_am_stat_req     (rlc_am_entity_t *rlc_pP,
225 226 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
                              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)
//-----------------------------------------------------------------------------
{
gauthier's avatar
gauthier committed
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 279 280
    *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;
281 282 283 284

}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
285
rlc_am_get_pdus (rlc_am_entity_t *rlc_pP, frame_t frameP)
286 287 288 289 290 291 292 293 294 295 296
{
//-----------------------------------------------------------------------------
  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
297
    switch (rlc_pP->protocol_state) {
298 299 300 301 302 303

        case RLC_NULL_STATE:
            break;

        case RLC_DATA_TRANSFER_READY_STATE:
            // TRY TO SEND CONTROL PDU FIRST
gauthier's avatar
gauthier committed
304
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) {
305 306 307 308 309 310 311 312 313 314
                // 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
315 316 317
                if (rlc_pP->t_status_prohibit.running == 0) {
                    rlc_am_send_status_pdu(rlc_pP,frameP);
                    mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);
318
                    if (pdu) {
gauthier's avatar
gauthier committed
319 320 321
                        list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
                        rlc_pP->status_requested = 0;
                        rlc_am_start_timer_status_prohibit(rlc_pP,frameP);
322 323 324 325
                        return;
                    }
                }
                  else {
gauthier's avatar
gauthier committed
326 327 328 329 330 331 332
                      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",
                        frameP,
                        (rlc_pP->is_enb) ? "eNB" : "UE",
                        rlc_pP->enb_module_id,
                        rlc_pP->ue_module_id,
                        rlc_pP->rb_id,
                        rlc_pP->t_status_prohibit.frame_time_out);
333 334
                }
            }
gauthier's avatar
gauthier committed
335 336
            /*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);
337
                if (pdu != NULL {
gauthier's avatar
gauthier committed
338 339
                    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);
340
#ifdef TRACE_RLC_AM_TX
gauthier's avatar
gauthier committed
341
                        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, frameP);
342
#endif
gauthier's avatar
gauthier committed
343 344
                        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;
345 346 347 348 349 350 351 352
                    } else {
                      stay_on_this_list = 0;
                    }
                } else {
                    stay_on_this_list = 0;
                }
            }*/
            // THEN TRY TO SEND RETRANS PDU
gauthier's avatar
gauthier committed
353
            if (rlc_pP->first_retrans_pdu_sn >= 0) {
354 355
                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
356 357 358
                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)) {
359

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

gauthier's avatar
gauthier committed
362 363
                    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)) {
                        mem_block_t* copy = rlc_am_retransmit_get_copy(rlc_pP, frameP,rlc_pP->first_retrans_pdu_sn);
gauthier's avatar
gauthier committed
364 365 366 367 368 369 370 371
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RE-SEND DATA PDU SN %04d   %d BYTES\n",
                            frameP,
                            (rlc_pP->is_enb) ? "eNB" : "UE",
                            rlc_pP->enb_module_id,
                            rlc_pP->ue_module_id,
                            rlc_pP->rb_id,
                            rlc_pP->first_retrans_pdu_sn,
                            tx_data_pdu_management->header_and_payload_size);
gauthier's avatar
gauthier committed
372 373 374 375 376 377
                        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;
378

gauthier's avatar
gauthier committed
379 380
                        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;
381 382 383

                        tx_data_pdu_management->retx_count += 1;
                        return;
gauthier's avatar
gauthier committed
384
                    } 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
385 386 387 388 389 390
                        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",
                        frameP,
                        (rlc_pP->is_enb) ? "eNB" : "UE",
                        rlc_pP->enb_module_id,
                        rlc_pP->ue_module_id,
                        rlc_pP->rb_id,
gauthier's avatar
gauthier committed
391 392
                        rlc_pP->first_retrans_pdu_sn,
                        rlc_pP->nb_bytes_requested_by_mac,
393 394 395 396 397
                        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);

gauthier's avatar
gauthier committed
398
                        mem_block_t* copy = rlc_am_retransmit_get_subsegment(rlc_pP, frameP, rlc_pP->first_retrans_pdu_sn, &rlc_pP->nb_bytes_requested_by_mac);
gauthier's avatar
gauthier committed
399 400 401 402 403 404 405 406 407
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n",
                              frameP,
                              (rlc_pP->is_enb) ? "eNB" : "UE",
                              rlc_pP->enb_module_id,
                              rlc_pP->ue_module_id,
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn,
                              tx_data_pdu_management->nack_so_start);

gauthier's avatar
gauthier committed
408 409 410
                        rlc_pP->stat_tx_data_pdu                   += 1;
                        rlc_pP->stat_tx_retransmit_pdu             += 1;
                        rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
411 412 413
                        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
414
                        list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
415 416 417 418
                    } else {
                        break;
                    }
                    // update first_retrans_pdu_sn
gauthier's avatar
gauthier committed
419 420 421
                    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
422 423 424 425 426 427 428
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] UPDATED first_retrans_pdu_sn SN %04d\n",
                              frameP,
                              (rlc_pP->is_enb) ? "eNB" : "UE",
                              rlc_pP->enb_module_id,
                              rlc_pP->ue_module_id,
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn);
429 430 431
                    };

                    display_flag = 1;
gauthier's avatar
gauthier committed
432
                    if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
433
                        // no more pdu to be retransmited
gauthier's avatar
gauthier committed
434
                        rlc_pP->first_retrans_pdu_sn = -1;
435
                        display_flag = 0;
gauthier's avatar
gauthier committed
436 437 438 439 440 441
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] CLEAR first_retrans_pdu_sn\n",
                              frameP,
                              (rlc_pP->is_enb) ? "eNB" : "UE",
                              rlc_pP->enb_module_id,
                              rlc_pP->ue_module_id,
                              rlc_pP->rb_id);
442 443
                    }
                    if (display_flag > 0) {
gauthier's avatar
gauthier committed
444 445 446 447 448 449 450
                        LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] UPDATED first_retrans_pdu_sn %04d\n",
                              frameP,
                              (rlc_pP->is_enb) ? "eNB" : "UE",
                              rlc_pP->enb_module_id,
                              rlc_pP->ue_module_id,
                              rlc_pP->rb_id,
                              rlc_pP->first_retrans_pdu_sn);
451 452 453 454
                    }
                    return;

/* ONLY ONE TB PER TTI
gauthier's avatar
gauthier committed
455
                    if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
456
#ifdef TRACE_RLC_AM_TX
gauthier's avatar
gauthier committed
457
                      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",frameP,  ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, rlc_pP->nb_bytes_requested_by_mac);
458 459 460 461 462
#endif
                      break;
                    }*/
                }
            }
gauthier's avatar
gauthier committed
463 464 465 466 467
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
                rlc_am_segment_10(rlc_pP,frameP);
                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;
468
                    rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size);
469 470 471
                    return;
                }
            }
gauthier's avatar
gauthier committed
472 473
            if ((rlc_pP->pdus_to_mac_layer.head == NULL) && (rlc_am_is_timer_poll_retransmit_timed_out(rlc_pP)) && (rlc_pP->nb_bytes_requested_by_mac > 2)) {
                rlc_am_retransmit_any_pdu(rlc_pP,frameP);
474 475
                return;
            } else {
gauthier's avatar
gauthier committed
476 477 478 479 480 481
                LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] COULD NOT RETRANSMIT ANY PDU BECAUSE ",
                      frameP,
                      (rlc_pP->is_enb) ? "eNB" : "UE",
                      rlc_pP->enb_module_id,
                      rlc_pP->ue_module_id,
                      rlc_pP->rb_id);
gauthier's avatar
gauthier committed
482
                if (rlc_pP->pdus_to_mac_layer.head != NULL) {
483 484
                    LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
                }
gauthier's avatar
gauthier committed
485 486
                if (!(rlc_am_is_timer_poll_retransmit_timed_out(rlc_pP))) {
                    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);
487
                }
gauthier's avatar
gauthier committed
488 489
                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);
490 491 492 493 494 495
                }
                LOG_D(RLC, "\n");
            }
            break;

        default:
gauthier's avatar
gauthier committed
496 497 498 499 500 501 502
            LOG_E(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n",
                  frameP,
                  (rlc_pP->is_enb) ? "eNB" : "UE",
                  rlc_pP->enb_module_id,
                  rlc_pP->ue_module_id,
                  rlc_pP->rb_id,
                  rlc_pP->protocol_state);
503 504 505 506
    }
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
507
rlc_am_rx (void *arg_pP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
508 509 510
{
//-----------------------------------------------------------------------------

gauthier's avatar
gauthier committed
511
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
512 513 514 515

  switch (rlc->protocol_state) {

      case RLC_NULL_STATE:
gauthier's avatar
gauthier committed
516
       LOG_N(RLC, "[RLC_AM %p] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", arg_pP);
517 518 519 520
        list_free (&data_indP.data);
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
gauthier's avatar
gauthier committed
521
        rlc_am_receive_routing (rlc, frameP, eNB_flagP, data_indP);
522 523 524 525 526 527 528 529 530
        break;

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

//-----------------------------------------------------------------------------
struct mac_status_resp
gauthier's avatar
gauthier committed
531
rlc_am_mac_status_indication (void *rlc_pP, frame_t frameP, u16 tb_sizeP, struct mac_status_ind tx_statusP)
532 533 534
{
//-----------------------------------------------------------------------------
  struct mac_status_resp  status_resp;
535 536 537
  u16_t  sdu_size = 0;
  u16_t  sdu_remaining_size = 0;
  s32_t diff_time=0;
gauthier's avatar
gauthier committed
538
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
539

540 541 542 543 544
  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;
545 546
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

gauthier's avatar
gauthier committed
547 548 549 550
  if (rlc->last_frame_status_indication != frameP) {
    rlc_am_check_timer_poll_retransmit(rlc,frameP);
    rlc_am_check_timer_reordering(rlc,frameP);
    rlc_am_check_timer_status_prohibit(rlc,frameP);
551
  }
gauthier's avatar
gauthier committed
552
  rlc->last_frame_status_indication = frameP;
553 554 555

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

gauthier's avatar
gauthier committed
556
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(rlc,frameP);
557 558 559
  
  if ((rlc->input_sdus[rlc->current_sdu_index].mem_block != NULL) && (status_resp.buffer_occupancy_in_bytes)) {
          
gauthier's avatar
gauthier committed
560 561 562 563 564 565 566 567 568 569 570
          //status_resp.buffer_occupancy_in_bytes += ((rlc_am_entity_t *) rlc)->tx_header_min_length_in_bytes;
          status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu;
          diff_time =   frameP - ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_creation_time;

          status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (u32_t) diff_time :  (u32_t)(0xffffffff - diff_time + frameP) ;

          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)  {
571
           status_resp.head_sdu_is_segmented = 0; 
gauthier's avatar
gauthier committed
572 573 574 575 576
          }
          else {
              status_resp.head_sdu_is_segmented = 1;
          }

577 578 579 580
  } else {
  }
  
  
581 582
#ifdef TRACE_RLC_AM_TX_STATUS
  if (tb_sizeP > 0) {
gauthier's avatar
gauthier committed
583 584 585 586 587 588 589 590
      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n",
            frameP,
            (rlc->is_enb) ? "eNB" : "UE",
            rlc->enb_module_id,
            rlc->ue_module_id,
            rlc->rb_id,
            tb_sizeP,
            status_resp.buffer_occupancy_in_bytes);
591
      /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
592
          msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",rlc->module_id,
gauthier's avatar
gauthier committed
593
rlc->rb_id, frameP, tx_statusP.no_pdu);
594 595
      }
      if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
596
          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,
gauthier's avatar
gauthier committed
597
frameP, tx_statusP.no_pdu);
598 599 600 601 602 603 604
      }*/
  }
#endif
  return status_resp;
}
//-----------------------------------------------------------------------------
struct mac_data_req
gauthier's avatar
gauthier committed
605
rlc_am_mac_data_request (void *rlc_pP, frame_t frameP)
606 607 608
{
//-----------------------------------------------------------------------------
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
609 610 611 612 613 614 615 616 617 618
  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;
  s16_t               tb_size_in_bytes;
  int                 num_nack;
  char                message_string[9000];
  size_t              message_string_size = 0;
619
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
620
  MessageDef         *msg_p;
621
#   endif
gauthier's avatar
gauthier committed
622 623
  int                 octet_index, index;
#endif
624

gauthier's avatar
gauthier committed
625
  rlc_am_get_pdus (rlc_pP,frameP);
626 627

  list_init (&data_req.data, NULL);
gauthier's avatar
gauthier committed
628 629
  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;
630
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
gauthier's avatar
gauthier committed
631 632 633 634 635 636 637
      LOG_D(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n",
            frameP,
            (l_rlc_p->is_enb) ? "eNB" : "UE",
            l_rlc_p->enb_module_id,
            l_rlc_p->ue_module_id,
            nb_bytes_requested_by_mac,
            data_req.data.nb_elements);
638
  }
gauthier's avatar
gauthier committed
639 640
  data_req.buffer_occupancy_in_bytes   = rlc_am_get_buffer_occupancy_in_bytes(l_rlc_p,frameP);
  data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
641

gauthier's avatar
gauthier committed
642
#ifdef TRACE_RLC_AM_PDU
643
  if (data_req.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
644 645 646 647 648 649

      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;
650
          tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size;
gauthier's avatar
gauthier committed
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713

          if ((((struct mac_tb_req *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
              if (rlc_am_get_data_pdu_infos(frameP,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
#   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");

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

                  itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->module_id + NB_eNB_INST, msg_p);
# else
714
                  rlc_am_display_data_pdu_infos(l_rlc_p, frameP, &pdu_info);
gauthier's avatar
gauthier committed
715 716
# endif
              }
717
          } else {
gauthier's avatar
gauthier committed
718
              if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &g_rlc_am_control_pdu_info) >= 0) {
719
                  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
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

#   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);
                      }
                  }
                  msg_p = itti_alloc_new_message_sized (l_rlc_p->is_enb > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_STATUS_PDU_REQ, message_string_size + sizeof (IttiMsgText));
                  msg_p->ittiMsg.rlc_am_status_pdu_req.size = message_string_size;
                  memcpy(&msg_p->ittiMsg.rlc_am_status_pdu_req.text, message_string, message_string_size);

                  itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->module_id + NB_eNB_INST, msg_p);
#   endif
746 747
              }
          }
gauthier's avatar
gauthier committed
748
          tb_p = tb_p->next;
749 750
      }
  }
gauthier's avatar
gauthier committed
751
#endif
752 753 754 755
  return data_req;
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
756
rlc_am_mac_data_indication (void *rlc_pP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
757 758
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
759 760
    rlc_am_entity_t           *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
    /*rlc_am_control_pdu_info_t control_pdu_info;
761
    int                       num_li;
gauthier's avatar
gauthier committed
762 763 764 765 766 767 768 769 770
    s16_t                     tb_size;*/
#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;
  s16_t               tb_size_in_bytes;
  int                 num_nack;
  char                message_string[7000];
  size_t              message_string_size = 0;
771
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
772
  MessageDef         *msg_p;
773
#   endif
gauthier's avatar
gauthier committed
774 775
  int                 octet_index, index;
#endif
776

gauthier's avatar
gauthier committed
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
#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 ) {
              if (rlc_am_get_data_pdu_infos(frameP,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
#   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");

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

                  itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->module_id + NB_eNB_INST, msg_p);
# else
849
                  rlc_am_display_data_pdu_infos(l_rlc_p, frameP, &pdu_info);
gauthier's avatar
gauthier committed
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
# 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);
                  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 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);
                      }
                  }
                  msg_p = itti_alloc_new_message_sized (l_rlc_p->is_enb > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_STATUS_PDU_IND, message_string_size + sizeof (IttiMsgText));
                  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);

                  itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->module_id + NB_eNB_INST, msg_p);
#   endif
              }
          }
          tb_p = tb_p->next;
      }
  }
#endif
    rlc_am_rx (rlc_pP, frameP, eNB_flagP, data_indP);
887 888 889 890
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
891
rlc_am_data_req (void *rlc_pP, frame_t frameP, mem_block_t * sdu_pP)
892 893
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
894
  rlc_am_entity_t  *rlc_p = (rlc_am_entity_t *) rlc_pP;
895 896 897 898 899 900
  u32_t             mui;
  u16_t             data_offset;
  u16_t             data_size;
  u8_t              conf;


gauthier's avatar
gauthier committed
901 902 903
  if ((rlc_p->input_sdus[rlc_p->next_sdu_index].mem_block == NULL) &&
      (rlc_p->input_sdus[rlc_p->next_sdu_index].flags.segmented == 0) &&
      (((rlc_p->next_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE) != rlc_p->current_sdu_index)) {
904 905


gauthier's avatar
gauthier committed
906 907
      memset(&rlc_p->input_sdus[rlc_p->next_sdu_index], 0, sizeof(rlc_am_tx_sdu_management_t));
      rlc_p->input_sdus[rlc_p->next_sdu_index].mem_block = sdu_pP;
908

gauthier's avatar
gauthier committed
909 910 911 912
      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;
913 914


gauthier's avatar
gauthier committed
915 916
     rlc_p->stat_tx_pdcp_sdu   += 1;
     rlc_p->stat_tx_pdcp_bytes += data_size;
917

gauthier's avatar
gauthier committed
918 919 920
      rlc_p->input_sdus[rlc_p->next_sdu_index].mui      = mui;
      rlc_p->input_sdus[rlc_p->next_sdu_index].sdu_size = data_size;
      //rlc_p->input_sdus[rlc_p->next_sdu_index].confirm  = conf;
921

gauthier's avatar
gauthier committed
922 923 924
      rlc_p->sdu_buffer_occupancy += data_size;
      rlc_p->nb_sdu += 1;
      rlc_p->nb_sdu_no_segmented += 1;
925

gauthier's avatar
gauthier committed
926 927 928 929 930 931 932 933 934 935 936 937 938 939
      rlc_p->input_sdus[rlc_p->next_sdu_index].first_byte = (u8_t*)(&sdu_pP->data[data_offset]);
      rlc_p->input_sdus[rlc_p->next_sdu_index].sdu_remaining_size = rlc_p->input_sdus[rlc_p->next_sdu_index].sdu_size;
      rlc_p->input_sdus[rlc_p->next_sdu_index].sdu_segmented_size = 0;
      rlc_p->input_sdus[rlc_p->next_sdu_index].sdu_creation_time = frameP;
      rlc_p->input_sdus[rlc_p->next_sdu_index].nb_pdus = 0;
      rlc_p->input_sdus[rlc_p->next_sdu_index].nb_pdus_ack = 0;
      //rlc_p->input_sdus[rlc_p->next_sdu_index].nb_pdus_time = 0;
      //rlc_p->input_sdus[rlc_p->next_sdu_index].nb_pdus_internal_use = 0;
      rlc_p->input_sdus[rlc_p->next_sdu_index].flags.discarded = 0;
      rlc_p->input_sdus[rlc_p->next_sdu_index].flags.segmented = 0;
      rlc_p->input_sdus[rlc_p->next_sdu_index].flags.segmentation_in_progress = 0;
      rlc_p->input_sdus[rlc_p->next_sdu_index].flags.no_new_sdu_segmented_in_last_pdu = 0;
      //rlc_p->input_sdus[rlc_p->next_sdu_index].li_index_for_discard = -1;
      rlc_p->next_sdu_index = (rlc_p->next_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
gauthier's avatar
gauthier committed
940 941 942 943 944 945 946 947 948 949 950 951
      LOG_I(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RLC_AM_DATA_REQ size %d Bytes,  NB SDU %d current_sdu_index=%d next_sdu_index=%d conf %d mui %d\n",
            frameP,
            (rlc_p->is_enb) ? "eNB" : "UE",
            rlc_p->enb_module_id,
            rlc_p->ue_module_id,
            rlc_p->rb_id,
            data_size,
            rlc_p->nb_sdu,
            rlc_p->current_sdu_index,
            rlc_p->next_sdu_index,
            conf,
            mui);
952
  } else {
gauthier's avatar
gauthier committed
953 954 955 956 957 958 959 960 961 962
      LOG_W(RLC, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RLC_AM_DATA_REQ BUFFER FULL, NB SDU %d current_sdu_index=%d next_sdu_index=%d size_input_sdus_buffer=%d\n",
            frameP,
            (rlc_p->is_enb) ? "eNB" : "UE",
            rlc_p->enb_module_id,
            rlc_p->ue_module_id,
            rlc_p->rb_id,
            rlc_p->nb_sdu,
            rlc_p->current_sdu_index,
            rlc_p->next_sdu_index,
            RLC_AM_SDU_CONTROL_BUFFER_SIZE);
gauthier's avatar
gauthier committed
963 964 965 966
      LOG_W(RLC, "                                        input_sdus[].mem_block=%p next input_sdus[].flags.segmented=%d\n", rlc_p->input_sdus[rlc_p->next_sdu_index].mem_block, rlc_p->input_sdus[rlc_p->next_sdu_index].flags.segmented);
      rlc_p->stat_tx_pdcp_sdu_discarded   += 1;
      rlc_p->stat_tx_pdcp_bytes_discarded += ((struct rlc_am_data_req *) (sdu_pP->data))->data_size;
      free_mem_block (sdu_pP);
gauthier's avatar
gauthier committed
967 968 969 970 971 972 973 974 975 976 977 978
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
      AssertFatal(0, "[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] RLC_AM_DATA_REQ size %d Bytes, SDU DROPPED, INPUT BUFFER OVERFLOW NB SDU %d current_sdu_index=%d next_sdu_index=%d \n",
          frameP,
          (rlc_p->is_enb) ? "eNB" : "UE",
          rlc_p->enb_module_id,
          rlc_p->ue_module_id,
          rlc_p->rb_id,
          data_size,
          rlc_p->nb_sdu,
          rlc_p->current_sdu_index,
          rlc_p->next_sdu_index);
#endif
979 980
  }
}