pdcp.c 67 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
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 34 35
#ifndef USER_MODE
#include <rtai_fifos.h>
#endif
36
#include "assertions.h"
37
#include "hashtable.h"
38 39 40 41 42
#include "pdcp.h"
#include "pdcp_util.h"
#include "pdcp_sequence_manager.h"
#include "LAYER2/RLC/rlc.h"
#include "LAYER2/MAC/extern.h"
43
#include "RRC/LITE/proto.h"
44 45 46
#include "pdcp_primitives.h"
#include "OCG.h"
#include "OCG_extern.h"
47
#include "otg_rx.h"
48 49 50 51
#include "UTIL/LOG/log.h"
#include <inttypes.h>
#include "platform_constants.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
52
#include "msc.h"
53

54 55 56 57
#if defined(ENABLE_SECURITY)
# include "UTIL/OSA/osa_defs.h"
#endif

58 59 60 61
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

62
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
Lionel Gauthier's avatar
 
Lionel Gauthier committed
63
#  include "gtpv1u_eNB_task.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
64
#  include "gtpv1u.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
65 66
#endif

67 68 69 70 71 72 73 74 75 76 77 78 79
#ifndef OAI_EMU
extern int otg_enabled;
#endif


//-----------------------------------------------------------------------------
/*
 * 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()
 */
80
boolean_t pdcp_data_req(
81
  protocol_ctxt_t*  ctxt_pP,
82 83 84 85 86 87
  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,
88 89 90
  const pdcp_transmission_mode_t modeP
)
//-----------------------------------------------------------------------------
91
{
92

93
  pdcp_t            *pdcp_p          = NULL;
94 95 96 97 98
  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;
99 100
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
101
  boolean_t          ret             = TRUE;
102

103 104
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
105
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
106
  CHECK_CTXT_ARGS(ctxt_pP);
107

Cedric Roux's avatar
Cedric Roux committed
108 109 110 111 112
#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

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  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?
   */

  if (sdu_buffer_sizeP > MAX_IP_PACKET_SIZE) {
    LOG_E(PDCP, "Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
          sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
    // XXX What does following call do?
    mac_xface->macphy_exit("PDCP sdu buffer size > MAX_IP_PACKET_SIZE");
  }
  
129
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
130
    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);
131
  } else {
132
    if (srb_flagP) {
Navid Nikaein's avatar
Navid Nikaein committed
133
      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);
134
    } else {
135
      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);
136
    }
137
  }
138

139 140
  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);
141

142 143
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
144 145 146 147
      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;
148
      return FALSE;
149
    }
150 151
  }else{
    // instance for a given RB is configured
152
    ctxt_pP->configured=TRUE;
153
  }
154
    
155 156 157 158 159
  if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
160

161
  // PDCP transparent mode for MBMS traffic
162

163
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
164
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
165
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
166 167 168

    if (pdcp_pdu_p != NULL) {
      memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
169
#if defined(DEBUG_PDCP_PAYLOAD)
170 171 172
      rlc_util_print_hex_octets(PDCP,
                                (unsigned char*)&pdcp_pdu_p->data[0],
                                sdu_buffer_sizeP);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
173
#endif
174 175 176
      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;
177 178
      LOG_W(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
179
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
180 181
      AssertFatal(0, PROTOCOL_CTXT_FMT"[RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  PROTOCOL_CTXT_ARGS(ctxt_pP),
182
                  rb_idP);
183
#endif
184
    }
185
  } else {
186 187 188 189 190 191 192 193 194 195
    // 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;
196

197 198
    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),
199 200 201
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
202

203 204 205
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
206
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
207 208

    if (pdcp_pdu_p != NULL) {
209
      /*
210 211 212
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
213
       */
214

215 216 217 218 219 220
      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);
221

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

226 227 228 229 230
          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);
          }
231

232
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
233 234 235 236 237 238 239
          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 ;
240

241
        if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
242 243
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
244

245 246 247 248 249
          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);
          }
250

251
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
252 253
          return FALSE;
        }
254
      }
255

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

265
        free_mem_block(pdcp_pdu_p, __func__);
266

267 268 269 270 271
        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);
        }
272

273
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
274 275 276 277 278 279 280 281 282 283 284
        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
285
      for (i=0; i<pdcp_tailer_len; i++) {
286
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
287
      }
288 289 290 291 292 293 294

#if defined(ENABLE_SECURITY)

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

295 296 297 298 299
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
300 301 302 303 304 305 306 307 308 309

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

310 311 312 313 314
        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);
        }
315 316 317 318 319 320 321 322 323 324 325 326
      }

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

327 328 329 330 331
      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);
      }
332 333 334 335 336 337 338 339 340

#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
341
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
342 343 344 345 346 347 348
      return FALSE;
    }

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

353
    for (i = 0; i < pdcp_pdu_size; i++) {
354
      LOG_F(PDCP,"%02x ", ((uint8_t*)pdcp_pdu_p->data)[i]);
355
    }
356 357 358 359

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

361
  }
362

363 364 365
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
366
    ret=TRUE;
367 368 369 370
    break;

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

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

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

  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);
386 387
    ret= FALSE;
    break;
388
  }
389

390 391 392 393 394
  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);
  }
395

396 397 398 399
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
400
  /*
401
   if (rb_id>=DTCH) {
402
    if (ctxt_pP->enb_flag == 1) {
403 404 405 406 407 408 409
      Pdcp_stats_tx[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH]++;
      Pdcp_stats_tx_bytes[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH] += sdu_buffer_size;
    } else {
      Pdcp_stats_tx[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH]++;
      Pdcp_stats_tx_bytes[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH] += sdu_buffer_size;
    }
    }*/
410
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
411
  return ret;
412 413 414

}

415

416 417 418
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
419 420 421 422 423
  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,
424 425 426
  mem_block_t* const sdu_buffer_pP
)
//-----------------------------------------------------------------------------
427
{
428 429 430
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
431 432
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
433
  pdcp_sn_t    sequence_number = 0;
434
  volatile sdu_size_t   payload_offset  = 0;
435
  rb_id_t      rb_id            = rb_idP;
436
  boolean_t    packet_forwarded = FALSE;
437 438 439
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
440
  MessageDef  *message_p        = NULL;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
441
  uint8_t     *gtpu_buffer_p    = NULL;
442
#endif
443

444

445
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
446

447 448
#ifdef OAI_EMU

449
  CHECK_CTXT_ARGS(ctxt_pP);
450

451
#endif
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

Lionel Gauthier's avatar
sync  
Lionel 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);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
493
    }
494

Lionel Gauthier's avatar
sync  
Lionel 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__);
516
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
517
      return FALSE;
518
    }
519
  }
520

521
  sdu_list_p = &pdcp_sdu_list;
522

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

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
Lionel Gauthier's avatar
 
Lionel Gauthier committed
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 594 595 596
      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);
597
      /*
598 599
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
600 601
       */
#if 0
602
      LOG_D(PDCP, "Ignoring PDU...\n");
603
      free_mem_block(sdu_buffer, __func__);
604
      return FALSE;
605
#else
606
      //LOG_W(PDCP, "Delivering out-of-order SDU to upper layer...\n");
607
#endif
608
    }
609 610 611

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

614
      if (pdcp_p->security_activated == 1) {
615 616 617 618 619
        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);
        }
620 621 622 623 624 625 626 627 628 629

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

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

637 638
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
639 640 641 642 643 644 645
  	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);
646 647 648 649
      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]);
650
      free_mem_block(sdu_buffer_pP, __func__);
651

652
      // free_mem_block(new_sdu, __func__);
653 654 655 656 657
      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);
      }
658

659
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
660 661
      return TRUE;
    }
662 663 664 665

    /*
     * DRBs
     */
666 667
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
668

669
    if (pdcp_p->security_activated == 1) {
670 671 672 673 674
      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);
      }
675

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

686 687 688 689 690
      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);
      }
691

692
    }
693

694
#endif
695
  } else {
696
    payload_offset=0;
697
  }
698

699
#if defined(USER_MODE) && defined(OAI_EMU)
700

701
  if (oai_emulation.info.otg_enabled == 1) {
Cedric Roux's avatar
Cedric Roux committed
702
    //unsigned int dst_instance;
703 704
    int    ctime;

705
    if ((pdcp_p->rlc_mode == RLC_MODE_AM)&&(MBMS_flagP==0) ) {
706 707 708
      pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
    }

709
#if defined(DEBUG_PDCP_PAYLOAD)
710 711 712
    rlc_util_print_hex_octets(PDCP,
                              (unsigned char*)&sdu_buffer_pP->data[payload_offset],
                              sdu_buffer_sizeP - payload_offset);
713
#endif
714

715
    ctime = oai_emulation.info.time_ms; // avg current simulation time in ms : we may get the exact time through OCG?
716 717 718 719 720 721
    if (MBMS_flagP == 0){
      LOG_D(PDCP,
	    PROTOCOL_PDCP_CTXT_FMT"Check received buffer :  (dst %d)\n",
	    PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
	    ctxt_pP->instance);
    }
722 723 724 725
    if (otg_rx_pkt(
          ctxt_pP->instance,
          ctime,
          (const char*)(&sdu_buffer_pP->data[payload_offset]),
726
                   sdu_buffer_sizeP - payload_offset ) == 0 ) {
727
      free_mem_block(sdu_buffer_pP, __func__);
728

729 730 731 732 733
      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);
      }
734

735
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
736
      return TRUE;
737
    }
738
  }
739 740 741 742 743

#else

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

746 747 748 749 750
    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);
    }
751

752
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
753 754 755
    return TRUE;
  }

756 757
#endif

758

759 760 761 762 763 764 765 766
  // 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)
   */
767
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
768

769
  if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
770 771 772 773 774 775 776 777
    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);
778 779 780 781 782 783 784 785 786 787
    //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;
788
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
789 790 791
    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;
792
  }
793

794 795 796
#else
  packet_forwarded = FALSE;
#endif
797

798
  if (FALSE == packet_forwarded) {
799
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
800

801 802 803 804 805 806 807 808 809 810
    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;
811
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
812 813 814 815 816

      // 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;
817
#if defined(OAI_EMU)
818
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = ctxt_pP->module_id + oai_emulation.info.nb_enb_local - oai_emulation.info.first_ue_local;
Cedric Roux's avatar
Cedric Roux committed
819
#else
820 821 822 823 824
#  if defined(ENABLE_USE_MME)
        /* 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
825
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = 1;
826
#  endif
827
#endif
828
      } else {
829
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * maxDRB);
830
#if defined(OAI_EMU)
831
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = ctxt_pP->module_id - oai_emulation.info.first_enb_local;
832
#endif
833
      }
834 835 836 837 838
#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
839 840 841 842 843 844 845 846

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

      /* 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",
Cedric Roux's avatar
Cedric Roux committed
847
            sdu_buffer_sizeP  - payload_offset + (int)sizeof(pdcp_data_ind_header_t),
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
            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?
       */

      /*if (ctxt_pP->enb_flag == 1) {
          Pdcp_stats_rx[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH]++;
          Pdcp_stats_rx_bytes[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH] += sdu_buffer_sizeP;
        } else {
          Pdcp_stats_rx[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH]++;
          Pdcp_stats_rx_bytes[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH] += sdu_buffer_sizeP;
        }*/
    }
865
  }
866

867
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
868
  else {
869 870
    AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
871 872
  }

873
#endif
874

875
  free_mem_block(sdu_buffer_pP, __func__);
876

877 878 879 880 881
  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);
  }
882

883
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
884 885 886 887
  return TRUE;
}

//-----------------------------------------------------------------------------
888 889 890 891 892
void
pdcp_run (
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
893
{
894
#if defined(ENABLE_ITTI)
895 896 897 898
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
899
  protocol_ctxt_t  ctxt;
900
#endif
901

902 903 904 905 906
  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);
  }
907

908
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
909

910 911
#if defined(ENABLE_ITTI)

912 913 914 915 916 917 918 919 920 921
  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:
922
	PROTOCOL_CTXT_SET_BY_MODULE_ID(
923 924 925 926
          &ctxt,
          RRC_DCCH_DATA_REQ (msg_p).module_id,
          RRC_DCCH_DATA_REQ (msg_p).enb_flag,
          RRC_DCCH_DATA_REQ (msg_p).rnti,
927 928 929
          RRC_DCCH_DATA_REQ (msg_p).frame, 
	  0,
	  RRC_DCCH_DATA_REQ (msg_p).eNB_index);
930
        LOG_I(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
931 932 933 934 935 936 937 938
              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);
939 940 941 942 943 944 945 946 947

        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);
948 949
        if (result != TRUE)
          LOG_E(PDCP, "PDCP data request failed!\n");
950 951 952 953 954 955 956 957 958

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

      default:
        LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
        break;
959
      }
960 961 962 963

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

# if 0
  {
968
    MessageDef *msg_resp_p;
969

970
    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
971

972
    itti_send_msg_to_task(TASK_RRC_ENB, 1, msg_resp_p);
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
  }
  {
    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
989 990
#endif

991
#if defined(USER_MODE) && defined(OAI_EMU)
992
    pdcp_fifo_read_input_sdus_from_otg(ctxt_pP);
993

Lionel Gauthier's avatar
Lionel Gauthier committed
994
#endif
995 996

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

999
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
Lionel Gauthier's avatar
Lionel Gauthier committed
1000
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1001
  {
1002
    pdcp_fifo_read_input_sdus(ctxt_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
1003
  }
1004

1005
  // PDCP -> NAS/IP traffic: RX
1006 1007 1008
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1009

1010 1011 1012
  else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1013

1014
  pdcp_fifo_flush_sdus(ctxt_pP);
1015

1016 1017 1018 1019 1020
  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);
  }
1021

1022 1023 1024 1025 1026
  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);
  }
1027
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
1028 1029
}

Raymond Knopp's avatar
 
Raymond Knopp committed
1030

1031 1032 1033 1034 1035 1036 1037
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1038 1039
  DRB_Identity_t  srb_id         = 0;
  DRB_Identity_t  drb_id         = 0;
1040 1041
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
Raymond Knopp's avatar
 
Raymond Knopp committed
1042 1043 1044

  // check and remove SRBs first

1045
  for (srb_id=0; srb_id<2; srb_id++) {
1046 1047
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES);
    h_rc = hashtable_remove(pdcp_coll_p, key);
Raymond Knopp's avatar
 
Raymond Knopp committed
1048 1049
  }

1050
  for (drb_id=0; drb_id<maxDRB; drb_id++) {
1051 1052
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
    h_rc = hashtable_remove(pdcp_coll_p, key);
Raymond Knopp's avatar
 
Raymond Knopp committed
1053 1054 1055

  }

1056 1057
  (void)h_rc; /* remove gcc warning "set but not used" */

Raymond Knopp's avatar
 
Raymond Knopp committed
1058 1059 1060 1061
  return 1;
}


1062 1063 1064
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
1065 1066 1067 1068 1069 1070 1071 1072
  const protocol_ctxt_t* const  ctxt_pP,
  SRB_ToAddModList_t  *const srb2add_list_pP,
  DRB_ToAddModList_t  *const drb2add_list_pP,
  DRB_ToReleaseList_t *const drb2release_list_pP,
  const uint8_t                   security_modeP,
  uint8_t                  *const kRRCenc_pP,
  uint8_t                  *const kRRCint_pP,
  uint8_t                  *const kUPenc_pP
Cedric Roux's avatar
Cedric Roux committed
1073
#if defined(Rel10) || defined(Rel14)
1074
  ,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
1075
#endif
1076
  ,rb_id_t                 *const defaultDRB 
1077
)
1078
//-----------------------------------------------------------------------------
1079
{
1080
  long int        lc_id          = 0;
1081
  DRB_Identity_t  srb_id         = 0;
1082
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1083
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1084
  DRB_Identity_t  drb_id         = 0;
1085
  DRB_Identity_t *pdrb_id_p      = NULL;
1086
  uint8_t         drb_sn         = 12;
1087 1088
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1089
  long int        cnt            = 0;
1090 1091
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1092 1093 1094
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
1095

1096 1097
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1098 1099
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
Cedric Roux's avatar
Cedric Roux committed
1100
#if defined(Rel10) || defined(Rel14)
1101
  int i,j;
1102 1103
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1104 1105
#endif

1106 1107 1108 1109 1110 1111
  LOG_T(PDCP, PROTOCOL_CTXT_FMT" %s() SRB2ADD %p DRB2ADD %p DRB2RELEASE %p\n",
        PROTOCOL_CTXT_ARGS(ctxt_pP),
        __FUNCTION__,
        srb2add_list_pP,
        drb2add_list_pP,
        drb2release_list_pP);
1112

1113 1114
  // srb2add_list does not define pdcp config, we use rlc info to setup the pdcp dcch0 and dcch1 channels

1115
  if (srb2add_list_pP != NULL) {
1116 1117 1118 1119
    for (cnt=0; cnt<srb2add_list_pP->list.count; cnt++) {
      srb_id = srb2add_list_pP->list.array[cnt]->srb_Identity;
      srb_toaddmod_p = srb2add_list_pP->list.array[cnt];
      rlc_type = RLC_MODE_AM;
1120
      lc_id = srb_id;
1121 1122
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES);
      h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
1123

1124 1125 1126 1127 1128
      if (h_rc == HASH_TABLE_OK) {
        action = CONFIG_ACTION_MODIFY;
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_MODIFY key 0x%"PRIx64"\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
              key);
1129
      } else {
1130 1131 1132
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1133

1134 1135 1136 1137 1138 1139
        if (h_rc != HASH_TABLE_OK) {
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64" FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
          free(pdcp_p);
          return TRUE;
1140

1141
      } else {
1142 1143 1144 1145
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
      }

      if (srb_toaddmod_p->rlc_Config) {
        switch (srb_toaddmod_p->rlc_Config->present) {
        case SRB_ToAddMod__rlc_Config_PR_NOTHING:
          break;

        case SRB_ToAddMod__rlc_Config_PR_explicitValue:
          switch (srb_toaddmod_p->rlc_Config->choice.explicitValue.present) {
          case RLC_Config_PR_NOTHING:
            break;
1157

1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
          default:
            pdcp_config_req_asn1 (
              ctxt_pP,
              pdcp_p,
              SRB_FLAG_YES,
              rlc_type,
              action,
              lc_id,
              mch_id,
              srb_id,
              srb_sn,
              0, // drb_report
              0, // header compression
              security_modeP,
              kRRCenc_pP,
              kRRCint_pP,
              kUPenc_pP);
            break;
1176
          }
1177 1178 1179 1180

          break;

        case SRB_ToAddMod__rlc_Config_PR_defaultValue:
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
        	pdcp_config_req_asn1 (
        	              ctxt_pP,
        	              pdcp_p,
        	              SRB_FLAG_YES,
        	              rlc_type,
        	              action,
        	              lc_id,
        	              mch_id,
        	              srb_id,
        	              srb_sn,
        	              0, // drb_report
        	              0, // header compression
        	              security_modeP,
        	              kRRCenc_pP,
        	              kRRCint_pP,
        	              kUPenc_pP);
1197 1198 1199 1200
          // already the default values
          break;

        default:
1201
          DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
1202 1203
          break;
        }
1204
      }
1205
    }
1206
  }
1207

1208 1209
  // reset the action

1210
  if (drb2add_list_pP != NULL) {
1211
    for (cnt=0; cnt<drb2add_list_pP->list.count; cnt++) {
1212

1213
      drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
1214

1215
      drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1216 1217 1218 1219 1220 1221 1222 1223 1224
      if (drb_toaddmod_p->logicalChannelIdentity) {
        lc_id = *(drb_toaddmod_p->logicalChannelIdentity);
      } else {
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" logicalChannelIdentity is missing in DRB-ToAddMod information element!\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
        continue;
      }

      if (lc_id == 1 || lc_id == 2) {
Cedric Roux's avatar
Cedric Roux committed
1225
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1226 1227 1228
        continue;
      }

1229 1230 1231
      DevCheck4(drb_id < maxDRB, drb_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, drb_id, SRB_FLAG_NO);
      h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
1232

1233 1234 1235 1236 1237
      if (h_rc == HASH_TABLE_OK) {
        action = CONFIG_ACTION_MODIFY;
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_MODIFY key 0x%"PRIx64"\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
              key);
1238

1239 1240
      } else {
        action = CONFIG_ACTION_ADD;
1241 1242 1243
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1244
        // save the first configured DRB-ID as the default DRB-ID
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
        if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
          key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
          h_defaultDRB_rc = hashtable_insert(pdcp_coll_p, key_defaultDRB, pdcp_p);
        } else {
          h_defaultDRB_rc = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
        }

        if (h_defaultDRB_rc != HASH_TABLE_OK) {
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD default DRB key 0x%"PRIx64" FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key_defaultDRB);
          free(pdcp_p);
          return TRUE;
1258
        } else if (h_rc != HASH_TABLE_OK) {
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64" FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
          free(pdcp_p);
          return TRUE;
        } else {
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64"\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
         }
      }
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295

      if (drb_toaddmod_p->pdcp_Config) {
        if (drb_toaddmod_p->pdcp_Config->discardTimer) {
          // set the value of the timer
        }

        if (drb_toaddmod_p->pdcp_Config->rlc_AM) {
          drb_report = drb_toaddmod_p->pdcp_Config->rlc_AM->statusReportRequired;
          drb_sn = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size
          rlc_type = RLC_MODE_AM;
        }

        if (drb_toaddmod_p->pdcp_Config->rlc_UM) {
          drb_sn = drb_toaddmod_p->pdcp_Config->rlc_UM->pdcp_SN_Size;
          rlc_type =RLC_MODE_UM;
        }

        switch (drb_toaddmod_p->pdcp_Config->headerCompression.present) {
        case PDCP_Config__headerCompression_PR_NOTHING:
        case PDCP_Config__headerCompression_PR_notUsed:
          header_compression_profile=0x0;
          break;

        case PDCP_Config__headerCompression_PR_rohc:

          // parse the struc and get the rohc profile
1296
          if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0001) {
1297
            header_compression_profile=0x0001;
1298
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0002) {
1299
            header_compression_profile=0x0002;
1300
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0003) {
1301
            header_compression_profile=0x0003;
1302
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0004) {
1303
            header_compression_profile=0x0004;
1304
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0006) {
1305
            header_compression_profile=0x0006;
1306
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0101) {
1307
            header_compression_profile=0x0101;
1308
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0102) {
1309
            header_compression_profile=0x0102;
1310
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0103) {
1311
            header_compression_profile=0x0103;
1312
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0104) {
1313
            header_compression_profile=0x0104;
1314
          } else {
1315 1316
            header_compression_profile=0x0;
            LOG_W(PDCP,"unknown header compresion profile\n");
1317
          }
1318 1319 1320 1321 1322

          // set the applicable profile
          break;

        default:
Cedric Roux's avatar
Cedric Roux committed
1323
          LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT"[RB %ld] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
1324
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), drb_id);
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
          break;
        }

        pdcp_config_req_asn1 (
          ctxt_pP,
          pdcp_p,
          SRB_FLAG_NO,
          rlc_type,
          action,
          lc_id,
          mch_id,
          drb_id,
          drb_sn,
          drb_report,
          header_compression_profile,
          security_modeP,
          kRRCenc_pP,
          kRRCint_pP,
          kUPenc_pP);
1344
      }
1345
    }
1346 1347
  }

1348
  if (drb2release_list_pP != NULL) {
1349 1350 1351
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1352 1353 1354 1355
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_NO);
      h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1356
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1357 1358 1359
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1360
      }
1361 1362
      lc_id = pdcp_p->lcid;

1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
      action = CONFIG_ACTION_REMOVE;
      pdcp_config_req_asn1 (
        ctxt_pP,
        pdcp_p,
        SRB_FLAG_NO,
        rlc_type,
        action,
        lc_id,
        mch_id,
        drb_id,
        0,
        0,
        0,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1380
      h_rc = hashtable_remove(pdcp_coll_p, key);
1381 1382

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1383
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
        key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
        h_defaultDRB_rc = hashtable_get(pdcp_coll_p, key_defaultDRB, (void**)&pdcp_p);

        if (h_defaultDRB_rc == HASH_TABLE_OK) {
          h_defaultDRB_rc = hashtable_remove(pdcp_coll_p, key_defaultDRB);
        } else {
          LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED default DRB\n", PROTOCOL_CTXT_ARGS(ctxt_pP));
        }
      } else {
        key_defaultDRB = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
      }
1395
    }
1396 1397
  }

Cedric Roux's avatar
Cedric Roux committed
1398
#if defined(Rel10) || defined(Rel14)
1399

1400
  if (pmch_InfoList_r9_pP != NULL) {
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412
    for (i=0; i<pmch_InfoList_r9_pP->list.count; i++) {
      mbms_SessionInfoList_r9_p = &(pmch_InfoList_r9_pP->list.array[i]->mbms_SessionInfoList_r9);

      for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
        MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
        lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string

        // can set the mch_id = i
        if (ctxt_pP->enb_flag) {
          drb_id =  (mch_id * maxSessionPerPMCH ) + lc_id ;//+ (maxDRB + 3)*MAX_MOBILES_PER_ENB; // 1

1413
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1414 1415 1416 1417 1418 1419 1420
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
          drb_id =  (mch_id * maxSessionPerPMCH ) + lc_id; // + (maxDRB + 3); // 15

1421
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1422 1423 1424
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1425
          }
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
        }

        pdcp_config_req_asn1 (
          ctxt_pP,
          NULL,  // unused for MBMS
          SRB_FLAG_NO,
          RLC_MODE_NONE,
          action,
          lc_id,
          mch_id,
          drb_id,
          0,   // unused for MBMS
          0,   // unused for MBMS
          0,   // unused for MBMS
          0,   // unused for MBMS
          NULL,  // unused for MBMS
          NULL,  // unused for MBMS
          NULL); // unused for MBMS
1444
      }
1445
    }
1446
  }
1447

1448
#endif
1449
  return 0;
1450 1451
}

1452 1453

//-----------------------------------------------------------------------------
1454 1455
boolean_t
pdcp_config_req_asn1 (
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
  const protocol_ctxt_t* const  ctxt_pP,
  pdcp_t         * const        pdcp_pP,
  const srb_flag_t              srb_flagP,
  const rlc_mode_t              rlc_modeP,
  const config_action_t         actionP,
  const uint16_t                lc_idP,
  const uint16_t                mch_idP,
  const rb_id_t                 rb_idP,
  const uint8_t                 rb_snP,
  const uint8_t                 rb_reportP,
  const uint16_t                header_compression_profileP,
  const uint8_t                 security_modeP,
  uint8_t         *const        kRRCenc_pP,
  uint8_t         *const        kRRCint_pP,
  uint8_t         *const        kUPenc_pP)
1471
//-----------------------------------------------------------------------------
1472
{
1473

1474
  switch (actionP) {
1475
  case CONFIG_ACTION_ADD:
1476
    DevAssert(pdcp_pP != NULL);
1477 1478
    if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
      pdcp_pP->is_ue = FALSE;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1479
      //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti;
1480
      pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1481
      //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % NUMBER_OF_UE_MAX;
1482 1483 1484 1485
    } else {
      pdcp_pP->is_ue = TRUE;
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
    }
1486
    pdcp_pP->is_srb                     = (srb_flagP == SRB_FLAG_YES) ? TRUE : FALSE;
Lionel Gauthier's avatar
Lionel Gauthier committed
1487
    pdcp_pP->lcid                       = lc_idP;
1488
    pdcp_pP->rb_id                      = rb_idP;
1489
    pdcp_pP->header_compression_profile = header_compression_profileP;
Lionel Gauthier's avatar
Lionel Gauthier committed
1490
    pdcp_pP->status_report              = rb_reportP;
1491

1492
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1493
      pdcp_pP->seq_num_size = PDCP_SN_12BIT;
1494
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1495
      pdcp_pP->seq_num_size = PDCP_SN_7BIT;
1496
    } else {
1497
      pdcp_pP->seq_num_size = PDCP_SN_5BIT;
1498
    }
1499

1500

1501 1502 1503 1504 1505 1506 1507 1508 1509
    pdcp_pP->rlc_mode                         = rlc_modeP;
    pdcp_pP->next_pdcp_tx_sn                  = 0;
    pdcp_pP->next_pdcp_rx_sn                  = 0;
    pdcp_pP->next_pdcp_rx_sn_before_integrity = 0;
    pdcp_pP->tx_hfn                           = 0;
    pdcp_pP->rx_hfn                           = 0;
    pdcp_pP->last_submitted_pdcp_rx_sn        = 4095;
    pdcp_pP->first_missing_pdu                = -1;
    pdcp_pP->rx_hfn_offset                    = 0;
1510

1511
    LOG_N(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %d) "
1512
            "configured with SN size %d bits and RLC %s\n",
1513 1514
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
1515
	  (srb_flagP == SRB_FLAG_YES) ? "SRB" : "DRB",
1516 1517
          rb_idP,
          pdcp_pP->seq_num_size,
1518
	  (rlc_modeP == RLC_MODE_AM ) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1519 1520
    /* Setup security */
    if (security_modeP != 0xff) {
1521 1522 1523 1524 1525 1526 1527 1528 1529
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1530 1531
    }
    break;
1532

1533
  case CONFIG_ACTION_MODIFY:
1534 1535 1536 1537
    DevAssert(pdcp_pP != NULL);
    pdcp_pP->header_compression_profile=header_compression_profileP;
    pdcp_pP->status_report = rb_reportP;
    pdcp_pP->rlc_mode = rlc_modeP;
1538

1539 1540
    /* Setup security */
    if (security_modeP != 0xff) {
1541 1542 1543 1544 1545 1546 1547 1548 1549
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1550
    }
1551

1552
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1553
      pdcp_pP->seq_num_size = 7;
1554
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1555
      pdcp_pP->seq_num_size = 12;
1556
    } else {
1557
      pdcp_pP->seq_num_size=5;
1558
    }
1559

1560
    LOG_N(PDCP,PROTOCOL_PDCP_CTXT_FMT" Action MODIFY LCID %d "
Navid Nikaein's avatar
Navid Nikaein committed
1561
            "RB id %d reconfigured with SN size %d and RLC %s \n",
1562 1563 1564 1565
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
          rb_idP,
          rb_snP,
1566
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1567
    break;
1568

1569
  case CONFIG_ACTION_REMOVE:
1570
    DevAssert(pdcp_pP != NULL);
1571
//#warning "TODO pdcp_module_id_to_rnti"
1572 1573 1574 1575 1576
    //pdcp_module_id_to_rnti[ctxt_pP.module_id ][dst_id] = NOT_A_RNTI;
    LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE LCID %d RBID %d configured\n",
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
          rb_idP);
1577

1578 1579
    /* Security keys */
    if (pdcp_pP->kUPenc != NULL) {
1580
      free(pdcp_pP->kUPenc);
1581
    }
1582

1583
    if (pdcp_pP->kRRCint != NULL) {
1584
      free(pdcp_pP->kRRCint);
1585
    }
1586

1587
    if (pdcp_pP->kRRCenc != NULL) {
1588
      free(pdcp_pP->kRRCenc);
1589
    }
1590

1591
    memset(pdcp_pP, 0, sizeof(pdcp_t));
1592
    break;
Cedric Roux's avatar
Cedric Roux committed
1593
#if defined(Rel10) || defined(Rel14)
1594

1595 1596
  case CONFIG_ACTION_MBMS_ADD:
  case CONFIG_ACTION_MBMS_MODIFY:
1597 1598
    LOG_D(PDCP," %s service_id/mch index %d, session_id/lcid %d, rbid %d configured\n",
          //PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
1599 1600 1601 1602 1603 1604 1605 1606
          actionP == CONFIG_ACTION_MBMS_ADD ? "CONFIG_ACTION_MBMS_ADD" : "CONFIG_ACTION_MBMS_MODIFY",
          mch_idP,
          lc_idP,
          rb_idP);

    if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
      pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = TRUE ;
      pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].rb_id = rb_idP;
1607
    } else {
1608 1609
      pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = TRUE ;
      pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].rb_id = rb_idP;
1610
    }
1611

1612
    break;
Lionel Gauthier's avatar
Lionel Gauthier committed
1613
#endif
1614

1615
  case CONFIG_ACTION_SET_SECURITY_MODE:
1616
    pdcp_config_set_security(
1617 1618 1619 1620 1621 1622 1623 1624
      ctxt_pP,
      pdcp_pP,
      rb_idP,
      lc_idP,
      security_modeP,
      kRRCenc_pP,
      kRRCint_pP,
      kUPenc_pP);
1625
    break;
1626

1627
  default:
1628
    DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1629
    break;
1630
  }
1631

1632 1633
  return 0;
}
1634

1635 1636 1637
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
1638 1639 1640 1641 1642 1643 1644 1645
  const protocol_ctxt_t* const  ctxt_pP,
  pdcp_t         * const pdcp_pP,
  const rb_id_t         rb_idP,
  const uint16_t        lc_idP,
  const uint8_t         security_modeP,
  uint8_t        * const kRRCenc,
  uint8_t        * const kRRCint,
  uint8_t        * const  kUPenc)
1646
//-----------------------------------------------------------------------------
1647
{
1648
  DevAssert(pdcp_pP != NULL);
1649

1650
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1651 1652
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1653

1654 1655
    LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_SET_SECURITY_MODE: cipheringAlgorithm %d integrityProtAlgorithm %d\n",
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
1656 1657 1658 1659 1660 1661
            pdcp_pP->cipheringAlgorithm,
            pdcp_pP->integrityProtAlgorithm);

    pdcp_pP->kRRCenc = kRRCenc;
    pdcp_pP->kRRCint = kRRCint;
    pdcp_pP->kUPenc  = kUPenc;
1662

1663 1664
    /* Activate security */
    pdcp_pP->security_activated = 1;
Lionel Gauthier's avatar
Lionel Gauthier committed
1665 1666
	MSC_LOG_EVENT(
	  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1667
	  "0 Set security ciph %X integ %x UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1668 1669 1670
	  pdcp_pP->cipheringAlgorithm,
	  pdcp_pP->integrityProtAlgorithm,
	  ctxt_pP->rnti);
1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
  }
  /*particular case activated by SecurityModeFailure*/
  else if(security_modeP == -1){
	  // in this way in NB_pdcp_data_req function you never call "pdcp_apply_security"
	  // and we never call pdcp_validate_security in NB_pdcp_data_indi
	    	pdcp_pP->security_activated = 0;
	    	pdcp_pP->cipheringAlgorithm = 0;
	    	pdcp_pP->integrityProtAlgorithm = 0;
  }
  else {
Lionel Gauthier's avatar
Lionel Gauthier committed
1681 1682
	  MSC_LOG_EVENT(
	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1683
	    "0 Set security failed UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1684 1685
	    ctxt_pP->rnti);
	  LOG_E(PDCP,PROTOCOL_PDCP_CTXT_FMT"  bad security mode %d",
1686 1687
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
1688
  }
1689 1690
}

1691
//-----------------------------------------------------------------------------
1692
// MP: seems to be no more used (old code)
1693 1694
void
rrc_pdcp_config_req (
1695 1696 1697 1698 1699
  const protocol_ctxt_t* const  ctxt_pP,
  const srb_flag_t srb_flagP,
  const uint32_t actionP,
  const rb_id_t rb_idP,
  const uint8_t security_modeP)
1700
//-----------------------------------------------------------------------------
1701
{
1702
  pdcp_t *pdcp_p = NULL;
1703 1704 1705
  hash_key_t       key           = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
  hashtable_rc_t   h_rc;
  h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
1706

1707
  if (h_rc == HASH_TABLE_OK) {
1708 1709

  /*
1710 1711 1712
   * Initialize sequence number state variables of relevant PDCP entity
   */
  switch (actionP) {
1713
  case CONFIG_ACTION_ADD:
1714 1715
    pdcp_p->is_srb = srb_flagP;
    pdcp_p->rb_id  = rb_idP;
1716

1717
    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
1718
      pdcp_p->is_ue = TRUE;
1719
    } else {
1720
      pdcp_p->is_ue = FALSE;
1721
    }
1722 1723 1724 1725 1726 1727 1728 1729 1730

    pdcp_p->next_pdcp_tx_sn = 0;
    pdcp_p->next_pdcp_rx_sn = 0;
    pdcp_p->tx_hfn = 0;
    pdcp_p->rx_hfn = 0;
    /* SN of the last PDCP SDU delivered to upper layers */
    pdcp_p->last_submitted_pdcp_rx_sn = 4095;

    if (rb_idP < DTCH) { // SRB
1731
      pdcp_p->seq_num_size = 5;
1732
    } else { // DRB
1733
      pdcp_p->seq_num_size = 12;
1734
    }
1735

1736
    pdcp_p->first_missing_pdu = -1;
1737 1738 1739
      LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %d (already added) configured\n",
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
            rb_idP);
1740
    break;
1741

1742
  case CONFIG_ACTION_MODIFY:
1743
    break;
1744

1745
  case CONFIG_ACTION_REMOVE:
1746 1747 1748
      LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE: radio bearer id %d configured\n",
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
            rb_idP);
1749 1750 1751 1752 1753 1754 1755 1756
    pdcp_p->next_pdcp_tx_sn = 0;
    pdcp_p->next_pdcp_rx_sn = 0;
    pdcp_p->tx_hfn = 0;
    pdcp_p->rx_hfn = 0;
    pdcp_p->last_submitted_pdcp_rx_sn = 4095;
    pdcp_p->seq_num_size = 0;
    pdcp_p->first_missing_pdu = -1;
    pdcp_p->security_activated = 0;
1757
      h_rc = hashtable_remove(pdcp_coll_p, key);
1758 1759

    break;
1760

1761
  case CONFIG_ACTION_SET_SECURITY_MODE:
1762
    if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1763 1764
      pdcp_p->cipheringAlgorithm= security_modeP & 0x0f;
      pdcp_p->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1765 1766
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_SET_SECURITY_MODE: cipheringAlgorithm %d integrityProtAlgorithm %d\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
1767 1768
            pdcp_p->cipheringAlgorithm,
            pdcp_p->integrityProtAlgorithm );
1769
    } else {
Cedric Roux's avatar
Cedric Roux committed
1770
        LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT" bad security mode %d", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), security_modeP);
1771
    }
1772

1773
    break;
1774

1775
  default:
1776
      DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1777
    break;
1778
  }
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798
  } else {
    switch (actionP) {
    case CONFIG_ACTION_ADD:
      pdcp_p = calloc(1, sizeof(pdcp_t));
      h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

      if (h_rc != HASH_TABLE_OK) {
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" PDCP ADD FAILED\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
        free(pdcp_p);

      } else {
        pdcp_p->is_srb = srb_flagP;
        pdcp_p->rb_id  = rb_idP;

        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          pdcp_p->is_ue = TRUE;

        } else {
          pdcp_p->is_ue = FALSE;
1799 1800
}

1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838
        pdcp_p->next_pdcp_tx_sn = 0;
        pdcp_p->next_pdcp_rx_sn = 0;
        pdcp_p->tx_hfn = 0;
        pdcp_p->rx_hfn = 0;
        /* SN of the last PDCP SDU delivered to upper layers */
        pdcp_p->last_submitted_pdcp_rx_sn = 4095;

        if (rb_idP < DTCH) { // SRB
          pdcp_p->seq_num_size = 5;

        } else { // DRB
          pdcp_p->seq_num_size = 12;
        }

        pdcp_p->first_missing_pdu = -1;
        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Inserting PDCP instance in collection key 0x%"PRIx64"\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), key);
        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %d configured\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              rb_idP);
      }

      break;

    case CONFIG_ACTION_REMOVE:
      LOG_D(PDCP, PROTOCOL_CTXT_FMT" CONFIG_REQ PDCP CONFIG_ACTION_REMOVE PDCP instance not found\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
      break;

    default:
      LOG_E(PDCP, PROTOCOL_CTXT_FMT" CONFIG_REQ PDCP NOT FOUND\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
    }
  }
}


//-----------------------------------------------------------------------------
1839
// TODO PDCP module initialization code might be removed
1840 1841 1842 1843 1844
int
pdcp_module_init (
  void
)
//-----------------------------------------------------------------------------
1845
{
1846
#ifdef PDCP_USE_RT_FIFO
1847 1848
  int ret;

1849
  ret=rtf_create(PDCP2NW_DRIVER_FIFO,32768);
1850 1851

  if (ret < 0) {
1852
    LOG_E(PDCP, "Cannot create PDCP2NW_DRIVER_FIFO fifo %d (ERROR %d)\n", PDCP2NW_DRIVER_FIFO, ret);
1853
    return -1;
1854
  } else {
1855 1856
    LOG_D(PDCP, "Created PDCP2NAS fifo %d\n", PDCP2NW_DRIVER_FIFO);
    rtf_reset(PDCP2NW_DRIVER_FIFO);
1857 1858
  }

1859
  ret=rtf_create(NW_DRIVER2PDCP_FIFO,32768);
1860 1861

  if (ret < 0) {
1862
    LOG_E(PDCP, "Cannot create NW_DRIVER2PDCP_FIFO fifo %d (ERROR %d)\n", NW_DRIVER2PDCP_FIFO, ret);
1863

1864
    return -1;
1865
  } else {
1866 1867
    LOG_D(PDCP, "Created NW_DRIVER2PDCP_FIFO fifo %d\n", NW_DRIVER2PDCP_FIFO);
    rtf_reset(NW_DRIVER2PDCP_FIFO);
1868 1869 1870 1871 1872 1873 1874 1875
  }

  pdcp_2_nas_irq = 0;
  pdcp_input_sdu_remaining_size_to_read=0;
  pdcp_input_sdu_size_read=0;
#endif

  return 0;
1876 1877 1878 1879 1880 1881 1882 1883 1884 1885
}

//-----------------------------------------------------------------------------
void
pdcp_free (
  void* pdcp_pP
)
//-----------------------------------------------------------------------------
{
  pdcp_t* pdcp_p = (pdcp_t*)pdcp_pP;
1886

1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902
  if (pdcp_p != NULL) {
    if (pdcp_p->kUPenc != NULL) {
      free(pdcp_p->kUPenc);
    }

    if (pdcp_p->kRRCint != NULL) {
      free(pdcp_p->kRRCint);
    }

    if (pdcp_p->kRRCenc != NULL) {
      free(pdcp_p->kRRCenc);
    }

    memset(pdcp_pP, 0, sizeof(pdcp_t));
    free(pdcp_pP);
  }
1903 1904 1905
}

//-----------------------------------------------------------------------------
1906 1907
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
1908
{
1909 1910 1911
#ifdef PDCP_USE_RT_FIFO
  rtf_destroy(NW_DRIVER2PDCP_FIFO);
  rtf_destroy(PDCP2NW_DRIVER_FIFO);
1912 1913 1914 1915
#endif
}

//-----------------------------------------------------------------------------
1916
void pdcp_layer_init(void)
1917
//-----------------------------------------------------------------------------
1918
{
1919

Lionel Gauthier's avatar
Lionel Gauthier committed
1920
  module_id_t       instance;
Cedric Roux's avatar
Cedric Roux committed
1921
#if defined(Rel10) || defined(Rel14)
Lionel Gauthier's avatar
Lionel Gauthier committed
1922 1923 1924
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
#endif
1925
  /*
1926 1927
   * Initialize SDU list
   */
1928
  list_init(&pdcp_sdu_list, NULL);
1929 1930
  pdcp_coll_p = hashtable_create ((maxDRB + 2) * 16, NULL, pdcp_free);
  AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
1931

1932
  for (instance = 0; instance < NUMBER_OF_UE_MAX; instance++) {
Cedric Roux's avatar
Cedric Roux committed
1933
#if defined(Rel10) || defined(Rel14)
1934 1935 1936 1937

    for (service_id = 0; service_id < maxServiceCount; service_id++) {
      for (session_id = 0; session_id < maxSessionPerPMCH; session_id++) {
        memset(&pdcp_mbms_array_ue[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
1938
      }
1939
    }
Lionel Gauthier's avatar
Lionel Gauthier committed
1940
#endif
1941
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
1942
  }
1943
  pdcp_eNB_UE_instance_to_rnti_index = 0; 
1944

1945
    
1946
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
Cedric Roux's avatar
Cedric Roux committed
1947
#if defined(Rel10) || defined(Rel14)
1948 1949 1950 1951

    for (service_id = 0; service_id < maxServiceCount; service_id++) {
      for (session_id = 0; session_id < maxSessionPerPMCH; session_id++) {
        memset(&pdcp_mbms_array_eNB[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
1952
      }
1953 1954
    }

Lionel Gauthier's avatar
Lionel Gauthier committed
1955
#endif
1956
  }
1957 1958

  LOG_I(PDCP, "PDCP layer has been initialized\n");
1959

1960 1961 1962
  pdcp_output_sdu_bytes_to_write=0;
  pdcp_output_header_bytes_to_write=0;
  pdcp_input_sdu_remaining_size_to_read=0;
1963 1964 1965 1966 1967 1968 1969 1970 1971 1972

  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
  memset(Pdcp_stats_tx_bytes_last, 0, sizeof(Pdcp_stats_tx_bytes_last));
  memset(Pdcp_stats_tx_rate, 0, sizeof(Pdcp_stats_tx_rate));

  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
  memset(Pdcp_stats_rx_bytes_last, 0, sizeof(Pdcp_stats_rx_bytes_last));
  memset(Pdcp_stats_rx_rate, 0, sizeof(Pdcp_stats_rx_rate));
1973 1974 1975
}

//-----------------------------------------------------------------------------
1976 1977
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
1978 1979
{
  list_free (&pdcp_sdu_list);
1980
  hashtable_destroy(pdcp_coll_p);
1981 1982
}

1983
#ifdef PDCP_USE_RT_FIFO
1984
EXPORT_SYMBOL(pdcp_2_nas_irq);
1985
#endif //PDCP_USE_RT_FIFO