pdcp.c 77.1 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
#include "common/ngran_types.h"
53

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

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

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

67 68 69
#include "ENB_APP/enb_config.h"
#include "LAYER2/PROTO_AGENT/proto_agent.h"

70 71
extern int otg_enabled;

72 73
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
74

75 76 77
/* global PDCP protocol context for this */
protocol_ctxt_t ctxt;

78 79 80 81 82 83 84 85 86 87 88
#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

89 90 91 92 93 94 95 96
//-----------------------------------------------------------------------------
/*
 * 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()
 */
97
boolean_t pdcp_data_req(
98
  protocol_ctxt_t*  ctxt_pP,
99 100 101 102 103 104
  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,
105
  const pdcp_transmission_mode_t modeP
106
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
107 108 109
    ,const uint32_t * const sourceL2Id
    ,const uint32_t * const destinationL2Id
#endif
110 111
)
//-----------------------------------------------------------------------------
112
{
113

114
  pdcp_t            *pdcp_p          = NULL;
115 116 117 118 119
  uint8_t            i               = 0;
  uint8_t            pdcp_header_len = 0;
  uint8_t            pdcp_tailer_len = 0;
  uint16_t           pdcp_pdu_size   = 0;
  uint16_t           current_sn      = 0;
120 121
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
122
  boolean_t          ret             = TRUE;
123

124 125
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
126 127
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
128
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
129
  CHECK_CTXT_ARGS(ctxt_pP);
130

131

Cedric Roux's avatar
Cedric Roux committed
132 133 134 135 136
#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

137 138 139 140 141 142 143 144
  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?
   */
145
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
146 147
          sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
  
148
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
149
    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);
150
  } else {
151
    if (srb_flagP) {
Navid Nikaein's avatar
Navid Nikaein committed
152
      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);
153
    } else {
154
      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);
155
    }
156
  }
157

158 159
  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);
160

161 162 163
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
164 165 166
	    PROTOCOL_CTXT_ARGS(ctxt_pP),
	    rb_idP);
      ctxt_pP->configured=FALSE;
167
      return FALSE;
168
    }
169 170
  }else{
    // instance for a given RB is configured
171
    ctxt_pP->configured=TRUE;
172
  }
173
    
174
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
175 176 177 178
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
179

180
  // PDCP transparent mode for MBMS traffic
181

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

    if (pdcp_pdu_p != NULL) {
      memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
188
#if defined(DEBUG_PDCP_PAYLOAD)
189 190 191
      rlc_util_print_hex_octets(PDCP,
                                (unsigned char*)&pdcp_pdu_p->data[0],
                                sdu_buffer_sizeP);
Lionel Gauthier's avatar
 
Lionel Gauthier committed
192
#endif
193 194 195 196 197 198 199 200 201 202 203 204
      if (RC.rrc[ctxt_pP->module_id]->node_type == ngran_eNB_CU
          || RC.rrc[ctxt_pP->module_id]->node_type == ngran_ng_eNB_CU
          || RC.rrc[ctxt_pP->module_id]->node_type == ngran_gNB_CU) {
        /* currently, there is no support to send also the source/destinationL2Id */
        proto_agent_send_rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
                                      confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
        /* assume good status */
        rlc_status = RLC_OP_STATUS_OK;

      } else {
        rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP,
                                  confirmP, sdu_buffer_sizeP, pdcp_pdu_p
205
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
206
                                  ,NULL, NULL
207
#endif
208 209
                                  );
      }
210 211
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
212 213
      LOG_W(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
214
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
215 216
      AssertFatal(0, PROTOCOL_CTXT_FMT"[RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  PROTOCOL_CTXT_ARGS(ctxt_pP),
217
                  rb_idP);
218
#endif
219
    }
220
  } else {
221 222 223 224 225 226 227 228 229 230
    // 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;
231

232 233
    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),
234 235 236
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
237

238 239 240
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
241
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
242 243

    if (pdcp_pdu_p != NULL) {
244
      /*
245 246 247
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
248
       */
249

250 251 252 253 254 255
      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);
256

257
        if (pdcp_serialize_control_plane_data_pdu_with_SRB_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
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
266

267
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
268 269 270 271 272 273 274
          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 ;
275

276
        if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
277 278
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
279 280
         
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
281

282 283 284 285
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
286

287
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
288 289
          return FALSE;
        }
290
      }
291

292
      /*
293
       * Validate incoming sequence number, there might be a problem with PDCP initialization
294
       */
295
      if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
Cedric Roux's avatar
Cedric Roux committed
296
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Generated sequence number (%"PRIu16") is greater than a sequence number could ever be!\n"\
297 298 299
              "There must be a problem with PDCP initialization, ignoring this PDU...\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              current_sn);
300

301
        free_mem_block(pdcp_pdu_p, __func__);
302

303
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
304 305 306 307
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
308

309
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
310 311 312 313 314 315 316 317 318 319 320
        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
321
      for (i=0; i<pdcp_tailer_len; i++) {
322
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
323
      }
324 325 326 327 328 329 330

#if defined(ENABLE_SECURITY)

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

331
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
332 333 334 335
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
336 337 338 339 340 341 342 343 344 345

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

346 347 348 349 350
        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);
        }
351 352 353 354 355 356 357 358 359 360 361 362
      }

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

363 364 365 366 367
      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);
      }
368 369 370 371 372 373 374 375 376

#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
377
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
378 379 380 381 382 383 384 385
      return FALSE;
    }

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

386 387
    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);
388 389

    LOG_F(PDCP,"\n");
Wolfgang A. Mozart's avatar
Wolfgang A. Mozart committed
390
#ifndef UETARGET
391 392
    if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1))
    {
393 394 395 396 397 398 399 400 401
      if (RC.rrc[ctxt_pP->module_id]->node_type == ngran_eNB_CU
          || RC.rrc[ctxt_pP->module_id]->node_type == ngran_ng_eNB_CU
          || RC.rrc[ctxt_pP->module_id]->node_type == ngran_gNB_CU) {
        /* currently, there is no support to send also the source/destinationL2Id */
        proto_agent_send_rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
                                      confirmP, pdcp_pdu_size, pdcp_pdu_p);
        /* assume good status */
        rlc_status = RLC_OP_STATUS_OK;
      } else {
402

403 404
        rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
            confirmP, pdcp_pdu_size, pdcp_pdu_p
405
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
406 407
                             ,sourceL2Id
                             ,destinationL2Id
408
#endif
409 410
                             );
      } /* end if node_type is CU */
411
    
412 413
      free_mem_block(pdcp_pdu_p, __FUNCTION__);
      rlc_status = ack_result;
414
    }
415
    else // SRB
416
#endif /*UETARGET*/ 
417
    {
418 419
     LOG_I(PDCP, "Sending F1AP_DL_RRC_MESSAGE with ITTI\n");

420
      //It should never get here
421 422 423 424 425
      if ((RC.rrc[ctxt_pP->module_id]->node_type  == ngran_eNB_CU)   ||
        (RC.rrc[ctxt_pP->module_id]->node_type   == ngran_ng_eNB_CU)||
        (RC.rrc[ctxt_pP->module_id]->node_type   == ngran_gNB_CU)  ) {
        // DL transfer
        MessageDef                            *message_p;
426 427
        // Note: the acyual task must be TASK_PDCP, but this task is not created
        message_p = itti_alloc_new_message (TASK_PDCP, F1AP_DL_RRC_MESSAGE);
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
        F1AP_DL_RRC_MESSAGE (message_p).rrc_container =  &pdcp_pdu_p->data[0] ;
        F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = pdcp_pdu_size;
        F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id  = 0;  
        F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id  = 0;
        F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id  = 0xFFFFFFFF; // unknown
        F1AP_DL_RRC_MESSAGE (message_p).rnti = ctxt_pP->rnti;
        F1AP_DL_RRC_MESSAGE (message_p).srb_id = rb_idP;
        F1AP_DL_RRC_MESSAGE (message_p).execute_duplication      = 1;
        F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc      = 0;
        itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p);
        //CU_send_DL_RRC_MESSAGE_TRANSFER(ctxt_pP->module_id, message_p);
        LOG_I(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n");
        ret=TRUE;

      } else{
        rlc_status = rlc_data_req(ctxt_pP
                                  , srb_flagP
                                  , MBMS_FLAG_NO
                                  , rb_idP
                                  , muiP
                                  , confirmP
                                  , pdcp_pdu_size
                                  , pdcp_pdu_p
#ifdef Rel14
                                  ,NULL
                                  ,NULL
#endif
                                  );
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;

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

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

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

          default:
            LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
            ret= FALSE;
            break;
        } // switch case
      }
483
    }
484
  }
485

486
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
487 488 489 490
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
491

492 493 494 495
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
496

497
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
498
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ) 
499 500 501 502 503
      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]++;
504
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
505
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
506
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
507
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;
508

509
  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]);
510
  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]); 
511
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
512
    
513
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
514
  return ret;
515
 
516 517
}

518

519 520 521
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
522 523 524 525 526
  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,
527 528 529
  mem_block_t* const sdu_buffer_pP
)
//-----------------------------------------------------------------------------
530
{
531 532 533
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
534 535
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
536
  pdcp_sn_t    sequence_number = 0;
537
  volatile sdu_size_t   payload_offset  = 0;
538
  rb_id_t      rb_id            = rb_idP;
539
  boolean_t    packet_forwarded = FALSE;
540 541
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
542 543 544
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
  uint16_t     pdcp_uid=0;      
  uint8_t      oo_flag=0;
545
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
546
  MessageDef  *message_p        = NULL;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
547
  uint8_t     *gtpu_buffer_p    = NULL;
548
#endif
549

550

551
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
552 553
  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);
554

Cedric Roux's avatar
Cedric Roux committed
555 556 557 558 559
#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

560
  if (MBMS_flagP) {
561 562 563 564 565 566
    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);
567 568

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
569
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
570
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
571 572 573 574 575
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
576

Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
577
    } else {
578 579 580 581 582 583 584
      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
585
    }
586

Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
587
  } else {
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
    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);
607
      free_mem_block(sdu_buffer_pP, __func__);
608
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
609
      return FALSE;
610
    }
611
  }
612

613
  sdu_list_p = &pdcp_sdu_list;
614

615
  if (sdu_buffer_sizeP == 0) {
616 617
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
618
  }
619

620 621 622 623 624
  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);
  }
625 626

  /*
627 628
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
629
   */
630

631
  if (MBMS_flagP == 0 ) {
632 633 634 635 636 637
    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;
638 639 640 641 642 643 644

      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);
645
      } else {
646
        //sequence_number = 4095;
647 648 649 650
        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);
651
      }
652

653 654
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
655

656 657 658 659
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
660 661 662 663
      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);
664
      free_mem_block(sdu_buffer_pP, __func__);
665

666 667 668 669 670
      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);
      }
671

672
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
673 674 675
      return FALSE;
    }

676
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
677
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
678
      /* if (dc == PDCP_DATA_PDU )
679 680 681
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
682
    } else {
683
      oo_flag=1;
684 685 686 687
      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);
688
      /*
689 690
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
691
       */
bruno mongazon's avatar
bruno mongazon committed
692 693
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
694 695
      return FALSE;
    }
696 697 698

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

701
      if (pdcp_p->security_activated == 1) {
702 703 704 705 706
        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);
        }
707 708 709 710 711 712 713 714 715 716

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

717 718 719 720 721
        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);
        }
722
      }
723

724 725
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
726 727 728 729 730 731 732
  	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);
733
        rrc_data_ind(ctxt_pP,
734 735 736
		   rb_id,
		   sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
		   (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len]);
737
        free_mem_block(sdu_buffer_pP, __func__);
738

739

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

747
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
748 749
      return TRUE;
    }
750 751 752 753

    /*
     * DRBs
     */
754 755
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
756

757
    if (pdcp_p->security_activated == 1) {
758 759 760 761 762
      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);
      }
763

764
      pdcp_validate_security(
765 766 767 768 769 770 771 772 773
        ctxt_pP,
        pdcp_p,
        srb_flagP,
        rb_idP,
        pdcp_header_len,
        sequence_number,
        sdu_buffer_pP->data,
        sdu_buffer_sizeP - pdcp_tailer_len);

774 775 776 777 778
      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);
      }
779

780
    }
781

782
#endif
783
  } else {
784
    payload_offset=0;
785
  }
786 787 788

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

791 792 793 794 795
    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);
    }
796

797
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
798 799 800
    return TRUE;
  }

801 802 803 804 805 806 807 808
  // 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)
   */
809
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
810

811
  if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
812 813 814 815 816 817 818 819
    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);
820
    //LOG_T(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
821
    gtpu_buffer_p = itti_malloc(TASK_PDCP, TASK_GTPV1_U,
822 823 824
                                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);
825
    message_p = itti_alloc_new_message(TASK_PDCP, GTPV1U_ENB_TUNNEL_DATA_REQ);
826 827 828 829
    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;
830
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
831 832
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
    itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
833
    packet_forwarded = TRUE;    
834
  }
Navid Nikaein's avatar
Navid Nikaein committed
835
  
836 837 838
#else
  packet_forwarded = FALSE;
#endif
839

840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
#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

855
  if (FALSE == packet_forwarded) {
856
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
857

858
    if (new_sdu_p) {
859
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
860 861 862 863 864 865 866 867
        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;
868
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
869 870 871 872 873

      // 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;
874
#if defined(ENABLE_USE_MME)
875 876 877 878
        /* 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
879
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = 1;
880
#endif
881
      } else {
882
        ((pdcp_data_ind_header_t*) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * maxDRB);
883
      }
884 885
      ((pdcp_data_ind_header_t*) new_sdu_p->data)->inst  = ctxt_pP->module_id;

886 887 888 889 890
#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
891 892 893 894 895

      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);
896 897
      /* directly send -> this is a hack, send single packet directly */
      pdcp_fifo_flush_sdus(ctxt_pP);
898

899 900
      
      
901 902
    }

903 904 905 906 907 908 909 910 911 912 913 914
  /* 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?
   */
  
915
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
916
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ){
917
      break;
918
    }
919 920 921
  }	
  
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
922
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
923
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
924
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
925 926 927 928 929 930
  
  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]++;
  
931
  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]);
932
  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]);
933
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
934 935

  
936
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
937 938 939 940
    else {
      AssertFatal(0, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
                  PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
    }
941
#endif
942

943 944
  }

945
  free_mem_block(sdu_buffer_pP, __func__);
946

947 948 949 950 951
  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);
  }
952

953
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
954 955 956
  return TRUE;
}

Navid Nikaein's avatar
Navid Nikaein committed
957 958
void pdcp_update_stats(const protocol_ctxt_t* const  ctxt_pP){

959
  uint16_t           pdcp_uid = 0;
Navid Nikaein's avatar
Navid Nikaein committed
960 961
  uint8_t            rb_id     = 0;
  
962
 // these stats are measured for both eNB and UE on per seond basis 
963
  for (rb_id =0; rb_id < NB_RB_MAX; rb_id ++){
964
    for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB;pdcp_uid++){
965 966
      //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
967 968
      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){
969
	// unit: bit/s
970 971 972 973 974 975 976 977 978 979 980 981
	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
982
	
983
      }
Raymond Knopp's avatar
Raymond Knopp committed
984 985
      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
986
	// rx stats
987 988 989
	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
990
	
991 992 993 994 995
	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
996
	
997 998 999 1000
	// 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
1001 1002
      } 
    }
1003
    
Navid Nikaein's avatar
Navid Nikaein committed
1004 1005
  }
}
1006

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
#if defined(ENABLE_ITTI)
//-----------------------------------------------------------------------------
void
pdcp_task(void *arg)
{
//-----------------------------------------------------------------------------
  MessageDef      *msg_p;
  int              result;
  instance_t       instance;

  LOG_I(PDCP, "Starting PDCP task\n");
  itti_mark_task_ready(TASK_PDCP);

  while (1) {
    itti_receive_msg(TASK_PDCP, &msg_p);
    instance = ITTI_MSG_INSTANCE(msg_p);

    switch (ITTI_MSG_ID(msg_p)) {
    case RRC_DCCH_DATA_REQ:
      PROTOCOL_CTXT_SET_BY_MODULE_ID(
        &ctxt,
        RRC_DCCH_DATA_REQ (msg_p).module_id,
        RRC_DCCH_DATA_REQ (msg_p).enb_flag,
        RRC_DCCH_DATA_REQ (msg_p).rnti,
        RRC_DCCH_DATA_REQ (msg_p).frame,
        0,
        RRC_DCCH_DATA_REQ (msg_p).eNB_index);

      LOG_I(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
            PROTOCOL_CTXT_ARGS(&ctxt),
            ITTI_MSG_NAME (msg_p),
            ITTI_MSG_ORIGIN_NAME(msg_p),
            ITTI_MSG_INSTANCE (msg_p),
            RRC_DCCH_DATA_REQ (msg_p).rb_id,
            RRC_DCCH_DATA_REQ (msg_p).muip,
            RRC_DCCH_DATA_REQ (msg_p).confirmp,
            RRC_DCCH_DATA_REQ (msg_p).mode);

      log_dump(PDCP, RRC_DCCH_DATA_REQ (msg_p).sdu_p, RRC_DCCH_DATA_REQ (msg_p).sdu_size, LOG_DUMP_CHAR,"[MSG] pdcp run\n");

      result = pdcp_data_req (&ctxt,
                              SRB_FLAG_YES,
                              RRC_DCCH_DATA_REQ (msg_p).rb_id,
                              RRC_DCCH_DATA_REQ (msg_p).muip,
                              RRC_DCCH_DATA_REQ (msg_p).confirmp,
                              RRC_DCCH_DATA_REQ (msg_p).sdu_size,
                              RRC_DCCH_DATA_REQ (msg_p).sdu_p,
                              RRC_DCCH_DATA_REQ (msg_p).mode
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
                              , NULL, NULL
#endif
                              );
      if (result != TRUE)
        LOG_E(PDCP, "PDCP data request failed!\n");

      break;

    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[instance]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP;
        if (sdu_buffer_sizeP > 0)
          memcpy(RC.rrc[instance]->carrier[CC_id].paging[ue_index],
                 RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP);
        LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
      }
      break;

    case PDCP_UPDATE_STATS:
1079 1080 1081 1082 1083 1084 1085 1086
      // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
      if (ctxt.enb_flag == ENB_FLAG_NO)
#endif
      {
        pdcp_fifo_read_input_sdus(&ctxt);
      }

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
      //pdcp_process_fifo(ctxt_pP);

      //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;
      //pdcp_update_stats(ctxt_pP);
      break;

    case TERMINATE_MESSAGE:
      LOG_W(PDCP, " *** Exiting PDCP task\n");
      itti_exit_task();
      break;

    default:
      LOG_E(PDCP, "Received unexpected message %s (%d)\n", ITTI_MSG_NAME(msg_p), ITTI_MSG_ID(msg_p));
      break;
    }

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

  } // while
1111

1112
}
1113
#endif
1114

1115
void pdcp_add_UE(const protocol_ctxt_t* const  ctxt_pP){
1116
  int i, ue_flag=1; //, ret=-1; to be decied later
1117
  for (i=0; i < MAX_MOBILES_PER_ENB; i++){
1118 1119 1120 1121 1122 1123
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti) {
      ue_flag=-1;
      break;
    }
  }
  if (ue_flag == 1 ){
1124
    for (i=0; i < MAX_MOBILES_PER_ENB ; i++){
1125 1126 1127 1128
      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++;
1129
	LOG_I(PDCP,"add new uid is %d %x\n\n", i, ctxt_pP->rnti);
1130
	// ret=1;
1131 1132 1133 1134 1135 1136
	break;
      }
    }
  }
  //return ret;
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1137

1138 1139 1140 1141 1142 1143 1144
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
  const protocol_ctxt_t* const  ctxt_pP
)
//-----------------------------------------------------------------------------
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1145 1146
  DRB_Identity_t  srb_id         = 0;
  DRB_Identity_t  drb_id         = 0;
1147 1148
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
Navid Nikaein's avatar
Navid Nikaein committed
1149
  int i; 
1150
   // check and remove SRBs first
Raymond Knopp's avatar
 
Raymond Knopp committed
1151

1152
  for(int i = 0;i<MAX_MOBILES_PER_ENB;i++){
1153 1154 1155 1156 1157 1158
    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
1159
  for (srb_id=1; srb_id<3; srb_id++) {
1160 1161
    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
1162 1163
  }

1164
  for (drb_id=0; drb_id<maxDRB; drb_id++) {
1165 1166
    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
1167 1168 1169

  }

1170 1171
  (void)h_rc; /* remove gcc warning "set but not used" */

1172
  // remove ue for pdcp enb inst
1173
   for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
    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
1185 1186 1187 1188
  return 1;
}


1189 1190 1191
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
1192 1193 1194 1195 1196 1197 1198 1199
  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
1200
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1201
  ,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
1202
#endif
1203
  ,rb_id_t                 *const defaultDRB 
1204
)
1205
//-----------------------------------------------------------------------------
1206
{
1207
  long int        lc_id          = 0;
1208
  DRB_Identity_t  srb_id         = 0;
1209
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1210
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1211
  DRB_Identity_t  drb_id         = 0;
1212
  DRB_Identity_t *pdrb_id_p      = NULL;
1213
  uint8_t         drb_sn         = 12;
1214 1215
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1216
  long int        cnt            = 0;
1217 1218
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1219 1220 1221
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
1222

1223 1224
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1225 1226
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
1227
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1228
  int i,j;
1229 1230
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1231 1232
#endif

1233 1234 1235 1236 1237 1238
  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);
1239

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

1242
  if (srb2add_list_pP != NULL) {
1243 1244 1245 1246
    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;
1247
      lc_id = srb_id;
1248 1249
      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);
1250

1251 1252 1253 1254 1255
      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);
1256
      } else {
1257 1258 1259
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1260

1261 1262 1263 1264 1265 1266
        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;
1267

1268
      } else {
1269
	  LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
1270 1271 1272
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
      }

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

1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
          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;
1303
          }
1304 1305 1306 1307

          break;

        case SRB_ToAddMod__rlc_Config_PR_defaultValue:
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
        	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);
1324 1325 1326 1327
          // already the default values
          break;

        default:
1328
          DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
1329 1330
          break;
        }
1331
      }
1332
    }
1333
  }
1334

1335 1336
  // reset the action

1337
  if (drb2add_list_pP != NULL) {
1338
    for (cnt=0; cnt<drb2add_list_pP->list.count; cnt++) {
1339

1340
      drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
1341

1342
      drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1343 1344 1345 1346 1347 1348 1349 1350 1351
      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
1352
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1353 1354
        continue;
      }
1355

1356 1357 1358
      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);
1359

1360 1361 1362 1363 1364
      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);
1365

1366 1367
      } else {
        action = CONFIG_ACTION_ADD;
1368 1369 1370
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1371
        // save the first configured DRB-ID as the default DRB-ID
1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
        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;
1385
        } else if (h_rc != HASH_TABLE_OK) {
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
          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);
         }
      }
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422

      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
1423
          if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0001) {
1424
            header_compression_profile=0x0001;
1425
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0002) {
1426
            header_compression_profile=0x0002;
1427
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0003) {
1428
            header_compression_profile=0x0003;
1429
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0004) {
1430
            header_compression_profile=0x0004;
1431
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0006) {
1432
            header_compression_profile=0x0006;
1433
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0101) {
1434
            header_compression_profile=0x0101;
1435
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0102) {
1436
            header_compression_profile=0x0102;
1437
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0103) {
1438
            header_compression_profile=0x0103;
1439
          } else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0104) {
1440
            header_compression_profile=0x0104;
1441
          } else {
1442 1443
            header_compression_profile=0x0;
            LOG_W(PDCP,"unknown header compresion profile\n");
1444
          }
1445 1446 1447 1448 1449

          // set the applicable profile
          break;

        default:
Cedric Roux's avatar
Cedric Roux committed
1450
          LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT"[RB %ld] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
1451
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), drb_id);
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
          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);
1471
      }
1472
    }
1473 1474
  }

1475
  if (drb2release_list_pP != NULL) {
1476 1477 1478
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1479
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
1480 1481 1482
      h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1483
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1484 1485 1486
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1487
      }
1488
      lc_id = pdcp_p->lcid;
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506

      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);
1507
      h_rc = hashtable_remove(pdcp_coll_p, key);
1508 1509

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1510
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
        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
      }
1522
    }
1523 1524
  }

1525
#if (RRC_VERSION >= MAKE_VERSION(9, 0, 0))
1526

1527
  if (pmch_InfoList_r9_pP != NULL) {
1528 1529 1530 1531 1532
    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];
1533 1534 1535 1536
        if (MBMS_SessionInfo_p->sessionId_r9)
          lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        else
          lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
1537
        mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
1538
//        mch_id = j;
1539 1540 1541 1542 1543

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

1544
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1545 1546 1547 1548 1549 1550 1551
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
          drb_id =  (mch_id * maxSessionPerPMCH ) + lc_id; // + (maxDRB + 3); // 15

1552
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1553 1554 1555
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1556
          }
1557 1558
        }

1559 1560 1561 1562 1563 1564 1565 1566
        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);

1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
        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
1583
      }
1584
    }
1585
  }
1586

1587
#endif
1588
  return 0;
1589 1590
}

1591
//-----------------------------------------------------------------------------
1592 1593
boolean_t
pdcp_config_req_asn1 (
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608
  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)
1609
//-----------------------------------------------------------------------------
1610
{
1611
  
1612
  switch (actionP) {
1613
  case CONFIG_ACTION_ADD:
1614
    DevAssert(pdcp_pP != NULL);
1615 1616
    if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
      pdcp_pP->is_ue = FALSE;
Navid Nikaein's avatar
Navid Nikaein committed
1617
      pdcp_add_UE(ctxt_pP);
1618
      
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1619
      //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti;
1620 1621
//      pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
      if( srb_flagP == SRB_FLAG_NO ) {
1622
          for(int i = 0;i<MAX_MOBILES_PER_ENB;i++){
1623 1624 1625
              if(pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] == NOT_A_RNTI){
                  break;
              }
1626
              pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1627 1628
          }
          pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
1629
          pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1630
      }
1631
      //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1632 1633 1634 1635
    } else {
      pdcp_pP->is_ue = TRUE;
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
    }
1636
    pdcp_pP->is_srb                     = (srb_flagP == SRB_FLAG_YES) ? TRUE : FALSE;
Lionel Gauthier's avatar
Lionel Gauthier committed
1637
    pdcp_pP->lcid                       = lc_idP;
1638
    pdcp_pP->rb_id                      = rb_idP;
1639
    pdcp_pP->header_compression_profile = header_compression_profileP;
Lionel Gauthier's avatar
Lionel Gauthier committed
1640
    pdcp_pP->status_report              = rb_reportP;
1641

1642
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1643
      pdcp_pP->seq_num_size = PDCP_SN_12BIT;
1644
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1645
      pdcp_pP->seq_num_size = PDCP_SN_7BIT;
1646
    } else {
1647
      pdcp_pP->seq_num_size = PDCP_SN_5BIT;
1648
    }
1649

1650

1651 1652 1653 1654 1655 1656 1657 1658 1659
    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;
1660

1661
    LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %d) "
1662
            "configured with SN size %d bits and RLC %s\n",
1663 1664
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
1665
	  (srb_flagP == SRB_FLAG_YES) ? "SRB" : "DRB",
1666 1667
          rb_idP,
          pdcp_pP->seq_num_size,
1668
	  (rlc_modeP == RLC_MODE_AM ) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1669 1670
    /* Setup security */
    if (security_modeP != 0xff) {
1671 1672 1673 1674 1675 1676 1677 1678 1679
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1680 1681
    }
    break;
1682

1683
  case CONFIG_ACTION_MODIFY:
1684 1685 1686 1687
    DevAssert(pdcp_pP != NULL);
    pdcp_pP->header_compression_profile=header_compression_profileP;
    pdcp_pP->status_report = rb_reportP;
    pdcp_pP->rlc_mode = rlc_modeP;
1688

1689 1690
    /* Setup security */
    if (security_modeP != 0xff) {
1691 1692 1693 1694 1695 1696 1697 1698 1699
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1700
    }
1701

1702
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1703
      pdcp_pP->seq_num_size = 7;
1704
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1705
      pdcp_pP->seq_num_size = 12;
1706
    } else {
1707
      pdcp_pP->seq_num_size=5;
1708
    }
1709

1710
    LOG_I(PDCP,PROTOCOL_PDCP_CTXT_FMT" Action MODIFY LCID %d "
Navid Nikaein's avatar
Navid Nikaein committed
1711
            "RB id %d reconfigured with SN size %d and RLC %s \n",
1712 1713 1714 1715
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          lc_idP,
          rb_idP,
          rb_snP,
1716
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
1717
    break;
1718

1719
  case CONFIG_ACTION_REMOVE:
1720
    DevAssert(pdcp_pP != NULL);
1721
//#warning "TODO pdcp_module_id_to_rnti"
1722 1723 1724 1725 1726
    //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);
1727

1728
   if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
1729
     // pdcp_remove_UE(ctxt_pP);
1730
   }
1731

1732 1733
    /* Security keys */
    if (pdcp_pP->kUPenc != NULL) {
1734
      free(pdcp_pP->kUPenc);
1735
    }
1736

1737
    if (pdcp_pP->kRRCint != NULL) {
1738
      free(pdcp_pP->kRRCint);
1739
    }
1740

1741
    if (pdcp_pP->kRRCenc != NULL) {
1742
      free(pdcp_pP->kRRCenc);
1743
    }
1744

1745
    memset(pdcp_pP, 0, sizeof(pdcp_t));
1746
    break;
1747
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
1748

1749 1750
  case CONFIG_ACTION_MBMS_ADD:
  case CONFIG_ACTION_MBMS_MODIFY:
1751 1752
    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),
1753 1754 1755 1756 1757 1758 1759 1760
          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;
1761
    } else {
1762 1763
      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;
1764
    }
1765

1766
    break;
Lionel Gauthier's avatar
Lionel Gauthier committed
1767
#endif
1768

1769
  case CONFIG_ACTION_SET_SECURITY_MODE:
1770
    pdcp_config_set_security(
1771 1772 1773 1774 1775 1776 1777 1778
      ctxt_pP,
      pdcp_pP,
      rb_idP,
      lc_idP,
      security_modeP,
      kRRCenc_pP,
      kRRCint_pP,
      kUPenc_pP);
1779
    break;
1780

1781
  default:
1782
    DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1783
    break;
1784
  }
1785

1786 1787
  return 0;
}
1788

1789 1790 1791
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
1792 1793 1794 1795 1796 1797 1798 1799
  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)
1800
//-----------------------------------------------------------------------------
1801
{
1802
  DevAssert(pdcp_pP != NULL);
1803

1804
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1805 1806
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1807

1808 1809
    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),
1810 1811 1812 1813 1814 1815
            pdcp_pP->cipheringAlgorithm,
            pdcp_pP->integrityProtAlgorithm);

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

1817 1818
    /* Activate security */
    pdcp_pP->security_activated = 1;
Lionel Gauthier's avatar
Lionel Gauthier committed
1819 1820
	MSC_LOG_EVENT(
	  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1821
	  "0 Set security ciph %X integ %x UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1822 1823 1824
	  pdcp_pP->cipheringAlgorithm,
	  pdcp_pP->integrityProtAlgorithm,
	  ctxt_pP->rnti);
1825
  } else {
Lionel Gauthier's avatar
Lionel Gauthier committed
1826 1827
	  MSC_LOG_EVENT(
	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
1828
	    "0 Set security failed UE %"PRIx16" ",
Lionel Gauthier's avatar
Lionel Gauthier committed
1829 1830
	    ctxt_pP->rnti);
	  LOG_E(PDCP,PROTOCOL_PDCP_CTXT_FMT"  bad security mode %d",
1831 1832
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
1833
  }
1834 1835
}

1836
//-----------------------------------------------------------------------------
1837 1838
void
rrc_pdcp_config_req (
1839 1840 1841 1842 1843
  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)
1844
//-----------------------------------------------------------------------------
1845
{
1846
  pdcp_t *pdcp_p = NULL;
1847 1848 1849
  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);
1850

1851
  if (h_rc == HASH_TABLE_OK) {
1852 1853

  /*
1854 1855 1856
   * Initialize sequence number state variables of relevant PDCP entity
   */
  switch (actionP) {
1857
  case CONFIG_ACTION_ADD:
1858 1859
    pdcp_p->is_srb = srb_flagP;
    pdcp_p->rb_id  = rb_idP;
1860

1861
    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
1862
      pdcp_p->is_ue = TRUE;
1863
      pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1864
    } else {
1865
      pdcp_p->is_ue = FALSE;
1866
    }
1867 1868 1869 1870 1871 1872 1873 1874 1875

    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
1876
      pdcp_p->seq_num_size = 5;
1877
    } else { // DRB
1878
      pdcp_p->seq_num_size = 12;
1879
    }
1880

1881
    pdcp_p->first_missing_pdu = -1;
1882 1883 1884
    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);
1885
    break;
1886

1887
  case CONFIG_ACTION_MODIFY:
1888
    break;
1889

1890
  case CONFIG_ACTION_REMOVE:
1891 1892 1893
      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);
1894 1895 1896 1897 1898 1899 1900 1901
    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;
1902
      h_rc = hashtable_remove(pdcp_coll_p, key);
1903 1904

    break;
1905

1906
  case CONFIG_ACTION_SET_SECURITY_MODE:
1907
    if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
1908 1909
      pdcp_p->cipheringAlgorithm= security_modeP & 0x0f;
      pdcp_p->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1910 1911
        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),
1912 1913
            pdcp_p->cipheringAlgorithm,
            pdcp_p->integrityProtAlgorithm );
1914
    } else {
Cedric Roux's avatar
Cedric Roux committed
1915
        LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT" bad security mode %d", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), security_modeP);
1916
    }
1917

1918
    break;
1919

1920
  default:
1921
      DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
1922
    break;
1923
  }
1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940
  } 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;
1941
	  pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1942 1943
        } else {
          pdcp_p->is_ue = FALSE;
1944
	}
1945

1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
        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));
    }
  }
}


//-----------------------------------------------------------------------------
1984
 
1985 1986 1987 1988 1989
int
pdcp_module_init (
  void
)
//-----------------------------------------------------------------------------
1990
{
1991
 
1992
#ifdef PDCP_USE_RT_FIFO
1993 1994
  int ret;

1995
  ret=rtf_create(PDCP2NW_DRIVER_FIFO,32768);
1996 1997

  if (ret < 0) {
1998
    LOG_E(PDCP, "Cannot create PDCP2NW_DRIVER_FIFO fifo %d (ERROR %d)\n", PDCP2NW_DRIVER_FIFO, ret);
1999
    return -1;
2000
  } else {
2001 2002
    LOG_D(PDCP, "Created PDCP2NAS fifo %d\n", PDCP2NW_DRIVER_FIFO);
    rtf_reset(PDCP2NW_DRIVER_FIFO);
2003 2004
  }

2005
  ret=rtf_create(NW_DRIVER2PDCP_FIFO,32768);
2006 2007

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

2010
    return -1;
2011
  } else {
2012 2013
    LOG_D(PDCP, "Created NW_DRIVER2PDCP_FIFO fifo %d\n", NW_DRIVER2PDCP_FIFO);
    rtf_reset(NW_DRIVER2PDCP_FIFO);
2014 2015 2016 2017 2018 2019 2020 2021
  }

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

  return 0;
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
}

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

2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048
  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);
  }
2049 2050 2051
}

//-----------------------------------------------------------------------------
2052 2053
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
2054
{
2055 2056 2057
#ifdef PDCP_USE_RT_FIFO
  rtf_destroy(NW_DRIVER2PDCP_FIFO);
  rtf_destroy(PDCP2NW_DRIVER_FIFO);
2058 2059 2060 2061
#endif
}

//-----------------------------------------------------------------------------
2062
void pdcp_layer_init(void)
2063
//-----------------------------------------------------------------------------
2064
{
2065

Lionel Gauthier's avatar
Lionel Gauthier committed
2066
  module_id_t       instance;
2067
  int i,j;
2068
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
Lionel Gauthier's avatar
Lionel Gauthier committed
2069 2070 2071
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
#endif
2072
  /*
2073 2074
   * Initialize SDU list
   */
2075
  list_init(&pdcp_sdu_list, NULL);
2076 2077
  pdcp_coll_p = hashtable_create ((maxDRB + 2) * 16, NULL, pdcp_free);
  AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
2078

2079
  for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
2080
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2081 2082 2083 2084

    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));
2085
      }
2086
    }
Lionel Gauthier's avatar
Lionel Gauthier committed
2087
#endif
2088
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
2089
  }
2090
  pdcp_eNB_UE_instance_to_rnti_index = 0; 
2091

2092
    
2093
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
2094
#if (RRC_VERSION >= MAKE_VERSION(10, 0, 0))
2095 2096 2097 2098

    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));
2099
      }
2100 2101
    }

Lionel Gauthier's avatar
Lionel Gauthier committed
2102
#endif
2103
  }
2104

2105 2106 2107 2108 2109 2110
#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

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

2113 2114 2115
  pdcp_output_sdu_bytes_to_write=0;
  pdcp_output_header_bytes_to_write=0;
  pdcp_input_sdu_remaining_size_to_read=0;
2116

2117 2118
  memset(pdcp_enb, 0, sizeof(pdcp_enb_t));

2119
  
2120 2121 2122
  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 ++){
2123
    for (j=0; j< MAX_MOBILES_PER_ENB;j++){
2124 2125 2126 2127 2128
      Pdcp_stats_tx_window_ms[i][j]=100;
      Pdcp_stats_rx_window_ms[i][j]=100;
    }
  }
  
2129
  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
2130 2131
  memset(Pdcp_stats_tx_w, 0, sizeof(Pdcp_stats_tx_w));
  memset(Pdcp_stats_tx_tmp_w, 0, sizeof(Pdcp_stats_tx_tmp_w));
2132
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
2133 2134
  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));
2135
  memset(Pdcp_stats_tx_sn, 0, sizeof(Pdcp_stats_tx_sn));
2136
  memset(Pdcp_stats_tx_throughput_w, 0, sizeof(Pdcp_stats_tx_throughput_w));
2137 2138 2139
  memset(Pdcp_stats_tx_aiat, 0, sizeof(Pdcp_stats_tx_aiat));
  memset(Pdcp_stats_tx_iat, 0, sizeof(Pdcp_stats_tx_iat));
  
2140 2141

  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
2142 2143
  memset(Pdcp_stats_rx_w, 0, sizeof(Pdcp_stats_rx_w));
  memset(Pdcp_stats_rx_tmp_w, 0, sizeof(Pdcp_stats_rx_tmp_w));
2144
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
2145 2146
  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));
2147
  memset(Pdcp_stats_rx_sn, 0, sizeof(Pdcp_stats_rx_sn));
2148
  memset(Pdcp_stats_rx_goodput_w, 0, sizeof(Pdcp_stats_rx_goodput_w));
2149 2150 2151 2152
  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));
    
2153 2154 2155
}

//-----------------------------------------------------------------------------
2156 2157
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
2158 2159
{
  list_free (&pdcp_sdu_list);
2160
  hashtable_destroy(pdcp_coll_p);
2161 2162 2163 2164 2165 2166
#ifdef MBMS_MULTICAST_OUT
  if(mbms_socket != -1) {
    close(mbms_socket);
    mbms_socket = -1;
  }
#endif
2167 2168
}

2169
#ifdef PDCP_USE_RT_FIFO
2170
EXPORT_SYMBOL(pdcp_2_nas_irq);
2171
#endif //PDCP_USE_RT_FIFO