pdcp.c 65.5 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
  const protocol_ctxt_t* const  ctxt_pP,
  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)
93 94
{
  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
95
  pdcp_t            *pdcp_p          = NULL;
96 97 98 99 100
  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
101 102
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
103
  boolean_t          ret             = TRUE;
gauthier's avatar
gauthier committed
104

105

106 107
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);

108 109
  AssertError (ctxt_pP->enb_module_id < NUMBER_OF_eNB_MAX, return FALSE, "eNB id is too high (%u/%d) %u %u!\n", ctxt_pP->enb_module_id, NUMBER_OF_eNB_MAX, ctxt_pP->ue_module_id, rb_idP);
  AssertError (ctxt_pP->ue_module_id < NUMBER_OF_UE_MAX, return FALSE, "UE id is too high (%u/%d) %u %u!\n", ctxt_pP->ue_module_id, NUMBER_OF_UE_MAX, ctxt_pP->enb_module_id, rb_idP);
110

111
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
112
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);
113
  } else {
114 115 116 117 118
    if (srb_flagP) {
      AssertError (rb_idP < 2, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 2, ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);
    } else {
      AssertError (rb_idP < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, maxDRB, ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);
    }
119
  }
gauthier's avatar
gauthier committed
120

121
  if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
122 123 124 125 126
    if (srb_flagP) {
      pdcp_p = &pdcp_array_srb_ue[ctxt_pP->ue_module_id][rb_idP-1];
    } else {
      pdcp_p = &pdcp_array_drb_ue[ctxt_pP->ue_module_id][rb_idP-1];
    }
127
  } else {
128 129 130 131 132
    if (srb_flagP) {
      pdcp_p = &pdcp_array_srb_eNB[ctxt_pP->enb_module_id][ctxt_pP->ue_module_id][rb_idP-1];
    } else {
      pdcp_p = &pdcp_array_drb_eNB[ctxt_pP->enb_module_id][ctxt_pP->ue_module_id][rb_idP-1];
    }
133
  }
134

135
  if ((pdcp_p->instanciated_instance == FALSE) && (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT)) {
136 137 138 139 140 141 142 143 144
    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
      LOG_W(PDCP, "[UE %d] Instance is not configured for eNB %d, rb_id %d Ignoring SDU...\n",
            ctxt_pP->ue_module_id, ctxt_pP->enb_module_id, rb_idP);
    } else {
      LOG_W(PDCP, "[eNB %d] Instance is not configured for UE %d, rb_id %d Ignoring SDU...\n",
            ctxt_pP->enb_module_id, ctxt_pP->ue_module_id, rb_idP);
    }

    return FALSE;
145
  }
146

gauthier's avatar
gauthier committed
147
  if (sdu_buffer_sizeP == 0) {
148 149
    LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
    return FALSE;
150
  }
151

152 153 154 155
  /*
   * XXX MAX_IP_PACKET_SIZE is 4096, shouldn't this be MAX SDU size, which is 8188 bytes?
   */

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

163 164
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
    start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_req);
165
  else
166
    start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_req);
167 168


169
  // PDCP transparent mode for MBMS traffic
170

171
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
172 173 174 175 176
    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);
177
#if defined(DEBUG_PDCP_PAYLOAD)
178 179 180
      rlc_util_print_hex_octets(PDCP,
                                (unsigned char*)&pdcp_pdu_p->data[0],
                                sdu_buffer_sizeP);
181
#endif
182 183 184 185
      rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
      LOG_W(PDCP,"[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
186 187 188 189
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->enb_module_id,
            ctxt_pP->ue_module_id,
gauthier's avatar
gauthier committed
190
            rb_idP);
191 192 193 194 195 196 197
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
      AssertFatal(0, "[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  ctxt_pP->frame,
                  (ctxt_pP->enb_flag) ? "eNB" : "UE",
                  ctxt_pP->enb_module_id,
                  ctxt_pP->ue_module_id,
                  rb_idP);
gauthier's avatar
gauthier committed
198
#endif
199
    }
200
  } else {
201 202 203 204 205 206 207 208 209 210
    // calculate the pdcp header and trailer size
    if (srb_flagP) {
      pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
      pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
    } else {
      pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
      pdcp_tailer_len = 0;
    }

    pdcp_pdu_size = sdu_buffer_sizeP + pdcp_header_len + pdcp_tailer_len;
gauthier's avatar
gauthier committed
211

212
    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",
213
          (ctxt_pP->enb_flag) ? "eNB" : "UE",
214 215 216 217 218 219
          ctxt_pP->enb_module_id,
          ctxt_pP->ue_module_id,
          rb_idP,
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
gauthier's avatar
gauthier committed
220

221 222 223 224 225 226 227
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
    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) {
228
      /*
229 230 231
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
232
       */
233

234 235 236 237 238 239
      if (srb_flagP) { // this Control plane PDCP Data PDU
        pdcp_control_plane_data_pdu_header pdu_header;
        pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p);
        current_sn = pdu_header.sn;
        memset(&pdu_header.mac_i[0],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
        memset(&pdcp_pdu_p->data[sdu_buffer_sizeP + pdcp_header_len],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
240

241 242
        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");
243

244 245 246 247
          if (ctxt_pP->enb_flag == ENB_FLAG_NO)
            stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_req);
          else
            stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_req);
248

249 250 251 252 253 254 255 256
          vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
          return FALSE;
        }
      } else {
        pdcp_user_plane_data_pdu_header_with_long_sn pdu_header;
        pdu_header.dc = (modeP == PDCP_TRANSMISSION_MODE_DATA) ? PDCP_DATA_PDU_BIT_SET :  PDCP_CONTROL_PDU_BIT_SET;
        pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p);
        current_sn = pdu_header.sn ;
257

258 259
        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");
260

261
          if (ctxt_pP->enb_flag == ENB_FLAG_NO)
262
            stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_req);
263
          else
264 265 266 267 268
            stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_req);

          vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
          return FALSE;
        }
gauthier's avatar
gauthier committed
269
      }
270

gauthier's avatar
gauthier committed
271
      /*
272
       * Validate incoming sequence number, there might be a problem with PDCP initialization
gauthier's avatar
gauthier committed
273
       */
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
      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);

        if (ctxt_pP->enb_flag == ENB_FLAG_NO)
          stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_req);
        else
          stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_req);

        vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
        return FALSE;
      }

      LOG_D(PDCP, "Sequence number %d is assigned to current PDU\n", current_sn);

      /* Then append data... */
      memcpy(&pdcp_pdu_p->data[pdcp_header_len], sdu_buffer_pP, sdu_buffer_sizeP);

      //For control plane data that are not integrity protected,
      // the MAC-I field is still present and should be padded with padding bits set to 0.
      // NOTE: user-plane data are never integrity protected
      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];

#if defined(ENABLE_SECURITY)

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

        if (ctxt_pP->enb_flag == ENB_FLAG_NO)
          start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].apply_security);
        else
          start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].apply_security);

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

        if (ctxt_pP->enb_flag == ENB_FLAG_NO)
          stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].apply_security);
        else
          stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].apply_security);
      }

#endif

      /* Print octets of outgoing data in hexadecimal form */
      LOG_D(PDCP, "Following content with size %d will be sent over RLC (PDCP PDU header is the first two bytes)\n",
            pdcp_pdu_size);
      //util_print_hex_octets(PDCP, (unsigned char*)pdcp_pdu_p->data, pdcp_pdu_size);
      //util_flush_hex_octets(PDCP, (unsigned char*)pdcp_pdu->data, pdcp_pdu_size);
    } else {
      LOG_E(PDCP, "Cannot create a mem_block for a PDU!\n");

      if (ctxt_pP->enb_flag == ENB_FLAG_NO)
        stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_req);
      else
        stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_req);

#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
      AssertFatal(0, "[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
                  ctxt_pP->frame,
                  (ctxt_pP->enb_flag) ? "eNB" : "UE",
                  ctxt_pP->enb_module_id,
                  ctxt_pP->ue_module_id,
                  rb_idP);
#endif
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
      return FALSE;
    }

    /*
     * Ask sublayer to transmit data and check return value
     * to see if RLC succeeded
     */
357
#ifdef PDCP_MSG_PRINT
358 359 360 361 362 363 364 365 366
    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
    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
367

368
  }
369

370 371 372
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
373
    ret=TRUE;
374 375 376 377
    break;

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

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

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

  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);
393 394
    ret= FALSE;
    break;
395
  }
396

397 398
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
    stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_req);
399
  else
400
    stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_req);
401

402 403 404 405
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
406
  /*
407
   if (rb_id>=DTCH) {
408
    if (ctxt_pP->enb_flag == 1) {
409 410 411 412 413 414 415
      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;
    }
    }*/
416
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
417
  return ret;
418 419 420

}

gauthier's avatar
gauthier committed
421

422
boolean_t pdcp_data_ind(
423 424 425 426 427 428
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t   srb_flagP,
  const MBMS_flag_t  MBMS_flagP,
  const rb_id_t      rb_idP,
  const sdu_size_t   sdu_buffer_sizeP,
  mem_block_t* const sdu_buffer_pP)
429 430
{
  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
431 432 433
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
434 435
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
gauthier's avatar
gauthier committed
436
  pdcp_sn_t    sequence_number = 0;
437
  volatile sdu_size_t   payload_offset  = 0;
438
  rb_id_t      rb_id            = rb_idP;
439
  boolean_t    packet_forwarded = FALSE;
440 441
#if defined(LINK_PDCP_TO_GTPV1U)
  MessageDef  *message_p        = NULL;
442
  uint8_t     *gtpu_buffer_p    = NULL;
443
#endif
444

445

446 447
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);

448 449
#ifdef OAI_EMU

450
  if (ctxt_pP->enb_flag) {
451 452 453 454 455 456 457 458 459 460 461 462
    AssertFatal ((ctxt_pP->enb_module_id  == oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
                 "eNB module id is too low (%u/%d)!\n",
                 ctxt_pP->enb_module_id,
                 oai_emulation.info.first_enb_local);
    AssertFatal ((ctxt_pP->enb_module_id < (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",
                 ctxt_pP->enb_module_id,
                 oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
    AssertFatal (ctxt_pP->ue_module_id  < NB_UE_INST,
                 "UE module id is too high (%u/%d)!\n",
                 ctxt_pP->ue_module_id,
                 oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
463
  } else {
464 465 466 467 468 469 470 471
    AssertFatal (ctxt_pP->ue_module_id  < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
                 "UE module id is too high (%u/%d)!\n",
                 ctxt_pP->ue_module_id,
                 oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
    AssertFatal (ctxt_pP->ue_module_id  >= oai_emulation.info.first_ue_local,
                 "UE module id is too low (%u/%d)!\n",
                 ctxt_pP->ue_module_id,
                 oai_emulation.info.first_ue_local);
472
  }
473

474
#endif
475
#ifdef PDCP_MSG_PRINT
476 477 478 479 480 481 482 483
  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
484

485
  if (MBMS_flagP) {
486 487 488 489 490 491 492 493 494 495 496
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);

    if (ctxt_pP->enb_flag == 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 ctxt_pP->enb_flag %d\n",
            ctxt_pP->enb_module_id, ctxt_pP->ue_module_id, rb_idP, sdu_buffer_sizeP, ctxt_pP->enb_flag);
    } 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 ctxt_pP->enb_flag %d eNB_id %d\n",
            ctxt_pP->ue_module_id, ctxt_pP->enb_module_id , rb_idP, sdu_buffer_sizeP, ctxt_pP->enb_flag, ctxt_pP->enb_module_id);
    }
497
  } else {
498 499 500 501 502 503 504
    rb_id = rb_idP % maxDRB;
    AssertError (rb_id < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_id, maxDRB, ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);
    AssertError (rb_id > 0, return FALSE, "RB id is too low (%u/%d) %u %u!\n", rb_id, maxDRB, ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
      if (srb_flagP) {
        pdcp_p = &pdcp_array_srb_ue[ctxt_pP->ue_module_id][rb_id-1];
505
#if 0
506 507 508
        LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
              "and signalling radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
              ctxt_pP->enb_module_id, ctxt_pP->ue_module_id, rb_id, sdu_buffer_sizeP, ctxt_pP->enb_flag);
509
#endif
510 511
      } else {
        pdcp_p = &pdcp_array_drb_ue[ctxt_pP->ue_module_id][rb_id-1];
512
#if 0
513 514 515
        LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
              "and data radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
              ctxt_pP->enb_module_id, ctxt_pP->ue_module_id, rb_id, sdu_buffer_sizeP, ctxt_pP->enb_flag);
516
#endif
517
      }
518

519 520 521
    } else {
      if (srb_flagP) {
        pdcp_p = &pdcp_array_srb_eNB[ctxt_pP->enb_module_id][ctxt_pP->ue_module_id][rb_id-1];
522
#if 0
523 524 525
        LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
              "and signalling radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d eNB_id %d\n",
              ctxt_pP->ue_module_id, ctxt_pP->enb_module_id , rb_id, sdu_buffer_sizeP, ctxt_pP->enb_flag, ctxt_pP->enb_module_id);
526
#endif
527 528
      } else {
        pdcp_p = &pdcp_array_drb_eNB[ctxt_pP->enb_module_id][ctxt_pP->ue_module_id][rb_id-1];
529
#if 0
530 531 532
        LOG_D(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
              "and data radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d eNB_id %d\n",
              ctxt_pP->ue_module_id, ctxt_pP->enb_module_id , rb_id, sdu_buffer_sizeP, ctxt_pP->enb_flag, ctxt_pP->enb_module_id);
533
#endif
534
      }
535 536

    }
537
  }
538

gauthier's avatar
gauthier committed
539
  sdu_list_p = &pdcp_sdu_list;
540

gauthier's avatar
gauthier committed
541
  if (sdu_buffer_sizeP == 0) {
542 543
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
544
  }
545

546 547
  if (ctxt_pP->enb_flag)
    start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_ind);
548
  else
549
    start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_ind);
550 551

  /*
552 553
   * 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
554
   */
555

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

      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
570
      } else {
571 572
        //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
573
      }
574

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

578 579 580 581
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
582 583 584 585 586 587 588 589 590 591 592 593
      LOG_W(PDCP, "Incoming (from RLC) SDU is short of size (size:%d)! Ignoring...\n", sdu_buffer_sizeP);
      free_mem_block(sdu_buffer_pP);

      if (ctxt_pP->enb_flag)
        stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_ind);
      else
        stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_ind);

      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
      return FALSE;
    }

594
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
595
#if 0
596
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
597
#endif
598
      /* if (dc == PDCP_DATA_PDU )
599 600 601
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
602
    } else {
603
      LOG_W(PDCP, "Incoming PDU has an unexpected sequence number (%d), RX window synchronisation have probably been lost!\n", sequence_number);
gauthier's avatar
gauthier committed
604
      /*
605 606
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
607 608
       */
#if 0
609 610 611
      LOG_D(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer);
      return FALSE;
612
#else
613
      //LOG_W(PDCP, "Delivering out-of-order SDU to upper layer...\n");
614
#endif
615
    }
616 617 618

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

621
      if (pdcp_p->security_activated == 1) {
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
        if (ctxt_pP->enb_flag == ENB_FLAG_NO)
          start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].validate_security);
        else
          start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].validate_security);

        pdcp_validate_security(ctxt_pP,
                               pdcp_p,
                               srb_flagP,
                               rb_idP,
                               pdcp_header_len,
                               sequence_number,
                               sdu_buffer_pP->data,
                               sdu_buffer_sizeP - pdcp_tailer_len);

        if (ctxt_pP->enb_flag == ENB_FLAG_NO)
          stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].validate_security);
        else
          stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].validate_security);
gauthier's avatar
gauthier committed
640
      }
641

642 643
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
644
      pdcp_rrc_data_ind(ctxt_pP->enb_module_id,
645 646 647 648 649 650
                        ctxt_pP->ue_module_id,
                        ctxt_pP->frame,
                        ctxt_pP->enb_flag,
                        rb_id,
                        sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
                        (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len]);
651
      free_mem_block(sdu_buffer_pP);
652

653
      // free_mem_block(new_sdu);
654
      if (ctxt_pP->enb_flag)
655
        stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_ind);
656
      else
657 658
        stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_ind);

659
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
660 661
      return TRUE;
    }
662 663 664 665

    /*
     * DRBs
     */
666 667
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
668

669
    if (pdcp_p->security_activated == 1) {
670
      if (ctxt_pP->enb_flag == ENB_FLAG_NO)
671
        start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].validate_security);
672
      else
673 674
        start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].validate_security);

675
      pdcp_validate_security(
676 677 678 679 680 681 682 683 684
        ctxt_pP,
        pdcp_p,
        srb_flagP,
        rb_idP,
        pdcp_header_len,
        sequence_number,
        sdu_buffer_pP->data,
        sdu_buffer_sizeP - pdcp_tailer_len);

685
      if (ctxt_pP->enb_flag == ENB_FLAG_NO)
686
        stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].validate_security);
687
      else
688 689
        stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].validate_security);

690
    }
691

692
#endif
693
  } else {
694
    payload_offset=0;
695
  }
696

697
#if defined(USER_MODE) && defined(OAI_EMU)
698

699
  if (oai_emulation.info.otg_enabled == 1) {
700 701 702 703 704 705 706 707 708
    module_id_t src_id, dst_id;
    int    ctime;

    DevAssert(pdcp_p);

    if (pdcp_p->rlc_mode == RLC_MODE_AM ) {
      pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
    }

709
#if defined(DEBUG_PDCP_PAYLOAD)
710 711 712
    rlc_util_print_hex_octets(PDCP,
                              (unsigned char*)&sdu_buffer_pP->data[payload_offset],
                              sdu_buffer_sizeP - payload_offset);
713
#endif
gauthier's avatar
gauthier committed
714

715 716 717 718
    src_id = (ctxt_pP->enb_flag == ENB_FLAG_NO) ?  ctxt_pP->enb_module_id : ctxt_pP->ue_module_id +   NB_eNB_INST;
    dst_id = (ctxt_pP->enb_flag == ENB_FLAG_NO) ? ctxt_pP->ue_module_id +  NB_eNB_INST: ctxt_pP->enb_module_id;
    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",
719
          ctxt_pP->enb_flag, rb_id, src_id, dst_id);
gauthier's avatar
gauthier committed
720

721 722
    if (otg_rx_pkt(src_id, dst_id,ctime,&sdu_buffer_pP->data[payload_offset],
                   sdu_buffer_sizeP - payload_offset ) == 0 ) {
gauthier's avatar
gauthier committed
723
      free_mem_block(sdu_buffer_pP);
724

725
      if (ctxt_pP->enb_flag)
726
        stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_ind);
727
      else
728 729
        stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_ind);

730
      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
gauthier's avatar
gauthier committed
731
      return TRUE;
732
    }
733
  }
734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749

#else

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

    if (ctxt_pP->enb_flag)
      stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_ind);
    else
      stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_ind);

    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
    return TRUE;
  }

750 751
#endif

gauthier's avatar
gauthier committed
752

753 754 755 756 757 758 759 760 761
  // 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)
762

763
  if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
764 765 766 767 768 769 770 771 772 773 774 775 776 777
    //LOG_T(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
    gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
                                sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
    AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
    memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
    message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
    AssertFatal(message_p != NULL, "OUT OF MEMORY");
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer       = gtpu_buffer_p;
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length       = sdu_buffer_sizeP - payload_offset;
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset       = GTPU_HEADER_OVERHEAD_MAX;
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).ue_index     = ctxt_pP->ue_module_id;
    GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
    itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
    packet_forwarded = TRUE;
778
  }
779

780 781 782
#else
  packet_forwarded = FALSE;
#endif
783

784
  if (FALSE == packet_forwarded) {
785
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t));
786

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
    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 (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id;
gauthier's avatar
gauthier committed
802
#if defined(OAI_EMU)
803
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->ue_module_id + oai_emulation.info.nb_enb_local - oai_emulation.info.first_ue_local;
gauthier's avatar
gauthier committed
804
#endif
805 806
      } else {
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->ue_module_id * maxDRB);
gauthier's avatar
gauthier committed
807
#if defined(OAI_EMU)
808
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->enb_module_id - oai_emulation.info.first_enb_local;
809
#endif
810
      }
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836

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

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

      /*
       * Update PDCP statistics
       * XXX Following two actions are identical, is there a merge error?
       */

      /*if (ctxt_pP->enb_flag == 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
837
  }
838

gauthier's avatar
gauthier committed
839
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
840 841 842 843 844 845 846 847 848
  else {
    AssertFatal(0, "[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u] PDCP_DATA_IND SDU DROPPED, OUT OF MEMORY \n",
                ctxt_pP->frame,
                (ctxt_pP->enb_flag) ? "eNB" : "UE",
                ctxt_pP->enb_module_id,
                ctxt_pP->ue_module_id,
                rb_id);
  }

gauthier's avatar
gauthier committed
849
#endif
850

gauthier's avatar
gauthier committed
851
  free_mem_block(sdu_buffer_pP);
852

853 854
  if (ctxt_pP->enb_flag)
    stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].data_ind);
855
  else
856
    stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].data_ind);
857

858
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
859 860 861 862
  return TRUE;
}

//-----------------------------------------------------------------------------
863 864
void pdcp_run (const protocol_ctxt_t* const  ctxt_pP)
{
865
  //-----------------------------------------------------------------------------
866
#if defined(ENABLE_ITTI)
867 868 869 870
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
871
  protocol_ctxt_t  ctxt;
872
#endif
873

874 875
  if (ctxt_pP->enb_flag)
    start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].pdcp_run);
876
  else
877
    start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].pdcp_run);
878

879
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
880

881 882
#if defined(ENABLE_ITTI)

883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
  do {
    // Checks if a message has been sent to PDCP sub-task
    itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);

    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);

      switch (ITTI_MSG_ID(msg_p)) {
      case RRC_DCCH_DATA_REQ:
        LOG_D(PDCP, "Received %s from %s: instance %d, frame %d, ctxt_pP->enb_flag %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              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);

        ctxt.enb_module_id = RRC_DCCH_DATA_REQ (msg_p).eNB_index;
        ctxt.ue_module_id  = RRC_DCCH_DATA_REQ (msg_p).ue_index;
        ctxt.frame         = RRC_DCCH_DATA_REQ (msg_p).frame;
        ctxt.enb_flag      = RRC_DCCH_DATA_REQ (msg_p).enb_flag;

        result = pdcp_data_req (&ctxt,
                                SRB_FLAG_YES,
                                RRC_DCCH_DATA_REQ (msg_p).rb_id,
                                RRC_DCCH_DATA_REQ (msg_p).muip,
                                RRC_DCCH_DATA_REQ (msg_p).confirmp,
                                RRC_DCCH_DATA_REQ (msg_p).sdu_size,
                                RRC_DCCH_DATA_REQ (msg_p).sdu_p,
                                RRC_DCCH_DATA_REQ (msg_p).mode);
        AssertFatal (result == TRUE, "PDCP data request failed!\n");

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

      default:
        LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
        break;
gauthier's avatar
gauthier committed
921
      }
922 923 924 925

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

# if 0
  {
930
    MessageDef *msg_resp_p;
931

932
    msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
933

934
    itti_send_msg_to_task(TASK_RRC_ENB, 1, msg_resp_p);
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
  }
  {
    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
951 952
#endif

953 954
#if defined(USER_MODE) && defined(OAI_EMU)
  pdcp_t            *pdcp_p          = NULL;
nikaeinn's avatar
nikaeinn committed
955 956 957
  int               drb_id=1 ;
  int               ue_id=0;
  int               read_otg=1;
958 959

  // add check for other rb_ids later
960 961
  if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
    if (pdcp_array_drb_ue[ctxt_pP->ue_module_id][drb_id-1].instanciated_instance  != TRUE )
nikaeinn's avatar
nikaeinn committed
962 963 964
      read_otg=0;
  } else {
    for (ue_id=0; ue_id < NB_UE_INST; ue_id++)
965 966 967
      if (pdcp_array_drb_eNB[ctxt_pP->enb_module_id][ue_id][drb_id-1].instanciated_instance  != TRUE ) {
        read_otg =0;
        break;
968
      }
nikaeinn's avatar
nikaeinn committed
969
  }
970

nikaeinn's avatar
nikaeinn committed
971
  if (read_otg == 1 )
972
    pdcp_fifo_read_input_sdus_from_otg(ctxt_pP);
973

gauthier's avatar
gauthier committed
974
#endif
975 976

  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
gauthier's avatar
gauthier committed
977
#if defined(LINK_PDCP_TO_GTPV1U)
978

979
  if (ctxt_pP->enb_flag == ENB_FLAG_NO)
gauthier's avatar
gauthier committed
980
#endif
gauthier's avatar
gauthier committed
981
  {
982
    pdcp_fifo_read_input_sdus(ctxt_pP);
gauthier's avatar
gauthier committed
983
  }
984

985
  // PDCP -> NAS/IP traffic: RX
986 987
  if (ctxt_pP->enb_flag)
    start_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].pdcp_ip);
988
  else
989
    start_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].pdcp_ip);
gauthier's avatar
gauthier committed
990

991
  pdcp_fifo_flush_sdus(ctxt_pP);
992

993 994
  if (ctxt_pP->enb_flag)
    stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].pdcp_ip);
995
  else
996
    stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].pdcp_ip);
997

998 999
  if (ctxt_pP->enb_flag)
    stop_meas(&eNB_pdcp_stats[ctxt_pP->enb_module_id].pdcp_run);
1000
  else
1001
    stop_meas(&UE_pdcp_stats[ctxt_pP->ue_module_id].pdcp_run);
1002

1003 1004
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);

1005 1006
}

1007 1008
boolean_t pdcp_remove_UE(const protocol_ctxt_t* const  ctxt_pP)
{
1009 1010 1011 1012 1013 1014 1015 1016


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

  // check and remove SRBs first

1017
  for (srb_id=0; srb_id<2; srb_id++) {
1018
    AssertFatal( srb_id-1 > 0, "Array index below zero (hard coded). FIXME!" );
1019
    pdcp_p = &pdcp_array_srb_eNB[ctxt_pP->enb_module_id][ctxt_pP->ue_module_id][srb_id-1];
1020

1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
    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;
1037

1038 1039 1040 1041
      /* Security keys */
      if (pdcp_p->kUPenc != NULL) {
        free(pdcp_p->kUPenc);
      }
1042

1043 1044 1045
      if (pdcp_p->kRRCint != NULL) {
        free(pdcp_p->kRRCint);
      }
1046

1047 1048 1049 1050 1051 1052
      if (pdcp_p->kRRCenc != NULL) {
        free(pdcp_p->kRRCenc);
      }
    }
  }

1053
  for (drb_id=0; drb_id<maxDRB; drb_id++) {
1054
    pdcp_p = &pdcp_array_drb_eNB[ctxt_pP->enb_module_id][ctxt_pP->ue_module_id][drb_id-1];
1055

1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
    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);
      }
1077

1078 1079 1080
      if (pdcp_p->kRRCint != NULL) {
        free(pdcp_p->kRRCint);
      }
1081

1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
      if (pdcp_p->kRRCenc != NULL) {
        free(pdcp_p->kRRCenc);
      }
    }

  }

  return 1;
}


1093
boolean_t rrc_pdcp_config_asn1_req (
1094 1095 1096 1097 1098 1099 1100 1101
  const protocol_ctxt_t* const  ctxt_pP,
  SRB_ToAddModList_t  *const srb2add_list_pP,
  DRB_ToAddModList_t  *const drb2add_list_pP,
  DRB_ToReleaseList_t *const drb2release_list_pP,
  const uint8_t                   security_modeP,
  uint8_t                  *const kRRCenc_pP,
  uint8_t                  *const kRRCint_pP,
  uint8_t                  *const kUPenc_pP
1102
#ifdef Rel10
1103
  ,PMCH_InfoList_r9_t*  const pmch_InfoList_r9_pP
1104
#endif
gauthier's avatar
gauthier committed
1105
)
1106
{
1107
  long int        lc_id          = 0;
1108
  DRB_Identity_t  srb_id         = 0;
1109
  long int        mch_id         = 0;
gauthier's avatar
gauthier committed
1110
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1111
  DRB_Identity_t  drb_id         = 0;
gauthier's avatar
gauthier committed
1112
  DRB_Identity_t *pdrb_id_p      = NULL;
1113
  uint8_t         drb_sn         = 12;
1114 1115
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1116
  long int        cnt            = 0;
1117 1118
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
1119 1120 1121
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
1122 1123 1124

#ifdef Rel10
  int i,j;
gauthier's avatar
gauthier committed
1125 1126
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1127 1128
#endif

1129
  if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
1130
    LOG_D(PDCP, "[UE %u] CONFIG REQ ASN1 for eNB %u\n", ctxt_pP->ue_module_id, ctxt_pP->enb_module_id);
1131
  } else {
1132
    LOG_D(PDCP, "[eNB %u] CONFIG REQ ASN1 for UE %u\n", ctxt_pP->enb_module_id, ctxt_pP->ue_module_id);
1133
  }
1134

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

gauthier's avatar
gauthier committed
1137
  if (srb2add_list_pP != NULL) {
1138 1139 1140 1141 1142
    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;
      lc_id = srb_id + 2;