pdcp.c 63.3 KB
Newer Older
1
/*******************************************************************************
gauthier's avatar
gauthier committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

gauthier's avatar
gauthier committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


gauthier's avatar
gauthier committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

gauthier's avatar
gauthier committed
16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
gauthier's avatar
gauthier committed
22 23 24 25
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

gauthier's avatar
gauthier committed
28
 *******************************************************************************/
29 30 31 32 33 34 35 36 37 38 39 40

/*! \file pdcp.c
 * \brief pdcp interface with RLC
 * \author  Lionel GAUTHIER and Navid Nikaein
 * \date 2009-2012
 * \version 1.0
 */

#define PDCP_C
#ifndef USER_MODE
#include <rtai_fifos.h>
#endif
41
#include "assertions.h"
42 43 44 45 46 47 48 49 50 51 52 53 54 55
#include "pdcp.h"
#include "pdcp_util.h"
#include "pdcp_sequence_manager.h"
#include "LAYER2/RLC/rlc.h"
#include "LAYER2/MAC/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "pdcp_primitives.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "UTIL/LOG/log.h"
#include <inttypes.h>
#include "platform_constants.h"
#include "UTIL/LOG/vcd_signal_dumper.h"

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

60 61 62 63
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

64 65
#if defined(LINK_PDCP_TO_GTPV1U)
#  include "gtpv1u_eNB_task.h"
66
#  include "gtpv1u.h"
67 68
#endif

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
#ifndef OAI_EMU
extern int otg_enabled;
#endif

//extern char *packet_gen(int src, int dst, int ctime, int *pkt_size);
extern int otg_rx_pkt( int src, int dst, int ctime, char *buffer_tx, unsigned int size);

//-----------------------------------------------------------------------------
/*
 * 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()
 */
84
boolean_t pdcp_data_req(
85 86 87 88 89 90 91 92 93 94 95
        const module_id_t    enb_mod_idP,
        const module_id_t    ue_mod_idP,
        const frame_t        frameP,
        const eNB_flag_t     enb_flagP,
        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,
        const pdcp_transmission_mode_t modeP)
96 97
{
  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
98
  pdcp_t            *pdcp_p          = NULL;
99 100 101 102 103
  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;
gauthier's avatar
gauthier committed
104 105
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
106
  boolean_t          ret             = TRUE;
gauthier's avatar
gauthier committed
107 108 109

  AssertError (enb_mod_idP < NUMBER_OF_eNB_MAX, return FALSE, "eNB id is too high (%u/%d) %u %u!\n", enb_mod_idP, NUMBER_OF_eNB_MAX, ue_mod_idP, rb_idP);
  AssertError (ue_mod_idP < NUMBER_OF_UE_MAX, return FALSE, "UE id is too high (%u/%d) %u %u!\n", ue_mod_idP, NUMBER_OF_UE_MAX, enb_mod_idP, rb_idP);
110 111 112
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
      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, ue_mod_idP, enb_mod_idP);
  } else {
113 114 115 116 117
      if (srb_flagP) {
          AssertError (rb_idP < 2, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 2, ue_mod_idP, enb_mod_idP);
      } else {
          AssertError (rb_idP < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, maxDRB, ue_mod_idP, enb_mod_idP);
      }
118
  }
gauthier's avatar
gauthier committed
119

120
  if (enb_flagP == ENB_FLAG_NO) {
121 122 123 124 125
      if (srb_flagP) {
          pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][rb_idP-1];
  } else {
          pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][rb_idP-1];
      }
126
  } else {
127 128 129 130 131
      if (srb_flagP) {
          pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][rb_idP-1];
      } else {
          pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][rb_idP-1];
      }
132
  }
133

134 135
  if ((pdcp_p->instanciated_instance == FALSE) && (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT)) {
      if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
136 137 138 139 140 141 142
          LOG_W(PDCP, "[UE %d] Instance is not configured for eNB %d, rb_id %d Ignoring SDU...\n",
              ue_mod_idP, enb_mod_idP, rb_idP);
      } else {
          LOG_W(PDCP, "[eNB %d] Instance is not configured for UE %d, rb_id %d Ignoring SDU...\n",
              enb_mod_idP, ue_mod_idP, rb_idP);
      }
      return FALSE;
143
  }
gauthier's avatar
gauthier committed
144 145 146
  if (sdu_buffer_sizeP == 0) {
      LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
      return FALSE;
147 148 149 150 151
  }
  /*
   * XXX MAX_IP_PACKET_SIZE is 4096, shouldn't this be MAX SDU size, which is 8188 bytes?
   */

gauthier's avatar
gauthier committed
152 153 154 155 156
  if (sdu_buffer_sizeP > MAX_IP_PACKET_SIZE) {
      LOG_E(PDCP, "Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
          sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
      // XXX What does following call do?
      mac_xface->macphy_exit("PDCP sdu buffer size > MAX_IP_PACKET_SIZE");
157
  }
158

159
  if (enb_flagP == ENB_FLAG_NO)
160
    start_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
161
  else
162
    start_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
163 164 165
 
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
   
166
  // PDCP transparent mode for MBMS traffic
167

168
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
gauthier's avatar
gauthier committed
169 170 171 172
      LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
      pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP);
      if (pdcp_pdu_p != NULL) {
          memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
173 174 175 176
          rlc_util_print_hex_octets(PDCP,
                                    (unsigned char*)&pdcp_pdu_p->data[0],
                                    sdu_buffer_sizeP);

177
          rlc_status = rlc_data_req(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
gauthier's avatar
gauthier committed
178 179
      } else {
        rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
180 181 182 183 184 185
	LOG_W(PDCP,"[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
	      frameP,
	      (enb_flagP) ? "eNB" : "UE",
	      enb_mod_idP,
	      ue_mod_idP,
	      rb_idP);
gauthier's avatar
gauthier committed
186 187 188 189 190 191 192 193 194
#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",
            frameP,
            (enb_flagP) ? "eNB" : "UE",
            enb_mod_idP,
            ue_mod_idP,
            rb_idP);
#endif
      }
195
  } else {
gauthier's avatar
gauthier committed
196
      // calculate the pdcp header and trailer size
197
      if (srb_flagP) {
gauthier's avatar
gauthier committed
198 199
          pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
          pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
200
      } else {
gauthier's avatar
gauthier committed
201 202
          pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
          pdcp_tailer_len = 0;
203
      }
gauthier's avatar
gauthier committed
204 205
      pdcp_pdu_size = sdu_buffer_sizeP + pdcp_header_len + pdcp_tailer_len;

206
      LOG_D(PDCP, "Data request notification for PDCP entity %s enb id %u ue_id %u and radio bearer ID %d pdu size %d (header%d, trailer%d)\n",
gauthier's avatar
gauthier committed
207 208 209 210 211 212 213 214
          (enb_flagP) ? "eNB" : "UE",
              enb_mod_idP,
              ue_mod_idP,
              rb_idP,
              pdcp_pdu_size,
              pdcp_header_len,
              pdcp_tailer_len);

215
      /*
gauthier's avatar
gauthier committed
216
       * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
217
       */
gauthier's avatar
gauthier committed
218 219 220 221 222 223 224 225 226 227
      LOG_D(PDCP, "Asking for a new mem_block of size %d\n", pdcp_pdu_size);
      pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size);

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

228
          if (srb_flagP) { // this Control plane PDCP Data PDU
gauthier's avatar
gauthier committed
229 230 231 232
              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);
233
              memset(&pdcp_pdu_p->data[sdu_buffer_sizeP + pdcp_header_len],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
gauthier's avatar
gauthier committed
234 235
              if (pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
                  LOG_E(PDCP, "Cannot fill PDU buffer with relevant header fields!\n");
gauthier's avatar
gauthier committed
236 237 238 239
                  if (enb_flagP == ENB_FLAG_NO)
                    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
                  else
                    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
240
		  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
241
                  return FALSE;
gauthier's avatar
gauthier committed
242 243 244
              }
          } else {
              pdcp_user_plane_data_pdu_header_with_long_sn pdu_header;
245
              pdu_header.dc = (modeP == PDCP_TRANSMISSION_MODE_DATA) ? PDCP_DATA_PDU_BIT_SET :  PDCP_CONTROL_PDU_BIT_SET;
gauthier's avatar
gauthier committed
246 247 248 249
              pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p);
              current_sn = pdu_header.sn ;
              if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char*)pdcp_pdu_p->data, &pdu_header) == FALSE) {
                  LOG_E(PDCP, "Cannot fill PDU buffer with relevant header fields!\n");
gauthier's avatar
gauthier committed
250 251 252 253
                  if (enb_flagP == ENB_FLAG_NO)
                    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
                  else
                    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
254
		  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
255
                  return FALSE;
gauthier's avatar
gauthier committed
256 257 258 259 260 261 262 263 264 265
              }
          }
          /*
           * Validate incoming sequence number, there might be a problem with PDCP initialization
           */
          if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
              LOG_E(PDCP, "Generated sequence number (%lu) is greater than a sequence number could ever be!\n", current_sn);
              LOG_E(PDCP, "There must be a problem with PDCP initialization, ignoring this PDU...\n");

              free_mem_block(pdcp_pdu_p);
gauthier's avatar
gauthier committed
266 267 268 269
              if (enb_flagP == ENB_FLAG_NO)
                stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
              else
                stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
270
	      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
271 272
              return FALSE;
          }
273

gauthier's avatar
gauthier committed
274
          LOG_D(PDCP, "Sequence number %d is assigned to current PDU\n", current_sn);
275

gauthier's avatar
gauthier committed
276 277
          /* Then append data... */
          memcpy(&pdcp_pdu_p->data[pdcp_header_len], sdu_buffer_pP, sdu_buffer_sizeP);
278

gauthier's avatar
gauthier committed
279 280 281 282 283
          //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
          for (i=0;i<pdcp_tailer_len;i++)
            pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
284 285

#if defined(ENABLE_SECURITY)
286
          if ((pdcp_p->security_activated != 0) &&
287
              (((pdcp_p->cipheringAlgorithm) != 0) ||
gauthier's avatar
gauthier committed
288 289 290 291 292 293
              ((pdcp_p->integrityProtAlgorithm) != 0))) {

              if (enb_flagP == ENB_FLAG_NO)
                start_meas(&eNB_pdcp_stats[enb_mod_idP].apply_security);
              else
                start_meas(&UE_pdcp_stats[ue_mod_idP].apply_security);
294

gauthier's avatar
gauthier committed
295
              pdcp_apply_security(pdcp_p,
296 297 298 299 300 301
                      srb_flagP,
                      rb_idP % maxDRB,
                      pdcp_header_len,
                      current_sn,
                      pdcp_pdu_p->data,
                      sdu_buffer_sizeP);
302

gauthier's avatar
gauthier committed
303 304 305 306 307
              if (enb_flagP == ENB_FLAG_NO)
                stop_meas(&eNB_pdcp_stats[enb_mod_idP].apply_security);
              else
                stop_meas(&UE_pdcp_stats[ue_mod_idP].apply_security);
          }
308

309 310
#endif

gauthier's avatar
gauthier committed
311 312 313 314 315 316 317
          /* 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");
318 319 320 321
          if (enb_flagP == ENB_FLAG_NO)
              stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
          else
              stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
gauthier's avatar
gauthier committed
322 323 324 325 326 327 328 329
#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",
            frameP,
            (enb_flagP) ? "eNB" : "UE",
            enb_mod_idP,
            ue_mod_idP,
            rb_idP);
#endif
330 331
	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
	return FALSE;
gauthier's avatar
gauthier committed
332 333 334 335 336
      }
      /*
       * Ask sublayer to transmit data and check return value
       * to see if RLC succeeded
       */
337 338 339 340 341 342 343
#ifdef PDCP_MSG_PRINT
      int i=0;
      LOG_F(PDCP,"[MSG] PDCP DL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
      for (i = 0; i < pdcp_pdu_size; i++)
	LOG_F(PDCP,"%02x ", ((uint8_t*)pdcp_pdu_p->data)[i]);
      LOG_F(PDCP,"\n");
#endif 
344
      rlc_status = rlc_data_req(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
345

346 347 348 349
  }
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
350
    ret=TRUE;
351 352 353 354
    break;

  case RLC_OP_STATUS_BAD_PARAMETER:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
355 356
    ret= FALSE;
    break;
357 358
  case RLC_OP_STATUS_INTERNAL_ERROR:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
359 360
    ret= FALSE;
    break;
361 362 363

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

  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);
369 370
    ret= FALSE;
    break;
371
  }
372
  if (enb_flagP == ENB_FLAG_NO)
373
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
374
  else
375
    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
376 377 378 379
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
380
  /*
381
   if (rb_id>=DTCH) {
382
    if (enb_flagP == 1) {
383 384 385 386 387 388 389
      Pdcp_stats_tx[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH]++;
      Pdcp_stats_tx_bytes[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH] += sdu_buffer_size;
    } else {
      Pdcp_stats_tx[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH]++;
      Pdcp_stats_tx_bytes[module_id][(rb_id & RAB_OFFSET2 )>> RAB_SHIFT2][(rb_id & RAB_OFFSET)-DTCH] += sdu_buffer_size;
    }
    }*/
390
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
391
  return ret;
392 393 394

}

gauthier's avatar
gauthier committed
395

396
boolean_t pdcp_data_ind(
397 398 399 400 401 402 403 404
        const module_id_t  enb_mod_idP,
        const module_id_t  ue_mod_idP,
        const frame_t      frameP,
        const eNB_flag_t   enb_flagP,
        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,
405
        mem_block_t* const sdu_buffer_pP)
406 407
{
  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
408 409 410
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
411 412
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
gauthier's avatar
gauthier committed
413
  pdcp_sn_t    sequence_number = 0;
414
  volatile sdu_size_t   payload_offset  = 0;
415
  rb_id_t      rb_id            = rb_idP;
416
  boolean_t    packet_forwarded = FALSE;
417 418
#if defined(LINK_PDCP_TO_GTPV1U)
  MessageDef  *message_p        = NULL;
419
  uint8_t     *gtpu_buffer_p    = NULL;
420
#endif
421
 
422

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
#ifdef OAI_EMU
  if (enb_flagP) {
      AssertFatal ((enb_mod_idP >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
          "eNB module id is too low (%u/%d)!\n",
          enb_mod_idP,
          oai_emulation.info.first_enb_local);
      AssertFatal ((enb_mod_idP < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.nb_enb_local > 0),
          "eNB module id is too high (%u/%d)!\n",
          enb_mod_idP,
          oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
      AssertFatal (ue_mod_idP  < NB_UE_INST,
          "UE module id is too high (%u/%d)!\n",
          ue_mod_idP,
          oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
  } else {
      AssertFatal (ue_mod_idP  < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
          "UE module id is too high (%u/%d)!\n",
          ue_mod_idP,
          oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
      AssertFatal (ue_mod_idP  >= oai_emulation.info.first_ue_local,
          "UE module id is too low (%u/%d)!\n",
          ue_mod_idP,
          oai_emulation.info.first_ue_local);
  }
#endif
448 449 450 451 452 453 454 455
#ifdef PDCP_MSG_PRINT
      int i=0;
      LOG_F(PDCP,"[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
      for (i = 0; i < sdu_buffer_sizeP; i++)
	LOG_F(PDCP,"%02x ", ((uint8_t*)sdu_buffer_pP->data)[i]);
      LOG_F(PDCP,"\n");
#endif 

456 457 458 459 460 461 462 463 464 465 466
  if (MBMS_flagP) {
      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, ue_mod_idP, enb_mod_idP);
      if (enb_flagP == ENB_FLAG_NO) {
          LOG_I(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %u "
                "and radio bearer ID %d rlc sdu size %d enb_flagP %d\n",
                enb_mod_idP, ue_mod_idP, rb_idP, sdu_buffer_sizeP, enb_flagP);
      } else {
          LOG_I(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
          "and radio bearer ID %d rlc sdu size %d enb_flagP %d eNB_id %d\n",
          ue_mod_idP, enb_mod_idP , rb_idP, sdu_buffer_sizeP, enb_flagP, enb_mod_idP);
      }
467
  } else {
468 469
      rb_id = rb_idP % maxDRB;
      AssertError (rb_id < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_id, maxDRB, ue_mod_idP, enb_mod_idP);
470
      AssertError (rb_id > 0, return FALSE, "RB id is too low (%u/%d) %u %u!\n", rb_id, maxDRB, ue_mod_idP, enb_mod_idP);
471

472
      if (enb_flagP == ENB_FLAG_NO) {
473 474
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][rb_id-1];
475
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
476 477 478 479
                    "and signalling radio bearer ID %d rlc sdu size %d enb_flagP %d\n",
                    enb_mod_idP, ue_mod_idP, rb_id, sdu_buffer_sizeP, enb_flagP);
          } else {
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][rb_id-1];
480
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
481 482 483
                    "and data radio bearer ID %d rlc sdu size %d enb_flagP %d\n",
                    enb_mod_idP, ue_mod_idP, rb_id, sdu_buffer_sizeP, enb_flagP);
          }
484

485
      } else {
486 487
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][rb_id-1];
488
              LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
489 490 491 492
                  "and signalling radio bearer ID %d rlc sdu size %d enb_flagP %d eNB_id %d\n",
                  ue_mod_idP, enb_mod_idP , rb_id, sdu_buffer_sizeP, enb_flagP, enb_mod_idP);
          } else {
              pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][rb_id-1];
493
              LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
494 495 496
                  "and data radio bearer ID %d rlc sdu size %d enb_flagP %d eNB_id %d\n",
                  ue_mod_idP, enb_mod_idP , rb_id, sdu_buffer_sizeP, enb_flagP, enb_mod_idP);
          }
497 498

      }
499
  }
500
  
gauthier's avatar
gauthier committed
501
  sdu_list_p = &pdcp_sdu_list;
502

gauthier's avatar
gauthier committed
503 504 505
  if (sdu_buffer_sizeP == 0) {
      LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
      return FALSE;
506
  }
507 508 509 510 511 512
  
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
  else
    start_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);  
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
513 514

  /*
515 516
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
gauthier's avatar
gauthier committed
517
   */
518
  
519
  if (MBMS_flagP == 0 ) {
520 521 522 523 524 525 526 527 528 529 530 531
    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;
      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);
gauthier's avatar
gauthier committed
532
      } else {
533 534
	//sequence_number = 4095;
	LOG_E(PDCP,"wrong sequence number  (%d) for this pdcp entity \n", pdcp_p->seq_num_size);
gauthier's avatar
gauthier committed
535
      }
536 537 538 539 540 541 542
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
    
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
gauthier's avatar
gauthier committed
543 544
          LOG_W(PDCP, "Incoming (from RLC) SDU is short of size (size:%d)! Ignoring...\n", sdu_buffer_sizeP);
          free_mem_block(sdu_buffer_pP);
gauthier's avatar
gauthier committed
545 546 547 548
          if (enb_flagP)
            stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
          else
            stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
549
	  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
550
          return FALSE;
gauthier's avatar
gauthier committed
551
      }
552 553 554 555 556 557 558 559 560
  
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
      LOG_D(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
      /* if (dc == PDCP_DATA_PDU )
	 LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
	 else
	 LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
    } else {
      LOG_W(PDCP, "Incoming PDU has an unexpected sequence number (%d), RX window snychronisation have probably been lost!\n", sequence_number);
gauthier's avatar
gauthier committed
561
      /*
562 563
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
564 565
       */
#if 0
566 567 568
      LOG_D(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer);
      return FALSE;
569
#else
570
      LOG_W(PDCP, "Delivering out-of-order SDU to upper layer...\n");
571
#endif
572
    }
gauthier's avatar
gauthier committed
573
      // SRB1/2: control-plane data
574
    if (srb_flagP){
575
#if defined(ENABLE_SECURITY)
576
      if (pdcp_p->security_activated == 1) {
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
          if (enb_flagP == ENB_FLAG_NO)
              start_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
          else
              start_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);

          pdcp_validate_security(pdcp_p,
                  srb_flagP,
                  rb_idP,
                  pdcp_header_len,
                  sequence_number,
                  sdu_buffer_pP->data,
                  sdu_buffer_sizeP - pdcp_tailer_len);
          if (enb_flagP == ENB_FLAG_NO)
              stop_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
          else
              stop_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
gauthier's avatar
gauthier committed
593
      }
594 595 596
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
      pdcp_rrc_data_ind(enb_mod_idP,
597 598 599 600 601 602
              ue_mod_idP,
              frameP,
              enb_flagP,
              rb_id,
              sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
              (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len]);
603 604 605
      free_mem_block(sdu_buffer_pP);
      // free_mem_block(new_sdu);
      if (enb_flagP)
606
          stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
607
      else
608
          stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
609
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
610 611 612 613 614 615 616 617 618
      return TRUE;
    }
  /*
   * DRBs 
   */
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
    if (pdcp_p->security_activated == 1) {
      if (enb_flagP == ENB_FLAG_NO)
619
          start_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
620
      else
621
          start_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
622 623
      
      pdcp_validate_security(pdcp_p, 
624 625 626 627 628 629
              srb_flagP,
              rb_idP,
              pdcp_header_len,
              sequence_number,
              sdu_buffer_pP->data,
              sdu_buffer_sizeP - pdcp_tailer_len);
630
      if (enb_flagP == ENB_FLAG_NO)
631
          stop_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
632
      else
633
          stop_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
634 635 636
      
    }
    
637
#endif
638
  } else {
gauthier's avatar
gauthier committed
639
      payload_offset=0;
640
  }
641
  
642
#if defined(USER_MODE) && defined(OAI_EMU)
643
  if (oai_emulation.info.otg_enabled == 1) {
gauthier's avatar
gauthier committed
644 645
      module_id_t src_id, dst_id;
      int    ctime;
646 647
   
      if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
648
          pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
649 650
      }
   
651
      rlc_util_print_hex_octets(PDCP,
652
                                (unsigned char*)&sdu_buffer_pP->data[payload_offset],
653
                                sdu_buffer_sizeP - payload_offset);
gauthier's avatar
gauthier committed
654

655 656
      src_id = (enb_flagP == ENB_FLAG_NO) ?  enb_mod_idP : ue_mod_idP +   NB_eNB_INST;
      dst_id = (enb_flagP == ENB_FLAG_NO) ? ue_mod_idP +  NB_eNB_INST: enb_mod_idP;
gauthier's avatar
gauthier committed
657 658
      ctime = oai_emulation.info.time_ms; // avg current simulation time in ms : we may get the exact time through OCG?
      LOG_D(PDCP, "Check received buffer : enb_flag %d  rab id %d (src %d, dst %d)\n",
659
          enb_flagP, rb_id, src_id, dst_id);
gauthier's avatar
gauthier committed
660 661 662

      if (otg_rx_pkt(src_id, dst_id,ctime,&sdu_buffer_pP->data[payload_offset],
          sdu_buffer_sizeP - payload_offset ) == 0 ) {
663 664 665 666 667 668 669
            free_mem_block(sdu_buffer_pP);
            if (enb_flagP)
                stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
            else
                stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
            vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
            return TRUE;
gauthier's avatar
gauthier committed
670
      }
671 672 673
  }
#else
  if (otg_enabled==1) {
gauthier's avatar
gauthier committed
674 675
      LOG_D(OTG,"Discarding received packed\n");
      free_mem_block(sdu_buffer_pP);
676
      if (enb_flagP)
677
          stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
678
      else
679
          stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
680
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
681
      return TRUE;
682 683 684
  }
#endif

gauthier's avatar
gauthier committed
685

686 687 688 689 690 691 692 693 694
  // 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)
   */
#if defined(LINK_PDCP_TO_GTPV1U)
695
  if ((TRUE == enb_flagP) && (FALSE == srb_flagP)) {
696
      LOG_I(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
697 698
      gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
               sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
699
      AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
700
      memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
701
      message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
702
      AssertFatal(message_p != NULL, "OUT OF MEMORY");
703 704
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer       = gtpu_buffer_p;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length       = sdu_buffer_sizeP - payload_offset;
705
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset       = GTPU_HEADER_OVERHEAD_MAX;
706 707
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).ue_index     = ue_mod_idP;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
708 709
      itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
      /*gtpv1u_new_data_req(
710 711
              enb_mod_idP, //gtpv1u_data_t *gtpv1u_data_p,
              ue_mod_idP,//rb_id/maxDRB, TO DO UE ID
712
              rb_id + 4,
713 714
              &sdu_buffer_pP->data[payload_offset],
              sdu_buffer_sizeP - payload_offset);
715
              */
716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
      packet_forwarded = TRUE;
  }
#else
  packet_forwarded = FALSE;
#endif
  if (FALSE == packet_forwarded) {
      new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t));

      if (new_sdu_p) {
          if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
              pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
          }
          /*
           * Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
           */
          memset(new_sdu_p->data, 0, sizeof (pdcp_data_ind_header_t));
          ((pdcp_data_ind_header_t *) new_sdu_p->data)->data_size = sdu_buffer_sizeP - payload_offset;

          // Here there is no virtualization possible
          // set ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst for IP layer here
          if (enb_flagP == ENB_FLAG_NO) {
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id;
gauthier's avatar
gauthier committed
738
#if defined(OAI_EMU)
739
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ue_mod_idP + oai_emulation.info.nb_enb_local - oai_emulation.info.first_ue_local;
gauthier's avatar
gauthier committed
740
#endif
741 742
          } else {
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id + (ue_mod_idP * maxDRB);
gauthier's avatar
gauthier committed
743
#if defined(OAI_EMU)
744
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = enb_mod_idP - oai_emulation.info.first_enb_local;
745
#endif
746
          }
gauthier's avatar
gauthier committed
747

748 749 750 751
          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);
752

753 754 755 756 757 758
          /* 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 + 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);
gauthier's avatar
gauthier committed
759

760 761 762 763
          /*
           * Update PDCP statistics
           * XXX Following two actions are identical, is there a merge error?
           */
gauthier's avatar
gauthier committed
764

765 766 767 768 769 770 771 772
          /*if (enb_flagP == 1) {
              Pdcp_stats_rx[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH]++;
              Pdcp_stats_rx_bytes[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH] += sdu_buffer_sizeP;
            } else {
              Pdcp_stats_rx[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH]++;
              Pdcp_stats_rx_bytes[module_id][(rb_idP & RAB_OFFSET2) >> RAB_SHIFT2][(rb_idP & RAB_OFFSET) - DTCH] += sdu_buffer_sizeP;
            }*/
      }
gauthier's avatar
gauthier committed
773 774
  }
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
775 776 777 778 779 780 781 782
else {
  AssertFatal(0, "[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
        frameP,
        (enb_flagP) ? "eNB" : "UE",
        enb_mod_idP,
        ue_mod_idP,
        rb_id);
}
gauthier's avatar
gauthier committed
783
#endif
784

gauthier's avatar
gauthier committed
785
  free_mem_block(sdu_buffer_pP);
786 787
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
788
  else
789
    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
790
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
791 792 793 794
  return TRUE;
}

//-----------------------------------------------------------------------------
795 796 797 798 799
void pdcp_run (
        const frame_t frameP,
        const eNB_flag_t  enb_flagP,
        const module_id_t ue_mod_idP,
        const module_id_t enb_mod_idP) {
800
  //-----------------------------------------------------------------------------
801
#if defined(ENABLE_ITTI)
802 803 804 805
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
806
#endif
807 808
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_run);
809
  else
810
    start_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_run);
811

812
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
813

814 815
#if defined(ENABLE_ITTI)
  do {
gauthier's avatar
gauthier committed
816
      // Checks if a message has been sent to PDCP sub-task
817
      itti_poll_msg (enb_flagP ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
818

gauthier's avatar
gauthier committed
819 820 821
      if (msg_p != NULL) {
          msg_name = ITTI_MSG_NAME (msg_p);
          instance = ITTI_MSG_INSTANCE (msg_p);
822

gauthier's avatar
gauthier committed
823 824
          switch (ITTI_MSG_ID(msg_p)) {
          case RRC_DCCH_DATA_REQ:
825
            LOG_D(PDCP, "Received %s from %s: instance %d, frame %d, enb_flagP %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
826
                msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
827 828 829
                RRC_DCCH_DATA_REQ (msg_p).frame, RRC_DCCH_DATA_REQ (msg_p).enb_flag, 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);

830 831 832 833 834 835 836 837 838 839 840
            result = pdcp_data_req (RRC_DCCH_DATA_REQ (msg_p).eNB_index,
                RRC_DCCH_DATA_REQ (msg_p).ue_index,
                RRC_DCCH_DATA_REQ (msg_p).frame,
                RRC_DCCH_DATA_REQ (msg_p).enb_flag,
                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);
gauthier's avatar
gauthier committed
841
            AssertFatal (result == TRUE, "PDCP data request failed!\n");
842

gauthier's avatar
gauthier committed
843 844 845 846
            // 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;
847

gauthier's avatar
gauthier committed
848 849 850 851
          default:
            LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
            break;
          }
852

gauthier's avatar
gauthier committed
853 854 855
          result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
          AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
856
  } while(msg_p != NULL);
857 858 859

# if 0
  {
gauthier's avatar
gauthier committed
860
      MessageDef *msg_resp_p;
861

gauthier's avatar
gauthier committed
862
      msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
863

gauthier's avatar
gauthier committed
864
      itti_send_msg_to_task(TASK_RRC_ENB, 1, msg_resp_p);
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
  }
  {
    MessageDef *msg_resp_p;

    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);

    itti_send_msg_to_task(TASK_ENB_APP, 2, msg_resp_p);
  }
  {
    MessageDef *msg_resp_p;

    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);

    itti_send_msg_to_task(TASK_MAC_ENB, 3, msg_resp_p);
  }
# endif
881 882
#endif

883 884
#if defined(USER_MODE) && defined(OAI_EMU)
  pdcp_t            *pdcp_p          = NULL;
nikaeinn's avatar
nikaeinn committed
885 886 887 888 889 890 891 892 893 894 895 896
  int               drb_id=1 ;
  int               ue_id=0;
  int               read_otg=1;
    // add check for other rb_ids later
  if (enb_flagP == ENB_FLAG_NO) {
    if (pdcp_array_drb_ue[ue_mod_idP][drb_id-1].instanciated_instance  != TRUE )
      read_otg=0;
  } else {
    for (ue_id=0; ue_id < NB_UE_INST; ue_id++)
      if (pdcp_array_drb_eNB[enb_mod_idP][ue_id][drb_id-1].instanciated_instance  != TRUE ){
	read_otg =0;
	break;
897
      }
nikaeinn's avatar
nikaeinn committed
898 899 900
  }
  if (read_otg == 1 )
    pdcp_fifo_read_input_sdus_from_otg(frameP, enb_flagP, ue_mod_idP, enb_mod_idP);
gauthier's avatar
gauthier committed
901
#endif
902 903

  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
gauthier's avatar
gauthier committed
904
#if defined(LINK_PDCP_TO_GTPV1U)
gauthier's avatar
gauthier committed
905
  if (enb_flagP == ENB_FLAG_NO)
gauthier's avatar
gauthier committed
906
#endif
gauthier's avatar
gauthier committed
907
  {
gauthier's avatar
gauthier committed
908 909
      pdcp_fifo_read_input_sdus(frameP, enb_flagP, ue_mod_idP, enb_mod_idP);
  }
910
  // PDCP -> NAS/IP traffic: RX
911 912 913 914
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_ip);
  else
    start_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_ip);
gauthier's avatar
gauthier committed
915

916
  pdcp_fifo_flush_sdus(frameP, enb_flagP, enb_mod_idP, ue_mod_idP);
917

918 919 920 921 922
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_ip);
  else
    stop_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_ip);

923 924
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_run);
925
  else
926 927
    stop_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_run);

928 929
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);

930 931
}

932 933 934 935 936 937 938 939 940 941 942 943
boolean_t rrc_pdcp_config_asn1_req (
        const module_id_t               enb_mod_idP,
        const module_id_t               ue_mod_idP,
        const frame_t              frameP,
        const eNB_flag_t           enb_flagP,
        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
944
#ifdef Rel10
945
,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
946
#endif
gauthier's avatar
gauthier committed
947
)
948
{
949
  long int        lc_id          = 0;
950
  DRB_Identity_t  srb_id         = 0;
951
  long int        mch_id         = 0;
gauthier's avatar
gauthier committed
952
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
953
  DRB_Identity_t  drb_id         = 0;
gauthier's avatar
gauthier committed
954
  DRB_Identity_t *pdrb_id_p      = NULL;
955
  uint8_t         drb_sn         = 12;
956 957
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
958
  long int        cnt            = 0;
959 960
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
961 962 963
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
964 965 966

#ifdef Rel10
  int i,j;
gauthier's avatar
gauthier committed
967 968
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
969 970
#endif

971
  if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
972
      LOG_D(PDCP, "[UE %u] CONFIG REQ ASN1 for eNB %u\n", ue_mod_idP, enb_mod_idP);
973
  } else {
gauthier's avatar
gauthier committed
974
      LOG_D(PDCP, "[eNB %u] CONFIG REQ ASN1 for UE %u\n", enb_mod_idP, ue_mod_idP);
975
  }
976 977
  // srb2add_list does not define pdcp config, we use rlc info to setup the pdcp dcch0 and dcch1 channels

gauthier's avatar
gauthier committed
978 979 980 981 982
  if (srb2add_list_pP != NULL) {
      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;
983
          lc_id = srb_id + 2;
gauthier's avatar
gauthier committed
984

985
          if (enb_flagP == ENB_FLAG_NO) {
986
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][srb_id-1];
gauthier's avatar
gauthier committed
987
          } else {
988
              pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][srb_id-1];
gauthier's avatar
gauthier committed
989
          }
990

991

992 993
          if (pdcp_p->instanciated_instance == TRUE) {
              action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
994
          } else {
995
              action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
996
          }
997

gauthier's avatar
gauthier committed
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011
          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;
                default:
                  pdcp_config_req_asn1 (pdcp_p,
                      enb_mod_idP,
                      ue_mod_idP,
                      frameP,
                      enb_flagP, // not really required
1012
                      SRB_FLAG_YES,
gauthier's avatar
gauthier committed
1013 1014 1015 1016
                      rlc_type,
                      action,
                      lc_id,
                      mch_id,
1017
                      srb_id,
gauthier's avatar
gauthier committed
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
                      srb_sn,
                      0, // drb_report
                      0, // header compression
                      security_modeP,
                      kRRCenc_pP,
                      kRRCint_pP,
                      kUPenc_pP);
                  break;
                }
                break;
                case SRB_ToAddMod__rlc_Config_PR_defaultValue:
                  // already the default values
                  break;
                default:
                  DevParam(srb_toaddmod_p->rlc_Config->present, ue_mod_idP, enb_mod_idP);
                  break;
              }
          }
1036 1037 1038 1039
      }
  }
  // reset the action

gauthier's avatar
gauthier committed
1040 1041
  if (drb2add_list_pP != NULL) {
      for (cnt=0;cnt<drb2add_list_pP->list.count;cnt++) {
1042

gauthier's avatar
gauthier committed
1043
          drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
1044

1045
          drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1046 1047

          lc_id = drb_id + 2;
1048

1049

1050
          DevCheck4(drb_id < maxDRB, drb_id, maxDRB, ue_mod_idP, enb_mod_idP);
1051

1052
          if (enb_flagP == ENB_FLAG_NO) {
1053
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1054
          } else {
1055
              pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1056
          }
1057

1058 1059
          if (pdcp_p->instanciated_instance == TRUE)
            action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
1060
          else
1061
            action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1062 1063 1064 1065 1066 1067 1068

          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;
1069 1070
		  drb_sn = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size 
                  rlc_type = RLC_MODE_AM;
gauthier's avatar
gauthier committed
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
              }
              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
                if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0001)
                  header_compression_profile=0x0001;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0002)
                  header_compression_profile=0x0002;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0003)
                  header_compression_profile=0x0003;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0004)
                  header_compression_profile=0x0004;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0006)
                  header_compression_profile=0x0006;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0101)
                  header_compression_profile=0x0101;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0102)
                  header_compression_profile=0x0102;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0103)
                  header_compression_profile=0x0103;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0104)
                  header_compression_profile=0x0104;
                else {
                    header_compression_profile=0x0;
                    LOG_W(PDCP,"unknown header compresion profile\n");
                }
                // set the applicable profile
                break;
              default:
gauthier's avatar
gauthier committed
1108 1109
                LOG_W(PDCP,"[MOD_id %u/%u][RB %u] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
                    enb_mod_idP, ue_mod_idP, drb_id);
gauthier's avatar
gauthier committed
1110 1111 1112 1113 1114 1115 1116
                break;
              }
              pdcp_config_req_asn1 (pdcp_p,
                  enb_mod_idP,
                  ue_mod_idP,
                  frameP,
                  enb_flagP, // not really required
1117
                  SRB_FLAG_NO,
gauthier's avatar
gauthier committed
1118 1119 1120 1121
                  rlc_type,
                  action,
                  lc_id,
                  mch_id,
1122
                  drb_id,
gauthier's avatar
gauthier committed
1123 1124 1125 1126 1127 1128 1129
                  drb_sn,
                  drb_report,
                  header_compression_profile,
                  security_modeP,
                  kRRCenc_pP,
                  kRRCint_pP,
                  kUPenc_pP);
1130 1131 1132 1133
          }
      }
  }

gauthier's avatar
gauthier committed
1134 1135 1136
  if (drb2release_list_pP != NULL) {
      for (cnt=0;cnt<drb2release_list_pP->list.count;cnt++) {
          pdrb_id_p = drb2release_list_pP->list.array[cnt];
1137 1138
          drb_id =  *pdrb_id_p;
          lc_id = drb_id + 2;
1139
          if (enb_flagP == ENB_FLAG_NO) {
1140
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1141
          } else {
1142
              pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1143
          }
1144
          action = CONFIG_ACTION_REMOVE;
gauthier's avatar
gauthier committed
1145 1146 1147 1148 1149
          pdcp_config_req_asn1 (pdcp_p,
              enb_mod_idP,
              ue_mod_idP,
              frameP,
              enb_flagP, // not really required