pdcp.c 72.5 KB
Newer Older
1 2 3 4 5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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
 */
21 22 23

/*! \file pdcp.c
 * \brief pdcp interface with RLC
24
 * \author Navid Nikaein and Lionel GAUTHIER
25
 * \date 2009-2012
26
 * \email navid.nikaein@eurecom.fr
27 28 29 30
 * \version 1.0
 */

#define PDCP_C
31 32
//#define DEBUG_PDCP_FIFO_FLUSH_SDU

33
#include "assertions.h"
34
#include "hashtable.h"
35 36 37 38 39
#include "pdcp.h"
#include "pdcp_util.h"
#include "pdcp_sequence_manager.h"
#include "LAYER2/RLC/rlc.h"
#include "LAYER2/MAC/extern.h"
40
#include "RRC/LITE/proto.h"
41 42 43
#include "pdcp_primitives.h"
#include "OCG.h"
#include "OCG_extern.h"
44
#include "otg_rx.h"
45 46 47 48
#include "UTIL/LOG/log.h"
#include <inttypes.h>
#include "platform_constants.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
gauthier's avatar
gauthier committed
49
#include "msc.h"
50

51 52 53 54
#if defined(ENABLE_SECURITY)
# include "UTIL/OSA/osa_defs.h"
#endif

55 56 57 58
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

59
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
60
#  include "gtpv1u_eNB_task.h"
61
#  include "gtpv1u.h"
62 63
#endif

64 65
extern int otg_enabled;

66 67
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
68 69 70 71 72 73 74 75 76

//-----------------------------------------------------------------------------
/*
 * If PDCP_UNIT_TEST is set here then data flow between PDCP and RLC is broken
 * and PDCP has no longer anything to do with RLC. In this case, after it's handed
 * an SDU it appends PDCP header and returns (by filling in incoming pointer parameters)
 * this mem_block_t to be dissected for testing purposes. For further details see test
 * code at targets/TEST/PDCP/test_pdcp.c:test_pdcp_data_req()
 */
77
boolean_t pdcp_data_req(
78
  protocol_ctxt_t*  ctxt_pP,
79 80 81 82 83 84
  const srb_flag_t     srb_flagP,
  const rb_id_t        rb_idP,
  const mui_t          muiP,
  const confirm_t      confirmP,
  const sdu_size_t     sdu_buffer_sizeP,
  unsigned char *const sdu_buffer_pP,
85 86 87
  const pdcp_transmission_mode_t modeP
)
//-----------------------------------------------------------------------------
88
{
89

gauthier's avatar
gauthier committed
90
  pdcp_t            *pdcp_p          = NULL;
91 92 93 94 95
  uint8_t            i               = 0;
  uint8_t            pdcp_header_len = 0;
  uint8_t            pdcp_tailer_len = 0;
  uint16_t           pdcp_pdu_size   = 0;
  uint16_t           current_sn      = 0;
gauthier's avatar
gauthier committed
96 97
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
98
  boolean_t          ret             = TRUE;
gauthier's avatar
gauthier committed
99

100 101
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
102 103
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
gauthier's avatar
gauthier committed
104
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
105
  CHECK_CTXT_ARGS(ctxt_pP);
106

Cedric Roux's avatar
Cedric Roux committed
107 108 109 110 111
#if T_TRACER
  if (ctxt_pP->enb_flag != ENB_FLAG_NO)
    T(T_ENB_PDCP_DL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
#endif

112 113 114 115 116 117 118 119
  if (sdu_buffer_sizeP == 0) {
    LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
    return FALSE;
  }

  /*
   * XXX MAX_IP_PACKET_SIZE is 4096, shouldn't this be MAX SDU size, which is 8188 bytes?
   */
120
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
121 122
          sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
  
123
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
124
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
125
  } else {
126
    if (srb_flagP) {
nikaeinn's avatar
nikaeinn committed
127
      AssertError (rb_idP < 3, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
128
    } else {
129
      AssertError (rb_idP < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
130
    }
131
  }
gauthier's avatar
gauthier committed
132

133 134
  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
  h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
135

136 137
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
138 139 140 141
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
	    PROTOCOL_CTXT_ARGS(ctxt_pP),
	    rb_idP);
      ctxt_pP->configured=FALSE;
142
      return FALSE;
143
    }
144 145
  }else{
    // instance for a given RB is configured
146
    ctxt_pP->configured=TRUE;
147
  }
148
    
149
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
150 151 152 153
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
154

155
  // PDCP transparent mode for MBMS traffic
156

157
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
158
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
159
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
160 161 162

    if (pdcp_pdu_p != NULL) {
      memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
163
#if defined(DEBUG_PDCP_PAYLOAD)
164 165 166
      rlc_util_print_hex_octets(PDCP,
                                (unsigned char*)&pdcp_pdu_p->data[0],
                                sdu_buffer_sizeP);
167
#endif
168 169 170
      rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
171 172
      LOG_W(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
173
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
174 175
      AssertFatal(0, PROTOCOL_CTXT_FMT"[RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  PROTOCOL_CTXT_ARGS(ctxt_pP),
176
                  rb_idP);
gauthier's avatar
gauthier committed
177
#endif
178
    }
179
  } else {
180 181 182 183 184 185 186 187 188 189
    // calculate the pdcp header and trailer size
    if (srb_flagP) {
      pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
      pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
    } else {
      pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
      pdcp_tailer_len = 0;
    }

    pdcp_pdu_size = sdu_buffer_sizeP + pdcp_header_len + pdcp_tailer_len;
gauthier's avatar
gauthier committed
190

191 192
    LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT"Data request notification  pdu size %d (header%d, trailer%d)\n",
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
193 194 195
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
gauthier's avatar
gauthier committed
196

197 198 199
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
200
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
201 202

    if (pdcp_pdu_p != NULL) {
203
      /*
204 205 206
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
207
       */
208

209 210 211 212 213 214
      if (srb_flagP) { // this Control plane PDCP Data PDU
        pdcp_control_plane_data_pdu_header pdu_header;
        pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p);
        current_sn = pdu_header.sn;
        memset(&pdu_header.mac_i[0],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
        memset(&pdcp_pdu_p->data[sdu_buffer_sizeP + pdcp_header_len],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
215

216
        if (pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
217 218
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
219

220
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
221 222 223 224
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
225

gauthier's avatar
gauthier committed
226
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
227 228 229 230 231 232 233
          return FALSE;
        }
      } else {
        pdcp_user_plane_data_pdu_header_with_long_sn pdu_header;
        pdu_header.dc = (modeP == PDCP_TRANSMISSION_MODE_DATA) ? PDCP_DATA_PDU_BIT_SET :  PDCP_CONTROL_PDU_BIT_SET;
        pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p);
        current_sn = pdu_header.sn ;
234

235
        if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
236 237
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
238 239
         
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
240

241 242 243 244
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
245

gauthier's avatar
gauthier committed
246
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
247 248
          return FALSE;
        }
gauthier's avatar
gauthier committed
249
      }
250

gauthier's avatar
gauthier committed
251
      /*
252
       * Validate incoming sequence number, there might be a problem with PDCP initialization
gauthier's avatar
gauthier committed
253
       */
254
      if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
Cedric Roux's avatar
Cedric Roux committed
255
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Generated sequence number (%"PRIu16") is greater than a sequence number could ever be!\n"\
256 257 258
              "There must be a problem with PDCP initialization, ignoring this PDU...\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              current_sn);
259

260
        free_mem_block(pdcp_pdu_p, __func__);
261

262
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
263 264 265 266
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
267

gauthier's avatar
gauthier committed
268
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
269 270 271 272 273 274 275 276 277 278 279
        return FALSE;
      }

      LOG_D(PDCP, "Sequence number %d is assigned to current PDU\n", current_sn);

      /* Then append data... */
      memcpy(&pdcp_pdu_p->data[pdcp_header_len], sdu_buffer_pP, sdu_buffer_sizeP);

      //For control plane data that are not integrity protected,
      // the MAC-I field is still present and should be padded with padding bits set to 0.
      // NOTE: user-plane data are never integrity protected
280
      for (i=0; i<pdcp_tailer_len; i++) {
281
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
282
      }
283 284 285 286 287 288 289

#if defined(ENABLE_SECURITY)

      if ((pdcp_p->security_activated != 0) &&
          (((pdcp_p->cipheringAlgorithm) != 0) ||
           ((pdcp_p->integrityProtAlgorithm) != 0))) {

290
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
291 292 293 294
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
295 296 297 298 299 300 301 302 303 304

        pdcp_apply_security(ctxt_pP,
                            pdcp_p,
                            srb_flagP,
                            rb_idP % maxDRB,
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);

305 306 307 308 309
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
310 311 312 313 314 315 316 317 318 319 320 321
      }

#endif

      /* Print octets of outgoing data in hexadecimal form */
      LOG_D(PDCP, "Following content with size %d will be sent over RLC (PDCP PDU header is the first two bytes)\n",
            pdcp_pdu_size);
      //util_print_hex_octets(PDCP, (unsigned char*)pdcp_pdu_p->data, pdcp_pdu_size);
      //util_flush_hex_octets(PDCP, (unsigned char*)pdcp_pdu->data, pdcp_pdu_size);
    } else {
      LOG_E(PDCP, "Cannot create a mem_block for a PDU!\n");

322 323 324 325 326
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
      }
327 328 329 330 331 332 333 334 335

#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
      AssertFatal(0, "[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  ctxt_pP->frame,
                  (ctxt_pP->enb_flag) ? "eNB" : "UE",
                  ctxt_pP->enb_module_id,
                  ctxt_pP->ue_module_id,
                  rb_idP);
#endif
gauthier's avatar
gauthier committed
336
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
337 338 339 340 341 342 343
      return FALSE;
    }

    /*
     * Ask sublayer to transmit data and check return value
     * to see if RLC succeeded
     */
344
#ifdef PDCP_MSG_PRINT
345 346 347
    int i=0;
    LOG_F(PDCP,"[MSG] PDCP DL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);

348
    for (i = 0; i < pdcp_pdu_size; i++) {
349
      LOG_F(PDCP,"%02x ", ((uint8_t*)pdcp_pdu_p->data)[i]);
350
    }
351 352 353 354

    LOG_F(PDCP,"\n");
#endif
    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
355

356
  }
357

358 359 360
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
361
    ret=TRUE;
362 363 364 365
    break;

  case RLC_OP_STATUS_BAD_PARAMETER:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
366 367
    ret= FALSE;
    break;
368

369 370
  case RLC_OP_STATUS_INTERNAL_ERROR:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
371 372
    ret= FALSE;
    break;
373 374 375

  case RLC_OP_STATUS_OUT_OF_RESSOURCES:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
376 377
    ret= FALSE;
    break;
378 379 380

  default:
    LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
381 382
    ret= FALSE;
    break;
383
  }
384

385
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
386 387 388 389
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
390

391 392 393 394
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
395 396
  
  for (pdcp_uid=0; pdcp_uid< NUMBER_OF_UE_MAX;pdcp_uid++){
397
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ) 
398 399 400 401 402
      break;
  }

  //LOG_I(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, rb_idP+rb_offset, current_sn);
  Pdcp_stats_tx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
403
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
404
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
405
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
406 407
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;

408
  Pdcp_stats_tx_aiat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+= (pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
409
  Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+= (pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]); 
410
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
411
    
gauthier's avatar
gauthier committed
412
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
413
  return ret;
414 415 416

}

gauthier's avatar
gauthier committed
417

418 419 420
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
421 422 423 424 425
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t   srb_flagP,
  const MBMS_flag_t  MBMS_flagP,
  const rb_id_t      rb_idP,
  const sdu_size_t   sdu_buffer_sizeP,
426 427 428
  mem_block_t* const sdu_buffer_pP
)
//-----------------------------------------------------------------------------
429
{
gauthier's avatar
gauthier committed
430 431 432
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
433 434
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
gauthier's avatar
gauthier committed
435
  pdcp_sn_t    sequence_number = 0;
436
  volatile sdu_size_t   payload_offset  = 0;
437
  rb_id_t      rb_id            = rb_idP;
438
  boolean_t    packet_forwarded = FALSE;
439 440
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
441 442 443
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
  uint16_t     pdcp_uid=0;      
  uint8_t      oo_flag=0;
444
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
445
  MessageDef  *message_p        = NULL;
446
  uint8_t     *gtpu_buffer_p    = NULL;
447
#endif
448

449

gauthier's avatar
gauthier committed
450
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
451

452
#ifdef PDCP_MSG_PRINT
453 454 455
  int i=0;
  LOG_F(PDCP,"[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);

456
  for (i = 0; i < sdu_buffer_sizeP; i++) {
457
    LOG_F(PDCP,"%02x ", ((uint8_t*)sdu_buffer_pP->data)[i]);
458
  }
459 460 461

  LOG_F(PDCP,"\n");
#endif
462

Cedric Roux's avatar
Cedric Roux committed
463 464 465 466 467
#if T_TRACER
  if (ctxt_pP->enb_flag != ENB_FLAG_NO)
    T(T_ENB_PDCP_UL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
#endif

468
  if (MBMS_flagP) {
469 470 471 472 473 474
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE,
                 "RB id is too high (%u/%d) %u rnti %x!\n",
                 rb_idP,
                 NB_RB_MBMS_MAX,
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
475 476

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
477
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
478
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
479 480 481 482 483
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
484

gauthier's avatar
sync  
gauthier committed
485
    } else {
486 487 488 489 490 491 492
      LOG_D(PDCP, "Data indication notification for PDCP entity from UE %x to eNB %u "
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
            ctxt_pP->rnti,
            ctxt_pP->module_id ,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
gauthier's avatar
sync  
gauthier committed
493
    }
494

gauthier's avatar
sync  
gauthier committed
495
  } else {
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
    rb_id = rb_idP % maxDRB;
    AssertError (rb_id < maxDRB, return FALSE, "RB id is too high (%u/%d) %u UE %x!\n",
                 rb_id,
                 maxDRB,
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
    AssertError (rb_id > 0, return FALSE, "RB id is too low (%u/%d) %u UE %x!\n",
                 rb_id,
                 maxDRB,
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_id, srb_flagP);
    h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

    if (h_rc != HASH_TABLE_OK) {
      LOG_W(PDCP,
            PROTOCOL_CTXT_FMT"Could not get PDCP instance key 0x%"PRIx64"\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            key);
515
      free_mem_block(sdu_buffer_pP, __func__);
gauthier's avatar
gauthier committed
516
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
517
      return FALSE;
518
    }
519
  }
520

gauthier's avatar
gauthier committed
521
  sdu_list_p = &pdcp_sdu_list;
522

gauthier's avatar
gauthier committed
523
  if (sdu_buffer_sizeP == 0) {
524 525
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
526
  }
527

528 529 530 531 532
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
  }
533 534

  /*
535 536
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
gauthier's avatar
gauthier committed
537
   */
538

539
  if (MBMS_flagP == 0 ) {
540 541 542 543 544 545
    if (srb_flagP) { //SRB1/2
      pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
      pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
      sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char*)sdu_buffer_pP->data);
    } else { // DRB
      pdcp_tailer_len = 0;
546 547 548 549 550 551 552

      if (pdcp_p->seq_num_size == PDCP_SN_7BIT) {
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_SHORT_SN_HEADER_SIZE;
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char*)sdu_buffer_pP->data);
      } else if (pdcp_p->seq_num_size == PDCP_SN_12BIT) {
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char*)sdu_buffer_pP->data);
gauthier's avatar
gauthier committed
553
      } else {
554
        //sequence_number = 4095;
555 556 557 558
        LOG_E(PDCP,
              PROTOCOL_PDCP_CTXT_FMT"wrong sequence number  (%d) for this pdcp entity \n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
              pdcp_p->seq_num_size);
gauthier's avatar
gauthier committed
559
      }
560

561 562
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
563

564 565 566 567
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
568 569 570 571
      LOG_W(PDCP,
            PROTOCOL_PDCP_CTXT_FMT"Incoming (from RLC) SDU is short of size (size:%d)! Ignoring...\n",
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
            sdu_buffer_sizeP);
572
      free_mem_block(sdu_buffer_pP, __func__);
573

574 575 576 577 578
      if (ctxt_pP->enb_flag) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
      }
579

gauthier's avatar
gauthier committed
580
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
581 582 583
      return FALSE;
    }

584
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
585
#if 0
586
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
587
#endif
588
      /* if (dc == PDCP_DATA_PDU )
589 590 591
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
592
    } else {
593
      oo_flag=1;
594 595 596 597
      LOG_W(PDCP,
            PROTOCOL_PDCP_CTXT_FMT"Incoming PDU has an unexpected sequence number (%d), RX window synchronisation have probably been lost!\n",
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
            sequence_number);
gauthier's avatar
gauthier committed
598
      /*
599 600
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
601 602
       */
#if 0
603
      LOG_D(PDCP, "Ignoring PDU...\n");
604
      free_mem_block(sdu_buffer, __func__);
605
      return FALSE;
606
#else
607
      //LOG_W(PDCP, "Delivering out-of-order SDU to upper layer...\n");
608
#endif
609
    }
610 611 612

    // SRB1/2: control-plane data
    if (srb_flagP) {
613
#if defined(ENABLE_SECURITY)
614

615
      if (pdcp_p->security_activated == 1) {
616 617 618 619 620
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
        }
621 622 623 624 625 626 627 628 629 630

        pdcp_validate_security(ctxt_pP,
                               pdcp_p,
                               srb_flagP,
                               rb_idP,
                               pdcp_header_len,
                               sequence_number,
                               sdu_buffer_pP->data,
                               sdu_buffer_sizeP - pdcp_tailer_len);

631 632 633 634 635
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
        }
gauthier's avatar
gauthier committed
636
      }
637

638 639
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
640 641 642 643 644 645 646
  	MSC_LOG_TX_MESSAGE(
  	    (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_PDCP_UE:MSC_PDCP_ENB,
        (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_RRC_UE:MSC_RRC_ENB,
        NULL,0,
        PROTOCOL_PDCP_CTXT_FMT" DATA-IND len %u",
        PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
        sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len);
647
        rrc_data_ind(ctxt_pP,
648 649 650
		   rb_id,
		   sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
		   (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len]);
651
        free_mem_block(sdu_buffer_pP, __func__);
652

653

654
      // free_mem_block(new_sdu, __func__);
655 656 657 658 659
      if (ctxt_pP->enb_flag) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
      }
660

gauthier's avatar
gauthier committed
661
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
662 663
      return TRUE;
    }
664 665 666 667

    /*
     * DRBs
     */
668 669
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
670

671
    if (pdcp_p->security_activated == 1) {
672 673 674 675 676
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
      } else {
        start_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
      }
677

678
      pdcp_validate_security(
679 680 681 682 683 684 685 686 687
        ctxt_pP,
        pdcp_p,
        srb_flagP,
        rb_idP,
        pdcp_header_len,
        sequence_number,
        sdu_buffer_pP->data,
        sdu_buffer_sizeP - pdcp_tailer_len);

688 689 690 691 692
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
      }
693

694
    }
695

696
#endif
697
  } else {
698
    payload_offset=0;
699
  }
700 701 702

  if (otg_enabled==1) {
    LOG_D(OTG,"Discarding received packed\n");
703
    free_mem_block(sdu_buffer_pP, __func__);
704

705 706 707 708 709
    if (ctxt_pP->enb_flag) {
      stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
    } else {
      stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
    }
710

gauthier's avatar
gauthier committed
711
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
712 713 714
    return TRUE;
  }

715 716 717 718 719 720 721 722
  // XXX Decompression would be done at this point

  /*
   * After checking incoming sequence number PDCP header
   * has to be stripped off so here we copy SDU buffer starting
   * from its second byte (skipping 0th and 1st octets, i.e.
   * PDCP header)
   */
723
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
724

725
  if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
726 727 728 729 730 731 732 733
    MSC_LOG_TX_MESSAGE(
    		MSC_PDCP_ENB,
    		MSC_GTPU_ENB,
    		NULL,0,
    		"0 GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %u len %u",
    		ctxt_pP->rnti,
    		rb_id + 4,
    		sdu_buffer_sizeP - payload_offset);
734 735 736 737 738 739 740 741 742 743
    //LOG_T(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
    gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
                                sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
    AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
    memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
    message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
    AssertFatal(message_p != NULL, "OUT OF MEMORY");
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer       = gtpu_buffer_p;
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length       = sdu_buffer_sizeP - payload_offset;
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset       = GTPU_HEADER_OVERHEAD_MAX;
744
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
745 746
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
    itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
747
    packet_forwarded = TRUE;    
748
  }
nikaeinn's avatar
nikaeinn committed
749
  
750 751 752
#else
  packet_forwarded = FALSE;
#endif
753

754
  if (FALSE == packet_forwarded) {
755
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
756

757 758 759 760 761 762 763 764 765 766
    if (new_sdu_p) {
      if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
        pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
      }

      /*
       * Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
       */
      memset(new_sdu_p->data, 0, sizeof (pdcp_data_ind_header_t));
      ((pdcp_data_ind_header_t *) new_sdu_p->data)->data_size = sdu_buffer_sizeP - payload_offset;
767
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
768 769 770 771 772

      // Here there is no virtualization possible
      // set ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst for IP layer here
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id;
773
#if defined(ENABLE_USE_MME)
Cedric Roux's avatar
Cedric Roux committed
774 775 776 777
        /* for the UE compiled in S1 mode, we need 1 here
         * for the UE compiled in noS1 mode, we need 0
         * TODO: be sure of this
         */
Cedric Roux's avatar
Cedric Roux committed
778
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = 1;
gauthier's avatar
gauthier committed
779
#endif
780
      } else {
781
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * maxDRB);
782
      }
783 784 785 786 787
#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
      static uint32_t pdcp_inst = 0;
      ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = pdcp_inst++;
      LOG_D(PDCP, "inst=%d size=%d\n", ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst, ((pdcp_data_ind_header_t *) new_sdu_p->data)->data_size);
#endif
788 789 790 791 792 793

      memcpy(&new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], \
             &sdu_buffer_pP->data[payload_offset], \
             sdu_buffer_sizeP - payload_offset);
      list_add_tail_eurecom (new_sdu_p, sdu_list_p);

794 795
      
      
796
    }
gauthier's avatar
gauthier committed
797
  }
798

799 800 801 802 803 804 805 806 807 808 809 810 811
  /* Print octets of incoming data in hexadecimal form */
  LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
	sdu_buffer_sizeP  - payload_offset + (int)sizeof(pdcp_data_ind_header_t),
	sdu_buffer_sizeP  - payload_offset);
  //util_print_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset);
  //util_flush_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset);
  
  /*
     * Update PDCP statistics
   * XXX Following two actions are identical, is there a merge error?
   */
  
  for (pdcp_uid=0; pdcp_uid< NUMBER_OF_UE_MAX;pdcp_uid++){
812
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ){
813
      break;
814
    }
815 816 817
  }	
  
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
818
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
819
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
820
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
821 822 823 824 825 826
  
  Pdcp_stats_rx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=sequence_number;
  
  if (oo_flag == 1 )
    Pdcp_stats_rx_outoforder[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
  
827
  Pdcp_stats_rx_aiat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+= (pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
828
  Pdcp_stats_rx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
829
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
830 831

  
gauthier's avatar
gauthier committed
832
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
833
  else {
834 835
    AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
836 837
  }

gauthier's avatar
gauthier committed
838
#endif
839

840
  free_mem_block(sdu_buffer_pP, __func__);
841

842 843 844 845 846
  if (ctxt_pP->enb_flag) {
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
  }
847

gauthier's avatar
gauthier committed
848
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
849 850 851
  return TRUE;
}

nikaeinn's avatar
nikaeinn committed
852 853 854 855 856
void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){

  uint8_t            pdcp_uid = 0;
  uint8_t            rb_id     = 0;
  
857
 // these stats are measured for both eNB and UE on per seond basis 
858 859 860 861
  for (rb_id =0; rb_id < NB_RB_MAX; rb_id ++){
    for (pdcp_uid=0; pdcp_uid< NUMBER_OF_UE_MAX;pdcp_uid++){
      //printf("frame %d and subframe %d \n", pdcp_enb[ctxt_pP->module_id].frame, pdcp_enb[ctxt_pP->module_id].subframe);
      // tx stats
knopp's avatar
knopp committed
862 863
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
864
	// unit: bit/s
865 866 867 868 869 870 871 872 873 874 875 876
	Pdcp_stats_tx_throughput_w[ctxt_pP->module_id][pdcp_uid][rb_id]=Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]*8;
	Pdcp_stats_tx_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
	Pdcp_stats_tx_bytes_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
	if (Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id] > 0){
	  Pdcp_stats_tx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]=(Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]/Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]);
	}else {
	  Pdcp_stats_tx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
	}
	// reset the tmp vars 
	Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
	Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
	Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
nikaeinn's avatar
nikaeinn committed
877
	
878
      }
knopp's avatar
knopp committed
879 880
      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
nikaeinn's avatar
nikaeinn committed
881
	// rx stats
882 883 884
	Pdcp_stats_rx_goodput_w[ctxt_pP->module_id][pdcp_uid][rb_id]=Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]*8;
	Pdcp_stats_rx_w[ctxt_pP->module_id][pdcp_uid][rb_id]= 	Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
	Pdcp_stats_rx_bytes_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
nikaeinn's avatar
nikaeinn committed
885
	
886 887 888 889 890
	if(Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id] > 0){
	  Pdcp_stats_rx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]= (Pdcp_stats_rx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]/Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]);
	} else {
	  Pdcp_stats_rx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
	}
nikaeinn's avatar
nikaeinn committed
891
	
892 893 894 895
	// reset the tmp vars 
	Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
	Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
	Pdcp_stats_rx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
nikaeinn's avatar
nikaeinn committed
896 897
      } 
    }
898
    
nikaeinn's avatar
nikaeinn committed
899 900
  }
}
901
//-----------------------------------------------------------------------------
902 903 904 905 906
void
pdcp_run (
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
907
{
nikaeinn's avatar
nikaeinn committed
908
  
909
#if defined(ENABLE_ITTI)
910 911 912 913
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
914
  protocol_ctxt_t  ctxt;
915
#endif
916

nikaeinn's avatar
nikaeinn committed
917
  
918 919 920 921 922
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  }
923

924 925 926
  pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
  pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023 
  pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
nikaeinn's avatar
nikaeinn committed
927 928
  pdcp_update_stats(ctxt_pP);
   
gauthier's avatar
gauthier committed
929
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
930

931 932
#if defined(ENABLE_ITTI)

933 934 935 936 937 938 939 940 941 942
  do {
    // Checks if a message has been sent to PDCP sub-task
    itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);

    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);

      switch (ITTI_MSG_ID(msg_p)) {
      case RRC_DCCH_DATA_REQ:
943
	PROTOCOL_CTXT_SET_BY_MODULE_ID(
944 945 946 947
          &ctxt,
          RRC_DCCH_DATA_REQ (msg_p).module_id,
          RRC_DCCH_DATA_REQ (msg_p).enb_flag,
          RRC_DCCH_DATA_REQ (msg_p).rnti,
948 949 950
          RRC_DCCH_DATA_REQ (msg_p).frame, 
	  0,
	  RRC_DCCH_DATA_REQ (msg_p).eNB_index);
nikaeinn's avatar
nikaeinn committed
951
        LOG_I(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
952 953 954 955 956 957 958 959
              PROTOCOL_CTXT_ARGS(&ctxt),
              msg_name,
              ITTI_MSG_ORIGIN_NAME(msg_p),
              instance,
              RRC_DCCH_DATA_REQ (msg_p).rb_id,
              RRC_DCCH_DATA_REQ (msg_p).muip,
              RRC_DCCH_DATA_REQ (msg_p).confirmp,
              RRC_DCCH_DATA_REQ (msg_p).mode);
960 961 962 963 964 965 966 967 968

        result = pdcp_data_req (&ctxt,
                                SRB_FLAG_YES,
                                RRC_DCCH_DATA_REQ (msg_p).rb_id,
                                RRC_DCCH_DATA_REQ (msg_p).muip,
                                RRC_DCCH_DATA_REQ (msg_p).confirmp,
                                RRC_DCCH_DATA_REQ (msg_p).sdu_size,
                                RRC_DCCH_DATA_REQ (msg_p).sdu_p,
                                RRC_DCCH_DATA_REQ (msg_p).mode);
969 970
        if (result != TRUE)
          LOG_E(PDCP, "PDCP data request failed!\n");
971 972 973 974 975 976

        // Message buffer has been processed, free it now.
        result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ (msg_p).sdu_p);
        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
        break;

977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
      case RRC_PCCH_DATA_REQ:
      {
        sdu_size_t     sdu_buffer_sizeP;
        sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size;
        uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id;
        uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index;
        RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP;
        if (sdu_buffer_sizeP > 0) {
        	memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP);
        }
        //paging pdcp log
        LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
      }
      break;

992 993 994
      default:
        LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
        break;
gauthier's avatar
gauthier committed
995
      }
996 997 998 999

      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    }
1000
  } while(msg_p != NULL);
1001 1002 1003

# if 0
  {
1004
    MessageDef *msg_resp_p;
1005

1006
    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
1007

1008
    itti_send_msg_to_task(TASK_RRC_ENB, 1, msg_resp_p);
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
  }
  {
    MessageDef *msg_resp_p;

    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);

    itti_send_msg_to_task(TASK_ENB_APP, 2, msg_resp_p);
  }
  {
    MessageDef *msg_resp_p;

    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);

    itti_send_msg_to_task(TASK_MAC_ENB, 3, msg_resp_p);
  }
# endif
gauthier's avatar
gauthier committed
1025
#endif
1026 1027

  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
1028
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
1029

1030
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
gauthier's avatar
gauthier committed
1031
#endif
gauthier's avatar
gauthier committed
1032
  {
1033
    pdcp_fifo_read_input_sdus(ctxt_pP);
gauthier's avatar
gauthier committed
1034
  }
1035

1036
  // PDCP -> NAS/IP traffic: RX
1037 1038 1039
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
gauthier's avatar
gauthier committed
1040

1041 1042 1043
  else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1044

1045
  pdcp_fifo_flush_sdus(ctxt_pP);
1046

1047 1048 1049 1050 1051
  if (ctxt_pP->enb_flag) {
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1052

1053 1054 1055 1056 1057
  if (ctxt_pP->enb_flag) {
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  }
gauthier's avatar
gauthier committed
1058
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
Cedric Roux's avatar