pdcp.c 87.4 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
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 33
#define MBMS_MULTICAST_OUT

34
#include "assertions.h"
35
#include "hashtable.h"
36 37 38 39
#include "pdcp.h"
#include "pdcp_util.h"
#include "pdcp_sequence_manager.h"
#include "LAYER2/RLC/rlc.h"
40 41
#include "LAYER2/MAC/mac_extern.h"
#include "RRC/LTE/rrc_proto.h"
42 43 44
#include "pdcp_primitives.h"
#include "OCG.h"
#include "OCG_extern.h"
45
#include "otg_rx.h"
46
#include "common/utils/LOG/log.h"
47 48
#include <inttypes.h>
#include "platform_constants.h"
frtabu's avatar
frtabu committed
49
#include "nfapi/oai_integration/vendor_ext.h"
50
#include "common/utils/LOG/vcd_signal_dumper.h"
gauthier's avatar
gauthier committed
51
#include "msc.h"
52
#include "common/ngran_types.h"
Yoshihiro Tomita's avatar
Yoshihiro Tomita committed
53
#include "targets/COMMON/openairinterface5g_limits.h"
frtabu's avatar
frtabu committed
54
#include "targets/RT/USER/lte-softmodem.h"
55
#include "SIMULATION/ETH_TRANSPORT/proto.h"
56
#include "UTIL/OSA/osa_defs.h"
57
#include "openair2/RRC/NAS/nas_config.h"
58
# include "intertask_interface.h"
59

60 61 62

#  include "gtpv1u_eNB_task.h"
#  include "gtpv1u.h"
63

64
#include "ENB_APP/enb_config.h"
frtabu's avatar
frtabu committed
65 66


67

68
extern int otg_enabled;
69
extern uint8_t nfapi_mode;
70 71
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
72
hash_table_t  *pdcp_coll_p = NULL;
73

74
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
75 76 77 78 79 80 81 82
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <netinet/ip.h>
  #include <netinet/udp.h>
  #include <unistd.h>

  static int mbms_socket = -1;
83 84
#endif

85 86

/* pdcp module parameters and related functions*/
frtabu's avatar
frtabu committed
87
static pdcp_params_t pdcp_params= {0,NULL};
88 89 90 91

uint64_t get_pdcp_optmask(void) {
  return pdcp_params.optmask;
}
92 93 94 95 96 97 98 99
//-----------------------------------------------------------------------------
/*
 * 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()
 */
100
boolean_t pdcp_data_req(
frtabu's avatar
frtabu committed
101
  protocol_ctxt_t  *ctxt_pP,
102 103 104 105 106 107
  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,
108 109 110
  const pdcp_transmission_mode_t modeP,
  const uint32_t *const sourceL2Id,
  const uint32_t *const destinationL2Id
111 112
)
//-----------------------------------------------------------------------------
113
{
114
  pdcp_t            *pdcp_p          = NULL;
115 116 117 118 119
  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;
120 121
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
122
  boolean_t          ret             = TRUE;
123 124
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
125 126
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
gauthier's avatar
gauthier committed
127
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
128
  CHECK_CTXT_ARGS(ctxt_pP);
129
#if T_TRACER
frtabu's avatar
frtabu committed
130

131 132
  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));
frtabu's avatar
frtabu committed
133

134 135
#endif

136 137 138 139 140 141 142 143
  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?
   */
144
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
frtabu's avatar
frtabu committed
145 146
              sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);

147
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
148
    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);
149
  } else {
150
    if (srb_flagP) {
nikaeinn's avatar
nikaeinn committed
151
      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);
152
    } else {
153
      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
154
    }
155
  }
156

157
  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
frtabu's avatar
frtabu committed
158
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
159

160 161 162
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
frtabu's avatar
frtabu committed
163 164
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
165
      ctxt_pP->configured=FALSE;
166
      return FALSE;
167
    }
frtabu's avatar
frtabu committed
168
  } else {
169
    // instance for a given RB is configured
170
    ctxt_pP->configured=TRUE;
171
  }
frtabu's avatar
frtabu committed
172

173
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
174 175 176 177
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
178

179
  // PDCP transparent mode for MBMS traffic
180

181
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
182
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
183
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
184 185 186

    if (pdcp_pdu_p != NULL) {
      memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
187

188 189 190 191 192 193
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
        rlc_util_print_hex_octets(PDCP,
                                  (unsigned char *)&pdcp_pdu_p->data[0],
                                  sdu_buffer_sizeP);
        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %d \n", srb_flagP, rb_idP);
      }
frtabu's avatar
frtabu committed
194 195 196

      rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)?MBMS_FLAG_NO:MBMS_FLAG_YES, rb_idP, muiP,
                   confirmP, sdu_buffer_sizeP, pdcp_pdu_p,NULL,NULL);
197 198
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
199
      LOG_E(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
200
            PROTOCOL_CTXT_ARGS(ctxt_pP));
201
    }
202
  } else {
203 204 205 206 207 208 209 210 211 212
    // 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;
213 214
    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),
215 216 217 218 219 220
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
221
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
222 223

    if (pdcp_pdu_p != NULL) {
224
      /*
225 226 227
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
228
       */
229 230 231 232 233 234
      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);
235

frtabu's avatar
frtabu committed
236
        if (pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == FALSE) {
237 238
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
239

240
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
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 249 250 251 252 253
          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 ;
254

frtabu's avatar
frtabu committed
255
        if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == FALSE) {
256 257
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
258

frtabu's avatar
frtabu committed
259
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
260 261 262 263
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
264

gauthier's avatar
gauthier committed
265
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
266 267
          return FALSE;
        }
268
      }
269

270
      /*
271
       * Validate incoming sequence number, there might be a problem with PDCP initialization
272
       */
273
      if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
Cedric Roux's avatar
Cedric Roux committed
274
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Generated sequence number (%"PRIu16") is greater than a sequence number could ever be!\n"\
275 276 277
              "There must be a problem with PDCP initialization, ignoring this PDU...\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              current_sn);
278
        free_mem_block(pdcp_pdu_p, __func__);
279

280
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
281 282 283 284
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
285

gauthier's avatar
gauthier committed
286
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
287 288 289 290 291 292 293 294 295 296
        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
297
      for (i=0; i<pdcp_tailer_len; i++) {
298
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
299
      }
300 301 302 303

      if ((pdcp_p->security_activated != 0) &&
          (((pdcp_p->cipheringAlgorithm) != 0) ||
           ((pdcp_p->integrityProtAlgorithm) != 0))) {
304
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
305 306 307 308
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
309 310 311 312

        pdcp_apply_security(ctxt_pP,
                            pdcp_p,
                            srb_flagP,
313
                            rb_idP % LTE_maxDRB,
314 315 316 317 318
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);

319 320 321 322 323
        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);
        }
324 325 326 327 328 329 330 331 332 333
      }

      /* 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");

334 335 336 337 338
      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);
      }
339

340
      LOG_E(PDCP,  "[FRAME %5u][%s][PDCP][MOD %u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
341 342 343 344
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->module_id,
            rb_idP);
gauthier's avatar
gauthier committed
345
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
346 347 348 349 350 351 352
      return FALSE;
    }

    /*
     * Ask sublayer to transmit data and check return value
     * to see if RLC succeeded
     */
353 354
    LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
                "[MSG] PDCP DL %s PDU on rb_id %d\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
355

frtabu's avatar
frtabu committed
356 357
    if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1)) {
      LOG_D(PDCP, "pdcp data req on drb %d, size %d, rnti %x, node_type %d \n",
358 359
            rb_idP, pdcp_pdu_size, ctxt_pP->rnti, RC.rrc[ctxt_pP->module_id]->node_type);

frtabu's avatar
frtabu committed
360
      if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_DU(RC.rrc[ctxt_pP->module_id]->node_type)) {
361 362
        LOG_E(PDCP, "Can't be DU, bad node type %d \n", RC.rrc[ctxt_pP->module_id]->node_type);
        ret=FALSE;
frtabu's avatar
frtabu committed
363 364 365 366
      } else {
        rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
                     confirmP, pdcp_pdu_size, pdcp_pdu_p,sourceL2Id,
                     destinationL2Id);
367

frtabu's avatar
frtabu committed
368 369 370 371 372
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;
373

frtabu's avatar
frtabu committed
374 375 376 377
          case RLC_OP_STATUS_BAD_PARAMETER:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
            ret= FALSE;
            break;
378

frtabu's avatar
frtabu committed
379 380 381 382
          case RLC_OP_STATUS_INTERNAL_ERROR:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
            ret= FALSE;
            break;
383

frtabu's avatar
frtabu committed
384 385 386 387
          case RLC_OP_STATUS_OUT_OF_RESSOURCES:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
            ret= FALSE;
            break;
388

frtabu's avatar
frtabu committed
389 390 391 392 393 394 395 396
          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);
            ret= FALSE;
            break;
        } // switch case
      } /* end if node_type is not DU */
    } else { // SRB
      if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) {
397 398 399 400 401 402
        // DL transfer
        MessageDef                            *message_p;
        // Note: the acyual task must be TASK_PDCP_ENB, but this task is not created
        message_p = itti_alloc_new_message (TASK_PDCP_ENB, F1AP_DL_RRC_MESSAGE);
        F1AP_DL_RRC_MESSAGE (message_p).rrc_container =  &pdcp_pdu_p->data[0] ;
        F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = pdcp_pdu_size;
frtabu's avatar
frtabu committed
403
        F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id  = 0;
404 405 406 407 408 409 410 411 412 413
        F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id  = 0;
        F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id  = 0xFFFFFFFF; // unknown
        F1AP_DL_RRC_MESSAGE (message_p).rnti = ctxt_pP->rnti;
        F1AP_DL_RRC_MESSAGE (message_p).srb_id = rb_idP;
        F1AP_DL_RRC_MESSAGE (message_p).execute_duplication      = 1;
        F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc      = 0;
        itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p);
        //CU_send_DL_RRC_MESSAGE_TRANSFER(ctxt_pP->module_id, message_p);
        LOG_I(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n");
        ret=TRUE;
frtabu's avatar
frtabu committed
414
      } else {
415 416 417 418 419 420 421 422 423 424
        rlc_status = rlc_data_req(ctxt_pP
                                  , srb_flagP
                                  , MBMS_FLAG_NO
                                  , rb_idP
                                  , muiP
                                  , confirmP
                                  , pdcp_pdu_size
                                  , pdcp_pdu_p
                                  ,NULL
                                  ,NULL
frtabu's avatar
frtabu committed
425 426
                                 );

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;

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

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

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

          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);
            ret= FALSE;
            break;
        } // switch case
      }
454
    }
455
  }
456

457
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
458 459 460 461
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
462

463 464 465 466
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
467

frtabu's avatar
frtabu committed
468
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
469
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
470 471 472 473 474
      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]++;
475
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
476
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
477
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
478
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;
479
  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]);
frtabu's avatar
frtabu committed
480
  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]);
481
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
gauthier's avatar
gauthier committed
482
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
483
  return ret;
484 485
}

486

487 488 489
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
frtabu's avatar
frtabu committed
490
  const protocol_ctxt_t *const ctxt_pP,
491 492 493 494
  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,
frtabu's avatar
frtabu committed
495
  mem_block_t *const sdu_buffer_pP
496 497
)
//-----------------------------------------------------------------------------
498
{
499 500 501
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
502 503
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
gauthier's avatar
gauthier committed
504
  pdcp_sn_t    sequence_number = 0;
505
  volatile sdu_size_t   payload_offset  = 0;
506
  rb_id_t      rb_id            = rb_idP;
507
  boolean_t    packet_forwarded = FALSE;
508 509
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
510
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
frtabu's avatar
frtabu committed
511
  uint16_t     pdcp_uid=0;
512
  MessageDef  *message_p        = NULL;
513
  uint8_t     *gtpu_buffer_p    = NULL;
514 515 516
  uint32_t    rx_hfn_for_count;
  int         pdcp_sn_for_count;
  int         security_ok;
gauthier's avatar
gauthier committed
517
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
518 519
  LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
              "[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
520
#if T_TRACER
frtabu's avatar
frtabu committed
521

522 523
  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));
frtabu's avatar
frtabu committed
524

525 526
#endif

527
  if (MBMS_flagP) {
528 529 530 531 532 533
    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);
534 535

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
536
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
537
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
538 539 540 541 542
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
gauthier's avatar
gauthier committed
543
    } else {
544 545 546
      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,
547
            ctxt_pP->module_id,
548 549 550
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
gauthier's avatar
gauthier committed
551 552
    }
  } else {
553 554
    rb_id = rb_idP % LTE_maxDRB;
    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u UE %x!\n",
555
                 rb_id,
556
                 LTE_maxDRB,
557 558 559 560
                 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,
561
                 LTE_maxDRB,
562 563 564
                 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);
frtabu's avatar
frtabu committed
565
    h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
566 567 568 569 570 571

    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);
572
      free_mem_block(sdu_buffer_pP, __func__);
gauthier's avatar
gauthier committed
573
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
574
      return FALSE;
575
    }
576
  }
577

578
  sdu_list_p = &pdcp_sdu_list;
579

580
  if (sdu_buffer_sizeP == 0) {
581 582
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
583
  }
584

585 586 587 588 589
  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);
  }
590 591

  /*
592 593
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
594
   */
595

596
  if (MBMS_flagP == 0 ) {
597 598 599
    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;
frtabu's avatar
frtabu committed
600
      sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char *)sdu_buffer_pP->data);
601 602
    } else { // DRB
      pdcp_tailer_len = 0;
603

604
      if (pdcp_p->seq_num_size == 7) {
605
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_SHORT_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
606
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char *)sdu_buffer_pP->data);
607
      } else if (pdcp_p->seq_num_size == 12) {
608
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
609
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char *)sdu_buffer_pP->data);
610
      } else {
611
        //sequence_number = 4095;
612 613 614 615
        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);
616
        exit(1);
617
      }
618

619 620
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
621

622 623 624 625
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
626 627 628 629
      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);
630
      free_mem_block(sdu_buffer_pP, __func__);
631

632 633 634 635 636
      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);
      }
637

gauthier's avatar
gauthier committed
638
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
639 640 641
      return FALSE;
    }

642
#if 0
643

644
    /* Removed by Cedric */
645
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
646
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
647
      /* if (dc == PDCP_DATA_PDU )
648 649 650
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
651
    } else {
frtabu's avatar
frtabu committed
652 653
      Pdcp_stats_rx_outoforder[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
      LOG_E(PDCP,
654 655 656
            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);
657
      /*
658 659
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
660
       */
Mongazon's avatar
Mongazon committed
661 662
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
663 664
      return FALSE;
    }
665

666
#endif
667 668 669

    // SRB1/2: control-plane data
    if (srb_flagP) {
670 671 672 673 674 675 676 677
      /* process as described in 36.323 5.1.2.2 */
      if (sequence_number < pdcp_p->next_pdcp_rx_sn) {
        rx_hfn_for_count  = pdcp_p->rx_hfn + 1;
        pdcp_sn_for_count = sequence_number;
      } else {
        rx_hfn_for_count  = pdcp_p->rx_hfn;
        pdcp_sn_for_count = sequence_number;
      }
678

679
      if (pdcp_p->security_activated == 1) {
680 681 682 683 684
        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);
        }
685

686
        security_ok = pdcp_validate_security(ctxt_pP,
frtabu's avatar
frtabu committed
687 688 689 690
                                             pdcp_p,
                                             srb_flagP,
                                             rb_idP,
                                             pdcp_header_len,
691 692
                                             rx_hfn_for_count,
                                             pdcp_sn_for_count,
frtabu's avatar
frtabu committed
693
                                             sdu_buffer_pP->data,
694
                                             sdu_buffer_sizeP - pdcp_tailer_len) == 0;
695

696 697 698 699 700
        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);
        }
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
      } else {
        security_ok = 1;
      }

      if (security_ok == 0) {
        LOG_W(PDCP,
              PROTOCOL_PDCP_CTXT_FMT"security not validated for incoming PDCP SRB PDU\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
        LOG_W(PDCP, "Ignoring PDU...\n");
        free_mem_block(sdu_buffer_pP, __func__);
        /* TODO: indicate integrity verification failure to upper layer */
        return FALSE;
      }

      if (sequence_number < pdcp_p->next_pdcp_rx_sn)
        pdcp_p->rx_hfn++;

      pdcp_p->next_pdcp_rx_sn = sequence_number + 1;

      if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
        pdcp_p->next_pdcp_rx_sn = 0;
        pdcp_p->rx_hfn++;
723
      }
724

725
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
frtabu's avatar
frtabu committed
726 727
      MSC_LOG_TX_MESSAGE(
        (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_PDCP_UE:MSC_PDCP_ENB,
728 729 730 731 732
        (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);
frtabu's avatar
frtabu committed
733 734 735 736 737
      rrc_data_ind(ctxt_pP,
                   rb_id,
                   sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
                   (uint8_t *)&sdu_buffer_pP->data[pdcp_header_len]);
      free_mem_block(sdu_buffer_pP, __func__);
738

739
      // free_mem_block(new_sdu, __func__);
740 741 742 743 744
      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);
      }
745

gauthier's avatar
gauthier committed
746
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
747
      return TRUE;
748
    } /* if (srb_flagP) */
749 750 751 752

    /*
     * DRBs
     */
753
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
754

755
    switch (pdcp_p->rlc_mode) {
frtabu's avatar
frtabu committed
756 757 758
      case RLC_MODE_AM: {
        /* process as described in 36.323 5.1.2.1.2 */
        int reordering_window;
759

frtabu's avatar
frtabu committed
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
        if (pdcp_p->seq_num_size == 7)
          reordering_window = REORDERING_WINDOW_SN_7BIT;
        else
          reordering_window = REORDERING_WINDOW_SN_12BIT;

        if (sequence_number - pdcp_p->last_submitted_pdcp_rx_sn > reordering_window ||
            (pdcp_p->last_submitted_pdcp_rx_sn - sequence_number >= 0 &&
             pdcp_p->last_submitted_pdcp_rx_sn - sequence_number < reordering_window)) {
          /* TODO: specs say to decipher and do header decompression */
          LOG_W(PDCP,
                PROTOCOL_PDCP_CTXT_FMT"discard PDU, out of\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          LOG_W(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer_pP, __func__);
          /* TODO: indicate integrity verification failure to upper layer */
          return FALSE;
        } else if (pdcp_p->next_pdcp_rx_sn - sequence_number > reordering_window) {
777
          pdcp_p->rx_hfn++;
frtabu's avatar
frtabu committed
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
          rx_hfn_for_count  = pdcp_p->rx_hfn;
          pdcp_sn_for_count = sequence_number;
          pdcp_p->next_pdcp_rx_sn = sequence_number + 1;
        } else if (sequence_number - pdcp_p->next_pdcp_rx_sn >= reordering_window) {
          rx_hfn_for_count  = pdcp_p->rx_hfn - 1;
          pdcp_sn_for_count = sequence_number;
        } else if (sequence_number >= pdcp_p->next_pdcp_rx_sn) {
          rx_hfn_for_count  = pdcp_p->rx_hfn;
          pdcp_sn_for_count = sequence_number;
          pdcp_p->next_pdcp_rx_sn = sequence_number + 1;

          if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
            pdcp_p->next_pdcp_rx_sn = 0;
            pdcp_p->rx_hfn++;
          }
        } else { /* sequence_number < pdcp_p->next_pdcp_rx_sn */
          rx_hfn_for_count  = pdcp_p->rx_hfn;
          pdcp_sn_for_count = sequence_number;
796
        }
797

frtabu's avatar
frtabu committed
798 799 800 801 802 803
        if (pdcp_p->security_activated == 1) {
          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);
          }
804

frtabu's avatar
frtabu committed
805 806 807 808 809 810 811 812 813
          security_ok = pdcp_validate_security(ctxt_pP,
                                               pdcp_p,
                                               srb_flagP,
                                               rb_idP,
                                               pdcp_header_len,
                                               rx_hfn_for_count,
                                               pdcp_sn_for_count,
                                               sdu_buffer_pP->data,
                                               sdu_buffer_sizeP - pdcp_tailer_len) == 0;
814

frtabu's avatar
frtabu committed
815 816 817 818 819 820 821 822
          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);
          }
        } else {
          security_ok = 1;
        }
823

frtabu's avatar
frtabu committed
824 825 826 827 828 829 830 831 832
        if (security_ok == 0) {
          LOG_W(PDCP,
                PROTOCOL_PDCP_CTXT_FMT"security not validated for incoming PDPC DRB RLC/AM PDU\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          LOG_W(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer_pP, __func__);
          /* TODO: indicate integrity verification failure to upper layer */
          return FALSE;
        }
833

frtabu's avatar
frtabu committed
834 835 836 837 838 839 840 841 842 843 844 845 846 847
        /* TODO: specs say we have to store this PDU in a list and then deliver
         *       stored packets to upper layers according to a well defined
         *       procedure. The code below that deals with delivery is today
         *       too complex to do this properly, so we only send the current
         *       received packet. This is not correct and has to be fixed
         *       some day.
         *       In the meantime, let's pretend the last submitted PDCP SDU
         *       is the current one.
         * TODO: we also have to deal with re-establishment PDU (control PDUs)
         *       that contain no SDU.
         */
        pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
        break;
        } /* case RLC_MODE_AM */
848

frtabu's avatar
frtabu committed
849
      case RLC_MODE_UM:
850

frtabu's avatar
frtabu committed
851 852 853 854
        /* process as described in 36.323 5.1.2.1.3 */
        if (sequence_number < pdcp_p->next_pdcp_rx_sn) {
          pdcp_p->rx_hfn++;
        }
855

frtabu's avatar
frtabu committed
856 857 858
        rx_hfn_for_count  = pdcp_p->rx_hfn;
        pdcp_sn_for_count = sequence_number;
        pdcp_p->next_pdcp_rx_sn = sequence_number + 1;
859

frtabu's avatar
frtabu committed
860 861 862
        if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
          pdcp_p->next_pdcp_rx_sn = 0;
          pdcp_p->rx_hfn++;
863 864
        }

frtabu's avatar
frtabu committed
865 866 867 868 869 870
        if (pdcp_p->security_activated == 1) {
          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);
          }
871

frtabu's avatar
frtabu committed
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
          security_ok = pdcp_validate_security(ctxt_pP,
                                               pdcp_p,
                                               srb_flagP,
                                               rb_idP,
                                               pdcp_header_len,
                                               rx_hfn_for_count,
                                               pdcp_sn_for_count,
                                               sdu_buffer_pP->data,
                                               sdu_buffer_sizeP - pdcp_tailer_len) == 0;

          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);
          }
887
        } else {
frtabu's avatar
frtabu committed
888
          security_ok = 1;
889
        }
890

frtabu's avatar
frtabu committed
891 892 893 894 895 896 897 898 899
        if (security_ok == 0) {
          LOG_W(PDCP,
                PROTOCOL_PDCP_CTXT_FMT"security not validated for incoming PDPC DRB RLC/UM PDU\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          LOG_W(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer_pP, __func__);
          /* TODO: indicate integrity verification failure to upper layer */
          return FALSE;
        }
900

frtabu's avatar
frtabu committed
901
        break;
902

frtabu's avatar
frtabu committed
903 904 905
      default:
        LOG_E(PDCP, "bad RLC mode, cannot happen.\n");
        exit(1);
906 907
    } /* switch (pdcp_p->rlc_mode) */
  } else { /* MBMS_flagP == 0 */
908
    payload_offset=0;
909
  }
910 911 912

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

915 916 917 918 919
    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);
    }
920

gauthier's avatar
gauthier committed
921
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
922 923 924
    return TRUE;
  }

925 926 927 928 929 930 931
  // 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)
   */
932

933
  if (LINK_ENB_PDCP_TO_GTPV1U) {
frtabu's avatar
frtabu committed
934 935
    if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
      LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %u len %u\n",
936 937 938
            ctxt_pP->rnti,
            rb_id + 4,
            sdu_buffer_sizeP - payload_offset );
frtabu's avatar
frtabu committed
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
      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);
      //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;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
      itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
      packet_forwarded = TRUE;
    }
962
  } else {
frtabu's avatar
frtabu committed
963
    packet_forwarded = FALSE;
964
  }
frtabu's avatar
frtabu committed
965

966
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
967

968
  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
frtabu's avatar
frtabu committed
969 970
    struct iphdr   *ip_header = (struct iphdr *)&sdu_buffer_pP->data[payload_offset];
    struct udphdr *udp_header = (struct udphdr *)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
971 972 973 974
    struct sockaddr_in dest_addr;
    dest_addr.sin_family      = AF_INET;
    dest_addr.sin_port        = udp_header->dest;
    dest_addr.sin_addr.s_addr = ip_header->daddr;
frtabu's avatar
frtabu committed
975
    sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
976 977
    packet_forwarded = TRUE;
  }
frtabu's avatar
frtabu committed
978

979 980
#endif

981
  if (FALSE == packet_forwarded) {
982
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
983

984
    if (new_sdu_p) {
985
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
986 987 988 989 990 991 992 993
        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;
994
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
995 996 997 998 999

      // 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;
frtabu's avatar
frtabu committed
1000

1001
        if (EPC_MODE_ENABLED) {
frtabu's avatar
frtabu committed
1002 1003 1004 1005 1006
          /* 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
           */
          if (NFAPI_MODE == NFAPI_UE_STUB_PNF ) {
1007
#ifdef UESIM_EXPANSION
1008

1009
            if (UE_NAS_USE_TUN) {
1010
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
1011
            } else {
frtabu's avatar
frtabu committed
1012
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = 0;
1013
            }
1014

1015
#else
frtabu's avatar
frtabu committed
1016
            ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
1017
#endif
frtabu's avatar
frtabu committed
1018 1019 1020
          } else {  // nfapi_mode
            if (UE_NAS_USE_TUN) {
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
frtabu's avatar
frtabu committed
1021 1022 1023
            } else {
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = 1;
            }
frtabu's avatar
frtabu committed
1024
          } // nfapi_mode
1025
        }
1026
      } else {
frtabu's avatar
frtabu committed
1027 1028
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
1029
      }
1030

1031
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
frtabu's avatar
frtabu committed
1032 1033 1034
        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);
1035 1036 1037 1038
      }

      memcpy(&new_sdu_p->data[sizeof (pdcp_data_ind_header_t)],
             &sdu_buffer_pP->data[payload_offset],
1039 1040 1041 1042
             sdu_buffer_sizeP - payload_offset);
      list_add_tail_eurecom (new_sdu_p, sdu_list_p);
    }

frtabu's avatar
frtabu committed
1043 1044 1045 1046 1047 1048
    /* 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);
1049 1050 1051
  }

  /* Update PDCP statistics */
frtabu's avatar
frtabu committed
1052 1053
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ) {
1054
      break;
1055
    }
frtabu's avatar
frtabu committed
1056 1057
  }

1058
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1059
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1060
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1061
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1062
  Pdcp_stats_rx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=sequence_number;
1063
  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]);
1064
  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]);
1065
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
1066
  free_mem_block(sdu_buffer_pP, __func__);
1067

1068 1069 1070 1071 1072
  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);
  }
1073

gauthier's avatar
gauthier committed
1074
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
1075 1076 1077
  return TRUE;
}

frtabu's avatar
frtabu committed
1078
void pdcp_update_stats(const protocol_ctxt_t *const  ctxt_pP) {
1079
  uint16_t           pdcp_uid = 0;
nikaeinn's avatar
nikaeinn committed
1080
  uint8_t            rb_id     = 0;
frtabu's avatar
frtabu committed
1081 1082 1083 1084

  // these stats are measured for both eNB and UE on per seond basis
  for (rb_id =0; rb_id < NB_RB_MAX; rb_id ++) {
    for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
1085 1086
      //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
1087
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0) {
        // unit: bit/s
        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;
1104
      }
frtabu's avatar
frtabu committed
1105

knopp's avatar
knopp committed
1106
      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0) {
        // rx stats
        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];

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

        // 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
1124 1125 1126
    }
  }
}
1127 1128


1129
//-----------------------------------------------------------------------------
1130 1131
void
pdcp_run (
frtabu's avatar
frtabu committed
1132
  const protocol_ctxt_t *const  ctxt_pP
1133 1134
)
//-----------------------------------------------------------------------------
1135
{
1136 1137 1138 1139 1140
  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);
  }
1141

1142
  pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
frtabu's avatar
frtabu committed
1143
  pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023
1144
  pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
nikaeinn's avatar
nikaeinn committed
1145
  pdcp_update_stats(ctxt_pP);
gauthier's avatar
gauthier committed
1146
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
1147 1148 1149
  MessageDef   *msg_p;
  int           result;
  protocol_ctxt_t  ctxt;
1150

1151 1152 1153 1154 1155 1156
  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) {
      switch (ITTI_MSG_ID(msg_p)) {
frtabu's avatar
frtabu committed
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
        case RRC_DCCH_DATA_REQ:
          PROTOCOL_CTXT_SET_BY_MODULE_ID(
            &ctxt,
            RRC_DCCH_DATA_REQ (msg_p).module_id,
            RRC_DCCH_DATA_REQ (msg_p).enb_flag,
            RRC_DCCH_DATA_REQ (msg_p).rnti,
            RRC_DCCH_DATA_REQ (msg_p).frame,
            0,
            RRC_DCCH_DATA_REQ (msg_p).eNB_index);
          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
                PROTOCOL_CTXT_ARGS(&ctxt),
                ITTI_MSG_NAME (msg_p),
                ITTI_MSG_ORIGIN_NAME(msg_p),
                ITTI_MSG_INSTANCE (msg_p),
                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);
          LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %d \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
          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,
1183 1184
                                  RRC_DCCH_DATA_REQ (msg_p).mode,
                                  NULL, NULL
frtabu's avatar
frtabu committed
1185
                                 );
1186

frtabu's avatar
frtabu committed
1187 1188
          if (result != TRUE)
            LOG_E(PDCP, "PDCP data request failed!\n");
1189

frtabu's avatar
frtabu committed
1190 1191 1192 1193
          // 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;
1194

frtabu's avatar
frtabu committed
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
        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);
        }
1209
        break;
frtabu's avatar
frtabu committed
1210 1211 1212 1213

        default:
          LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
          break;
1214
      }
1215 1216 1217 1218

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