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

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

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

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

  Address      : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France.

 *******************************************************************************/
29 30 31 32 33 34
#define RLC_AM_MODULE
#define RLC_AM_C
//-----------------------------------------------------------------------------
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
35 36 37
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif
38 39
#include "assertions.h"
#include "hashtable.h"
40 41 42 43 44 45 46 47 48 49 50 51 52
#include "rlc_am.h"
#include "rlc_am_segment.h"
#include "rlc_am_timer_poll_retransmit.h"
#include "mac_primitives.h"
#include "rlc_primitives.h"
#include "list.h"
#include "LAYER2/MAC/extern.h"
#include "UTIL/LOG/log.h"
#include "UL-AM-RLC.h"
#include "DL-AM-RLC.h"
//#define TRACE_RLC_AM_DATA_REQUEST
//#define TRACE_RLC_AM_TX_STATUS
//#define TRACE_RLC_AM_TX
53
//#define TRACE_RLC_AM_RX
54
//#define TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
55 56 57 58
#define TRACE_RLC_AM_PDU 1

extern rlc_am_control_pdu_info_t  g_rlc_am_control_pdu_info;

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

  // priority of control trafic
gauthier's avatar
gauthier committed
68 69
  if (rlc_pP->status_requested) {
      if (rlc_pP->t_status_prohibit.running == 0) {
70
#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
71
          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
72
              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));
73 74
          }
#endif
gauthier's avatar
gauthier committed
75
          return ((15  +  rlc_pP->num_nack_sn*(10+1)  +  rlc_pP->num_nack_so*(15+15+1) + 7) >> 3);
76 77 78 79
      }
  }

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


#ifdef TRACE_RLC_AM_BO
gauthier's avatar
gauthier committed
93
  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
94 95 96
    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);
97 98
  }
#endif
gauthier's avatar
gauthier committed
99
  return rlc_pP->status_buffer_occupancy + rlc_pP->retransmission_buffer_occupancy + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead;
100 101
}
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
102
void rlc_am_release (rlc_am_entity_t *rlc_pP)
103 104 105 106 107
//-----------------------------------------------------------------------------
{

}
//-----------------------------------------------------------------------------
108 109 110 111 112 113 114 115
void config_req_rlc_am (
    module_id_t     enb_module_idP,
    module_id_t     ue_module_idP,
    frame_t         frameP,
    eNB_flag_t      eNB_flagP,
    srb_flag_t      srb_flagP,
    rlc_am_info_t  *config_am_pP,
    rb_id_t         rb_idP)
116 117
{
//-----------------------------------------------------------------------------
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
    rlc_union_t       *rlc_union_p = NULL;
    rlc_am_entity_t *rlc_p         = NULL;
    hash_key_t       key           = RLC_COLL_KEY_VALUE(enb_module_idP, ue_module_idP, eNB_flagP, rb_idP, srb_flagP);
    hashtable_rc_t   h_rc;

    h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
    if (h_rc == HASH_TABLE_OK) {
        rlc_p = &rlc_union_p->rlc.am;
        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 > 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,
            rb_idP);
        rlc_am_init(rlc_p,frameP);
        rlc_am_set_debug_infos(rlc_p, frameP, eNB_flagP, enb_module_idP, ue_module_idP, rb_idP, srb_flagP);
        rlc_am_configure(rlc_p,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);
gauthier's avatar
gauthier committed
150
    } else {
151 152 153 154 155 156 157 158
        LOG_E(RLC, "[FRAME %5u][%s][RRC][MOD %u/%u][][--- CONFIG_REQ  --->][RLC_AM][MOD %u/%u][RB %u] RLC NOT FOUND\n",
            frameP,
            (eNB_flagP) ? "eNB" : "UE",
            enb_module_idP,
            ue_module_idP,
            enb_module_idP,
            ue_module_idP,
            rb_idP);
gauthier's avatar
gauthier committed
159
    }
160
}
gauthier's avatar
gauthier committed
161 162 163 164 165 166
uint32_t pollPDU_tab[PollPDU_pInfinity+1]={4,8,16,32,64,128,256,1024};  // What is PollPDU_pInfinity??? 1024 for now
uint32_t maxRetxThreshold_tab[UL_AM_RLC__maxRetxThreshold_t32+1]={1,2,3,4,6,8,16,32};
uint32_t pollByte_tab[PollByte_spare1]={25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,10000};  // What is PollByte_kBinfinity??? 10000 for now
uint32_t PollRetransmit_tab[T_PollRetransmit_spare9]={5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500};
uint32_t am_t_Reordering_tab[T_Reordering_spare1]={0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200};
uint32_t t_StatusProhibit_tab[T_StatusProhibit_spare8]={0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500};
167 168

//-----------------------------------------------------------------------------
169 170 171 172 173 174 175 176
void config_req_rlc_am_asn1 (
    const module_id_t             enb_module_idP,
    const module_id_t             ue_module_idP,
    const frame_t                 frameP,
    const eNB_flag_t              eNB_flagP,
    const srb_flag_t              srb_flagP,
    const struct RLC_Config__am  * const config_am_pP,
    const rb_id_t                 rb_idP)
177 178
{
//-----------------------------------------------------------------------------
179 180 181 182 183 184 185 186 187 188 189 190 191 192 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 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
  rlc_union_t     *rlc_union_p   = NULL;
  rlc_am_entity_t *rlc_p         = NULL;
  hash_key_t       key           = RLC_COLL_KEY_VALUE(enb_module_idP, ue_module_idP, eNB_flagP, rb_idP, srb_flagP);
  hashtable_rc_t   h_rc;

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
  if (h_rc == HASH_TABLE_OK) {
      rlc_p = &rlc_union_p->rlc.am;
      if ((config_am_pP->ul_AM_RLC.maxRetxThreshold <= UL_AM_RLC__maxRetxThreshold_t32) &&
          (config_am_pP->ul_AM_RLC.pollPDU<=PollPDU_pInfinity) &&
          (config_am_pP->ul_AM_RLC.pollByte<PollByte_spare1) &&
          (config_am_pP->ul_AM_RLC.t_PollRetransmit<T_PollRetransmit_spare9) &&
          (config_am_pP->dl_AM_RLC.t_Reordering<T_Reordering_spare1) &&
          (config_am_pP->dl_AM_RLC.t_StatusProhibit<T_StatusProhibit_spare8) ){

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

          rlc_am_init(rlc_p,frameP);
          rlc_am_set_debug_infos(rlc_p, frameP, eNB_flagP, srb_flagP, enb_module_idP, ue_module_idP, rb_idP);
          rlc_am_configure(rlc_p,
              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);
      }
  } else {
      LOG_E(RLC, "[FRAME %5u][%s][RRC][MOD %u/%u][][--- CONFIG_REQ  --->][RLC_AM][MOD %u/%u][RB %u] RLC NOT FOUND\n",
          frameP,
          (eNB_flagP) ? "eNB" : "UE",
          enb_module_idP,
          ue_module_idP,
          enb_module_idP,
          ue_module_idP,
          rb_idP);
  }
246 247 248
}

  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
249
void rlc_am_stat_req     (rlc_am_entity_t *rlc_pP,
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
                              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
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
    *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;
306 307 308 309

}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
310
rlc_am_get_pdus (rlc_am_entity_t *rlc_pP, frame_t frameP)
311 312 313 314 315 316 317 318 319 320 321
{
//-----------------------------------------------------------------------------
  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
322
    switch (rlc_pP->protocol_state) {
323 324 325 326 327 328

        case RLC_NULL_STATE:
            break;

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

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

gauthier's avatar
gauthier committed
387 388
                    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
389 390 391 392 393 394 395 396
                        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
397 398 399 400 401 402
                        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;
403

gauthier's avatar
gauthier committed
404 405
                        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;
406 407 408

                        tx_data_pdu_management->retx_count += 1;
                        return;
gauthier's avatar
gauthier committed
409
                    } 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
410
                        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",
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
                                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,
                                rlc_pP->nb_bytes_requested_by_mac,
                                tx_data_pdu_management->header_and_payload_size,
                                tx_data_pdu_management->retx_count,
                                tx_data_pdu_management->nack_so_start,
                                tx_data_pdu_management->nack_so_stop);

                        mem_block_t* copy = rlc_am_retransmit_get_subsegment(
                                rlc_pP,
                                frameP,
                                rlc_pP->first_retrans_pdu_sn,
                                &rlc_pP->nb_bytes_requested_by_mac);
gauthier's avatar
gauthier committed
428 429 430 431 432 433 434 435 436
                        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
437 438 439
                        rlc_pP->stat_tx_data_pdu                   += 1;
                        rlc_pP->stat_tx_retransmit_pdu             += 1;
                        rlc_pP->stat_tx_retransmit_pdu_by_status   += 1;
440 441 442
                        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
443
                        list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
444 445 446 447
                    } else {
                        break;
                    }
                    // update first_retrans_pdu_sn
gauthier's avatar
gauthier committed
448 449 450
                    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
451 452 453 454 455 456 457
                        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);
458 459 460
                    };

                    display_flag = 1;
gauthier's avatar
gauthier committed
461
                    if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
462
                        // no more pdu to be retransmited
gauthier's avatar
gauthier committed
463
                        rlc_pP->first_retrans_pdu_sn = -1;
464
                        display_flag = 0;
gauthier's avatar
gauthier committed
465 466 467 468 469 470
                        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);
471 472
                    }
                    if (display_flag > 0) {
gauthier's avatar
gauthier committed
473 474 475 476 477 478 479
                        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);
480 481 482 483
                    }
                    return;

/* ONLY ONE TB PER TTI
gauthier's avatar
gauthier committed
484
                    if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
485
#ifdef TRACE_RLC_AM_TX
gauthier's avatar
gauthier committed
486
                      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);
487 488 489 490 491
#endif
                      break;
                    }*/
                }
            }
gauthier's avatar
gauthier committed
492 493 494 495 496
            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;
497
                    rlc_pP->stat_tx_data_bytes                 += (((struct mac_tb_req*)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size);
498 499 500
                    return;
                }
            }
gauthier's avatar
gauthier committed
501 502
            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);
503 504
                return;
            } else {
gauthier's avatar
gauthier committed
505 506 507 508 509 510
                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
511
                if (rlc_pP->pdus_to_mac_layer.head != NULL) {
512 513
                    LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
                }
gauthier's avatar
gauthier committed
514 515
                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);
516
                }
gauthier's avatar
gauthier committed
517 518
                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);
519 520 521 522 523 524
                }
                LOG_D(RLC, "\n");
            }
            break;

        default:
gauthier's avatar
gauthier committed
525 526 527 528 529 530 531
            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);
532 533 534 535
    }
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
536
rlc_am_rx (void *arg_pP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
537 538 539
{
//-----------------------------------------------------------------------------

gauthier's avatar
gauthier committed
540
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
541 542 543 544

  switch (rlc->protocol_state) {

      case RLC_NULL_STATE:
gauthier's avatar
gauthier committed
545
       LOG_N(RLC, "[RLC_AM %p] ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", arg_pP);
546 547 548 549
        list_free (&data_indP.data);
        break;

      case RLC_DATA_TRANSFER_READY_STATE:
gauthier's avatar
gauthier committed
550
        rlc_am_receive_routing (rlc, frameP, eNB_flagP, data_indP);
551 552 553 554 555 556 557 558 559
        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
560
rlc_am_mac_status_indication (void *rlc_pP, frame_t frameP, uint16_t tb_sizeP, struct mac_status_ind tx_statusP)
561 562 563
{
//-----------------------------------------------------------------------------
  struct mac_status_resp  status_resp;
gauthier's avatar
gauthier committed
564 565 566
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
567
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
568

569 570 571 572 573
  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;
574 575
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

gauthier's avatar
gauthier committed
576 577 578 579
  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);
580
  }
gauthier's avatar
gauthier committed
581
  rlc->last_frame_status_indication = frameP;
582 583 584

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

gauthier's avatar
gauthier committed
585
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(rlc,frameP);
586

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

gauthier's avatar
gauthier committed
589 590 591 592
          //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;

gauthier's avatar
gauthier committed
593
          status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time :  (uint32_t)(0xffffffff - diff_time + frameP) ;
gauthier's avatar
gauthier committed
594 595 596 597 598 599

          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)  {
600
           status_resp.head_sdu_is_segmented = 0;
gauthier's avatar
gauthier committed
601 602 603 604 605
          }
          else {
              status_resp.head_sdu_is_segmented = 1;
          }

606 607
  } else {
  }
608 609


610 611
#ifdef TRACE_RLC_AM_TX_STATUS
  if (tb_sizeP > 0) {
gauthier's avatar
gauthier committed
612 613 614 615 616 617 618 619
      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);
620
      /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
621
          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
622
rlc->rb_id, frameP, tx_statusP.no_pdu);
623 624
      }
      if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
gauthier's avatar
gauthier committed
625
          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
626
frameP, tx_statusP.no_pdu);
627 628 629 630 631 632 633
      }*/
  }
#endif
  return status_resp;
}
//-----------------------------------------------------------------------------
struct mac_data_req
gauthier's avatar
gauthier committed
634
rlc_am_mac_data_request (void *rlc_pP, frame_t frameP)
635 636 637
{
//-----------------------------------------------------------------------------
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
638 639 640 641 642 643
  rlc_am_entity_t *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
  unsigned int nb_bytes_requested_by_mac = ((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac;
#ifdef TRACE_RLC_AM_PDU
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
644
  tb_size_t           tb_size_in_bytes;
gauthier's avatar
gauthier committed
645 646 647
  int                 num_nack;
  char                message_string[9000];
  size_t              message_string_size = 0;
648
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
649
  MessageDef         *msg_p;
650
#   endif
gauthier's avatar
gauthier committed
651 652
  int                 octet_index, index;
#endif
653

gauthier's avatar
gauthier committed
654
  rlc_am_get_pdus (rlc_pP,frameP);
655 656

  list_init (&data_req.data, NULL);
gauthier's avatar
gauthier committed
657 658
  list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
  //((rlc_am_entity_t *) rlc_pP)->tx_pdus += data_req.data.nb_elements;
659
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
gauthier's avatar
gauthier committed
660 661 662 663 664 665 666
      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);
667
  }
gauthier's avatar
gauthier committed
668 669
  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;
670

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

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

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

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

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

777 778 779 780 781
                  if (l_rlc_p->is_enb) {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->enb_module_id, msg_p);
                  } else {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->ue_module_id + NB_eNB_INST, msg_p);
                  }
gauthier's avatar
gauthier committed
782
#   endif
783 784
              }
          }
gauthier's avatar
gauthier committed
785
          tb_p = tb_p->next;
786 787
      }
  }
gauthier's avatar
gauthier committed
788
#endif
789 790 791 792
  return data_req;
}
//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
793
rlc_am_mac_data_indication (void *rlc_pP, frame_t frameP, eNB_flag_t eNB_flagP, struct mac_data_ind data_indP)
794 795
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
796 797
    rlc_am_entity_t           *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
    /*rlc_am_control_pdu_info_t control_pdu_info;
798
    int                       num_li;
gauthier's avatar
gauthier committed
799
    int16_t                     tb_size;*/
gauthier's avatar
gauthier committed
800 801 802 803
#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;
804
  sdu_size_t          tb_size_in_bytes;
gauthier's avatar
gauthier committed
805 806 807
  int                 num_nack;
  char                message_string[7000];
  size_t              message_string_size = 0;
808
#   if defined(ENABLE_ITTI)
gauthier's avatar
gauthier committed
809
  MessageDef         *msg_p;
810
#   endif
gauthier's avatar
gauthier committed
811 812
  int                 octet_index, index;
#endif
813

gauthier's avatar
gauthier committed
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 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
#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);

884 885 886 887 888
                  if (l_rlc_p->is_enb) {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->enb_module_id, msg_p);
                  } else {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->ue_module_id + NB_eNB_INST, msg_p);
                  }
gauthier's avatar
gauthier committed
889
# else
890
                  rlc_am_display_data_pdu_infos(l_rlc_p, frameP, &pdu_info);
gauthier's avatar
gauthier committed
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918
# 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);

919 920 921 922 923
                  if (l_rlc_p->is_enb) {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->enb_module_id, msg_p);
                  } else {
                      itti_send_msg_to_task(TASK_UNKNOWN, l_rlc_p->ue_module_id + NB_eNB_INST, msg_p);
                  }
gauthier's avatar
gauthier committed
924 925 926 927 928 929 930 931
#   endif
              }
          }
          tb_p = tb_p->next;
      }
  }
#endif
    rlc_am_rx (rlc_pP, frameP, eNB_flagP, data_indP);
932 933 934 935
}

//-----------------------------------------------------------------------------
void
gauthier's avatar
gauthier committed
936
rlc_am_data_req (void *rlc_pP, frame_t frameP, mem_block_t * sdu_pP)
937 938
{
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
939
  rlc_am_entity_t  *rlc_p = (rlc_am_entity_t *) rlc_pP;
gauthier's avatar
gauthier committed
940 941 942 943
  uint32_t             mui;
  uint16_t             data_offset;
  uint16_t             data_size;
  uint8_t              conf;
944 945


gauthier's avatar
gauthier committed
946 947 948
  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)) {
949 950


gauthier's avatar
gauthier committed
951 952
      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;
953

gauthier's avatar
gauthier committed
954 955 956 957
      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;
958 959


gauthier's avatar
gauthier committed
960 961
     rlc_p->stat_tx_pdcp_sdu   += 1;
     rlc_p->stat_tx_pdcp_bytes += data_size;
962

gauthier's avatar
gauthier committed
963 964 965
      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;
966

gauthier's avatar
gauthier committed
967 968 969
      rlc_p->sdu_buffer_occupancy += data_size;
      rlc_p->nb_sdu += 1;
      rlc_p->nb_sdu_no_segmented += 1;
970

gauthier's avatar
gauthier committed
971
      rlc_p->input_sdus[rlc_p->next_sdu_index].first_byte = (uint8_t*)(&sdu_pP->data[data_offset]);
gauthier's avatar
gauthier committed
972 973 974 975 976 977 978 979 980 981 982 983 984
      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
985 986 987 988 989 990 991 992 993 994 995 996
      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);
997
  } else {
gauthier's avatar
gauthier committed
998 999 1000 1001 1002 1003 1004 1005 1006 1007
      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
1008 1009 1010 1011
      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
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
#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
1024 1025
  }
}