pdcp.c 72.8 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
//#define DEBUG_PDCP_FIFO_FLUSH_SDU

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

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

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

59
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
Lionel Gauthier's avatar
 
Lionel Gauthier committed
60
#  include "gtpv1u_eNB_task.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
61
#  include "gtpv1u.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
62 63
#endif

64 65
extern int otg_enabled;

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

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

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

104 105
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
106 107
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
108
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
109
  CHECK_CTXT_ARGS(ctxt_pP);
110

Cedric Roux's avatar
Cedric Roux committed
111 112 113 114 115
#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

116 117 118 119 120 121 122 123
  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?
   */
124
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
125 126
          sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
  
127
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
128
    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);
129
  } else {
130
    if (srb_flagP) {
Navid Nikaein's avatar
Navid Nikaein committed
131
      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);
132
    } else {
133
      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);
134
    }
135
  }
136

137 138
  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);
139

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

159
  // PDCP transparent mode for MBMS traffic
160

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

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

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

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

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

217 218 219 220 221 222
      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);
223

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

228
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
229 230 231 232
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
233

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

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

249 250 251 252
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
253

254
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
255 256
          return FALSE;
        }
257
      }
258

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

268
        free_mem_block(pdcp_pdu_p, __func__);
269

270
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
271 272 273 274
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
275

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

#if defined(ENABLE_SECURITY)

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

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

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

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

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

330 331 332 333 334
      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);
      }
335 336 337 338 339 340 341 342 343

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

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

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

    LOG_F(PDCP,"\n");
#endif
362
    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
363
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
364 365 366 367
                             ,sourceL2Id
                             ,destinationL2Id
#endif
                             );
368

369
  }
370

371 372 373
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
374
    ret=TRUE;
375 376 377 378
    break;

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

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

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

  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);
394 395
    ret= FALSE;
    break;
396
  }
397

398
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
399 400 401 402
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
403

404 405 406 407
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
408
  
409
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
410
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ) 
411 412 413 414 415
      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]++;
416
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
417
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
418
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
419 420
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;

421
  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]);
422
  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]); 
423
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
424
    
425
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
426
  return ret;
427 428 429

}

430

431 432 433
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
434 435 436 437 438
  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,
439 440 441
  mem_block_t* const sdu_buffer_pP
)
//-----------------------------------------------------------------------------
442
{
443 444 445
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
446 447
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
448
  pdcp_sn_t    sequence_number = 0;
449
  volatile sdu_size_t   payload_offset  = 0;
450
  rb_id_t      rb_id            = rb_idP;
451
  boolean_t    packet_forwarded = FALSE;
452 453
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
454 455 456
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
  uint16_t     pdcp_uid=0;      
  uint8_t      oo_flag=0;
457
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
458
  MessageDef  *message_p        = NULL;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
459
  uint8_t     *gtpu_buffer_p    = NULL;
460
#endif
461

462

463
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
464

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

469
  for (i = 0; i < sdu_buffer_sizeP; i++) {
470
    LOG_F(PDCP,"%02x ", ((uint8_t*)sdu_buffer_pP->data)[i]);
471
  }
472 473 474

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

Cedric Roux's avatar
Cedric Roux committed
476 477 478 479 480
#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

481
  if (MBMS_flagP) {
482 483 484 485 486 487
    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);
488 489

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
490
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
491
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
492 493 494 495 496
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
497

Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
498
    } else {
499 500 501 502 503 504 505
      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
506
    }
507

Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
508
  } else {
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
    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);
528
      free_mem_block(sdu_buffer_pP, __func__);
529
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
530
      return FALSE;
531
    }
532
  }
533

534
  sdu_list_p = &pdcp_sdu_list;
535

536
  if (sdu_buffer_sizeP == 0) {
537 538
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
539
  }
540

541 542 543 544 545
  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);
  }
546 547

  /*
548 549
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
550
   */
551

552
  if (MBMS_flagP == 0 ) {
553 554 555 556 557 558
    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;
559 560 561 562 563 564 565

      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);
566
      } else {
567
        //sequence_number = 4095;
568 569 570 571
        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);
572
      }
573

574 575
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
576

577 578 579 580
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
581 582 583 584
      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);
585
      free_mem_block(sdu_buffer_pP, __func__);
586

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

593
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
594 595 596
      return FALSE;
    }

597
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
598
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
599
      /* if (dc == PDCP_DATA_PDU )
600 601 602
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
603
    } else {
604
      oo_flag=1;
605 606 607 608
      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);
609
      /*
610 611
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
612
       */
bruno mongazon's avatar
bruno mongazon committed
613 614
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
615 616
      return FALSE;
    }
617 618 619

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

622
      if (pdcp_p->security_activated == 1) {
623 624 625 626 627
        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);
        }
628 629 630 631 632 633 634 635 636 637

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

638 639 640 641 642
        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);
        }
643
      }
644

645 646
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
647 648 649 650 651 652 653
  	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);
654
        rrc_data_ind(ctxt_pP,
655 656 657
		   rb_id,
		   sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
		   (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len]);
658
        free_mem_block(sdu_buffer_pP, __func__);
659

660

661
      // free_mem_block(new_sdu, __func__);
662 663 664 665 666
      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);
      }
667

668
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
669 670
      return TRUE;
    }
671 672 673 674

    /*
     * DRBs
     */
675 676
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
677

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

685
      pdcp_validate_security(
686 687 688 689 690 691 692 693 694
        ctxt_pP,
        pdcp_p,
        srb_flagP,
        rb_idP,
        pdcp_header_len,
        sequence_number,
        sdu_buffer_pP->data,
        sdu_buffer_sizeP - pdcp_tailer_len);

695 696 697 698 699
      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);
      }
700

701
    }
702

703
#endif
704
  } else {
705
    payload_offset=0;
706
  }
707 708 709

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

712 713 714 715 716
    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);
    }
717

718
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
719 720 721
    return TRUE;
  }

722 723 724 725 726 727 728 729
  // 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)
   */
730
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
731

732
  if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
733 734 735 736 737 738 739 740
    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);
741 742 743 744 745 746 747 748 749 750
    //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;
751
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
752 753
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
    itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
754
    packet_forwarded = TRUE;    
755
  }
Navid Nikaein's avatar
Navid Nikaein committed
756
  
757 758 759
#else
  packet_forwarded = FALSE;
#endif
760

761
  if (FALSE == packet_forwarded) {
762
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
763

764 765 766 767 768 769 770 771 772 773
    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;
774
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
775 776 777 778 779

      // 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;
780
#if defined(ENABLE_USE_MME)
781 782 783 784
        /* 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
785
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = 1;
786
#endif
787
      } else {
788
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * maxDRB);
789
      }
790 791
      ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = ctxt_pP->module_id;

792 793 794 795 796
#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
797 798 799 800 801 802

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

803 804
      
      
805
    }
806
  }
807

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

  
841
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
842
  else {
843 844
    AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
845 846
  }

847
#endif
848

849
  free_mem_block(sdu_buffer_pP, __func__);
850

851 852 853 854 855
  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);
  }
856

857
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
858 859 860
  return TRUE;
}

Navid Nikaein's avatar
Navid Nikaein committed
861 862 863 864 865
void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){

  uint8_t            pdcp_uid = 0;
  uint8_t            rb_id     = 0;
  
866
 // these stats are measured for both eNB and UE on per seond basis 
867
  for (rb_id =0; rb_id < NB_RB_MAX; rb_id ++){
868
    for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
869 870
      //printf("frame %d and subframe %d \n", pdcp_enb[ctxt_pP->module_id].frame, pdcp_enb[ctxt_pP->module_id].subframe);
      // tx stats
Raymond Knopp's avatar
Raymond Knopp committed
871 872
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
873
	// unit: bit/s
874 875 876 877 878 879 880 881 882 883 884 885
	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;
Navid Nikaein's avatar
Navid Nikaein committed
886
	
887
      }
Raymond Knopp's avatar
Raymond Knopp committed
888 889
      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0){
Navid Nikaein's avatar
Navid Nikaein committed
890
	// rx stats
891 892 893
	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];
Navid Nikaein's avatar
Navid Nikaein committed
894
	
895 896 897 898 899
	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;
	}
Navid Nikaein's avatar
Navid Nikaein committed
900
	
901 902 903 904
	// 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;
Navid Nikaein's avatar
Navid Nikaein committed
905 906
      } 
    }
907
    
Navid Nikaein's avatar
Navid Nikaein committed
908 909
  }
}
910
//-----------------------------------------------------------------------------
911 912 913 914 915
void
pdcp_run (
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
916
{
Navid Nikaein's avatar
Navid Nikaein committed
917
  
918
#if defined(ENABLE_ITTI)
919 920 921 922
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
923
  protocol_ctxt_t  ctxt;
924
#endif
925

926

Navid Nikaein's avatar
Navid Nikaein committed
927
  
928 929 930 931 932
  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);
  }
933

934 935 936
  pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
  pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023 
  pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
Navid Nikaein's avatar
Navid Nikaein committed
937 938
  pdcp_update_stats(ctxt_pP);
   
939
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
940

941 942
#if defined(ENABLE_ITTI)

943 944 945 946 947 948 949 950 951 952
  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:
953
	PROTOCOL_CTXT_SET_BY_MODULE_ID(
954 955 956 957
          &ctxt,
          RRC_DCCH_DATA_REQ (msg_p).module_id,
          RRC_DCCH_DATA_REQ (msg_p).enb_flag,
          RRC_DCCH_DATA_REQ (msg_p).rnti,
958 959 960
          RRC_DCCH_DATA_REQ (msg_p).frame, 
	  0,
	  RRC_DCCH_DATA_REQ (msg_p).eNB_index);
961
        LOG_I(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
962 963 964 965 966 967 968 969
              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);
970 971 972 973 974 975 976 977

        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,
978
                                RRC_DCCH_DATA_REQ (msg_p).mode
979
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
980 981 982
                                , NULL, NULL
#endif
                                );
983 984
        if (result != TRUE)
          LOG_E(PDCP, "PDCP data request failed!\n");
985 986 987 988 989 990

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

991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
      case RRC_PCCH_DATA_REQ:
      {
        sdu_size_t     sdu_buffer_sizeP;
        sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size;
        uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id;
        uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index;
        RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP;
        if (sdu_buffer_sizeP > 0) {
        	memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP);
        }
        //paging pdcp log
        LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
      }
      break;

1006 1007 1008
      default:
        LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
        break;
1009
      }
1010 1011 1012 1013

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

Lionel Gauthier's avatar
Lionel Gauthier committed
1016
#endif
1017 1018

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

1021
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
Lionel Gauthier's avatar
Lionel Gauthier committed
1022
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1023
  {
1024
    pdcp_fifo_read_input_sdus(ctxt_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
1025
  }
1026

1027
  // PDCP -> NAS/IP traffic: RX
1028 1029 1030
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
Lionel Gauthier's avatar
Lionel Gauthier committed
1031

1032 1033 1034
  else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1035

1036
  pdcp_fifo_flush_sdus(ctxt_pP);
1037

1038 1039 1040 1041 1042
  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);
  }
1043

1044 1045 1046 1047 1048
  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);
  }
1049
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
1050 1051
}

1052
void pdcp_add_UE(const protocol_ctxt_t* const  ctxt_pP){
1053
  int i, ue_flag=1; //, ret=-1; to be decied later
1054
  for (i=0; i < MAX_MOBILES_PER_ENB; i++){
1055 1056 1057 1058 1059 1060
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti) {
      ue_flag=-1;
      break;
    }
  }
  if (ue_flag == 1 ){
1061
    for (i=0; i < MAX_MOBILES_PER_ENB ; i++){
1062 1063 1064 1065 1066
      if (pdcp_enb[ctxt_pP->module_id].rnti[i] == 0 ){
	pdcp_enb[ctxt_pP->module_id].rnti[i]=ctxt_pP->rnti;
	pdcp_enb[ctxt_pP->module_id].uid[i]=i;
	pdcp_enb[ctxt_pP->module_id].num_ues++;
	printf("add new uid is %d %x\n\n", i, ctxt_pP->rnti);
1067
	// ret=1;
1068 1069 1070 1071 1072 1073
	break;
      }
    }
  }
  //return ret;
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1074

1075 1076 1077 1078 1079 1080 1081
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1082 1083
  DRB_Identity_t  srb_id         = 0;
  DRB_Identity_t  drb_id         = 0;
1084 1085
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
Navid Nikaein's avatar
Navid Nikaein committed
1086
  int i; 
1087
   // check and remove SRBs first
Raymond Knopp's avatar
 
Raymond Knopp committed
1088

1089
  for(int i = 0;i<MAX_MOBILES_PER_ENB;i++){
1090 1091 1092 1093 1094 1095
    if(pdcp_eNB_UE_instance_to_rnti[i] == ctxt_pP->rnti){
      pdcp_eNB_UE_instance_to_rnti[i] = NOT_A_RNTI;
      break;
    }
  }

Emad's avatar
Emad committed
1096
  for (srb_id=1; srb_id<3; srb_id++) {
1097 1098
    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
1099 1100
  }

1101
  for (drb_id=0; drb_id<maxDRB; drb_id++) {
1102 1103
    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
1104 1105 1106

  }

1107 1108
  (void)h_rc; /* remove gcc warning "set but not used" */

1109
  // remove ue for pdcp enb inst
1110
   for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti ) {
      LOG_I(PDCP, "remove uid is %d/%d %x\n", i,
	    pdcp_enb[ctxt_pP->module_id].uid[i],
	    pdcp_enb[ctxt_pP->module_id].rnti[i]);
      pdcp_enb[ctxt_pP->module_id].uid[i]=0;
      pdcp_enb[ctxt_pP->module_id].rnti[i]=0;
      pdcp_enb[ctxt_pP->module_id].num_ues--;
      break;
    }
  }
   
Raymond Knopp's avatar
 
Raymond Knopp committed
1122 1123 1124 1125
  return 1;
}


1126 1127 1128
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
1129 1130 1131 1132 1133 1134 1135 1136
  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
1137
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1138
  ,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
1139
#endif
1140
  ,rb_id_t                 *const defaultDRB 
1141
)
1142
//-----------------------------------------------------------------------------
1143
{
1144
  long int        lc_id          = 0;
1145
  DRB_Identity_t  srb_id         = 0;
1146
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1147
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1148
  DRB_Identity_t  drb_id         = 0;
1149
  DRB_Identity_t *pdrb_id_p      = NULL;
1150
  uint8_t         drb_sn         = 12;
1151 1152
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1153
  long int        cnt            = 0;
1154 1155
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1156 1157 1158
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
1159

1160 1161
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1162 1163
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
1164
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1165
  int i,j;
1166 1167
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1168 1169
#endif

1170 1171 1172 1173 1174 1175
  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);
1176

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

1179
  if (srb2add_list_pP != NULL) {
1180 1181 1182 1183
    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;
1184
      lc_id = srb_id;
1185 1186
      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);
1187

1188 1189 1190 1191 1192
      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);
1193
      } else {
1194 1195 1196
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1197

1198 1199 1200 1201 1202 1203
        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;
1204

1205
      } else {
1206
	  LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
1207 1208 1209
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
      }

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

1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
          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;
1240
          }
1241 1242 1243 1244

          break;

        case SRB_ToAddMod__rlc_Config_PR_defaultValue:
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
        	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);
1261 1262 1263 1264
          // already the default values
          break;

        default:
1265
          DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
1266 1267
          break;
        }
1268
      }
1269
    }
1270
  }
1271

1272 1273
  // reset the action

1274
  if (drb2add_list_pP != NULL) {
1275
    for (cnt=0; cnt<drb2add_list_pP->list.count; cnt++) {
1276

1277
      drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
1278

1279
      drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1280 1281 1282 1283 1284 1285 1286 1287 1288
      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
1289
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1290 1291 1292
        continue;
      }

1293 1294 1295
      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);
1296

1297 1298 1299 1300 1301
      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);
1302

1303 1304
      } else {
        action = CONFIG_ACTION_ADD;
1305 1306 1307
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1308
        // save the first configured DRB-ID as the default DRB-ID
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
        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;
1322
        } else if (h_rc != HASH_TABLE_OK) {
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
          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);
         }
      }
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359

      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
1360
          if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0001) {
1361
            header_compression_profile=0x0001;
1362
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0002) {
1363
            header_compression_profile=0x0002;
1364
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0003) {
1365
            header_compression_profile=0x0003;
1366
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0004) {
1367
            header_compression_profile=0x0004;
1368
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0006) {
1369
            header_compression_profile=0x0006;
1370
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0101) {
1371
            header_compression_profile=0x0101;
1372
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0102) {
1373
            header_compression_profile=0x0102;
1374
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0103) {
1375
            header_compression_profile=0x0103;
1376
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0104) {
1377
            header_compression_profile=0x0104;
1378
          } else {
1379 1380
            header_compression_profile=0x0;
            LOG_W(PDCP,"unknown header compresion profile\n");
1381
          }
1382 1383 1384 1385 1386

          // set the applicable profile
          break;

        default:
Cedric Roux's avatar
Cedric Roux committed
1387
          LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT"[RB %ld] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
1388
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), drb_id);
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
          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);
1408
      }
1409
    }
1410 1411
  }

1412
  if (drb2release_list_pP != NULL) {
1413 1414 1415
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1416
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
1417 1418 1419
      h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1420
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1421 1422 1423
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1424
      }
1425 1426
      lc_id = pdcp_p->lcid;

1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
      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);
1444
      h_rc = hashtable_remove(pdcp_coll_p, key);
1445 1446

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1447
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
        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
      }
1459
    }
1460 1461
  }

1462
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1463

1464
  if (pmch_InfoList_r9_pP != NULL) {
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
    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

1477
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1478 1479 1480 1481 1482 1483 1484
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
          drb_id =  (mch_id * maxSessionPerPMCH ) + lc_id; // + (maxDRB + 3); // 15

1485
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1486 1487 1488
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1489
          }
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
        }

        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
1508
      }
1509
    }
1510
  }
1511

1512
#endif
1513
  return 0;
1514 1515
}

1516
//-----------------------------------------------------------------------------
1517 1518
boolean_t
pdcp_config_req_asn1 (
1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
  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)
1534
//-----------------------------------------------------------------------------
1535
{
1536
  
1537
  switch (actionP) {
1538
  case CONFIG_ACTION_ADD:
1539
    DevAssert(pdcp_pP != NULL);
1540 1541
    if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
      pdcp_pP->is_ue = FALSE;
Navid Nikaein's avatar
Navid Nikaein committed
1542
      pdcp_add_UE(ctxt_pP);
1543
      
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1544
      //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti;
1545 1546
//      pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
      if( srb_flagP == SRB_FLAG_NO ) {
1547
          for(int i = 0;i<MAX_MOBILES_PER_ENB;i++){
1548 1549 1550
              if(pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] == NOT_A_RNTI){
                  break;
              }
1551
              pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1552 1553
          }
          pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
1554
          pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1555
      }
1556
      //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1557 1558 1559 1560
    } else {
      pdcp_pP->is_ue = TRUE;
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
    }
1561
    pdcp_pP->is_srb                     = (srb_flagP == SRB_FLAG_YES) ? TRUE : FALSE;
Lionel Gauthier's avatar
Lionel Gauthier committed
1562
    pdcp_pP->lcid                       = lc_idP;
1563
    pdcp_pP->rb_id                      = rb_idP;
1564
    pdcp_pP->header_compression_profile = header_compression_profileP;
Lionel Gauthier's avatar
Lionel Gauthier committed
1565
    pdcp_pP->status_report              = rb_reportP;
1566

1567
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1568
      pdcp_pP->seq_num_size = PDCP_SN_12BIT;
1569
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1570
      pdcp_pP->seq_num_size = PDCP_SN_7BIT;
1571
    } else {
1572
      pdcp_pP->seq_num_size = PDCP_SN_5BIT;
1573
    }
1574

1575

1576 1577 1578 1579 1580 1581 1582 1583 1584
    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;
1585

1586
    LOG_N(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %d) "
1587
            "configured with SN size %d bits and RLC %s\n",
1588 1589
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
1590
	  (srb_flagP == SRB_FLAG_YES) ? "SRB" : "DRB",
1591 1592
          rb_idP,
          pdcp_pP->seq_num_size,
1593
	  (rlc_modeP == RLC_MODE_AM ) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1594 1595
    /* Setup security */
    if (security_modeP != 0xff) {
1596 1597 1598 1599 1600 1601 1602 1603 1604
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1605 1606
    }
    break;
1607

1608
  case CONFIG_ACTION_MODIFY:
1609 1610 1611 1612
    DevAssert(pdcp_pP != NULL);
    pdcp_pP->header_compression_profile=header_compression_profileP;
    pdcp_pP->status_report = rb_reportP;
    pdcp_pP->rlc_mode = rlc_modeP;
1613

1614 1615
    /* Setup security */
    if (security_modeP != 0xff) {
1616 1617 1618 1619 1620 1621 1622 1623 1624
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1625
    }
1626

1627
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1628
      pdcp_pP->seq_num_size = 7;
1629
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1630
      pdcp_pP->seq_num_size = 12;
1631
    } else {
1632
      pdcp_pP->seq_num_size=5;
1633
    }
1634

1635
    LOG_N(PDCP,PROTOCOL_PDCP_CTXT_FMT" Action MODIFY LCID %d "
Navid Nikaein's avatar
Navid Nikaein committed
1636
            "RB id %d reconfigured with SN size %d and RLC %s \n",
1637 1638 1639 1640
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
          rb_idP,
          rb_snP,
1641
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1642
    break;
1643

1644
  case CONFIG_ACTION_REMOVE:
1645
    DevAssert(pdcp_pP != NULL);
1646
//#warning "TODO pdcp_module_id_to_rnti"
1647 1648 1649 1650 1651
    //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);
1652

1653
   if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
1654
     // pdcp_remove_UE(ctxt_pP);
1655
   }
1656

1657 1658
    /* Security keys */
    if (pdcp_pP->kUPenc != NULL) {
1659
      free(pdcp_pP->kUPenc);
1660
    }
1661

1662
    if (pdcp_pP->kRRCint != NULL) {
1663
      free(pdcp_pP->kRRCint);
1664
    }
1665

1666
    if (pdcp_pP->kRRCenc != NULL) {
1667
      free(pdcp_pP->kRRCenc);
1668
    }
1669

1670
    memset(pdcp_pP, 0, sizeof(pdcp_t));
1671
    break;
1672
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
1673

1674 1675
  case CONFIG_ACTION_MBMS_ADD:
  case CONFIG_ACTION_MBMS_MODIFY:
1676 1677
    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),
1678 1679 1680 1681 1682 1683 1684 1685
          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;
1686
    } else {
1687 1688
      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;
1689
    }
1690

1691
    break;
Lionel Gauthier's avatar
Lionel Gauthier committed
1692
#endif
1693

1694
  case CONFIG_ACTION_SET_SECURITY_MODE:
1695
    pdcp_config_set_security(
1696 1697 1698 1699 1700 1701 1702 1703
      ctxt_pP,
      pdcp_pP,
      rb_idP,
      lc_idP,
      security_modeP,
      kRRCenc_pP,
      kRRCint_pP,
      kUPenc_pP);
1704
    break;
1705

1706
  default:
1707
    DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1708
    break;
1709
  }
1710

1711 1712
  return 0;
}
1713

1714 1715 1716
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
1717 1718 1719 1720 1721 1722 1723 1724
  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)
1725
//-----------------------------------------------------------------------------
1726
{
1727
  DevAssert(pdcp_pP != NULL);
1728

1729
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1730 1731
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1732

1733 1734
    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),
1735 1736 1737 1738 1739 1740
            pdcp_pP->cipheringAlgorithm,
            pdcp_pP->integrityProtAlgorithm);

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

1742 1743
    /* Activate security */
    pdcp_pP->security_activated = 1;
Lionel Gauthier's avatar
Lionel Gauthier committed
1744 1745
	MSC_LOG_EVENT(
	  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1746
	  "0 Set security ciph %X integ %x UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1747 1748 1749
	  pdcp_pP->cipheringAlgorithm,
	  pdcp_pP->integrityProtAlgorithm,
	  ctxt_pP->rnti);
1750
  } else {
Lionel Gauthier's avatar
Lionel Gauthier committed
1751 1752
	  MSC_LOG_EVENT(
	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1753
	    "0 Set security failed UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1754 1755
	    ctxt_pP->rnti);
	  LOG_E(PDCP,PROTOCOL_PDCP_CTXT_FMT"  bad security mode %d",
1756 1757
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
1758
  }
1759 1760
}

1761
//-----------------------------------------------------------------------------
1762 1763
void
rrc_pdcp_config_req (
1764 1765 1766 1767 1768
  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)
1769
//-----------------------------------------------------------------------------
1770
{
1771
  pdcp_t *pdcp_p = NULL;
1772 1773 1774
  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);
1775

1776
  if (h_rc == HASH_TABLE_OK) {
1777 1778

  /*
1779 1780 1781
   * Initialize sequence number state variables of relevant PDCP entity
   */
  switch (actionP) {
1782
  case CONFIG_ACTION_ADD:
1783 1784
    pdcp_p->is_srb = srb_flagP;
    pdcp_p->rb_id  = rb_idP;
1785

1786
    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
1787
      pdcp_p->is_ue = TRUE;
1788
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1789
    } else {
1790
      pdcp_p->is_ue = FALSE;
1791
    }
1792 1793 1794 1795 1796 1797 1798 1799 1800

    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
1801
      pdcp_p->seq_num_size = 5;
1802
    } else { // DRB
1803
      pdcp_p->seq_num_size = 12;
1804
    }
1805

1806
    pdcp_p->first_missing_pdu = -1;
1807 1808 1809
    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);
1810
    break;
1811

1812
  case CONFIG_ACTION_MODIFY:
1813
    break;
1814

1815
  case CONFIG_ACTION_REMOVE:
1816 1817 1818
      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);
1819 1820 1821 1822 1823 1824 1825 1826
    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;
1827
      h_rc = hashtable_remove(pdcp_coll_p, key);
1828 1829

    break;
1830

1831
  case CONFIG_ACTION_SET_SECURITY_MODE:
1832
    if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1833 1834
      pdcp_p->cipheringAlgorithm= security_modeP & 0x0f;
      pdcp_p->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1835 1836
        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),
1837 1838
            pdcp_p->cipheringAlgorithm,
            pdcp_p->integrityProtAlgorithm );
1839
    } else {
Cedric Roux's avatar
Cedric Roux committed
1840
        LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT" bad security mode %d", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), security_modeP);
1841
    }
1842

1843
    break;
1844

1845
  default:
1846
      DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1847
    break;
1848
  }
1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
  } 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;
1866
	  pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1867 1868
        } else {
          pdcp_p->is_ue = FALSE;
1869
	}
1870

1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908
        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));
    }
  }
}


//-----------------------------------------------------------------------------
1909
 
1910 1911 1912 1913 1914
int
pdcp_module_init (
  void
)
//-----------------------------------------------------------------------------
1915
{
1916
 
1917
#ifdef PDCP_USE_RT_FIFO
1918 1919
  int ret;

1920
  ret=rtf_create(PDCP2NW_DRIVER_FIFO,32768);
1921 1922

  if (ret < 0) {
1923
    LOG_E(PDCP, "Cannot create PDCP2NW_DRIVER_FIFO fifo %d (ERROR %d)\n", PDCP2NW_DRIVER_FIFO, ret);
1924
    return -1;
1925
  } else {
1926 1927
    LOG_D(PDCP, "Created PDCP2NAS fifo %d\n", PDCP2NW_DRIVER_FIFO);
    rtf_reset(PDCP2NW_DRIVER_FIFO);
1928 1929
  }

1930
  ret=rtf_create(NW_DRIVER2PDCP_FIFO,32768);
1931 1932

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

1935
    return -1;
1936
  } else {
1937 1938
    LOG_D(PDCP, "Created NW_DRIVER2PDCP_FIFO fifo %d\n", NW_DRIVER2PDCP_FIFO);
    rtf_reset(NW_DRIVER2PDCP_FIFO);
1939 1940 1941 1942 1943 1944 1945 1946
  }

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

  return 0;
1947 1948 1949 1950 1951 1952 1953 1954 1955 1956
}

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

1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973
  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);
  }
1974 1975 1976
}

//-----------------------------------------------------------------------------
1977 1978
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
1979
{
1980 1981 1982
#ifdef PDCP_USE_RT_FIFO
  rtf_destroy(NW_DRIVER2PDCP_FIFO);
  rtf_destroy(PDCP2NW_DRIVER_FIFO);
1983 1984 1985 1986
#endif
}

//-----------------------------------------------------------------------------
1987
void pdcp_layer_init(void)
1988
//-----------------------------------------------------------------------------
1989
{
1990

Lionel Gauthier's avatar
Lionel Gauthier committed
1991
  module_id_t       instance;
1992
  int i,j;
1993
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
Lionel Gauthier's avatar
Lionel Gauthier committed
1994 1995 1996
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
#endif
1997
  /*
1998 1999
   * Initialize SDU list
   */
2000
  list_init(&pdcp_sdu_list, NULL);
2001 2002
  pdcp_coll_p = hashtable_create ((maxDRB + 2) * 16, NULL, pdcp_free);
  AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
2003

2004
  for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
2005
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2006 2007 2008 2009

    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));
2010
      }
2011
    }
Lionel Gauthier's avatar
Lionel Gauthier committed
2012
#endif
2013
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
2014
  }
2015
  pdcp_eNB_UE_instance_to_rnti_index = 0; 
2016

2017
    
2018
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
2019
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2020 2021 2022 2023

    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));
2024
      }
2025 2026
    }

Lionel Gauthier's avatar
Lionel Gauthier committed
2027
#endif
2028
  }
2029 2030

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

2032 2033 2034
  pdcp_output_sdu_bytes_to_write=0;
  pdcp_output_header_bytes_to_write=0;
  pdcp_input_sdu_remaining_size_to_read=0;
2035

2036 2037
  memset(pdcp_enb, 0, sizeof(pdcp_enb_t));

2038
  
2039 2040 2041
  memset(Pdcp_stats_tx_window_ms, 0, sizeof(Pdcp_stats_tx_window_ms));
  memset(Pdcp_stats_rx_window_ms, 0, sizeof(Pdcp_stats_rx_window_ms));
  for (i =0; i< MAX_NUM_CCs ; i ++){
2042
    for (j=0; j< MAX_MOBILES_PER_ENB;j++){
2043 2044 2045 2046 2047
      Pdcp_stats_tx_window_ms[i][j]=100;
      Pdcp_stats_rx_window_ms[i][j]=100;
    }
  }
  
2048
  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
2049 2050
  memset(Pdcp_stats_tx_w, 0, sizeof(Pdcp_stats_tx_w));
  memset(Pdcp_stats_tx_tmp_w, 0, sizeof(Pdcp_stats_tx_tmp_w));
2051
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
2052 2053
  memset(Pdcp_stats_tx_bytes_w, 0, sizeof(Pdcp_stats_tx_bytes_w));
  memset(Pdcp_stats_tx_bytes_tmp_w, 0, sizeof(Pdcp_stats_tx_bytes_tmp_w));
2054
  memset(Pdcp_stats_tx_sn, 0, sizeof(Pdcp_stats_tx_sn));
2055
  memset(Pdcp_stats_tx_throughput_w, 0, sizeof(Pdcp_stats_tx_throughput_w));
2056 2057 2058
  memset(Pdcp_stats_tx_aiat, 0, sizeof(Pdcp_stats_tx_aiat));
  memset(Pdcp_stats_tx_iat, 0, sizeof(Pdcp_stats_tx_iat));
  
2059 2060

  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
2061 2062
  memset(Pdcp_stats_rx_w, 0, sizeof(Pdcp_stats_rx_w));
  memset(Pdcp_stats_rx_tmp_w, 0, sizeof(Pdcp_stats_rx_tmp_w));
2063
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
2064 2065
  memset(Pdcp_stats_rx_bytes_w, 0, sizeof(Pdcp_stats_rx_bytes_w));
  memset(Pdcp_stats_rx_bytes_tmp_w, 0, sizeof(Pdcp_stats_rx_bytes_tmp_w));
2066
  memset(Pdcp_stats_rx_sn, 0, sizeof(Pdcp_stats_rx_sn));
2067
  memset(Pdcp_stats_rx_goodput_w, 0, sizeof(Pdcp_stats_rx_goodput_w));
2068 2069 2070 2071
  memset(Pdcp_stats_rx_aiat, 0, sizeof(Pdcp_stats_rx_aiat));
  memset(Pdcp_stats_rx_iat, 0, sizeof(Pdcp_stats_rx_iat));
  memset(Pdcp_stats_rx_outoforder, 0, sizeof(Pdcp_stats_rx_outoforder));
    
2072 2073 2074
}

//-----------------------------------------------------------------------------
2075 2076
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
2077 2078
{
  list_free (&pdcp_sdu_list);
2079
  hashtable_destroy(pdcp_coll_p);
2080 2081
}

2082
#ifdef PDCP_USE_RT_FIFO
2083
EXPORT_SYMBOL(pdcp_2_nas_irq);
2084
#endif //PDCP_USE_RT_FIFO