pdcp.c 63.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

476
      if (enb_flagP == ENB_FLAG_NO) {
477 478
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][rb_id-1];
479
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
480 481 482 483
                    "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];
484
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
485 486 487
                    "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);
          }
488

489
      } else {
490 491
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][rb_id-1];
492
              LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
493 494 495 496
                  "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];
497
              LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
498 499 500
                  "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);
          }
501 502

      }
503
  }
504
  
gauthier's avatar
gauthier committed
505
  sdu_list_p = &pdcp_sdu_list;
506

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

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

660 661
      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
662 663
      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",
664
          enb_flagP, rb_id, src_id, dst_id);
gauthier's avatar
gauthier committed
665 666 667

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

gauthier's avatar
gauthier committed
690

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

753 754 755 756
          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);
757

758 759 760 761 762 763
          /* 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
764

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

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

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

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

817
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
818

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

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

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

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

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

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

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

# if 0
  {
gauthier's avatar
gauthier committed
865
      MessageDef *msg_resp_p;
866

gauthier's avatar
gauthier committed
867
      msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
868

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

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

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

921
  pdcp_fifo_flush_sdus(frameP, enb_flagP, enb_mod_idP, ue_mod_idP);
922

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

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

933 934
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);

935 936
}

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

#ifdef Rel10
  int i,j;
gauthier's avatar
gauthier committed
972 973
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
974 975
#endif

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

gauthier's avatar
gauthier committed
983 984 985 986 987
  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;
988
          lc_id = srb_id + 2;
gauthier's avatar
gauthier committed
989

990
          if (enb_flagP == ENB_FLAG_NO) {
991
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][srb_id-1];
gauthier's avatar
gauthier committed
992
          } else {
993
              pdcp_p = &pdcp_array_srb_eNB[enb_mod_idP][ue_mod_idP][srb_id-1];
gauthier's avatar
gauthier committed
994
          }
995

996

997 998
          if (pdcp_p->instanciated_instance == TRUE) {
              action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
999
          } else {
1000
              action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1001
          }
1002

gauthier's avatar
gauthier committed
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
          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
1017
                      SRB_FLAG_YES,
gauthier's avatar
gauthier committed
1018 1019 1020 1021
                      rlc_type,
                      action,
                      lc_id,
                      mch_id,
1022
                      srb_id,
gauthier's avatar
gauthier committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040
                      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;
              }
          }
1041 1042 1043 1044
      }
  }
  // reset the action

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

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

1050
          drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
1051 1052

          lc_id = drb_id + 2;
1053

1054

1055
          DevCheck4(drb_id < maxDRB, drb_id, maxDRB, ue_mod_idP, enb_mod_idP);
1056

1057
          if (enb_flagP == ENB_FLAG_NO) {
1058
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1059
          } else {
1060
              pdcp_p = &pdcp_array_drb_eNB[enb_mod_idP][ue_mod_idP][drb_id-1];
gauthier's avatar
gauthier committed
1061
          }
1062

1063 1064
          if (pdcp_p->instanciated_instance == TRUE)
            action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
1065
          else
1066
            action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1067 1068 1069 1070 1071 1072 1073

          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;
1074 1075
		  drb_sn = PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size 
                  rlc_type = RLC_MODE_AM;
gauthier's avatar
gauthier committed
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 1108 1109 1110 1111 1112
              }
              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
1113 1114
                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
1115 1116 1117 1118 1119 1120 1121
                break;
              }
              pdcp_config_req_asn1 (pdcp_p,
                  enb_mod_idP,
                  ue_mod_idP,
                  frameP,
                  enb_flagP, // not really required
1122
                  SRB_FLAG_NO,
gauthier's avatar
gauthier committed
1123 1124 1125 1126
                  rlc_type,
                  action,
                  lc_id,
                  mch_id,
1127
                  drb_id,
gauthier's avatar
gauthier committed
1128 1129 1130 1131 1132 1133 1134
                  drb_sn,
                  drb_report,
                  header_compression_profile,
                  security_modeP,
                  kRRCenc_pP,
                  kRRCint_pP,
                  kUPenc_pP);
1135 1136 1137 1138
          }
      }
  }

gauthier's avatar
gauthier committed
1139 1140 1141
  if (drb2release_list_pP != NULL) {
      for (cnt=0;cnt<drb2release_list_pP->list.count;cnt++) {
          pdrb_id_p = drb2release_list_pP->list.array[cnt];