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

extern rlc_am_control_pdu_info_t  g_rlc_am_control_pdu_info;

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

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

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


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

}
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
106
void config_req_rlc_am (rlc_am_entity_t *rlc_pP, u32_t frameP, u8_t eNB_flagP, module_id_t module_idP, rlc_am_info_t * config_amP, rb_id_t rb_idP, rb_type_t rb_typeP)
107 108 109
{
//-----------------------------------------------------------------------------
  LOG_D(RLC, "[MSC_MSG][FRAME %05d][RRC_%s][MOD %02d][][--- 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 %02d][RB %02d]\n",
gauthier's avatar
gauthier committed
110
                                                                                                       frameP,
111 112 113 114 115 116 117 118 119 120 121
                                                                                                       ( Mac_rlc_xface->Is_cluster_head[module_idP] == 1) ? "eNB":"UE",
                                                                                                       module_idP,
                                                                                                       config_amP->max_retx_threshold,
                                                                                                       config_amP->poll_pdu,
                                                                                                       config_amP->poll_byte,
                                                                                                       config_amP->t_poll_retransmit,
                                                                                                       config_amP->t_reordering,
                                                                                                       config_amP->t_status_prohibit,
                                                                                                       module_idP,
                                                                                                       rb_idP);

gauthier's avatar
gauthier committed
122 123 124
  rlc_am_init(rlc_pP,frameP);
  rlc_am_set_debug_infos(rlc_pP, frameP, eNB_flagP, module_idP, rb_idP, rb_typeP);
  rlc_am_configure(rlc_pP,frameP,
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
           config_amP->max_retx_threshold,
           config_amP->poll_pdu,
           config_amP->poll_byte,
           config_amP->t_poll_retransmit,
           config_amP->t_reordering,
           config_amP->t_status_prohibit);

}
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
141
void config_req_rlc_am_asn1 (rlc_am_entity_t *rlc_pP, u32_t frameP, u8_t eNB_flagP, module_id_t module_idP, struct RLC_Config__am * config_amP, rb_id_t rb_idP, rb_type_t rb_typeP)
142 143 144 145 146 147 148 149 150 151
{
//-----------------------------------------------------------------------------
  if (	(config_amP->ul_AM_RLC.maxRetxThreshold <= UL_AM_RLC__maxRetxThreshold_t32) &&
	(config_amP->ul_AM_RLC.pollPDU<=PollPDU_pInfinity) &&
	(config_amP->ul_AM_RLC.pollByte<PollByte_spare1) &&
	(config_amP->ul_AM_RLC.t_PollRetransmit<T_PollRetransmit_spare9) &&
	(config_amP->dl_AM_RLC.t_Reordering<T_Reordering_spare1) &&
	(config_amP->dl_AM_RLC.t_StatusProhibit<T_StatusProhibit_spare8) ){

    LOG_D(RLC, "[MSC_MSG][FRAME %05d][RRC_%s][MOD %02d][][--- 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 %02d][RB %02d]\n",
gauthier's avatar
gauthier committed
152
	  frameP,
153 154 155 156 157 158 159 160 161 162 163
	  ( Mac_rlc_xface->Is_cluster_head[module_idP] == 1) ? "eNB":"UE",
	  module_idP,
	  maxRetxThreshold_tab[config_amP->ul_AM_RLC.maxRetxThreshold],
	  pollPDU_tab[config_amP->ul_AM_RLC.pollPDU],
	  pollByte_tab[config_amP->ul_AM_RLC.pollByte],
	  PollRetransmit_tab[config_amP->ul_AM_RLC.t_PollRetransmit],
	  am_t_Reordering_tab[config_amP->dl_AM_RLC.t_Reordering],
	  t_StatusProhibit_tab[config_amP->dl_AM_RLC.t_StatusProhibit],
	  module_idP,
	  rb_idP);
    
gauthier's avatar
gauthier committed
164 165 166
    rlc_am_init(rlc_pP,frameP);
    rlc_am_set_debug_infos(rlc_pP, frameP, eNB_flagP, module_idP, rb_idP, rb_typeP);
    rlc_am_configure(rlc_pP,frameP,
167 168 169 170 171 172 173 174 175 176
		     maxRetxThreshold_tab[config_amP->ul_AM_RLC.maxRetxThreshold],
		     pollPDU_tab[config_amP->ul_AM_RLC.pollPDU],
		     pollByte_tab[config_amP->ul_AM_RLC.pollByte],
		     PollRetransmit_tab[config_amP->ul_AM_RLC.t_PollRetransmit],
		     am_t_Reordering_tab[config_amP->dl_AM_RLC.t_Reordering],
		     t_StatusProhibit_tab[config_amP->dl_AM_RLC.t_StatusProhibit]);
    
  }
  else {
    LOG_D(RLC, "[MSC_MSG][FRAME %05d][RRC_%s][MOD %02d][][--- 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 %02d][RB %02d], RLC-AM NOT CONFIGURED\n",
gauthier's avatar
gauthier committed
177
	  frameP,
178 179 180 181 182 183 184 185 186 187 188 189 190 191
	  ( Mac_rlc_xface->Is_cluster_head[module_idP] == 1) ? "eNB":"UE",
	  module_idP,
	  config_amP->ul_AM_RLC.maxRetxThreshold,
	  config_amP->ul_AM_RLC.pollPDU,
	  config_amP->ul_AM_RLC.pollByte,
	  config_amP->ul_AM_RLC.t_PollRetransmit,
	  config_amP->dl_AM_RLC.t_Reordering,
	  config_amP->dl_AM_RLC.t_StatusProhibit,
	  module_idP,
	  rb_idP);
  }
}

  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
192
void rlc_am_stat_req     (rlc_am_entity_t *rlc_pP,
193 194 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 221
                              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
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
    *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;
249 250 251 252

}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
253
rlc_am_get_pdus (rlc_am_entity_t *rlc_pP,u32_t frameP)
254 255 256 257 258 259 260 261 262 263 264
{
//-----------------------------------------------------------------------------
  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
265
    switch (rlc_pP->protocol_state) {
266 267 268 269 270 271

        case RLC_NULL_STATE:
            break;

        case RLC_DATA_TRANSFER_READY_STATE:
            // TRY TO SEND CONTROL PDU FIRST
gauthier's avatar
gauthier committed
272
            if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->status_requested)) {
273 274 275 276 277 278 279 280 281 282
                // 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
283 284 285
                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);
286
                    if (pdu) {
gauthier's avatar
gauthier committed
287 288 289
                        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);
290 291 292 293
                        return;
                    }
                }
                  else {
gauthier's avatar
gauthier committed
294
                      LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] DELAYED SENT STATUS PDU BECAUSE T-STATUS-PROHIBIT RUNNING (TIME-OUT FRAME %05d)\n",frameP,  rlc_pP->module_id, rlc_pP->rb_id, rlc_pP->t_status_prohibit.frame_time_out);
295 296
                }
            }
gauthier's avatar
gauthier committed
297 298
            /*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);
299
                if (pdu != NULL {
gauthier's avatar
gauthier committed
300 301
                    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);
302
#ifdef TRACE_RLC_AM_TX
gauthier's avatar
gauthier committed
303
                        msg ("[FRAME %05d][RLC_AM][MOD %02d][RB %02d] SEND CONTROL PDU\n", ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, frameP);
304
#endif
gauthier's avatar
gauthier committed
305 306
                        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;
307 308 309 310 311 312 313 314
                    } else {
                      stay_on_this_list = 0;
                    }
                } else {
                    stay_on_this_list = 0;
                }
            }*/
            // THEN TRY TO SEND RETRANS PDU
gauthier's avatar
gauthier committed
315
            if (rlc_pP->first_retrans_pdu_sn >= 0) {
316 317
                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
318 319 320
                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)) {
321

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

gauthier's avatar
gauthier committed
324 325 326 327 328 329 330 331 332
                    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);
                        LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] RE-SEND DATA PDU SN %04d   %d BYTES\n",frameP,  rlc_pP->module_id,rlc_pP->rb_id, rlc_pP->first_retrans_pdu_sn, tx_data_pdu_management->header_and_payload_size);
                        rlc_pP->stat_tx_data_pdu                   += 1;
                        rlc_pP->stat_tx_retransmit_pdu             += 1;
                        rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
                        rlc_pP->stat_tx_data_bytes                 += tx_data_pdu_management->header_and_payload_size;
                        rlc_pP->stat_tx_retransmit_bytes           += tx_data_pdu_management->header_and_payload_size;
                        rlc_pP->stat_tx_retransmit_bytes_by_status += tx_data_pdu_management->header_and_payload_size;
333

gauthier's avatar
gauthier committed
334 335
                        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;
336 337 338

                        tx_data_pdu_management->retx_count += 1;
                        return;
gauthier's avatar
gauthier committed
339 340 341 342
                    } else if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac >= RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
                        LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] 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->module_id,rlc_pP->rb_id,
                        rlc_pP->first_retrans_pdu_sn,
                        rlc_pP->nb_bytes_requested_by_mac,
343 344 345 346 347
                        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
348 349 350 351 352 353 354 355 356
                        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);
                        LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n", frameP, rlc_pP->module_id,rlc_pP->rb_id, rlc_pP->first_retrans_pdu_sn, tx_data_pdu_management->nack_so_start);
                        rlc_pP->stat_tx_data_pdu                   += 1;
                        rlc_pP->stat_tx_retransmit_pdu             += 1;
                        rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
                        rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(copy->data))->tb_size_in_bits >> 3);
                        rlc_pP->stat_tx_retransmit_bytes           += (((struct mac_tb_req*)(copy->data))->tb_size_in_bits >> 3);
                        rlc_pP->stat_tx_retransmit_bytes_by_status += (((struct mac_tb_req*)(copy->data))->tb_size_in_bits >> 3);
                        list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
357 358 359 360
                    } else {
                        break;
                    }
                    // update first_retrans_pdu_sn
gauthier's avatar
gauthier committed
361 362 363 364
                    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;
                        LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] UPDATED first_retrans_pdu_sn SN %04d\n", frameP, rlc_pP->module_id, rlc_pP->rb_id, rlc_pP->first_retrans_pdu_sn);
365 366 367
                    };

                    display_flag = 1;
gauthier's avatar
gauthier committed
368
                    if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
369
                        // no more pdu to be retransmited
gauthier's avatar
gauthier committed
370
                        rlc_pP->first_retrans_pdu_sn = -1;
371
                        display_flag = 0;
gauthier's avatar
gauthier committed
372
                        LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] CLEAR first_retrans_pdu_sn\n",frameP, rlc_pP->module_id, rlc_pP->rb_id);
373 374
                    }
                    if (display_flag > 0) {
gauthier's avatar
gauthier committed
375
                        LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] UPDATED first_retrans_pdu_sn %04d\n", frameP, rlc_pP->module_id, rlc_pP->rb_id, rlc_pP->first_retrans_pdu_sn);
376 377 378 379
                    }
                    return;

/* ONLY ONE TB PER TTI
gauthier's avatar
gauthier committed
380
                    if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
381
#ifdef TRACE_RLC_AM_TX
gauthier's avatar
gauthier committed
382
                      msg ("[FRAME %05d][RLC_AM][MOD %02d][RB %02d] 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);
383 384 385 386 387
#endif
                      break;
                    }*/
                }
            }
gauthier's avatar
gauthier committed
388 389 390 391 392 393
            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;
                    rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size_in_bits >> 3);
394 395 396
                    return;
                }
            }
gauthier's avatar
gauthier committed
397 398
            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);
399 400
                return;
            } else {
gauthier's avatar
gauthier committed
401 402
                LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] COULD NOT RETRANSMIT ANY PDU BECAUSE ",frameP,  rlc_pP->module_id, rlc_pP->rb_id);
                if (rlc_pP->pdus_to_mac_layer.head != NULL) {
403 404
                    LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
                }
gauthier's avatar
gauthier committed
405 406
                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);
407
                }
gauthier's avatar
gauthier committed
408 409
                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);
410 411 412 413 414 415
                }
                LOG_D(RLC, "\n");
            }
            break;

        default:
gauthier's avatar
gauthier committed
416
            LOG_E(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n", frameP, rlc_pP->module_id, rlc_pP->rb_id, rlc_pP->protocol_state);
417 418 419 420
    }
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
421
rlc_am_rx (void *argP, u32_t frameP, u8_t eNB_flagP, struct mac_data_ind data_indP)
422 423 424 425 426 427 428 429 430 431 432 433 434
{
//-----------------------------------------------------------------------------

  rlc_am_entity_t *rlc = (rlc_am_entity_t *) argP;

  switch (rlc->protocol_state) {

      case RLC_NULL_STATE:
       LOG_N(RLC, "[RLC_AM %p] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", argP);
        list_free (&data_indP.data);
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
gauthier's avatar
gauthier committed
435
        rlc_am_receive_routing (rlc, frameP, eNB_flagP, data_indP);
436 437 438 439 440 441 442 443 444
        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
445
rlc_am_mac_status_indication (void *rlc_pP, u32 frameP, u16 tb_sizeP, struct mac_status_ind tx_statusP)
446 447 448
{
//-----------------------------------------------------------------------------
  struct mac_status_resp  status_resp;
449 450 451
  u16_t  sdu_size = 0;
  u16_t  sdu_remaining_size = 0;
  s32_t diff_time=0;
gauthier's avatar
gauthier committed
452
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
453

454 455 456 457 458
  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;
459 460
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

gauthier's avatar
gauthier committed
461 462 463 464
  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);
465
  }
gauthier's avatar
gauthier committed
466
  rlc->last_frame_status_indication = frameP;
467 468 469

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

gauthier's avatar
gauthier committed
470
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(rlc,frameP);
471 472 473 474 475
  
  if ((rlc->input_sdus[rlc->current_sdu_index].mem_block != NULL) && (status_resp.buffer_occupancy_in_bytes)) {
          
	  //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;
gauthier's avatar
gauthier committed
476
	  diff_time =   frameP - ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_creation_time;
477
	  
gauthier's avatar
gauthier committed
478
	  status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (u32_t) diff_time :  (u32_t)(0xffffffff - diff_time + frameP) ;
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
	  
	  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)  {
           status_resp.head_sdu_is_segmented = 0; 
	  }
	  else {
	   status_resp.head_sdu_is_segmented = 1; 
	  }
	
  } else {
  }
  
  
495 496
#ifdef TRACE_RLC_AM_TX_STATUS
  if (tb_sizeP > 0) {
gauthier's avatar
gauthier committed
497
      LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n", frameP, rlc->module_id, rlc->rb_id, tb_sizeP, status_resp.buffer_occupancy_in_bytes);
498 499
      /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
          msg ("[FRAME %05d][RLC_AM][MOD %02d][RB %02d] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",rlc->module_id,
gauthier's avatar
gauthier committed
500
rlc->rb_id, frameP, tx_statusP.no_pdu);
501 502 503
      }
      if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
          msg ("[FRAME %05d][RLC_AM][MOD %02d][RB %02d] MAC_STATUS_INDICATION  TX STATUS UNSUCCESSFUL %d PDUs\n",rlc->module_id, rlc->rb_id,
gauthier's avatar
gauthier committed
504
frameP, tx_statusP.no_pdu);
505 506 507 508 509 510 511
      }*/
  }
#endif
  return status_resp;
}
//-----------------------------------------------------------------------------
struct mac_data_req
gauthier's avatar
gauthier committed
512
rlc_am_mac_data_request (void *rlc_pP,u32 frameP)
513 514 515
{
//-----------------------------------------------------------------------------
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
516 517 518 519 520 521 522 523 524 525 526 527 528
  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;
  MessageDef         *msg_p;
  int                 octet_index, index;
#endif
529

gauthier's avatar
gauthier committed
530
  rlc_am_get_pdus (rlc_pP,frameP);
531 532

  list_init (&data_req.data, NULL);
gauthier's avatar
gauthier committed
533 534
  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;
535
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
gauthier's avatar
gauthier committed
536
      LOG_D(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n", frameP, l_rlc_p->module_id,l_rlc_p->rb_id, nb_bytes_requested_by_mac, data_req.data.nb_elements);
537
  }
gauthier's avatar
gauthier committed
538 539
  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;
540

gauthier's avatar
gauthier committed
541
#ifdef TRACE_RLC_AM_PDU
542
  if (data_req.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615

      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;
          tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size_in_bits >> 3;

          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
                  rlc_am_display_data_pdu_infos(l_rlc_p, frameP, pdu_info);
# endif
              }
616
          } else {
gauthier's avatar
gauthier committed
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
              if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &g_rlc_am_control_pdu_info) >= 0) {
                  tb_size_in_bytes   = ((struct mac_tb_req *) (tb_p->data))->tb_size_in_bits >> 3; //tb_size_in_bytes modified by rlc_am_get_control_pdu_infos!

#   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
645 646
              }
          }
gauthier's avatar
gauthier committed
647
          tb_p = tb_p->next;
648 649
      }
  }
gauthier's avatar
gauthier committed
650
#endif
651 652 653 654
  return data_req;
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
655
rlc_am_mac_data_indication (void *rlc_pP, u32_t frameP, u8 eNB_flagP, struct mac_data_ind data_indP)
656 657
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
658 659
    rlc_am_entity_t           *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
    /*rlc_am_control_pdu_info_t control_pdu_info;
660
    int                       num_li;
gauthier's avatar
gauthier committed
661 662 663 664 665 666 667 668 669 670 671 672
    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;
  MessageDef         *msg_p;
  int                 octet_index, index;
#endif
673

gauthier's avatar
gauthier committed
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 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 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
#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
                  rlc_am_display_data_pdu_infos(l_rlc_p, frameP, pdu_info);
# 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);
787 788 789 790
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
791
rlc_am_data_req (void *rlc_pP, u32_t frameP, mem_block_t * sdu_pP)
792 793
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
794
  rlc_am_entity_t  *rlc_p = (rlc_am_entity_t *) rlc_pP;
795 796 797 798 799 800
  u32_t             mui;
  u16_t             data_offset;
  u16_t             data_size;
  u8_t              conf;


gauthier's avatar
gauthier committed
801 802 803
  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)) {
804 805


gauthier's avatar
gauthier committed
806 807
      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;
808

gauthier's avatar
gauthier committed
809 810 811 812
      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;
813 814


gauthier's avatar
gauthier committed
815 816
     rlc_p->stat_tx_pdcp_sdu   += 1;
     rlc_p->stat_tx_pdcp_bytes += data_size;
817

gauthier's avatar
gauthier committed
818 819 820
      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;
821

gauthier's avatar
gauthier committed
822 823 824
      rlc_p->sdu_buffer_occupancy += data_size;
      rlc_p->nb_sdu += 1;
      rlc_p->nb_sdu_no_segmented += 1;
825

gauthier's avatar
gauthier committed
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
      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;
      LOG_I(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] 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->module_id, rlc_p->rb_id, data_size, rlc_p->nb_sdu, rlc_p->current_sdu_index, rlc_p->next_sdu_index, conf, mui);
841
  } else {
gauthier's avatar
gauthier committed
842 843 844 845 846
      LOG_W(RLC, "[FRAME %05d][RLC_AM][MOD %02d][RB %02d] 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->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);
      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);
847 848
  }
}