pdcp.c 65.4 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
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);

gauthier's avatar
gauthier committed
110 111
  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);
112 113 114
  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 {
115 116 117 118 119
      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);
      }
120
  }
gauthier's avatar
gauthier committed
121

122
  if (enb_flagP == ENB_FLAG_NO) {
123 124 125 126 127
      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];
      }
128
  } else {
129 130 131 132 133
      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];
      }
134
  }
135

136 137
  if ((pdcp_p->instanciated_instance == FALSE) && (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT)) {
      if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
138 139 140 141 142 143 144
          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;
145
  }
gauthier's avatar
gauthier committed
146 147 148
  if (sdu_buffer_sizeP == 0) {
      LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
      return FALSE;
149 150 151 152 153
  }
  /*
   * XXX MAX_IP_PACKET_SIZE is 4096, shouldn't this be MAX SDU size, which is 8188 bytes?
   */

gauthier's avatar
gauthier committed
154 155 156 157 158
  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");
159
  }
160

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

169
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
gauthier's avatar
gauthier committed
170 171 172 173
      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);
174
#if defined(DEBUG_PDCP_PAYLOAD)
175 176 177
          rlc_util_print_hex_octets(PDCP,
                                    (unsigned char*)&pdcp_pdu_p->data[0],
                                    sdu_buffer_sizeP);
178
#endif
179
          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
180 181
      } else {
        rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
182 183 184 185 186 187
	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
188 189 190 191 192 193 194 195 196
#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
      }
197
  } else {
gauthier's avatar
gauthier committed
198
      // calculate the pdcp header and trailer size
199
      if (srb_flagP) {
gauthier's avatar
gauthier committed
200 201
          pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
          pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
202
      } else {
gauthier's avatar
gauthier committed
203 204
          pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
          pdcp_tailer_len = 0;
205
      }
gauthier's avatar
gauthier committed
206 207
      pdcp_pdu_size = sdu_buffer_sizeP + pdcp_header_len + pdcp_tailer_len;

208
      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
209 210 211 212 213 214 215 216
          (enb_flagP) ? "eNB" : "UE",
              enb_mod_idP,
              ue_mod_idP,
              rb_idP,
              pdcp_pdu_size,
              pdcp_header_len,
              pdcp_tailer_len);

217
      /*
gauthier's avatar
gauthier committed
218
       * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
219
       */
gauthier's avatar
gauthier committed
220 221 222 223 224 225 226 227 228 229
      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
           */

230
          if (srb_flagP) { // this Control plane PDCP Data PDU
gauthier's avatar
gauthier committed
231 232 233 234
              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);
235
              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
236 237
              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
238 239 240 241
                  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);
242
		  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
243
                  return FALSE;
gauthier's avatar
gauthier committed
244 245 246
              }
          } else {
              pdcp_user_plane_data_pdu_header_with_long_sn pdu_header;
247
              pdu_header.dc = (modeP == PDCP_TRANSMISSION_MODE_DATA) ? PDCP_DATA_PDU_BIT_SET :  PDCP_CONTROL_PDU_BIT_SET;
gauthier's avatar
gauthier committed
248 249 250 251
              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
252 253 254 255
                  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);
256
		  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
257
                  return FALSE;
gauthier's avatar
gauthier committed
258 259 260 261 262 263 264 265 266 267
              }
          }
          /*
           * 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
268 269 270 271
              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);
272
	      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
273 274
              return FALSE;
          }
275

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

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

gauthier's avatar
gauthier committed
281 282 283 284 285
          //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];
286 287

#if defined(ENABLE_SECURITY)
288
          if ((pdcp_p->security_activated != 0) &&
289
              (((pdcp_p->cipheringAlgorithm) != 0) ||
gauthier's avatar
gauthier committed
290 291 292 293 294 295
              ((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);
296

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

gauthier's avatar
gauthier committed
305 306 307 308 309
              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);
          }
310

311 312
#endif

gauthier's avatar
gauthier committed
313 314 315 316 317 318 319
          /* 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");
320 321 322 323
          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
324 325 326 327 328 329 330 331
#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
332 333
	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
	return FALSE;
gauthier's avatar
gauthier committed
334 335 336 337 338
      }
      /*
       * Ask sublayer to transmit data and check return value
       * to see if RLC succeeded
       */
339 340 341 342 343 344 345
#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 
346
      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);
347

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

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

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

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

}

gauthier's avatar
gauthier committed
397

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

425 426 427
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);

  #ifdef OAI_EMU
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
  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
452 453 454 455 456 457 458 459
#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 

460 461 462 463 464 465 466 467 468 469 470
  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);
      }
471
  } else {
472 473
      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);
474
      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);
475
      if (enb_flagP == ENB_FLAG_NO) {
476 477
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][rb_id-1];
478
#if 0
479
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
480 481
                    "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);
482
#endif
483 484
          } else {
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][rb_id-1];
485
#if 0
486
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
487 488
                    "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);
489
#endif
490
          }
491

492
      } else {
493 494
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][rb_id-1];
495
#if 0
496
              LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
497 498
                  "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);
499
#endif
500 501
          } else {
              pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][rb_id-1];
502
#if 0
503
              LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
504 505
                  "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);
506
#endif
507
          }
508 509

      }
510
  }
511
  
gauthier's avatar
gauthier committed
512
  sdu_list_p = &pdcp_sdu_list;
513

gauthier's avatar
gauthier committed
514 515 516
  if (sdu_buffer_sizeP == 0) {
      LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
      return FALSE;
517
  }
518 519 520 521 522
  
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
  else
    start_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);  
523 524

  /*
525 526
   * 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
527
   */
528
  
529
  if (MBMS_flagP == 0 ) {
530 531 532 533 534 535 536 537 538 539 540 541
    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
542
      } else {
543 544
	//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
545
      }
546 547 548 549 550 551 552
      //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
553 554
          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
555 556 557 558
          if (enb_flagP)
            stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
          else
            stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
559
	  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
560
          return FALSE;
gauthier's avatar
gauthier committed
561
      }
562 563
  
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
564
#if 0
565
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
566
#endif
567 568 569 570 571 572
      /* 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
573
      /*
574 575
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
576 577
       */
#if 0
578 579 580
      LOG_D(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer);
      return FALSE;
581
#else
582
      //LOG_W(PDCP, "Delivering out-of-order SDU to upper layer...\n");
583
#endif
584
    }
gauthier's avatar
gauthier committed
585
      // SRB1/2: control-plane data
586
    if (srb_flagP){
587
#if defined(ENABLE_SECURITY)
588
      if (pdcp_p->security_activated == 1) {
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
          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
605
      }
606 607 608
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
      pdcp_rrc_data_ind(enb_mod_idP,
609 610 611 612 613 614
              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]);
615 616 617
      free_mem_block(sdu_buffer_pP);
      // free_mem_block(new_sdu);
      if (enb_flagP)
618
          stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
619
      else
620
          stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
621
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
622 623 624 625 626 627 628 629 630
      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)
631
          start_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
632
      else
633
          start_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
634 635
      
      pdcp_validate_security(pdcp_p, 
636 637 638 639 640 641
              srb_flagP,
              rb_idP,
              pdcp_header_len,
              sequence_number,
              sdu_buffer_pP->data,
              sdu_buffer_sizeP - pdcp_tailer_len);
642
      if (enb_flagP == ENB_FLAG_NO)
643
          stop_meas(&eNB_pdcp_stats[enb_mod_idP].validate_security);
644
      else
645
          stop_meas(&UE_pdcp_stats[ue_mod_idP].validate_security);
646 647 648
      
    }
    
649
#endif
650
  } else {
gauthier's avatar
gauthier committed
651
      payload_offset=0;
652
  }
653
  
654
#if defined(USER_MODE) && defined(OAI_EMU)
655
  if (oai_emulation.info.otg_enabled == 1) {
gauthier's avatar
gauthier committed
656 657
      module_id_t src_id, dst_id;
      int    ctime;
658 659
   
      if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
660
          pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
661 662
      }
   
663
#if defined(DEBUG_PDCP_PAYLOAD)
664
      rlc_util_print_hex_octets(PDCP,
665
                                (unsigned char*)&sdu_buffer_pP->data[payload_offset],
666
                                sdu_buffer_sizeP - payload_offset);
667
#endif
gauthier's avatar
gauthier committed
668

669 670
      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
671 672
      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",
673
          enb_flagP, rb_id, src_id, dst_id);
gauthier's avatar
gauthier committed
674 675 676

      if (otg_rx_pkt(src_id, dst_id,ctime,&sdu_buffer_pP->data[payload_offset],
          sdu_buffer_sizeP - payload_offset ) == 0 ) {
677 678 679 680 681 682 683
            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
684
      }
685 686 687
  }
#else
  if (otg_enabled==1) {
gauthier's avatar
gauthier committed
688 689
      LOG_D(OTG,"Discarding received packed\n");
      free_mem_block(sdu_buffer_pP);
690
      if (enb_flagP)
691
          stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
692
      else
693
          stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
694
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
695
      return TRUE;
696 697 698
  }
#endif

gauthier's avatar
gauthier committed
699

700 701 702 703 704 705 706 707 708
  // 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)
709
  if ((TRUE == enb_flagP) && (FALSE == srb_flagP)) {
710
      //LOG_T(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
711 712
      gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
               sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
713
      AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
714
      memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
715
      message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
716
      AssertFatal(message_p != NULL, "OUT OF MEMORY");
717 718
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer       = gtpu_buffer_p;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length       = sdu_buffer_sizeP - payload_offset;
719
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset       = GTPU_HEADER_OVERHEAD_MAX;
720 721
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).ue_index     = ue_mod_idP;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
722
      itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
      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
745
#if defined(OAI_EMU)
746
              ((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
747
#endif
748 749
          } else {
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id + (ue_mod_idP * maxDRB);
gauthier's avatar
gauthier committed
750
#if defined(OAI_EMU)
751
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = enb_mod_idP - oai_emulation.info.first_enb_local;
752
#endif
753
          }
gauthier's avatar
gauthier committed
754

755 756 757 758
          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);
759

760 761 762 763 764 765
          /* 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
766

767 768 769 770
          /*
           * Update PDCP statistics
           * XXX Following two actions are identical, is there a merge error?
           */
gauthier's avatar
gauthier committed
771

772 773 774 775 776 777 778 779
          /*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
780 781
  }
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
782 783 784 785 786 787 788 789
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
790
#endif
791

gauthier's avatar
gauthier committed
792
  free_mem_block(sdu_buffer_pP);
793 794
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
795
  else
796
    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
797
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
798 799 800 801
  return TRUE;
}

//-----------------------------------------------------------------------------
802 803 804 805 806
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) {
807
  //-----------------------------------------------------------------------------
808
#if defined(ENABLE_ITTI)
809 810 811 812
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
813
#endif
814 815
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_run);
816
  else
817
    start_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_run);
818

819
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
820

821 822
#if defined(ENABLE_ITTI)
  do {
gauthier's avatar
gauthier committed
823
      // Checks if a message has been sent to PDCP sub-task
824
      itti_poll_msg (enb_flagP ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
825

gauthier's avatar
gauthier committed
826 827 828
      if (msg_p != NULL) {
          msg_name = ITTI_MSG_NAME (msg_p);
          instance = ITTI_MSG_INSTANCE (msg_p);
829

gauthier's avatar
gauthier committed
830 831
          switch (ITTI_MSG_ID(msg_p)) {
          case RRC_DCCH_DATA_REQ:
832
            LOG_D(PDCP, "Received %s from %s: instance %d, frame %d, enb_flagP %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
833
                msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
834 835 836
                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);

837 838 839 840 841 842 843 844 845 846 847
            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
848
            AssertFatal (result == TRUE, "PDCP data request failed!\n");
849

gauthier's avatar
gauthier committed
850 851 852 853
            // 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;
854

gauthier's avatar
gauthier committed
855 856 857 858
          default:
            LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
            break;
          }
859

gauthier's avatar
gauthier committed
860 861 862
          result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
          AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
863
  } while(msg_p != NULL);
864 865 866

# if 0
  {
gauthier's avatar
gauthier committed
867
      MessageDef *msg_resp_p;
868

gauthier's avatar
gauthier committed
869
      msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
870

gauthier's avatar
gauthier committed
871
      itti_send_msg_to_task(TASK_RRC_ENB, 1, msg_resp_p);
872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
  }
  {
    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
888 889
#endif

890 891
#if defined(USER_MODE) && defined(OAI_EMU)
  pdcp_t            *pdcp_p          = NULL;
nikaeinn's avatar
nikaeinn committed
892 893 894 895 896 897 898 899 900 901 902 903
  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;
904
      }
nikaeinn's avatar
nikaeinn committed
905 906 907
  }
  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
908
#endif
909 910

  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
gauthier's avatar
gauthier committed
911
#if defined(LINK_PDCP_TO_GTPV1U)
gauthier's avatar
gauthier committed
912
  if (enb_flagP == ENB_FLAG_NO)
gauthier's avatar
gauthier committed
913
#endif
gauthier's avatar
gauthier committed
914
  {
gauthier's avatar
gauthier committed
915 916
      pdcp_fifo_read_input_sdus(frameP, enb_flagP, ue_mod_idP, enb_mod_idP);
  }
917
  // PDCP -> NAS/IP traffic: RX
918 919 920 921
  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
922

923
  pdcp_fifo_flush_sdus(frameP, enb_flagP, enb_mod_idP, ue_mod_idP);
924

925 926 927 928 929
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_ip);
  else
    stop_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_ip);

930 931
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_run);
932
  else
933 934
    stop_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_run);

935 936
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);

937 938
}

939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
boolean_t pdcp_remove_UE(
			 const moduled_id_t              enb_mod_idP,
		         const module_id_t               ue_mod_idP,
			 const frame_t              frameP) {


  pdcp_t         *pdcp_p         = NULL;
  DRB_Identity_t  srb_id         = 0;
  DRB_Identity_t  drb_id         = 0;

  // check and remove SRBs first

  for (srb_id=0;srb_id<2;srb_id++) {
    pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][srb_id-1];
    if (pdcp_p->instanciated_instance == TRUE) {
      pdcp_p->instanciated_instance = FALSE;
      pdcp_p->lcid = 0;
      pdcp_p->header_compression_profile = 0x0;
      pdcp_p->cipheringAlgorithm = 0xff;
      pdcp_p->integrityProtAlgorithm = 0xff;
      pdcp_p->status_report = 0;
      pdcp_p->rlc_mode = RLC_MODE_NONE;
      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;
      /* Security keys */
      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);
      }
    }

  }

  for (drb_id=0;drb_id<maxDRB;drb_id++) {
    pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][drb_id-1];
    if (pdcp_p->instanciated_instance == TRUE) {
      pdcp_p->instanciated_instance = FALSE;
      pdcp_p->lcid = 0;
      pdcp_p->header_compression_profile = 0x0;
      pdcp_p->cipheringAlgorithm = 0xff;
      pdcp_p->integrityProtAlgorithm = 0xff;
      pdcp_p->status_report = 0;
      pdcp_p->rlc_mode = RLC_MODE_NONE;
      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;

      /* Security keys */
      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);
      }
    }

  }

  return 1;
}


1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
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
1032
#ifdef Rel10
1033
,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
1034
#endif
gauthier's avatar
gauthier committed
1035
)
1036
{
1037
  long int        lc_id          = 0;
1038
  DRB_Identity_t  srb_id         = 0;
1039
  long int        mch_id         = 0;
gauthier's avatar
gauthier committed
1040
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1041
  DRB_Identity_t  drb_id         = 0;
gauthier's avatar
gauthier committed
1042
  DRB_Identity_t *pdrb_id_p      = NULL;
1043
  uint8_t         drb_sn         = 12;
1044 1045
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1046
  long int        cnt            = 0;
1047 1048
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1049 1050 1051
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
1052 1053 1054

#ifdef Rel10
  int i,j;
gauthier's avatar
gauthier committed
1055 1056
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1057 1058
#endif

1059
  if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
1060
      LOG_D(PDCP, "[UE %u] CONFIG REQ ASN1 for eNB %u\n", ue_mod_idP, enb_mod_idP);
1061
  } else {
gauthier's avatar
gauthier committed
1062
      LOG_D(PDCP, "[eNB %u] CONFIG REQ ASN1 for UE %u\n", enb_mod_idP, ue_mod_idP);
1063
  }
1064 1065
  // srb2add_list does not define pdcp config, we use rlc info to setup the pdcp dcch0 and dcch1 channels

gauthier's avatar
gauthier committed
1066 1067 1068 1069 1070
  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;
1071
          lc_id = srb_id + 2;
gauthier's avatar
gauthier committed
1072

1073
          if (enb_flagP == ENB_FLAG_NO) {
1074
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][srb_id-1];
gauthier's avatar
gauthier committed
1075
          } else {
1076
              pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][srb_id-1];
gauthier's avatar
gauthier committed
1077
          }
1078

1079

1080 1081
          if (pdcp_p->instanciated_instance == TRUE) {
              action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
1082
          } else {
1083
              action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1084
          }
1085

gauthier's avatar
gauthier committed
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
          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
1100
                      SRB_FLAG_YES,
gauthier's avatar
gauthier committed
1101 1102 1103 1104
                      rlc_type,
                      action,
                      lc_id,
                      mch_id,
1105
                      srb_id,
gauthier's avatar
gauthier committed
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
                      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;
              }
          }
1124 1125 1126 1127
      }
  }
  // reset the action

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

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

1133
          drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1134 1135

          lc_id = drb_id + 2;
1136

1137

1138
          DevCheck4(drb_id < maxDRB, drb_id, maxDRB, ue_mod_idP, enb_mod_idP);
1139

1140
          if (enb_flagP == ENB_FLAG_NO) {
1141
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1142
          } else {
1143
              pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1144
          }
1145

1146 1147
          if (pdcp_p->instanciated_instance == TRUE)
            action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
1148
          else
1149
            action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1150 1151 1152 1153 1154 1155 1156

          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;
nikaeinn's avatar