rlc_am.c 65.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
gauthier's avatar
gauthier committed
21

22 23
#define RLC_AM_MODULE 1
#define RLC_AM_C 1
24 25 26 27
//-----------------------------------------------------------------------------
#include "platform_types.h"
#include "platform_constants.h"
//-----------------------------------------------------------------------------
28
#if ENABLE_ITTI
gauthier's avatar
gauthier committed
29 30
# include "intertask_interface.h"
#endif
31
#include "assertions.h"
knopp's avatar
mutexes  
knopp committed
32
#include "msc.h"
33
#include "hashtable.h"
34 35 36 37 38 39 40 41 42 43
#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"
44

gauthier's avatar
gauthier committed
45

fnabet's avatar
fnabet committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 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
//-----------------------------------------------------------------------------
uint32_t
rlc_am_get_status_pdu_buffer_occupancy(
  rlc_am_entity_t * const      rlc_pP){

	//Compute Max Status PDU size according to what has been received and not received in the window [vrR vrMS[

    // minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1
	uint32_t                    nb_bits_to_transmit	  = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
	mem_block_t                  *cursor_p              = rlc_pP->receiver_buffer.head;
    rlc_am_pdu_info_t            *pdu_info_cursor_p     = NULL;
    int                           waited_so             = 0;

	rlc_sn_t sn_cursor = rlc_pP->vr_r;
	rlc_sn_t sn_prev = rlc_pP->vr_r;
	rlc_sn_t sn_end = rlc_pP->vr_ms;
	boolean_t	segment_loop_end	  = false;


	if (sn_prev != sn_end)
	{
		while ((RLC_AM_DIFF_SN(sn_prev,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)) && (cursor_p != NULL))
		{
			pdu_info_cursor_p     = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
			sn_cursor             = pdu_info_cursor_p->sn;

			// Add holes between sn_prev and sn_cursor
			while ((sn_prev != sn_cursor) && (sn_prev != sn_end))
			{
				  /* Add 1 NACK_SN + E1 + E2 */
				  nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
				  sn_prev = RLC_AM_NEXT_SN(sn_prev);
			} //end while (sn_prev != sn_cursor)

			/* Handle case sn_cursor is partially received */
			/* Each gap will add NACK_SN + E1 + E2 + SOStart + SOEnd */
			if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) && (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)))
			{
                 /* Check lsf */
				  segment_loop_end = (pdu_info_cursor_p->lsf == 1);

	    		  /* Fill for [0 SO[ if SO not null */
	    		  if (pdu_info_cursor_p->so) {
	    			  nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
	                  waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
	                  /* Go to next segment */
	                  cursor_p = cursor_p->next;
	                  if (cursor_p != NULL)
	                  {
		                  pdu_info_cursor_p     = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
	                  }
	    		  }
	    		  else {
	        		  waited_so = pdu_info_cursor_p->payload_size;
	    		  }

	    		  /* Fill following gaps if any */
	    		  while (!segment_loop_end)
	    		  {
	    			  if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor))
	    			  {
		                  /* Check lsf */
	    				  segment_loop_end = (pdu_info_cursor_p->lsf == 1);

            			  if (waited_so < pdu_info_cursor_p->so) {
    	                      nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
            			  }
            			  else {
            				  /* contiguous segment: only update waited_so */
            				  /* Assuming so and payload_size updated according to duplication removal done at reception ... */
            				  waited_so += pdu_info_cursor_p->payload_size;
            			  }

            			  /* Go to next received PDU or PDU Segment */
            			  cursor_p = cursor_p->next;
    	                  if (cursor_p != NULL)
    	                  {
    		                  pdu_info_cursor_p     = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
    	                  }
	    			  }
	    			  else
	    			  {
	    				  /* Fill last gap assuming LSF is not received */
	    				  nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
	    				  segment_loop_end = true;
	    			  }
	    		  } // end while (!segment_loop_end)
			} // end if segments
			else
			{
				 /* Go to next received PDU or PDU Segment */
				 cursor_p = cursor_p->next;
			}

			sn_prev = RLC_AM_NEXT_SN(sn_cursor);
		}
	} // end if (sn_prev != sn_end)

	// round up to the greatest byte
	return ((nb_bits_to_transmit + 7) >> 3);

}

149
//-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
150
uint32_t
151
rlc_am_get_buffer_occupancy_in_bytes (
152 153
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const      rlc_pP)
154
{
gauthier's avatar
gauthier committed
155 156
  uint32_t max_li_overhead;
  uint32_t header_overhead;
157 158

  // priority of control trafic
Bilel's avatar
Bilel committed
159
  rlc_pP->status_buffer_occupancy = 0;
fnabet's avatar
fnabet committed
160 161
  if ((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK)) {
      rlc_pP->status_buffer_occupancy = rlc_am_get_status_pdu_buffer_occupancy(rlc_pP);
162
#if TRACE_RLC_AM_BO
163

fnabet's avatar
fnabet committed
164 165 166
      LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT" BO : CONTROL PDU %d bytes \n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
			rlc_pP->status_buffer_occupancy);
167 168

#endif
169 170 171
  }

  // data traffic
gauthier's avatar
gauthier committed
172
  if (rlc_pP->nb_sdu_no_segmented <= 1) {
173
    max_li_overhead = 0;
174
  } else {
fnabet's avatar
fnabet committed
175 176 177
  	/* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/
	  uint32_t num_li = rlc_pP->nb_sdu_no_segmented - 1;
      max_li_overhead = num_li + (num_li >> 1) + (num_li & 1);
178
  }
179

gauthier's avatar
gauthier committed
180
  if (rlc_pP->sdu_buffer_occupancy == 0) {
181
    header_overhead = 0;
182
  } else {
183
    header_overhead = 2;
184 185 186
  }


187
#if TRACE_RLC_AM_BO
188

189
  if ((rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead) > 0) {
190
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : STATUS  BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->status_buffer_occupancy);
191
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retrans_num_bytes_to_retransmit);
192 193
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : SDU     BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
194 195 196 197
          rlc_pP->sdu_buffer_occupancy,
          max_li_overhead,
          header_overhead,
          rlc_pP->nb_sdu_no_segmented);
198
  }
199

200
#endif
201
  return rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy + max_li_overhead + header_overhead;
202 203
}
//-----------------------------------------------------------------------------
204 205
void
rlc_am_release (
206 207 208
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const      rlc_pP
)
209
{
210
  // empty
211 212
}
//-----------------------------------------------------------------------------
213 214
void
config_req_rlc_am (
215 216 217
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t             srb_flagP,
  rlc_am_info_t  * const       config_am_pP,
218
  const rb_id_t                rb_idP,
219
  const logical_chan_id_t      chan_idP 
220
)
221
{
222 223
  rlc_union_t       *rlc_union_p = NULL;
  rlc_am_entity_t *l_rlc_p         = NULL;
224
  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
225 226 227 228 229 230 231
  hashtable_rc_t   h_rc;

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);

  if (h_rc == HASH_TABLE_OK) {
    l_rlc_p = &rlc_union_p->rlc.am;
    LOG_D(RLC,
232 233
          PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d)\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
234 235 236 237 238 239 240
          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);
    rlc_am_init(ctxt_pP, l_rlc_p);
241
    rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
242 243 244 245 246 247 248 249
    rlc_am_configure(ctxt_pP, l_rlc_p,
                     config_am_pP->max_retx_threshold,
                     config_am_pP->poll_pdu,
                     config_am_pP->poll_byte,
                     config_am_pP->t_poll_retransmit,
                     config_am_pP->t_reordering,
                     config_am_pP->t_status_prohibit);
  } else {
250 251
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ RLC NOT FOUND\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
252
  }
253
}
fnabet's avatar
fnabet committed
254
uint16_t pollPDU_tab[PollPDU_pInfinity+1]= {4,8,16,32,64,128,256,RLC_AM_POLL_PDU_INFINITE}; //PollPDU_pInfinity is chosen to 0xFFFF for now
255
uint32_t maxRetxThreshold_tab[UL_AM_RLC__maxRetxThreshold_t32+1]= {1,2,3,4,6,8,16,32};
fnabet's avatar
fnabet committed
256
uint32_t pollByte_tab[PollByte_spare1]= {25000,50000,75000,100000,125000,250000,375000,500000,750000,1000000,1250000,1500000,2000000,3000000,RLC_AM_POLL_BYTE_INFINITE}; // PollByte_kBinfinity is chosen to 0xFFFFFFFF for now
257 258 259
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};
260 261

//-----------------------------------------------------------------------------
262
void config_req_rlc_am_asn1 (
263 264 265
  const protocol_ctxt_t* const         ctxt_pP,
  const srb_flag_t                     srb_flagP,
  const struct RLC_Config__am  * const config_am_pP,
266
  const rb_id_t                        rb_idP,
267
  const logical_chan_id_t              chan_idP)
268
{
269
  rlc_union_t     *rlc_union_p   = NULL;
gauthier's avatar
gauthier committed
270
  rlc_am_entity_t *l_rlc_p         = NULL;
271
  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
272 273 274
  hashtable_rc_t   h_rc;

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
275

276
  if (h_rc == HASH_TABLE_OK) {
277 278 279 280 281 282 283 284 285
    l_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) ) {

gauthier's avatar
gauthier committed
286
      MSC_LOG_RX_MESSAGE(
287 288 289 290 291 292 293 294 295 296
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
        NULL,
        0,
        MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ t_PollRetx %u t_Reord %u t_StatusPro %u",
        MSC_AS_TIME_ARGS(ctxt_pP),
        PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
        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]);
gauthier's avatar
gauthier committed
297

298 299
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d)\n",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
300 301 302 303 304 305 306 307
            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]);

      rlc_am_init(ctxt_pP, l_rlc_p);
308
      rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
309 310 311 312 313 314 315 316
      rlc_am_configure(ctxt_pP, l_rlc_p,
                       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 {
gauthier's avatar
gauthier committed
317
      MSC_LOG_RX_DISCARDED_MESSAGE(
318 319 320 321 322 323 324
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
        NULL,
        0,
        MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ",
        MSC_AS_TIME_ARGS(ctxt_pP),
        PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p));
gauthier's avatar
gauthier committed
325

326
      LOG_D(RLC,
Cedric Roux's avatar
Cedric Roux committed
327
            PROTOCOL_RLC_AM_CTXT_FMT"ILLEGAL CONFIG_REQ (max_retx_threshold=%ld poll_pdu=%ld poll_byte=%ld t_poll_retransmit=%ld t_reord=%ld t_status_prohibit=%ld), RLC-AM NOT CONFIGURED\n",
328
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
329 330 331 332 333 334 335
            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);
    }
336
  } else {
337 338
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"CONFIG_REQ RLC NOT FOUND\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
339
  }
340 341
}

342
//-----------------------------------------------------------------------------
343
void rlc_am_stat_req (
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
  const protocol_ctxt_t* const         ctxt_pP,
  rlc_am_entity_t * const              rlc_pP,
  unsigned int* stat_tx_pdcp_sdu,
  unsigned int* stat_tx_pdcp_bytes,
  unsigned int* stat_tx_pdcp_sdu_discarded,
  unsigned int* stat_tx_pdcp_bytes_discarded,
  unsigned int* stat_tx_data_pdu,
  unsigned int* stat_tx_data_bytes,
  unsigned int* stat_tx_retransmit_pdu_by_status,
  unsigned int* stat_tx_retransmit_bytes_by_status,
  unsigned int* stat_tx_retransmit_pdu,
  unsigned int* stat_tx_retransmit_bytes,
  unsigned int* stat_tx_control_pdu,
  unsigned int* stat_tx_control_bytes,
  unsigned int* stat_rx_pdcp_sdu,
  unsigned int* stat_rx_pdcp_bytes,
  unsigned int* stat_rx_data_pdus_duplicate,
  unsigned int* stat_rx_data_bytes_duplicate,
  unsigned int* stat_rx_data_pdu,
  unsigned int* stat_rx_data_bytes,
  unsigned int* stat_rx_data_pdu_dropped,
  unsigned int* stat_rx_data_bytes_dropped,
  unsigned int* stat_rx_data_pdu_out_of_window,
  unsigned int* stat_rx_data_bytes_out_of_window,
  unsigned int* stat_rx_control_pdu,
  unsigned int* stat_rx_control_bytes,
  unsigned int* stat_timer_reordering_timed_out,
  unsigned int* stat_timer_poll_retransmit_timed_out,
  unsigned int* stat_timer_status_prohibit_timed_out)
373
{
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
  *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;
401 402 403 404

}
//-----------------------------------------------------------------------------
void
405
rlc_am_get_pdus (
406 407 408
  const protocol_ctxt_t* const ctxt_pP,
  rlc_am_entity_t * const      rlc_pP
)
409 410 411 412 413 414 415 416 417 418
{
  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.


419 420 421 422 423 424 425 426
  switch (rlc_pP->protocol_state) {

  case RLC_NULL_STATE:
    break;

  case RLC_DATA_TRANSFER_READY_STATE:

    // TRY TO SEND CONTROL PDU FIRST
fnabet's avatar
fnabet committed
427 428
    if ((rlc_pP->nb_bytes_requested_by_mac >= 2) &&
    		((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK))) {
429 430 431 432 433 434 435 436 437 438 439
      // 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.

fnabet's avatar
fnabet committed
440 441 442 443
      rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
      mem_block_t* pdu = list_remove_head(&rlc_pP->control_pdu_list);

      if (pdu) {
444
          list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
fnabet's avatar
fnabet committed
445
          RLC_AM_CLEAR_ALL_STATUS(rlc_pP->status_requested);
Bilel's avatar
Bilel committed
446
          rlc_pP->status_buffer_occupancy = 0;
447 448 449 450
          rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
          return;
        }
      }
fnabet's avatar
fnabet committed
451 452 453 454
      else {
              LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU (Available MAC Data %u)(T-PROHIBIT %u) (DELAY FLAG %u)\n",
                    PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
					rlc_pP->nb_bytes_requested_by_mac,rlc_pP->t_status_prohibit.ms_time_out,(rlc_pP->status_requested & RLC_AM_STATUS_TRIGGERED_DELAYED));
455 456 457 458 459 460 461
    }

    /*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);
        if (pdu != NULL {
            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);
462
    #if TRACE_RLC_AM_TX
463 464 465 466
                msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] SEND CONTROL PDU\n", ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, ctxt_pP->frame);
    #endif
                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;
467
            } else {
468
              stay_on_this_list = 0;
469
            }
470 471 472 473 474
        } else {
            stay_on_this_list = 0;
        }
    }*/
    // THEN TRY TO SEND RETRANS PDU
fnabet's avatar
fnabet committed
475
    // BUG FIX : they can be PDU to ReTx due to received NACK or 1 PDU (SN = vtS - 1) to ReTx due TPoll Expiry if Buffer Occupancy is null
476 477 478 479 480 481 482 483
    if (rlc_pP->first_retrans_pdu_sn >= 0) {
      rlc_am_tx_data_pdu_management_t* tx_data_pdu_management;

      // tx min 3 bytes because of the size of the RLC header
      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)) {

484
        tx_data_pdu_management = &rlc_pP->tx_data_pdu_buffer[rlc_pP->first_retrans_pdu_sn];
485

486 487
        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)) {
488
          mem_block_t* copy = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, rlc_pP->first_retrans_pdu_sn);
489 490
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RE-SEND DATA PDU SN %04d   %d BYTES\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
491 492 493 494 495 496 497 498 499 500 501 502
                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;

          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;

503
          tx_data_pdu_management->retx_count = tx_data_pdu_management->retx_count_next;
504 505
          return;
        } else if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac >= RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
506 507
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" 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",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
508 509 510 511 512 513 514 515 516 517 518 519
                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(
                                ctxt_pP,
                                rlc_pP,
                                rlc_pP->first_retrans_pdu_sn,
                                &rlc_pP->nb_bytes_requested_by_mac);
520 521
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SEGMENT OF DATA PDU SN %04d (NEW SO %05d)\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
                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);
          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);
          list_add_tail_eurecom (copy, &rlc_pP->pdus_to_mac_layer);
        } else {
          break;
        }

        // update first_retrans_pdu_sn
        while ((rlc_pP->first_retrans_pdu_sn != rlc_pP->vt_s) &&
538
               (!(rlc_pP->tx_data_pdu_buffer[rlc_pP->first_retrans_pdu_sn].flags.retransmit))) {
539
          rlc_pP->first_retrans_pdu_sn = (rlc_pP->first_retrans_pdu_sn+1) & RLC_AM_SN_MASK;
540 541
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn SN %04d\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
542 543 544 545 546 547 548 549 550
                rlc_pP->first_retrans_pdu_sn);
        };

        display_flag = 1;

        if (rlc_pP->first_retrans_pdu_sn == rlc_pP->vt_s) {
          // no more pdu to be retransmited
          rlc_pP->first_retrans_pdu_sn = -1;
          display_flag = 0;
551 552
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CLEAR first_retrans_pdu_sn\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
553 554 555
        }

        if (display_flag > 0) {
556 557
          LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" UPDATED first_retrans_pdu_sn %04d\n",
                PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
558 559 560 561 562 563 564
                rlc_pP->first_retrans_pdu_sn);
        }

        return;

        /* ONLY ONE TB PER TTI
                            if ((tx_data_pdu_management->retx_count >= 0) && (rlc_pP->nb_bytes_requested_by_mac < RLC_AM_MIN_SEGMENT_SIZE_REQUEST)) {
565
        #if TRACE_RLC_AM_TX
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
                              msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] BREAK LOOP ON RETRANSMISSION BECAUSE ONLY %d BYTES ALLOWED TO TRANSMIT BY MAC\n",ctxt_pP->frame,  ((rlc_am_entity_t *) rlc_pP)->module_id,((rlc_am_entity_t *) rlc_pP)->rb_id, rlc_pP->nb_bytes_requested_by_mac);
        #endif
                              break;
                            }*/
      }
    }

    if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
      rlc_am_segment_10(ctxt_pP, rlc_pP);
      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);
        return;
      }
    }

    if ((rlc_pP->pdus_to_mac_layer.head == NULL) &&
        (rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP)) &&
        (rlc_pP->nb_bytes_requested_by_mac > 2)) {
      rlc_am_retransmit_any_pdu(ctxt_pP, rlc_pP);
      return;
    } else {
590 591
      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" COULD NOT RETRANSMIT ANY PDU BECAUSE ",
            PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
592 593 594 595 596 597

      if (rlc_pP->pdus_to_mac_layer.head != NULL) {
        LOG_D(RLC, "THERE ARE SOME PDUS READY TO TRANSMIT ");
      }

      if (!(rlc_am_is_timer_poll_retransmit_timed_out(ctxt_pP, rlc_pP))) {
598 599
        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);
600 601 602 603 604 605
      }

      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);
      }
      LOG_D(RLC, "\n");
606
    }
607 608 609 610

    break;

  default:
611 612
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
613 614
          rlc_pP->protocol_state);
  }
615 616 617
}
//-----------------------------------------------------------------------------
void
618
rlc_am_rx (
619 620 621 622
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 arg_pP,
  struct mac_data_ind          data_indP
)
623
{
gauthier's avatar
gauthier committed
624
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
625 626 627

  switch (rlc->protocol_state) {

628
  case RLC_NULL_STATE:
Cedric Roux's avatar
Cedric Roux committed
629
    LOG_N(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP, rlc));
630 631
    list_free (&data_indP.data);
    break;
632

633 634 635
  case RLC_DATA_TRANSFER_READY_STATE:
    rlc_am_receive_routing (ctxt_pP, rlc, data_indP);
    break;
636

637
  default:
Cedric Roux's avatar
Cedric Roux committed
638
    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" TX UNKNOWN PROTOCOL STATE 0x%02X\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP, rlc), rlc->protocol_state);
639 640 641 642 643
  }
}

//-----------------------------------------------------------------------------
struct mac_status_resp
644
rlc_am_mac_status_indication (
645 646 647 648
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 rlc_pP,
  const uint16_t               tb_sizeP,
  struct mac_status_ind        tx_statusP)
649 650
{
  struct mac_status_resp  status_resp;
gauthier's avatar
gauthier committed
651 652 653
  uint16_t  sdu_size = 0;
  uint16_t  sdu_remaining_size = 0;
  int32_t diff_time=0;
gauthier's avatar
gauthier committed
654
  rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
655

656 657 658 659 660
  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;
661 662
  status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;

Cedric Roux's avatar
Cedric Roux committed
663 664 665 666 667 668 669 670 671
  /* TODO: remove this hack. Problem is: there is a race.
   * UE comes. SRB2 is configured via message to RRC.
   * At some point the RLC AM is created but not configured yet.
   * At this moment (I think) MAC calls mac_rlc_status_ind
   * which calls this function. But the init was not finished yet
   * and we have a crash below when testing mem_block != NULL.
   */
  if (rlc->input_sdus == NULL) return status_resp;

672
  if (rlc->last_absolute_subframe_status_indication != (PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP))) {
673 674 675
    rlc_am_check_timer_poll_retransmit(ctxt_pP, rlc);
    rlc_am_check_timer_reordering(ctxt_pP, rlc);
    rlc_am_check_timer_status_prohibit(ctxt_pP, rlc);
676
  }
677

678
  rlc->last_absolute_subframe_status_indication = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
679 680 681

  rlc->nb_bytes_requested_by_mac = tb_sizeP;

682
  status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc);
683

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

686 687 688
    //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 =   ctxt_pP->frame - ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_creation_time;
gauthier's avatar
gauthier committed
689

690
    status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time :  (uint32_t)(0xffffffff - diff_time + ctxt_pP->frame) ;
gauthier's avatar
gauthier committed
691

692 693
    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;
gauthier's avatar
gauthier committed
694

695 696 697 698 699 700 701
    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;
    }
gauthier's avatar
gauthier committed
702

703
  } else {
704 705 706 707 708 709 710 711
	  /* Not so many possibilities ... */
	  /* either buffer_occupancy_in_bytes = 0 and that's it */
	  /* or we have segmented all received SDUs and buffer occupancy is then made of retransmissions and/or status pdu pending */
	  /* then consider only retransmission buffer for the specific BO values used by eNB scheduler (not used up to now...) */
	  if (rlc->retrans_num_bytes_to_retransmit) {
		  status_resp.buffer_occupancy_in_pdus = rlc->retrans_num_pdus;
		  status_resp.head_sdu_remaining_size_to_send = rlc->retrans_num_bytes_to_retransmit;
		  status_resp.head_sdu_is_segmented = 1;
712
	  }
713
  }
714
#if MESSAGE_CHART_GENERATOR_RLC_MAC
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
  MSC_LOG_RX_MESSAGE(
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_MAC_ENB:MSC_MAC_UE,
    NULL,0,
    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS-IND %u",
    MSC_AS_TIME_ARGS(ctxt_pP),
    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc),
    tb_sizeP);
  MSC_LOG_TX_MESSAGE(
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_MAC_ENB:MSC_MAC_UE,
    NULL,0,
    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS-RESP BO:%u/n%u(%u)  %s sdu remain %u",
    MSC_AS_TIME_ARGS(ctxt_pP),
    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc),
    status_resp.buffer_occupancy_in_bytes,
    status_resp.buffer_occupancy_in_pdus,rlc->nb_sdu,
    (status_resp.head_sdu_is_segmented)?"sdu seg":"sdu not seg",
    status_resp.head_sdu_remaining_size_to_send);
#endif
735

736
#if TRACE_RLC_AM_TX_STATUS
737

738
  if (tb_sizeP > 0) {
739 740
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
741 742 743 744 745 746 747 748 749 750
          tb_sizeP,
          status_resp.buffer_occupancy_in_bytes);
    /*if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
        msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] MAC_STATUS_INDICATION  TX STATUS   SUCCESSFUL %d PDUs\n",rlc->module_id,
    rlc->rb_id, ctxt_pP->frame, tx_statusP.no_pdu);
    }
    if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
        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,
    ctxt_pP->frame, tx_statusP.no_pdu);
    }*/
751
  }
752

753 754 755
#endif
  return status_resp;
}
756 757 758 759 760 761 762 763 764 765 766

//-----------------------------------------------------------------------------
void
rlc_am_set_nb_bytes_requested_by_mac (
  void * const            rlc_pP,
  const tb_size_t         tb_sizeP
)
{
	((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP;
}

767 768
//-----------------------------------------------------------------------------
struct mac_data_req
769
rlc_am_mac_data_request (
770 771 772
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 rlc_pP
)
773 774
{
  struct mac_data_req data_req;
gauthier's avatar
gauthier committed
775 776
  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;
777
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
gauthier's avatar
gauthier committed
778 779 780
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
781
  tb_size_t           tb_size_in_bytes;
gauthier's avatar
gauthier committed
782 783 784
  int                 num_nack;
  char                message_string[9000];
  size_t              message_string_size = 0;
785
#   if ENABLE_ITTI
gauthier's avatar
gauthier committed
786
  MessageDef         *msg_p;
787
#   endif
gauthier's avatar
gauthier committed
788
  int                 octet_index, index;
Cedric Roux's avatar
Cedric Roux committed
789 790 791 792 793 794
  /* for no gcc warnings */
  (void)num_nack;
  (void)message_string;
  (void)message_string_size;
  (void)octet_index;
  (void)index;
gauthier's avatar
gauthier committed
795
#endif
796 797

  list_init (&data_req.data, NULL);
798
  rlc_am_get_pdus (ctxt_pP, l_rlc_p);
gauthier's avatar
gauthier committed
799
  list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
800

gauthier's avatar
gauthier committed
801
  //((rlc_am_entity_t *) rlc_pP)->tx_pdus += data_req.data.nb_elements;
802
  if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
803 804
    LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n",
          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
805 806
          nb_bytes_requested_by_mac,
          data_req.data.nb_elements);
807
  }
808

809
  data_req.buffer_occupancy_in_bytes   = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, l_rlc_p);
gauthier's avatar
gauthier committed
810
  data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
811

812
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
813

814
  if (data_req.data.nb_elements > 0) {
gauthier's avatar
gauthier committed
815

816
    tb_p = data_req.data.head;
gauthier's avatar
gauthier committed
817

818
    while (tb_p != NULL) {
gauthier's avatar
gauthier committed
819

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

823
      if ((((struct mac_tb_req *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
824
        if (rlc_am_get_data_pdu_infos(ctxt_pP,l_rlc_p,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
825
#if MESSAGE_CHART_GENERATOR
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
          message_string_size = 0;
          message_string_size += sprintf(&message_string[message_string_size],
                                         MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" DATA SN %u size %u RF %u P %u FI %u",
                                         MSC_AS_TIME_ARGS(ctxt_pP),
                                         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
                                         pdu_info.sn,
                                         tb_size_in_bytes,
                                         pdu_info.rf,
                                         pdu_info.p,
                                         pdu_info.fi);

          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], "| HE:");

            for (index=0; index < pdu_info.num_li; index++) {
gauthier's avatar
gauthier committed
846
              message_string_size += sprintf(&message_string[message_string_size], " LI %u", pdu_info.li_list[index]);
847 848 849
            }
          }

gauthier's avatar
gauthier committed
850
          MSC_LOG_TX_MESSAGE(
851 852 853 854 855 856 857
            (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
            (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_UE:MSC_RLC_ENB,
            (char*)rlc_am_pdu_sn_10_p,
            tb_size_in_bytes,
            message_string);

#endif
858
#   if ENABLE_ITTI
859
          message_string_size = 0;
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
          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");
gauthier's avatar
gauthier committed
901
              }
902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927

              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 (ctxt_pP->enb_flag > 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);

928
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
929 930 931 932 933 934

# else
          rlc_am_display_data_pdu_infos(ctxt_pP, l_rlc_p, &pdu_info);
# endif
        }
      } else {
935
        if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &l_rlc_p->control_pdu_info) >= 0) {
936
          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!
937
#if MESSAGE_CHART_GENERATOR
938 939
          message_string_size = 0;
          message_string_size += sprintf(&message_string[message_string_size],
gauthier's avatar
gauthier committed
940
                                         MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS ACK_SN %u",
941 942
                                         MSC_AS_TIME_ARGS(ctxt_pP),
                                         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
943
                                         l_rlc_p->control_pdu_info.ack_sn);
gauthier's avatar
gauthier committed
944

945 946
          for (num_nack = 0; num_nack < l_rlc_p->control_pdu_info.num_nack; num_nack++) {
            if (l_rlc_p->control_pdu_info.nack_list[num_nack].e2) {
947
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %u SO START %u SO END %u",
948 949 950
            		  l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_start,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_end);
951 952 953

            } else {
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %u",
954
            		  l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn);
955 956 957
            }
          }

gauthier's avatar
gauthier committed
958
          MSC_LOG_TX_MESSAGE(
959 960 961 962 963 964 965
            (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
            (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_UE:MSC_RLC_ENB,
            (char*)rlc_am_pdu_sn_10_p,
            tb_size_in_bytes,
            message_string);

#endif
966
#   if ENABLE_ITTI
967
          message_string_size = 0;
968 969 970 971
          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");
972 973 974 975
          message_string_size += sprintf(&message_string[message_string_size], "  D/C       : %u\n", l_rlc_p->control_pdu_info.d_c);
          message_string_size += sprintf(&message_string[message_string_size], "  CPT       : %u\n", l_rlc_p->control_pdu_info.cpt);
          message_string_size += sprintf(&message_string[message_string_size], "  ACK_SN    : %u\n", l_rlc_p->control_pdu_info.ack_sn);
          message_string_size += sprintf(&message_string[message_string_size], "  E1        : %u\n", l_rlc_p->control_pdu_info.e1);
976

977 978
          for (num_nack = 0; num_nack < l_rlc_p->control_pdu_info.num_nack; num_nack++) {
            if (l_rlc_p->control_pdu_info.nack_list[num_nack].e2) {
979
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d SO START %05d SO END %05d",
980 981 982
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_start,
                                             l_rlc_p->control_pdu_info.nack_list[num_nack].so_end);
983
            } else {
984
              message_string_size += sprintf(&message_string[message_string_size], "  NACK SN %04d",  l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn);
985
            }
986
          }
987 988 989 990 991

          msg_p = itti_alloc_new_message_sized (ctxt_pP->enb_flag > 0 ? TASK_RLC_ENB:TASK_RLC_UE , RLC_AM_STATUS_PDU_REQ, message_string_size + sizeof (IttiMsgText));
          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);

992
          itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
993 994 995

#   endif
        }
996
      }
997 998 999

      tb_p = tb_p->next;
    }
1000
  }
1001

gauthier's avatar
gauthier committed
1002
#endif
1003 1004 1005 1006
  return data_req;
}
//-----------------------------------------------------------------------------
void
1007
rlc_am_mac_data_indication (
1008 1009 1010 1011
  const protocol_ctxt_t* const ctxt_pP,
  void * const                 rlc_pP,
  struct mac_data_ind          data_indP
)
1012
{
1013
  rlc_am_entity_t*           l_rlc_p = (rlc_am_entity_t*) rlc_pP;
1014 1015 1016
  /*rlc_am_control_pdu_info_t control_pdu_info;
  int                       num_li;
  int16_t                     tb_size;*/
1017
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
gauthier's avatar
gauthier committed
1018 1019 1020
  rlc_am_pdu_info_t   pdu_info;
  rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
  mem_block_t        *tb_p;
1021
  sdu_size_t          tb_size_in_bytes;
gauthier's avatar
gauthier committed
1022 1023 1024
  int                 num_nack;
  char                message_string[7000];
  size_t              message_string_size = 0;
1025
#   if ENABLE_ITTI
gauthier's avatar
gauthier committed
1026
  MessageDef         *msg_p;
1027
#   endif
gauthier's avatar
gauthier committed
1028
  int                 octet_index, index;
Cedric Roux's avatar
Cedric Roux committed
1029 1030 1031 1032 1033 1034
  /* for no gcc warnings */
  (void)num_nack;
  (void)message_string;
  (void)message_string_size;
  (void)octet_index;
  (void)index;
gauthier's avatar
gauthier committed
1035
#endif
1036

1037 1038
  (void)l_rlc_p; /* avoid gcc warning "unused variable" */

1039
#if TRACE_RLC_AM_PDU || MESSAGE_CHART_GENERATOR
1040

gauthier's avatar
gauthier committed
1041 1042
  if (data_indP.data.nb_elements > 0) {

1043
    tb_p = data_indP.data.head;
gauthier's avatar
gauthier committed
1044

1045
    while (tb_p != NULL) {
gauthier's avatar
gauthier committed
1046

1047 1048
      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;
gauthier's avatar
gauthier committed
1049

1050
      if ((((struct mac_tb_ind *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
1051
        if (rlc_am_get_data_pdu_infos(ctxt_pP,l_rlc_p,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
1052
#if MESSAGE_CHART_GENERATOR
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064