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

gauthier's avatar
 
gauthier committed
64 65
#if defined(LINK_PDCP_TO_GTPV1U)
#  include "gtpv1u_eNB_task.h"
gauthier's avatar
 
gauthier committed
66
#  include "gtpv1u.h"
gauthier's avatar
 
gauthier committed
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;
gauthier's avatar
gauthier committed
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;
gauthier's avatar
gauthier committed
106
  boolean_t          ret             = TRUE;
gauthier's avatar
gauthier committed
107

gauthier's avatar
 
gauthier committed
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

gauthier's avatar
gauthier committed
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

gauthier's avatar
gauthier committed
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

gauthier's avatar
gauthier committed
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

gauthier's avatar
gauthier committed
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);
gauthier's avatar
 
gauthier committed
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);
gauthier's avatar
 
gauthier committed
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;

knopp's avatar
 
knopp committed
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);
gauthier's avatar
 
gauthier committed
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;
gauthier's avatar
gauthier committed
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,
gauthier's avatar
 
gauthier committed
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
  }
gauthier's avatar
gauthier committed
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(
gauthier's avatar
 
gauthier committed
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;
gauthier's avatar
 
gauthier committed
421
  uint8_t     *gtpu_buffer_p    = NULL;
422
#endif
423
 
424

gauthier's avatar
gauthier committed
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
#ifdef OAI_EMU
  if (enb_flagP) {
      AssertFatal ((enb_mod_idP >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),
          "eNB module id is too low (%u/%d)!\n",
          enb_mod_idP,
          oai_emulation.info.first_enb_local);
      AssertFatal ((enb_mod_idP < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.nb_enb_local > 0),
          "eNB module id is too high (%u/%d)!\n",
          enb_mod_idP,
          oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);
      AssertFatal (ue_mod_idP  < NB_UE_INST,
          "UE module id is too high (%u/%d)!\n",
          ue_mod_idP,
          oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
  } else {
      AssertFatal (ue_mod_idP  < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),
          "UE module id is too high (%u/%d)!\n",
          ue_mod_idP,
          oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);
      AssertFatal (ue_mod_idP  >= oai_emulation.info.first_ue_local,
          "UE module id is too low (%u/%d)!\n",
          ue_mod_idP,
          oai_emulation.info.first_ue_local);
  }
#endif
450 451 452 453 454 455 456 457
#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 

458 459 460 461 462 463 464 465 466 467 468
  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);
      }
469
  } else {
470 471
      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);
472
      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);
473

474
      if (enb_flagP == ENB_FLAG_NO) {
475 476
          if (srb_flagP) {
              pdcp_p = &pdcp_array_srb_ue[ue_mod_idP][rb_id-1];
knopp's avatar
 
knopp committed
477
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
478 479 480 481
                    "and signalling radio bearer ID %d rlc sdu size %d enb_flagP %d\n",
                    enb_mod_idP, ue_mod_idP, rb_id, sdu_buffer_sizeP, enb_flagP);
          } else {
              pdcp_p = &pdcp_array_drb_ue[ue_mod_idP][rb_id-1];
knopp's avatar
 
knopp committed
482
              LOG_D(PDCP, "Data indication notification for PDCP entity from eNB %u to UE %u "
483 484 485
                    "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);
          }
486

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

      }
501
  }
502
  
gauthier's avatar
gauthier committed
503
  sdu_list_p = &pdcp_sdu_list;
504

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

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

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

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

gauthier's avatar
gauthier committed
689

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

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

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

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

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

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

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

816
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
817

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

932 933
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);

934 935
}

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

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

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

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

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

995

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

gauthier's avatar