pdcp.c 74.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 34
#define MBMS_MULTICAST_OUT

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

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

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

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

66 67
extern int otg_enabled;

68 69
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
70

71 72 73 74 75 76 77 78 79 80 81
#ifdef MBMS_MULTICAST_OUT
# include <sys/types.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <netinet/ip.h>
# include <netinet/udp.h>
# include <unistd.h>

static int mbms_socket = -1;
#endif

82 83 84 85 86 87 88 89
//-----------------------------------------------------------------------------
/*
 * 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()
 */
90
boolean_t pdcp_data_req(
91
  protocol_ctxt_t*  ctxt_pP,
92 93 94 95 96 97
  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,
98
  const pdcp_transmission_mode_t modeP
99
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
100 101 102
    ,const uint32_t * const sourceL2Id
    ,const uint32_t * const destinationL2Id
#endif
103 104
)
//-----------------------------------------------------------------------------
105
{
106

107
  pdcp_t            *pdcp_p          = NULL;
108 109 110 111 112
  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;
113 114
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
115
  boolean_t          ret             = TRUE;
116

117 118
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
119 120
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
121
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
122
  CHECK_CTXT_ARGS(ctxt_pP);
123

Cedric Roux's avatar
Cedric Roux committed
124 125 126 127 128
#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

129 130 131 132 133 134 135 136
  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?
   */
137
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
138 139
          sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
  
140
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
141
    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);
142
  } else {
143
    if (srb_flagP) {
Navid Nikaein's avatar
Navid Nikaein committed
144
      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);
145
    } else {
146
      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
147
    }
148
  }
149

150 151
  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);
152

153 154
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
155 156 157 158
      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;
159
      return FALSE;
160
    }
161 162
  }else{
    // instance for a given RB is configured
163
    ctxt_pP->configured=TRUE;
164
  }
165
    
166
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
167 168 169 170
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
171

172
  // PDCP transparent mode for MBMS traffic
173

174
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
175
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
176
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
177 178 179

    if (pdcp_pdu_p != NULL) {
      memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
180
#if defined(DEBUG_PDCP_PAYLOAD)
181 182 183
      rlc_util_print_hex_octets(PDCP,
                                (unsigned char*)&pdcp_pdu_p->data[0],
                                sdu_buffer_sizeP);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
184
#endif
185
      LOG_D(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %d \n", srb_flagP, rb_idP);
186
      rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p
187
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
188 189 190
                                ,NULL, NULL
#endif
                                );
191 192
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
193 194
      LOG_W(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
195
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
196 197
      AssertFatal(0, PROTOCOL_CTXT_FMT"[RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  PROTOCOL_CTXT_ARGS(ctxt_pP),
198
                  rb_idP);
199
#endif
200
    }
201
  } else {
202 203 204 205 206 207 208 209 210 211
    // 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;
212

213 214
    LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT"Data request notification  pdu size %d (header%d, trailer%d)\n",
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
215 216 217
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
218

219 220 221
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
222
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
223 224

    if (pdcp_pdu_p != NULL) {
225
      /*
226 227 228
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
229
       */
230

231 232 233 234 235 236
      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);
237

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

242
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
243 244 245 246
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
247

248
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
249 250 251 252 253 254 255
          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 ;
256

257
        if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
258 259
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
260 261
         
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
262

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

268
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
269 270
          return FALSE;
        }
271
      }
272

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

282
        free_mem_block(pdcp_pdu_p, __func__);
283

284
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
285 286 287 288
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
289

290
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
291 292 293 294 295 296 297 298 299 300 301
        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
302
      for (i=0; i<pdcp_tailer_len; i++) {
303
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
304
      }
305 306 307 308 309 310 311

#if defined(ENABLE_SECURITY)

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

312
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
313 314 315 316
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
317 318 319 320

        pdcp_apply_security(ctxt_pP,
                            pdcp_p,
                            srb_flagP,
321
                            rb_idP % LTE_maxDRB,
322 323 324 325 326
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);

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

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

344 345 346 347 348
      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);
      }
349 350 351 352 353 354 355 356 357

#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
358
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
359 360 361 362 363 364 365 366
      return FALSE;
    }

    /*
     * Ask sublayer to transmit data and check return value
     * to see if RLC succeeded
     */

367 368
    LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
                "[MSG] PDCP DL %s PDU on rb_id %d\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
369

370
    LOG_D(PDCP, "Before rlc_data_req 2, srb_flagP: %d, rb_idP: %d \n", srb_flagP, rb_idP);
371
    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
372
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
373 374
                             ,sourceL2Id
                             ,destinationL2Id
375
#endif
376 377
                             );

378
  }
379

380 381 382
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
383
    ret=TRUE;
384 385 386 387
    break;

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

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

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

401 402
  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);
403 404
    ret= FALSE;
    break;
405
  }
406

407
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
408 409 410 411
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
412

413 414 415 416 417 418 419 420 421 422
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */

  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
      break;
  }

423 424
  //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]++;
425
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
426
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
427
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
428 429
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;

430
  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]);
431
  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]); 
432
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
433
    
434
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
435
  return ret;
436 437 438

}

439

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

471

472
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
473 474
  LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
              "[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
475

476

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

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

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

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

Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
509
  } else {
510 511
    rb_id = rb_idP % LTE_maxDRB;
    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u UE %x!\n",
512
                 rb_id,
513
                 LTE_maxDRB,
514 515 516 517
                 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,
518
                 LTE_maxDRB,
519 520 521 522 523 524 525 526 527 528
                 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);
529
      free_mem_block(sdu_buffer_pP, __func__);
530
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
531
      return FALSE;
532
    }
533
  }
534

535
  sdu_list_p = &pdcp_sdu_list;
536

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

661

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

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

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

679
    if (pdcp_p->security_activated == 1) {
680 681 682 683 684
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
      } else {
        start_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
      }
685

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

696 697 698 699 700
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
      }
701

702
    }
703

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

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

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

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

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

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

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
#ifdef MBMS_MULTICAST_OUT
  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
    struct iphdr   *ip_header = (struct iphdr*)&sdu_buffer_pP->data[payload_offset];
    struct udphdr *udp_header = (struct udphdr*)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
    struct sockaddr_in dest_addr;

    dest_addr.sin_family      = AF_INET;
    dest_addr.sin_port        = udp_header->dest;
    dest_addr.sin_addr.s_addr = ip_header->daddr;

    sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
    packet_forwarded = TRUE;
  }
#endif

777
  if (FALSE == packet_forwarded) {
778
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
779

780
    if (new_sdu_p) {
781
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
782 783 784 785 786 787 788 789
        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;
790
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
791 792 793 794 795

      // 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;
796
#if defined(ENABLE_USE_MME)
797 798 799 800
        /* 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
801
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = 1;
802
#endif
803
      } else {
804
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
805
      }
806 807 808

      //Panos: Commented this out because it cancels the assignment in #if defined(ENABLE_USE_MME) case
      //((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = ctxt_pP->module_id;
809

810 811 812 813 814
#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
815
      //((pdcp_data_ind_header_t*) new_sdu_p->data)->inst = 1; //pdcp_inst++;
816 817 818 819 820 821

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

822 823
      
      
824 825
    }

826 827 828 829 830 831 832 833 834 835 836 837
  /* 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?
   */
  
838
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
839
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ){
840
      break;
841
    }
842 843 844
  }	
  
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
845
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
846
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
847
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
848 849 850 851 852 853
  
  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]++;
  
854
  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]);
855
  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]);
856
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
857 858

  
859
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
860 861 862 863
    else {
      AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
                  PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
    }
864
#endif
865

866 867
  }

868
  free_mem_block(sdu_buffer_pP, __func__);
869

870 871 872 873 874
  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);
  }
875

876
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
877 878 879
  return TRUE;
}

Navid Nikaein's avatar
Navid Nikaein committed
880 881
void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){

882
  uint16_t           pdcp_uid = 0;
Navid Nikaein's avatar
Navid Nikaein committed
883 884
  uint8_t            rb_id     = 0;
  
885
 // these stats are measured for both eNB and UE on per seond basis 
886
  for (rb_id =0; rb_id < NB_RB_MAX; rb_id ++){
887
    for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
888 889
      //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
890 891
      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){
892
	// unit: bit/s
893 894 895 896 897 898 899 900 901 902 903 904
	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
905
	
906
      }
Raymond Knopp's avatar
Raymond Knopp committed
907 908
      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
909
	// rx stats
910 911 912
	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
913
	
914 915 916 917 918
	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
919
	
920 921 922 923
	// 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
924 925
      } 
    }
926
    
Navid Nikaein's avatar
Navid Nikaein committed
927 928
  }
}
929
//-----------------------------------------------------------------------------
930 931 932 933 934
void
pdcp_run (
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
935
{
Navid Nikaein's avatar
Navid Nikaein committed
936
  
937 938 939 940 941
  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);
  }
942

943 944 945
  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
946 947
  pdcp_update_stats(ctxt_pP);
   
948
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
949

950
#if defined(ENABLE_ITTI)
951 952 953
  MessageDef   *msg_p;
  int           result;
  protocol_ctxt_t  ctxt;
954

955 956 957 958 959 960 961 962
  do {
    // Checks if a message has been sent to PDCP sub-task
    itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);

    if (msg_p != NULL) {

      switch (ITTI_MSG_ID(msg_p)) {
      case RRC_DCCH_DATA_REQ:
963
	PROTOCOL_CTXT_SET_BY_MODULE_ID(
964 965 966 967
          &ctxt,
          RRC_DCCH_DATA_REQ (msg_p).module_id,
          RRC_DCCH_DATA_REQ (msg_p).enb_flag,
          RRC_DCCH_DATA_REQ (msg_p).rnti,
968 969 970
          RRC_DCCH_DATA_REQ (msg_p).frame, 
	  0,
	  RRC_DCCH_DATA_REQ (msg_p).eNB_index);
971
        LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
972
              PROTOCOL_CTXT_ARGS(&ctxt),
973
              ITTI_MSG_NAME (msg_p),
974
              ITTI_MSG_ORIGIN_NAME(msg_p),
975
              ITTI_MSG_INSTANCE (msg_p),
976 977 978 979
              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);
980

981
        LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %d \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
982 983 984 985 986 987 988
        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,
989
                                RRC_DCCH_DATA_REQ (msg_p).mode
990
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
991 992 993
                                , NULL, NULL
#endif
                                );
994 995
        if (result != TRUE)
          LOG_E(PDCP, "PDCP data request failed!\n");
996 997 998 999 1000 1001

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

1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
      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;

1017
      default:
1018
        LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
1019
        break;
1020
      }
1021 1022 1023 1024

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

Lionel Gauthier's avatar
Lionel Gauthier committed
1027
#endif
1028 1029

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

1032
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
Lionel Gauthier's avatar
Lionel Gauthier committed
1033
#endif
Lionel Gauthier's avatar
Lionel Gauthier committed
1034
  {
1035
    pdcp_fifo_read_input_sdus(ctxt_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
1036
  }
1037

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

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

1047
  pdcp_fifo_flush_sdus(ctxt_pP);
1048

1049 1050 1051 1052 1053
  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);
  }
1054

1055 1056 1057 1058 1059
  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);
  }
1060
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
1061 1062
}

1063
void pdcp_add_UE(const protocol_ctxt_t* const  ctxt_pP){
1064
  int i, ue_flag=1; //, ret=-1; to be decied later
1065
  for (i=0; i < MAX_MOBILES_PER_ENB; i++){
1066 1067 1068 1069 1070 1071
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti) {
      ue_flag=-1;
      break;
    }
  }
  if (ue_flag == 1 ){
1072
    for (i=0; i < MAX_MOBILES_PER_ENB ; i++){
1073 1074 1075 1076 1077
      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);
1078
	// ret=1;
1079 1080 1081 1082 1083 1084
	break;
      }
    }
  }
  //return ret;
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1085

1086 1087 1088 1089 1090 1091 1092
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
{
1093 1094
  LTE_DRB_Identity_t  srb_id         = 0;
  LTE_DRB_Identity_t  drb_id         = 0;
1095 1096
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
Navid Nikaein's avatar
Navid Nikaein committed
1097
  int i; 
1098
   // check and remove SRBs first
Raymond Knopp's avatar
 
Raymond Knopp committed
1099

1100
  for(int i = 0;i<MAX_MOBILES_PER_ENB;i++){
1101 1102 1103 1104 1105 1106
    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
1107
  for (srb_id=1; srb_id<3; srb_id++) {
1108 1109
    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
1110 1111
  }

1112
  for (drb_id=0; drb_id<LTE_maxDRB; drb_id++) {
1113 1114
    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
1115 1116 1117

  }

1118 1119
  (void)h_rc; /* remove gcc warning "set but not used" */

1120
  // remove ue for pdcp enb inst
1121
   for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
    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
1133 1134 1135 1136
  return 1;
}


1137 1138 1139
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
1140
  const protocol_ctxt_t* const  ctxt_pP,
1141 1142 1143
  LTE_SRB_ToAddModList_t  *const srb2add_list_pP,
  LTE_DRB_ToAddModList_t  *const drb2add_list_pP,
  LTE_DRB_ToReleaseList_t *const drb2release_list_pP,
1144 1145 1146 1147
  const uint8_t                   security_modeP,
  uint8_t                  *const kRRCenc_pP,
  uint8_t                  *const kRRCint_pP,
  uint8_t                  *const kUPenc_pP
1148 1149
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
  ,LTE_PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
1150
#endif
1151
  ,rb_id_t                 *const defaultDRB 
1152
)
1153
//-----------------------------------------------------------------------------
1154
{
1155
  long int        lc_id          = 0;
1156
  LTE_DRB_Identity_t  srb_id     = 0;
1157
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1158
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1159 1160
  LTE_DRB_Identity_t  drb_id     = 0;
  LTE_DRB_Identity_t *pdrb_id_p  = NULL;
1161
  uint8_t         drb_sn         = 12;
1162 1163
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1164
  long int        cnt            = 0;
1165 1166
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1167 1168
  LTE_SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  LTE_DRB_ToAddMod_t *drb_toaddmod_p = NULL;
1169
  pdcp_t         *pdcp_p         = NULL;
1170

1171 1172
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1173 1174
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
1175
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1176
  int i,j;
1177 1178
  LTE_MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  LTE_MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1179 1180
#endif

1181 1182 1183 1184 1185 1186
  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);
1187

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

1190
  if (srb2add_list_pP != NULL) {
1191 1192 1193 1194
    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;
1195
      lc_id = srb_id;
1196 1197
      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);
1198

1199 1200 1201 1202 1203
      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);
1204
      } else {
1205 1206 1207
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1208

1209 1210 1211 1212 1213 1214
        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;
1215

1216
      } else {
1217
	  LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
1218 1219 1220
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1221 1222 1223 1224
      }

      if (srb_toaddmod_p->rlc_Config) {
        switch (srb_toaddmod_p->rlc_Config->present) {
1225
        case LTE_SRB_ToAddMod__rlc_Config_PR_NOTHING:
1226 1227
          break;

1228
        case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue:
1229
          switch (srb_toaddmod_p->rlc_Config->choice.explicitValue.present) {
1230
          case LTE_RLC_Config_PR_NOTHING:
1231
            break;
1232

1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
          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;
1251
          }
1252 1253 1254

          break;

1255
        case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue:
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
        	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);
1272 1273 1274 1275
          // already the default values
          break;

        default:
1276
          DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
1277 1278
          break;
        }
1279
      }
1280
    }
1281
  }
1282

1283 1284
  // reset the action

1285
  if (drb2add_list_pP != NULL) {
1286
    for (cnt=0; cnt<drb2add_list_pP->list.count; cnt++) {
1287

1288
      drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
1289

1290
      drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1291 1292 1293 1294 1295 1296 1297 1298 1299
      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
1300
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1301 1302 1303
        continue;
      }

1304
      DevCheck4(drb_id < LTE_maxDRB, drb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
1305 1306
      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);
1307

1308 1309 1310 1311 1312
      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);
1313

1314 1315
      } else {
        action = CONFIG_ACTION_ADD;
1316 1317 1318
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1319
        // save the first configured DRB-ID as the default DRB-ID
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
        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;
1333
        } else if (h_rc != HASH_TABLE_OK) {
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
          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);
         }
      }
1345 1346 1347 1348 1349 1350 1351 1352

      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;
1353
          drb_sn = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size
1354 1355 1356 1357 1358 1359 1360 1361 1362
          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) {
1363 1364
        case LTE_PDCP_Config__headerCompression_PR_NOTHING:
        case LTE_PDCP_Config__headerCompression_PR_notUsed:
1365 1366 1367
          header_compression_profile=0x0;
          break;

1368
        case LTE_PDCP_Config__headerCompression_PR_rohc:
1369 1370

          // parse the struc and get the rohc profile
1371
          if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0001) {
1372
            header_compression_profile=0x0001;
1373
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0002) {
1374
            header_compression_profile=0x0002;
1375
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0003) {
1376
            header_compression_profile=0x0003;
1377
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0004) {
1378
            header_compression_profile=0x0004;
1379
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0006) {
1380
            header_compression_profile=0x0006;
1381
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0101) {
1382
            header_compression_profile=0x0101;
1383
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0102) {
1384
            header_compression_profile=0x0102;
1385
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0103) {
1386
            header_compression_profile=0x0103;
1387
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0104) {
1388
            header_compression_profile=0x0104;
1389
          } else {
1390 1391
            header_compression_profile=0x0;
            LOG_W(PDCP,"unknown header compresion profile\n");
1392
          }
1393 1394 1395 1396 1397

          // set the applicable profile
          break;

        default:
Cedric Roux's avatar
Cedric Roux committed
1398
          LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT"[RB %ld] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
1399
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), drb_id);
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418
          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);
1419
      }
1420
    }
1421 1422
  }

1423
  if (drb2release_list_pP != NULL) {
1424 1425 1426
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1427
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
1428 1429 1430
      h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1431
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1432 1433 1434
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1435
      }
1436 1437
      lc_id = pdcp_p->lcid;

1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
      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);
1455
      h_rc = hashtable_remove(pdcp_coll_p, key);
1456 1457

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1458
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
        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
      }
1470
    }
1471 1472
  }

1473
#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1474

1475
  if (pmch_InfoList_r9_pP != NULL) {
1476 1477 1478 1479 1480
    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];
1481 1482 1483 1484
        if (MBMS_SessionInfo_p->sessionId_r9)
          lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        else
          lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
1485
        mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
1486
//        mch_id = j;
1487 1488 1489

        // can set the mch_id = i
        if (ctxt_pP->enb_flag) {
1490
          drb_id =  (mch_id * LTE_maxSessionPerPMCH ) + lc_id ;//+ (LTE_maxDRB + 3)*MAX_MOBILES_PER_ENB; // 1
1491

1492
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1493 1494 1495 1496 1497
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
1498
          drb_id =  (mch_id * LTE_maxSessionPerPMCH ) + lc_id; // + (LTE_maxDRB + 3); // 15
1499

1500
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1501 1502 1503
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1504
          }
1505 1506
        }

1507 1508 1509 1510 1511 1512 1513 1514
        LOG_D(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
          lc_id,
          MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[0],
          MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[1],
          MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2],
          drb_id,
          action);

1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
        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
1531
      }
1532
    }
1533
  }
1534

1535
#endif
1536
  return 0;
1537 1538
}

1539
//-----------------------------------------------------------------------------
1540 1541
boolean_t
pdcp_config_req_asn1 (
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556
  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)
1557
//-----------------------------------------------------------------------------
1558
{
1559
  
1560
  switch (actionP) {
1561
  case CONFIG_ACTION_ADD:
1562
    DevAssert(pdcp_pP != NULL);
1563 1564
    if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
      pdcp_pP->is_ue = FALSE;
Navid Nikaein's avatar
Navid Nikaein committed
1565
      pdcp_add_UE(ctxt_pP);
1566
      
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1567
      //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti;
1568 1569
//      pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
      if( srb_flagP == SRB_FLAG_NO ) {
1570
          for(int i = 0;i<MAX_MOBILES_PER_ENB;i++){
1571 1572 1573
              if(pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] == NOT_A_RNTI){
                  break;
              }
1574
              pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1575 1576
          }
          pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
1577
          pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1578
      }
1579
      //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1580 1581 1582 1583
    } else {
      pdcp_pP->is_ue = TRUE;
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
    }
1584
    pdcp_pP->is_srb                     = (srb_flagP == SRB_FLAG_YES) ? TRUE : FALSE;
Lionel Gauthier's avatar
Lionel Gauthier committed
1585
    pdcp_pP->lcid                       = lc_idP;
1586
    pdcp_pP->rb_id                      = rb_idP;
1587
    pdcp_pP->header_compression_profile = header_compression_profileP;
Lionel Gauthier's avatar
Lionel Gauthier committed
1588
    pdcp_pP->status_report              = rb_reportP;
1589

1590
    if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1591
      pdcp_pP->seq_num_size = PDCP_SN_12BIT;
1592
    } else if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1593
      pdcp_pP->seq_num_size = PDCP_SN_7BIT;
1594
    } else {
1595
      pdcp_pP->seq_num_size = PDCP_SN_5BIT;
1596
    }
1597

1598

1599 1600 1601 1602 1603 1604 1605 1606 1607
    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;
1608

1609
    LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %d) "
1610
            "configured with SN size %d bits and RLC %s\n",
1611 1612
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
1613
	  (srb_flagP == SRB_FLAG_YES) ? "SRB" : "DRB",
1614 1615
          rb_idP,
          pdcp_pP->seq_num_size,
1616
	  (rlc_modeP == RLC_MODE_AM ) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1617 1618
    /* Setup security */
    if (security_modeP != 0xff) {
1619 1620 1621 1622 1623 1624 1625 1626 1627
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1628 1629
    }
    break;
1630

1631
  case CONFIG_ACTION_MODIFY:
1632 1633 1634 1635
    DevAssert(pdcp_pP != NULL);
    pdcp_pP->header_compression_profile=header_compression_profileP;
    pdcp_pP->status_report = rb_reportP;
    pdcp_pP->rlc_mode = rlc_modeP;
1636

1637 1638
    /* Setup security */
    if (security_modeP != 0xff) {
1639 1640 1641 1642 1643 1644 1645 1646 1647
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1648
    }
1649

1650
    if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1651
      pdcp_pP->seq_num_size = 7;
1652
    } else if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1653
      pdcp_pP->seq_num_size = 12;
1654
    } else {
1655
      pdcp_pP->seq_num_size=5;
1656
    }
1657

1658
    LOG_I(PDCP,PROTOCOL_PDCP_CTXT_FMT" Action MODIFY LCID %d "
Navid Nikaein's avatar
Navid Nikaein committed
1659
            "RB id %d reconfigured with SN size %d and RLC %s \n",
1660 1661 1662 1663
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
          rb_idP,
          rb_snP,
1664
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1665
    break;
1666

1667
  case CONFIG_ACTION_REMOVE:
1668
    DevAssert(pdcp_pP != NULL);
1669
//#warning "TODO pdcp_module_id_to_rnti"
1670 1671 1672 1673 1674
    //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);
1675

1676
   if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
1677
     // pdcp_remove_UE(ctxt_pP);
1678
   }
1679

1680 1681
    /* Security keys */
    if (pdcp_pP->kUPenc != NULL) {
1682
      free(pdcp_pP->kUPenc);
1683
    }
1684

1685
    if (pdcp_pP->kRRCint != NULL) {
1686
      free(pdcp_pP->kRRCint);
1687
    }
1688

1689
    if (pdcp_pP->kRRCenc != NULL) {
1690
      free(pdcp_pP->kRRCenc);
1691
    }
1692

1693
    memset(pdcp_pP, 0, sizeof(pdcp_t));
1694
    break;
1695
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
1696

1697 1698
  case CONFIG_ACTION_MBMS_ADD:
  case CONFIG_ACTION_MBMS_MODIFY:
1699 1700
    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),
1701 1702 1703 1704 1705 1706 1707 1708
          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;
1709
    } else {
1710 1711
      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;
1712
    }
1713

1714
    break;
Lionel Gauthier's avatar
Lionel Gauthier committed
1715
#endif
1716

1717
  case CONFIG_ACTION_SET_SECURITY_MODE:
1718
    pdcp_config_set_security(
1719 1720 1721 1722 1723 1724 1725 1726
      ctxt_pP,
      pdcp_pP,
      rb_idP,
      lc_idP,
      security_modeP,
      kRRCenc_pP,
      kRRCint_pP,
      kUPenc_pP);
1727
    break;
1728

1729
  default:
1730
    DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1731
    break;
1732
  }
1733

1734 1735
  return 0;
}
1736

1737 1738 1739
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
1740 1741 1742 1743 1744 1745 1746 1747
  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)
1748
//-----------------------------------------------------------------------------
1749
{
1750
  DevAssert(pdcp_pP != NULL);
1751

1752
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1753 1754
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1755

1756 1757
    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),
1758 1759 1760 1761 1762 1763
            pdcp_pP->cipheringAlgorithm,
            pdcp_pP->integrityProtAlgorithm);

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

1765 1766
    /* Activate security */
    pdcp_pP->security_activated = 1;
Lionel Gauthier's avatar
Lionel Gauthier committed
1767 1768
	MSC_LOG_EVENT(
	  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1769
	  "0 Set security ciph %X integ %x UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1770 1771 1772
	  pdcp_pP->cipheringAlgorithm,
	  pdcp_pP->integrityProtAlgorithm,
	  ctxt_pP->rnti);
1773
  } else {
Lionel Gauthier's avatar
Lionel Gauthier committed
1774 1775
	  MSC_LOG_EVENT(
	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1776
	    "0 Set security failed UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1777 1778
	    ctxt_pP->rnti);
	  LOG_E(PDCP,PROTOCOL_PDCP_CTXT_FMT"  bad security mode %d",
1779 1780
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
1781
  }
1782 1783
}

1784
//-----------------------------------------------------------------------------
1785 1786
void
rrc_pdcp_config_req (
1787 1788 1789 1790 1791
  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)
1792
//-----------------------------------------------------------------------------
1793
{
1794
  pdcp_t *pdcp_p = NULL;
1795 1796 1797
  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);
1798

1799
  if (h_rc == HASH_TABLE_OK) {
1800 1801

  /*
1802 1803 1804
   * Initialize sequence number state variables of relevant PDCP entity
   */
  switch (actionP) {
1805
  case CONFIG_ACTION_ADD:
1806 1807
    pdcp_p->is_srb = srb_flagP;
    pdcp_p->rb_id  = rb_idP;
1808

1809
    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
1810
      pdcp_p->is_ue = TRUE;
1811
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1812
    } else {
1813
      pdcp_p->is_ue = FALSE;
1814
    }
1815 1816 1817 1818 1819 1820 1821 1822 1823

    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
1824
      pdcp_p->seq_num_size = 5;
1825
    } else { // DRB
1826
      pdcp_p->seq_num_size = 12;
1827
    }
1828

1829
    pdcp_p->first_missing_pdu = -1;
1830 1831 1832
    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);
1833
    break;
1834

1835
  case CONFIG_ACTION_MODIFY:
1836
    break;
1837

1838
  case CONFIG_ACTION_REMOVE:
1839 1840 1841
      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);
1842 1843 1844 1845 1846 1847 1848 1849
    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;
1850
      h_rc = hashtable_remove(pdcp_coll_p, key);
1851 1852

    break;
1853

1854
  case CONFIG_ACTION_SET_SECURITY_MODE:
1855
    if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1856 1857
      pdcp_p->cipheringAlgorithm= security_modeP & 0x0f;
      pdcp_p->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1858 1859
        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),
1860 1861
            pdcp_p->cipheringAlgorithm,
            pdcp_p->integrityProtAlgorithm );
1862
    } else {
Cedric Roux's avatar
Cedric Roux committed
1863
        LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT" bad security mode %d", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), security_modeP);
1864
    }
1865

1866
    break;
1867

1868
  default:
1869
      DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1870
    break;
1871
  }
1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888
  } 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;
1889
	  pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1890 1891
        } else {
          pdcp_p->is_ue = FALSE;
1892
	}
1893

1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931
        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));
    }
  }
}


//-----------------------------------------------------------------------------
1932
 
1933 1934 1935 1936 1937
int
pdcp_module_init (
  void
)
//-----------------------------------------------------------------------------
1938
{
1939
 
1940
#ifdef PDCP_USE_RT_FIFO
1941 1942
  int ret;

1943
  ret=rtf_create(PDCP2NW_DRIVER_FIFO,32768);
1944 1945

  if (ret < 0) {
1946
    LOG_E(PDCP, "Cannot create PDCP2NW_DRIVER_FIFO fifo %d (ERROR %d)\n", PDCP2NW_DRIVER_FIFO, ret);
1947
    return -1;
1948
  } else {
1949 1950
    LOG_D(PDCP, "Created PDCP2NAS fifo %d\n", PDCP2NW_DRIVER_FIFO);
    rtf_reset(PDCP2NW_DRIVER_FIFO);
1951 1952
  }

1953
  ret=rtf_create(NW_DRIVER2PDCP_FIFO,32768);
1954 1955

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

1958
    return -1;
1959
  } else {
1960 1961
    LOG_D(PDCP, "Created NW_DRIVER2PDCP_FIFO fifo %d\n", NW_DRIVER2PDCP_FIFO);
    rtf_reset(NW_DRIVER2PDCP_FIFO);
1962 1963 1964 1965 1966 1967 1968 1969
  }

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

  return 0;
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
}

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

1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
  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);
  }
1997 1998 1999
}

//-----------------------------------------------------------------------------
2000 2001
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
2002
{
2003 2004 2005
#ifdef PDCP_USE_RT_FIFO
  rtf_destroy(NW_DRIVER2PDCP_FIFO);
  rtf_destroy(PDCP2NW_DRIVER_FIFO);
2006 2007 2008 2009
#endif
}

//-----------------------------------------------------------------------------
2010
void pdcp_layer_init(void)
2011
//-----------------------------------------------------------------------------
2012
{
2013

Lionel Gauthier's avatar
Lionel Gauthier committed
2014
  module_id_t       instance;
2015
  int i,j;
2016
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
Lionel Gauthier's avatar
Lionel Gauthier committed
2017 2018 2019
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
#endif
2020
  /*
2021 2022
   * Initialize SDU list
   */
2023
  list_init(&pdcp_sdu_list, NULL);
2024
  pdcp_coll_p = hashtable_create ((LTE_maxDRB + 2) * 16, NULL, pdcp_free);
2025
  AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
2026

2027
  for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
2028
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2029

2030 2031
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2032
        memset(&pdcp_mbms_array_ue[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2033
      }
2034
    }
Lionel Gauthier's avatar
Lionel Gauthier committed
2035
#endif
2036
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
2037
  }
2038
  pdcp_eNB_UE_instance_to_rnti_index = 0; 
2039

2040
    
2041
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
2042
#if (LTE_RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2043

2044 2045
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2046
        memset(&pdcp_mbms_array_eNB[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2047
      }
2048 2049
    }

Lionel Gauthier's avatar
Lionel Gauthier committed
2050
#endif
2051
  }
2052

2053 2054 2055 2056 2057 2058
#ifdef MBMS_MULTICAST_OUT
  mbms_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if (mbms_socket == -1)
    LOG_W(PDCP, "Could not create RAW socket, MBMS packets will not be put to the network\n");
#endif

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

2061 2062 2063
  pdcp_output_sdu_bytes_to_write=0;
  pdcp_output_header_bytes_to_write=0;
  pdcp_input_sdu_remaining_size_to_read=0;
2064

2065 2066
  memset(pdcp_enb, 0, sizeof(pdcp_enb_t));

2067
  
2068 2069 2070
  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 ++){
2071
    for (j=0; j< MAX_MOBILES_PER_ENB;j++){
2072 2073 2074 2075 2076
      Pdcp_stats_tx_window_ms[i][j]=100;
      Pdcp_stats_rx_window_ms[i][j]=100;
    }
  }
  
2077
  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
2078 2079
  memset(Pdcp_stats_tx_w, 0, sizeof(Pdcp_stats_tx_w));
  memset(Pdcp_stats_tx_tmp_w, 0, sizeof(Pdcp_stats_tx_tmp_w));
2080
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
2081 2082
  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));
2083
  memset(Pdcp_stats_tx_sn, 0, sizeof(Pdcp_stats_tx_sn));
2084
  memset(Pdcp_stats_tx_throughput_w, 0, sizeof(Pdcp_stats_tx_throughput_w));
2085 2086 2087
  memset(Pdcp_stats_tx_aiat, 0, sizeof(Pdcp_stats_tx_aiat));
  memset(Pdcp_stats_tx_iat, 0, sizeof(Pdcp_stats_tx_iat));
  
2088 2089

  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
2090 2091
  memset(Pdcp_stats_rx_w, 0, sizeof(Pdcp_stats_rx_w));
  memset(Pdcp_stats_rx_tmp_w, 0, sizeof(Pdcp_stats_rx_tmp_w));
2092
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
2093 2094
  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));
2095
  memset(Pdcp_stats_rx_sn, 0, sizeof(Pdcp_stats_rx_sn));
2096
  memset(Pdcp_stats_rx_goodput_w, 0, sizeof(Pdcp_stats_rx_goodput_w));
2097 2098 2099 2100
  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));
    
2101 2102 2103
}

//-----------------------------------------------------------------------------
2104 2105
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
2106 2107
{
  list_free (&pdcp_sdu_list);
2108
  hashtable_destroy(pdcp_coll_p);
2109 2110 2111 2112 2113 2114
#ifdef MBMS_MULTICAST_OUT
  if(mbms_socket != -1) {
    close(mbms_socket);
    mbms_socket = -1;
  }
#endif
2115 2116
}

2117
#ifdef PDCP_USE_RT_FIFO
2118
EXPORT_SYMBOL(pdcp_2_nas_irq);
2119
#endif //PDCP_USE_RT_FIFO