pdcp.c 53 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*******************************************************************************

  Eurecom OpenAirInterface
  Copyright(c) 1999 - 2011 Eurecom

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope 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.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Contact Information
  Openair Admin: openair_admin@eurecom.fr
  Openair Tech : openair_tech@eurecom.fr
  Forums       : http://forums.eurecom.fsr/openairinterface
  Address      : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France

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 66 67 68 69 70 71 72 73 74 75 76 77 78
#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()
 */
79 80 81 82 83 84 85 86 87 88 89
boolean_t pdcp_data_req(
    module_id_t    enb_mod_idP,
    module_id_t    ue_mod_idP,
    frame_t        frameP,
    eNB_flag_t     enb_flagP,
    rb_id_t        rb_idP,
    mui_t          muiP,
    confirm_t      confirmP,
    sdu_size_t     sdu_buffer_sizeP,
    unsigned char *sdu_buffer_pP,
    pdcp_transmission_mode_t modeP)
90 91
{
  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
92
  pdcp_t            *pdcp_p          = NULL;
93 94 95 96 97
  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
98 99
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
100
  boolean_t          ret             = TRUE;
gauthier's avatar
gauthier committed
101 102 103

  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);
104 105 106 107 108
  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 {
      AssertError (rb_idP < NB_RB_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MAX, ue_mod_idP, enb_mod_idP);
  }
gauthier's avatar
gauthier committed
109

110
  if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
111
      pdcp_p = &pdcp_array_ue[ue_mod_idP][rb_idP];
112
  } else {
gauthier's avatar
gauthier committed
113
      pdcp_p = &pdcp_array_eNB[enb_mod_idP][ue_mod_idP][rb_idP];
114
  }
115

116 117
  if ((pdcp_p->instanciated_instance == FALSE) && (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT)) {
      if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
118 119 120 121 122 123 124
          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;
125
  }
gauthier's avatar
gauthier committed
126 127 128
  if (sdu_buffer_sizeP == 0) {
      LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
      return FALSE;
129 130 131 132 133
  }
  /*
   * XXX MAX_IP_PACKET_SIZE is 4096, shouldn't this be MAX SDU size, which is 8188 bytes?
   */

gauthier's avatar
gauthier committed
134 135 136 137 138
  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");
139
  }
140

141
  if (enb_flagP == ENB_FLAG_NO)
142
    start_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
143
  else
144
    start_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
145 146

  // PDCP transparent mode for MBMS traffic
147

148
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
gauthier's avatar
gauthier committed
149 150 151 152
      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);
153 154 155 156
          rlc_util_print_hex_octets(PDCP,
                                    (unsigned char*)&pdcp_pdu_p->data[0],
                                    sdu_buffer_sizeP);

gauthier's avatar
gauthier committed
157
          rlc_status = rlc_data_req(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
gauthier's avatar
gauthier committed
158 159 160 161 162 163 164 165 166 167 168
      } else {
        rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
#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
      }
169
  } else {
gauthier's avatar
gauthier committed
170 171 172 173
      // calculate the pdcp header and trailer size
      if (rb_idP < DTCH) {
          pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
          pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
174
      } else {
gauthier's avatar
gauthier committed
175 176
          pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
          pdcp_tailer_len = 0;
177
      }
gauthier's avatar
gauthier committed
178 179 180 181 182 183 184 185 186 187 188
      pdcp_pdu_size = sdu_buffer_sizeP + pdcp_header_len + pdcp_tailer_len;

      LOG_I(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",
          (enb_flagP) ? "eNB" : "UE",
              enb_mod_idP,
              ue_mod_idP,
              rb_idP,
              pdcp_pdu_size,
              pdcp_header_len,
              pdcp_tailer_len);

189
      /*
gauthier's avatar
gauthier committed
190
       * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
191
       */
gauthier's avatar
gauthier committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
      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
           */

          if ((rb_idP % NB_RB_MAX) < DTCH) { // 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);
              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");
209
		  if (enb_flagP == ENB_FLAG_NO)
210
		    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
211
		  else
212 213
		    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
		  return FALSE;
gauthier's avatar
gauthier committed
214 215 216
              }
          } else {
              pdcp_user_plane_data_pdu_header_with_long_sn pdu_header;
217
              pdu_header.dc = (modeP == PDCP_TRANSMISSION_MODE_DATA) ? PDCP_DATA_PDU_BIT_SET :  PDCP_CONTROL_PDU_BIT_SET;
gauthier's avatar
gauthier committed
218 219 220 221
              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");
222
		  if (enb_flagP == ENB_FLAG_NO)
223
		    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
224
		  else
225 226
		    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
		  return FALSE;
gauthier's avatar
gauthier committed
227 228 229 230 231 232 233 234 235 236
              }
          }
          /*
           * 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);
237
	      if (enb_flagP == ENB_FLAG_NO)
238
		stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
239
	      else
240
		stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
gauthier's avatar
gauthier committed
241 242
              return FALSE;
          }
243

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

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

gauthier's avatar
gauthier committed
249 250 251 252 253
          //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];
254 255

#if defined(ENABLE_SECURITY)
gauthier's avatar
gauthier committed
256 257 258 259 260 261 262
          if ((pdcp->security_activated != 0) &&
              ((pdcp->cipheringAlgorithm) != 0) &&
              ((pdcp->integrityProtAlgorithm) != 0)) {
              pdcp_apply_security(pdcp, rb_id % NB_RB_MAX,
                  pdcp_header_len, current_sn, pdcp_pdu->data,
                  sdu_buffer_size);
          }
263 264
#endif

gauthier's avatar
gauthier committed
265 266 267 268 269 270 271
          /* 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");
272 273 274 275
          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
276 277 278 279 280 281 282 283 284 285 286 287 288 289
#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
          return FALSE;
      }
      /*
       * Ask sublayer to transmit data and check return value
       * to see if RLC succeeded
       */
290
      rlc_status = rlc_data_req(enb_mod_idP, ue_mod_idP, frameP, enb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
291 292 293 294
  }
  switch (rlc_status) {
  case RLC_OP_STATUS_OK:
    LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
295
    ret=TRUE;
296 297 298 299
    break;

  case RLC_OP_STATUS_BAD_PARAMETER:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
300 301
    ret= FALSE;
    break;
302 303
  case RLC_OP_STATUS_INTERNAL_ERROR:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
304 305
    ret= FALSE;
    break;
306 307 308

  case RLC_OP_STATUS_OUT_OF_RESSOURCES:
    LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
309 310
    ret= FALSE;
    break;
311 312 313

  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);
314 315
    ret= FALSE;
    break;
316
  }
317
  if (enb_flagP == ENB_FLAG_NO)
318
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_req);
319
  else
320
    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_req);
321 322 323 324
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */
325
  /*
326
   if (rb_id>=DTCH) {
327
    if (enb_flagP == 1) {
328 329 330 331 332 333 334
      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;
    }
    }*/
335
  return ret;
336 337 338

}

gauthier's avatar
gauthier committed
339

gauthier's avatar
gauthier committed
340 341
boolean_t pdcp_data_ind(module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, eNB_flag_t enb_flagP, MBMS_flag_t MBMS_flagP, rb_id_t rb_idP, sdu_size_t sdu_buffer_sizeP, \
    mem_block_t* sdu_buffer_pP, boolean_t is_data_planeP)
342 343
{
  //-----------------------------------------------------------------------------
gauthier's avatar
gauthier committed
344 345 346
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
347 348
  uint8_t           pdcp_header_len = 0;
  uint8_t           pdcp_tailer_len = 0;
gauthier's avatar
gauthier committed
349
  pdcp_sn_t    sequence_number = 0;
350
  uint8_t           payload_offset  = 0;
gauthier's avatar
gauthier committed
351

352 353
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
354
  else
355 356
    start_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
#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
382 383 384 385 386 387 388 389 390 391 392
  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);
      }
393
  } else {
394 395 396 397
      rb_idP = rb_idP % NB_RB_MAX;
      AssertError (rb_idP < NB_RB_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MAX, ue_mod_idP, enb_mod_idP);
      if (enb_flagP == ENB_FLAG_NO) {
          pdcp_p = &pdcp_array_ue[ue_mod_idP][rb_idP];
398

399 400 401 402 403 404 405
          LOG_I(PDCP, "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 {
          pdcp_p = &pdcp_array_eNB[enb_mod_idP][ue_mod_idP][rb_idP];

          LOG_I(PDCP, "Data indication notification for PDCP entity from UE %u to eNB %u "
406
          "and radio bearer ID %d rlc sdu size %d enb_flagP %d eNB_id %d\n",
gauthier's avatar
gauthier committed
407
          ue_mod_idP, enb_mod_idP , rb_idP, sdu_buffer_sizeP, enb_flagP, enb_mod_idP);
408
      }
409
  }
410

gauthier's avatar
gauthier committed
411
  sdu_list_p = &pdcp_sdu_list;
412

413

gauthier's avatar
gauthier committed
414 415
  if (sdu_buffer_sizeP == 0) {
      LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
416 417
      if (enb_flagP)
	stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
418
      else
419
	stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
gauthier's avatar
gauthier committed
420
      return FALSE;
421 422 423
  }

  /*
gauthier's avatar
gauthier committed
424 425
   * Check if incoming SDU is long enough to carry a PDU header
   */
426
  if (MBMS_flagP == 0 ) {
gauthier's avatar
gauthier committed
427 428 429 430 431 432 433
      if ((rb_idP % NB_RB_MAX) < DTCH) {
          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;
      }
434

gauthier's avatar
gauthier committed
435 436 437
      if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
          LOG_W(PDCP, "Incoming (from RLC) SDU is short of size (size:%d)! Ignoring...\n", sdu_buffer_sizeP);
          free_mem_block(sdu_buffer_pP);
438 439
	  if (enb_flagP)
	    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
440
	  else
441 442
	    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
	  return FALSE;
gauthier's avatar
gauthier committed
443
      }
444

gauthier's avatar
gauthier committed
445
      /*
446 447 448 449
       * 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
450 451
      if (pdcp_header_len == PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE) { // DRB
          sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char*)sdu_buffer_pP->data);
452
          //       uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer->data);
gauthier's avatar
gauthier committed
453 454 455 456 457 458
      } else { //SRB1/2
          sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char*)sdu_buffer_pP->data);
      }
      if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p) == TRUE) {
          LOG_D(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
          /* if (dc == PDCP_DATA_PDU )
459 460 461
	   LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
	   else
	   LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
gauthier's avatar
gauthier committed
462 463 464 465 466 467
      } else {
          LOG_W(PDCP, "Incoming PDU has an unexpected sequence number (%d), RX window snychronisation have probably been lost!\n", sequence_number);
          /*
           * XXX Till we implement in-sequence delivery and duplicate discarding
           * mechanism all out-of-order packets will be delivered to RRC/IP
           */
468
#if 0
gauthier's avatar
gauthier committed
469 470 471
          LOG_D(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer);
          return FALSE;
472
#else
gauthier's avatar
gauthier committed
473
          LOG_W(PDCP, "Delivering out-of-order SDU to upper layer...\n");
474
#endif
475
      }
gauthier's avatar
gauthier committed
476 477 478 479 480 481 482 483
      // SRB1/2: control-plane data
      if ( (rb_idP % NB_RB_MAX) <  DTCH ){
#if defined(ENABLE_SECURITY)
          if (pdcp->security_activated == 1) {
              pdcp_validate_security(pdcp, rb_id, pdcp_header_len,
                  sequence_number, sdu_buffer->data,
                  sdu_buffer_size - pdcp_tailer_len);
          }
484
#endif
gauthier's avatar
gauthier committed
485 486 487 488 489 490 491
//rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
          pdcp_rrc_data_ind(enb_mod_idP,
              ue_mod_idP,
              frameP,
              enb_flagP,
              rb_idP,
              sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
492
              (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len]);
gauthier's avatar
gauthier committed
493 494
          free_mem_block(sdu_buffer_pP);
          // free_mem_block(new_sdu);
495 496
          if (enb_flagP)
	    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
497
	  else
498 499
	    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
	  return TRUE;
gauthier's avatar
gauthier committed
500 501
      }
      payload_offset=PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
502
#if defined(ENABLE_SECURITY)
gauthier's avatar
gauthier committed
503 504 505 506 507
      if (pdcp->security_activated == 1) {
          pdcp_validate_security(pdcp_p, rb_idP % NB_RB_MAX, pdcp_header_len,
              sequence_number, sdu_buffer->data,
              sdu_buffer_size - pdcp_tailer_len);
      }
508
#endif
509
  } else {
gauthier's avatar
gauthier committed
510
      payload_offset=0;
511 512
  }
#if defined(USER_MODE) && defined(OAI_EMU)
513
  if (oai_emulation.info.otg_enabled == 1) {
gauthier's avatar
gauthier committed
514 515
      module_id_t src_id, dst_id;
      int    ctime;
516 517 518
      rlc_util_print_hex_octets(PDCP,
                                &sdu_buffer_pP->data[payload_offset],
                                sdu_buffer_sizeP - payload_offset);
gauthier's avatar
gauthier committed
519 520

      src_id = (enb_flagP != 0) ? ue_mod_idP : enb_mod_idP;
521
      dst_id = (enb_flagP == ENB_FLAG_NO) ? ue_mod_idP : enb_mod_idP;
gauthier's avatar
gauthier committed
522 523 524 525 526 527 528
      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",
          enb_flagP, rb_idP, src_id, dst_id);

      if (otg_rx_pkt(src_id, dst_id,ctime,&sdu_buffer_pP->data[payload_offset],
          sdu_buffer_sizeP - payload_offset ) == 0 ) {
          free_mem_block(sdu_buffer_pP);
529 530
           if (enb_flagP)
	     stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
531
	   else
532 533
	     stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
	  return TRUE;
gauthier's avatar
gauthier committed
534
      }
535 536 537
  }
#else
  if (otg_enabled==1) {
gauthier's avatar
gauthier committed
538 539
      LOG_D(OTG,"Discarding received packed\n");
      free_mem_block(sdu_buffer_pP);
540 541
      if (enb_flagP)
	stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
542
      else
543
	stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
gauthier's avatar
gauthier committed
544
      return TRUE;
545 546
  }
#endif
gauthier's avatar
gauthier committed
547
  new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t));
548

gauthier's avatar
gauthier committed
549 550
  if (new_sdu_p) {
      /*
551 552
       * Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
       */
gauthier's avatar
gauthier committed
553 554 555 556 557
      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
558
      if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
559 560 561 562 563 564 565 566
          ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_idP;
#if defined(OAI_EMU)
          ((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;
#endif
      } else {
          ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_idP + (ue_mod_idP * NB_RB_MAX);
#if defined(OAI_EMU)
          ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = enb_mod_idP - oai_emulation.info.first_enb_local;
567
#endif
gauthier's avatar
gauthier committed
568 569
      }

570

gauthier's avatar
gauthier committed
571 572 573
      // XXX Decompression would be done at this point

      /*
574 575 576 577 578
       * 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)
       */
gauthier's avatar
gauthier committed
579 580 581 582 583 584 585 586 587 588 589 590 591
      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);

      /*
592 593 594
       * Update PDCP statistics
       * XXX Following two actions are identical, is there a merge error?
       */
gauthier's avatar
gauthier committed
595 596 597 598

      /*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;
599
    } else {
gauthier's avatar
gauthier committed
600 601 602 603 604 605 606 607 608 609 610 611
      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;
    }*/
  }
#if defined(STOP_ON_IP_TRAFFIC_OVERLOAD)
  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_idP);
612
  }
gauthier's avatar
gauthier committed
613
#endif
614

gauthier's avatar
gauthier committed
615
  free_mem_block(sdu_buffer_pP);
616 617
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].data_ind);
618
  else
619
    stop_meas(&UE_pdcp_stats[ue_mod_idP].data_ind);
620 621 622 623
  return TRUE;
}

//-----------------------------------------------------------------------------
624
void pdcp_run (frame_t frameP, eNB_flag_t  enb_flagP, module_id_t ue_mod_idP, module_id_t enb_mod_idP) {
625
  //-----------------------------------------------------------------------------
626
#if defined(ENABLE_ITTI)
627 628 629 630
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
631
#endif
632 633
  if (enb_flagP)
    start_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_run);
634
  else
635
    start_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_run);
636

637
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
638

639 640
#if defined(ENABLE_ITTI)
  do {
gauthier's avatar
gauthier committed
641
      // Checks if a message has been sent to PDCP sub-task
642
      itti_poll_msg (enb_flagP ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
643

gauthier's avatar
gauthier committed
644 645 646
      if (msg_p != NULL) {
          msg_name = ITTI_MSG_NAME (msg_p);
          instance = ITTI_MSG_INSTANCE (msg_p);
647

gauthier's avatar
gauthier committed
648 649
          switch (ITTI_MSG_ID(msg_p)) {
          case RRC_DCCH_DATA_REQ:
650
            LOG_I(PDCP, "Received %s from %s: instance %d, frame %d, enb_flagP %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
651
                msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
652 653 654
                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);

gauthier's avatar
gauthier committed
655 656 657 658 659
            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,
                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");
660

gauthier's avatar
gauthier committed
661 662 663 664
            // 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;
665

gauthier's avatar
gauthier committed
666 667 668 669
          default:
            LOG_E(PDCP, "Received unexpected message %s\n", msg_name);
            break;
          }
670

gauthier's avatar
gauthier committed
671 672 673
          result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
          AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
      }
674
  } while(msg_p != NULL);
675 676 677

# if 0
  {
gauthier's avatar
gauthier committed
678
      MessageDef *msg_resp_p;
679

gauthier's avatar
gauthier committed
680
      msg_resp_p = itti_alloc_new_message(TASK_PDCP_ENB, MESSAGE_TEST);
681

gauthier's avatar
gauthier committed
682
      itti_send_msg_to_task(TASK_RRC_ENB, 1, msg_resp_p);
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
  }
  {
    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
699 700
#endif

701
  pdcp_fifo_read_input_sdus_from_otg(frameP, enb_flagP, ue_mod_idP, enb_mod_idP);
702 703

  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
704
  pdcp_fifo_read_input_sdus(frameP, enb_flagP, ue_mod_idP, enb_mod_idP);
705 706

  // PDCP -> NAS/IP traffic: RX
707
  pdcp_fifo_flush_sdus(frameP, enb_flagP, enb_mod_idP, ue_mod_idP);
708

709
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
710 711
  if (enb_flagP)
    stop_meas(&eNB_pdcp_stats[enb_mod_idP].pdcp_run);
712
  else
713 714
    stop_meas(&UE_pdcp_stats[ue_mod_idP].pdcp_run);

715 716
}

gauthier's avatar
gauthier committed
717
boolean_t rrc_pdcp_config_asn1_req (module_id_t               enb_mod_idP,
gauthier's avatar
gauthier committed
718 719 720 721 722 723
    module_id_t               ue_mod_idP,
    frame_t              frameP,
    eNB_flag_t           enb_flagP,
    SRB_ToAddModList_t  *srb2add_list_pP,
    DRB_ToAddModList_t  *drb2add_list_pP,
    DRB_ToReleaseList_t *drb2release_list_pP,
724 725 726 727
    uint8_t                   security_modeP,
    uint8_t                  *kRRCenc_pP,
    uint8_t                  *kRRCint_pP,
    uint8_t                  *kUPenc_pP
728
#ifdef Rel10
gauthier's avatar
gauthier committed
729
,PMCH_InfoList_r9_t*  pmch_InfoList_r9_pP
730
#endif
gauthier's avatar
gauthier committed
731
)
732
{
733 734 735
  long int        rb_id          = 0;
  long int        lc_id          = 0;
  long int        srb_id         = 0;
736
  long int        mch_id         = 0;
gauthier's avatar
gauthier committed
737
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
738
  DRB_Identity_t  drb_id         = 0;
gauthier's avatar
gauthier committed
739
  DRB_Identity_t *pdrb_id_p      = NULL;
740 741 742
  uint8_t         drb_sn         = 0;
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
743
  long int        cnt            = 0;
744 745
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
746 747 748
  SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  DRB_ToAddMod_t *drb_toaddmod_p = NULL;
  pdcp_t         *pdcp_p         = NULL;
749 750 751

#ifdef Rel10
  int i,j;
gauthier's avatar
gauthier committed
752 753
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
754 755
#endif

756
  if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
757
      LOG_D(PDCP, "[UE %u] CONFIG REQ ASN1 for eNB %u\n", ue_mod_idP, enb_mod_idP);
758
  } else {
gauthier's avatar
gauthier committed
759
      LOG_D(PDCP, "[eNB %u] CONFIG REQ ASN1 for UE %u\n", enb_mod_idP, ue_mod_idP);
760
  }
761 762
  // srb2add_list does not define pdcp config, we use rlc info to setup the pdcp dcch0 and dcch1 channels

gauthier's avatar
gauthier committed
763 764 765 766 767 768 769 770
  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;
          rb_id = srb_id;
          lc_id = srb_id;

771
          if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
772 773 774 775
              pdcp_p = &pdcp_array_ue[ue_mod_idP][srb_id];
          } else {
              pdcp_p = &pdcp_array_eNB[enb_mod_idP][ue_mod_idP][srb_id];
          }
776

777 778
          if (pdcp_p->instanciated_instance == TRUE) {
              action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
779
          } else {
780
              action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
781
          }
782

gauthier's avatar
gauthier committed
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
          if (srb_toaddmod_p->rlc_Config) {
              switch (srb_toaddmod_p->rlc_Config->present) {
              case SRB_ToAddMod__rlc_Config_PR_NOTHING:
                break;
              case SRB_ToAddMod__rlc_Config_PR_explicitValue:
                switch (srb_toaddmod_p->rlc_Config->choice.explicitValue.present) {
                case RLC_Config_PR_NOTHING:
                  break;
                default:
                  pdcp_config_req_asn1 (pdcp_p,
                      enb_mod_idP,
                      ue_mod_idP,
                      frameP,
                      enb_flagP, // not really required
                      rlc_type,
                      action,
                      lc_id,
                      mch_id,
                      rb_id,
                      srb_sn,
                      0, // drb_report
                      0, // header compression
                      security_modeP,
                      kRRCenc_pP,
                      kRRCint_pP,
                      kUPenc_pP);
                  break;
                }
                break;
                case SRB_ToAddMod__rlc_Config_PR_defaultValue:
                  // already the default values
                  break;
                default:
                  DevParam(srb_toaddmod_p->rlc_Config->present, ue_mod_idP, enb_mod_idP);
                  break;
              }
          }
820 821 822 823
      }
  }
  // reset the action

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

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

gauthier's avatar
gauthier committed
829
          drb_id = drb_toaddmod_p->drb_Identity;
830

gauthier's avatar
gauthier committed
831 832 833 834 835 836
          if (drb_toaddmod_p->logicalChannelIdentity != null) {
              lc_id = *drb_toaddmod_p->logicalChannelIdentity;
          } else {
              lc_id = -1;
          }
          rb_id = lc_id;
837

gauthier's avatar
gauthier committed
838
          DevCheck4(rb_id < NB_RB_MAX, rb_id, NB_RB_MAX, ue_mod_idP, enb_mod_idP);
839

840
          if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
841 842 843 844
              pdcp_p = &pdcp_array_ue[ue_mod_idP][rb_id];
          } else {
              pdcp_p = &pdcp_array_eNB[enb_mod_idP][ue_mod_idP][rb_id];
          }
845

846 847
          if (pdcp_p->instanciated_instance == TRUE)
            action = CONFIG_ACTION_MODIFY;
gauthier's avatar
gauthier committed
848
          else
849
            action = CONFIG_ACTION_ADD;
gauthier's avatar
gauthier committed
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894

          if (drb_toaddmod_p->pdcp_Config){
              if (drb_toaddmod_p->pdcp_Config->discardTimer) {
                  // set the value of the timer
              }
              if (drb_toaddmod_p->pdcp_Config->rlc_AM) {
                  drb_report = drb_toaddmod_p->pdcp_Config->rlc_AM->statusReportRequired;
                  rlc_type =RLC_MODE_AM;
              }
              if (drb_toaddmod_p->pdcp_Config->rlc_UM){
                  drb_sn = drb_toaddmod_p->pdcp_Config->rlc_UM->pdcp_SN_Size;
                  rlc_type =RLC_MODE_UM;
              }
              switch (drb_toaddmod_p->pdcp_Config->headerCompression.present) {
              case PDCP_Config__headerCompression_PR_NOTHING:
              case PDCP_Config__headerCompression_PR_notUsed:
                header_compression_profile=0x0;
                break;
              case PDCP_Config__headerCompression_PR_rohc:
                // parse the struc and get the rohc profile
                if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0001)
                  header_compression_profile=0x0001;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0002)
                  header_compression_profile=0x0002;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0003)
                  header_compression_profile=0x0003;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0004)
                  header_compression_profile=0x0004;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0006)
                  header_compression_profile=0x0006;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0101)
                  header_compression_profile=0x0101;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0102)
                  header_compression_profile=0x0102;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0103)
                  header_compression_profile=0x0103;
                else if(drb_toaddmod_p->pdcp_Config->headerCompression.choice.rohc.profiles.profile0x0104)
                  header_compression_profile=0x0104;
                else {
                    header_compression_profile=0x0;
                    LOG_W(PDCP,"unknown header compresion profile\n");
                }
                // set the applicable profile
                break;
              default:
gauthier's avatar
gauthier committed
895 896
                LOG_W(PDCP,"[MOD_id %u/%u][RB %u] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
                    enb_mod_idP, ue_mod_idP, drb_id);
gauthier's avatar
gauthier committed
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
                break;
              }
              pdcp_config_req_asn1 (pdcp_p,
                  enb_mod_idP,
                  ue_mod_idP,
                  frameP,
                  enb_flagP, // not really required
                  rlc_type,
                  action,
                  lc_id,
                  mch_id,
                  rb_id,
                  drb_sn,
                  drb_report,
                  header_compression_profile,
                  security_modeP,
                  kRRCenc_pP,
                  kRRCint_pP,
                  kUPenc_pP);
916 917 918 919
          }
      }
  }

gauthier's avatar
gauthier committed
920 921 922 923
  if (drb2release_list_pP != NULL) {
      for (cnt=0;cnt<drb2release_list_pP->list.count;cnt++) {
          pdrb_id_p = drb2release_list_pP->list.array[cnt];
          rb_id =  *pdrb_id_p;
924
          if (enb_flagP == ENB_FLAG_NO) {
gauthier's avatar
gauthier committed
925 926 927 928
              pdcp_p = &pdcp_array_ue[ue_mod_idP][rb_id];
          } else {
              pdcp_p = &pdcp_array_eNB[enb_mod_idP][ue_mod_idP][rb_id];
          }
929
          action = CONFIG_ACTION_REMOVE;
gauthier's avatar
gauthier committed
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
          pdcp_config_req_asn1 (pdcp_p,
              enb_mod_idP,
              ue_mod_idP,
              frameP,
              enb_flagP, // not really required
              rlc_type,
              action,
              lc_id,
              mch_id,
              rb_id,
              0,
              0,
              0,
              security_modeP,
              kRRCenc_pP,
              kRRCint_pP,
              kUPenc_pP);
947
      }
948 949 950
  }

#ifdef Rel10
951 952 953 954 955 956 957
  if (pmch_InfoList_r9_pP != NULL) {
      for (i=0;i<pmch_InfoList_r9_pP->list.count;i++) {
          mbms_SessionInfoList_r9_p = &(pmch_InfoList_r9_pP->list.array[i]->mbms_SessionInfoList_r9);
          for (j=0;j<mbms_SessionInfoList_r9_p->list.count;j++) {
              MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
              lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
              mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
gauthier's avatar
gauthier committed
958 959

              // can set the mch_id = i
960
              if (enb_flagP) {
961
                rb_id =  (mch_id * maxSessionPerPMCH ) + lc_id + (maxDRB + 3)*MAX_MOBILES_PER_ENB; // 1
962 963
                if (pdcp_mbms_array_eNB[enb_mod_idP][mch_id][lc_id].instanciated_instance == TRUE)
                  action = CONFIG_ACTION_MBMS_MODIFY;
964
                else
965
                  action = CONFIG_ACTION_MBMS_ADD;
966
              } else {
gauthier's avatar
gauthier committed
967
                rb_id =  (mch_id * maxSessionPerPMCH ) + lc_id + (maxDRB + 3); // 15
968 969
                if (pdcp_mbms_array_ue[ue_mod_idP][mch_id][lc_id].instanciated_instance == TRUE)
                  action = CONFIG_ACTION_MBMS_MODIFY;
970
                else
971
                  action = CONFIG_ACTION_MBMS_ADD;
972 973
              }

gauthier's avatar
gauthier committed
974 975


976 977
              pdcp_config_req_asn1 (
                  NULL,  // unused for MBMS
gauthier's avatar
gauthier committed
978 979 980
                  enb_mod_idP,
                  ue_mod_idP,
                  frameP,
981
                  enb_flagP,
gauthier's avatar
gauthier committed
982
                  RLC_MODE_NONE,
gauthier's avatar
gauthier committed
983 984 985 986
                  action,
                  lc_id,
                  mch_id,
                  rb_id,
gauthier's avatar
gauthier committed
987 988 989 990 991 992 993
                  0,   // unused for MBMS
                  0,   // unused for MBMS
                  0,   // unused for MBMS
                  0,   // unused for MBMS
                  NULL,  // unused for MBMS
                  NULL,  // unused for MBMS
                  NULL); // unused for MBMS
gauthier's avatar
gauthier committed
994
          }
995 996 997 998 999 1000 1001 1002
      }
  }
#endif

  return 1;

}

gauthier's avatar
gauthier committed
1003
boolean_t pdcp_config_req_asn1 (pdcp_t   *pdcp_pP,
gauthier's avatar
gauthier committed
1004 1005
    module_id_t     enb_mod_idP,
    module_id_t     ue_mod_idP,
gauthier's avatar
gauthier committed
1006 1007 1008
    frame_t         frameP,
    eNB_flag_t      enb_flagP,
    rlc_mode_t      rlc_modeP,
1009 1010 1011
    config_action_t actionP,
    uint16_t        lc_idP,
    uint16_t        mch_idP,
gauthier's avatar
gauthier committed
1012
    rb_id_t         rb_idP,
1013 1014 1015 1016 1017 1018 1019
    uint8_t         rb_snP,
    uint8_t         rb_reportP,
    uint16_t        header_compression_profileP,
    uint8_t         security_modeP,
    uint8_t         *kRRCenc_pP,
    uint8_t         *kRRCint_pP,
    uint8_t         *kUPenc_pP)
1020
{
1021

gauthier's avatar
gauthier committed
1022
  switch (actionP) {
1023
  case CONFIG_ACTION_ADD:
gauthier's avatar
gauthier committed
1024
    DevAssert(pdcp_pP != NULL);
1025 1026
    pdcp_pP->instanciated_instance      = TRUE;
    pdcp_pP->is_ue                      = (enb_flagP == ENB_FLAG_NO) ? TRUE : FALSE;
gauthier's avatar
gauthier committed
1027
    pdcp_pP->lcid                       = lc_idP;
gauthier's avatar
gauthier committed
1028
    pdcp_pP->header_compression_profile = header_compression_profileP;
gauthier's avatar
gauthier committed
1029
    pdcp_pP->status_report              = rb_reportP;
gauthier's avatar
gauthier committed
1030 1031 1032 1033

    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
        pdcp_pP->seq_num_size = 7;
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
gauthier's avatar
gauthier committed
1034
        pdcp_pP->seq_num_size = 12;
gauthier's avatar
gauthier committed
1035
    } else {
gauthier's avatar
gauthier committed
1036
        pdcp_pP->seq_num_size = 5;
gauthier's avatar
gauthier committed
1037
    }
1038

gauthier's avatar
gauthier committed
1039 1040 1041 1042 1043
    pdcp_pP->rlc_mode                  = rlc_modeP;
    pdcp_pP->next_pdcp_tx_sn           = 0;
    pdcp_pP->next_pdcp_rx_sn           = 0;
    pdcp_pP->tx_hfn                    = 0;
    pdcp_pP->rx_hfn                    = 0;
gauthier's avatar
gauthier committed
1044
    pdcp_pP->last_submitted_pdcp_rx_sn = 4095;
gauthier's avatar
gauthier committed
1045
    pdcp_pP->first_missing_pdu         = -1;
gauthier's avatar
gauthier committed
1046

1047
    if (enb_flagP == ENB_FLAG_NO) {
1048
        LOG_I(PDCP, "[UE %d] Config request : Action ADD for eNB %d: Frame %d LCID %d (rb id %d) "
gauthier's avatar
gauthier committed
1049 1050 1051 1052
            "configured with SN size %d bits and RLC %s\n",
            ue_mod_idP, enb_mod_idP, frameP, lc_idP, rb_idP, pdcp_pP->seq_num_size,
            (rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
    } else {
1053
        LOG_I(PDCP, "[eNB %d] Config request : Action ADD for UE %d: Frame %d LCID %d (rb id %d) "
gauthier's avatar
gauthier committed
1054 1055 1056 1057
            "configured with SN size %d bits and RLC %s\n",
            enb_mod_idP, ue_mod_idP, frameP, lc_idP, rb_idP, pdcp_pP->seq_num_size,
            (rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
    }
1058

gauthier's avatar
gauthier committed
1059 1060 1061 1062
    /* Setup security */
    if (security_modeP != 0xff) {
        pdcp_config_set_security(pdcp_pP, enb_mod_idP, ue_mod_idP, frameP, enb_flagP, rb_idP, lc_idP, security_modeP, kRRCenc_pP, kRRCint_pP, kUPenc_pP);
    }
1063

1064
    LOG_D(PDCP, "[FRAME %5u][%s][PDCP][MOD %u/%u][RB %u]\n", frameP, (enb_flagP == ENB_FLAG_NO) ? "UE" : "eNB",  enb_mod_idP, ue_mod_idP, rb_idP);
gauthier's avatar
gauthier committed
1065
    break;
1066

1067
  case CONFIG_ACTION_MODIFY:
gauthier's avatar
gauthier committed
1068 1069 1070 1071
    DevAssert(pdcp_pP != NULL);
    pdcp_pP->header_compression_profile=header_compression_profileP;
    pdcp_pP->status_report = rb_reportP;
    pdcp_pP->rlc_mode = rlc_modeP;
1072

gauthier's avatar
gauthier committed
1073 1074 1075 1076
    /* Setup security */
    if (security_modeP != 0xff) {
        pdcp_config_set_security(pdcp_pP, enb_mod_idP, ue_mod_idP, frameP, enb_flagP, rb_idP, lc_idP, security_modeP, kRRCenc_pP, kRRCint_pP, kUPenc_pP);
    }
1077

gauthier's avatar
gauthier committed
1078 1079 1080 1081 1082 1083 1084
    if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
        pdcp_pP->seq_num_size = 7;
    } else if (rb_snP == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
        pdcp_pP->seq_num_size = 12;
    } else {
        pdcp_pP->seq_num_size=5;
    }
1085

1086
    if (enb_flagP == ENB_FLAG_NO) {
1087
        LOG_I(PDCP,"[UE %d] Config request : Action MODIFY for eNB %d: Frame %d LCID %d "
gauthier's avatar
gauthier committed
1088 1089 1090 1091
            "RB id %d configured with SN size %d and RLC %s \n",
            ue_mod_idP, enb_mod_idP, frameP, lc_idP, rb_idP, rb_snP,
            (rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
    } else {
1092
        LOG_I(PDCP,"[eNB %d] Config request : Action MODIFY for UE %d: Frame %d LCID %d "
gauthier's avatar
gauthier committed
1093 1094 1095 1096 1097
            "RB id %d configured with SN size %d and RLC %s \n",
            enb_mod_idP, ue_mod_idP, frameP, lc_idP, rb_idP, rb_snP,
            (rlc_modeP == 1) ? "AM" : (rlc_modeP == 2) ? "TM" : "UM");
    }
    break;
1098
  case CONFIG_ACTION_REMOVE:
gauthier's avatar
gauthier committed
1099
    DevAssert(pdcp_pP != NULL);
1100
    pdcp_pP->instanciated_instance = FALSE;
gauthier's avatar
gauthier committed
1101 1102 1103 1104 1105
    pdcp_pP->lcid = 0;
    pdcp_pP->header_compression_profile = 0x0;
    pdcp_pP->cipheringAlgorithm = 0xff;
    pdcp_pP->integrityProtAlgorithm = 0xff;
    pdcp_pP->status_report = 0;
gauthier's avatar
gauthier committed
1106
    pdcp_pP->rlc_mode = RLC_MODE_NONE;
gauthier's avatar
gauthier committed
1107 1108 1109 1110 1111 1112 1113 1114 1115
    pdcp_pP->next_pdcp_tx_sn = 0;
    pdcp_pP->next_pdcp_rx_sn = 0;
    pdcp_pP->tx_hfn = 0;
    pdcp_pP->rx_hfn = 0;
    pdcp_pP->last_submitted_pdcp_rx_sn = 4095;
    pdcp_pP->seq_num_size = 0;
    pdcp_pP->first_missing_pdu = -1;
    pdcp_pP->security_activated = 0;

1116 1117
    if (enb_flagP == ENB_FLAG_NO) {
        LOG_I(PDCP, "[UE %d] Config request : CONFIG_ACTION_REMOVE for eNB %d: Frame %d LCID %d RBID %d configured\n",
gauthier's avatar
gauthier committed
1118 1119
            ue_mod_idP, enb_mod_idP, frameP, lc_idP, rb_idP);
    } else {
1120
        LOG_I(PDCP, "[eNB %d] Config request : CONFIG_ACTION_REMOVE for UE %d: Frame %d LCID %d RBID %d configured\n",
gauthier's avatar
gauthier committed
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
            enb_mod_idP, ue_mod_idP, frameP, lc_idP, rb_idP);
    }
    /* Security keys */
    if (pdcp_pP->kUPenc != NULL) {
        free(pdcp_pP->kUPenc);
    }
    if (pdcp_pP->kRRCint != NULL) {
        free(pdcp_pP->kRRCint);
    }
    if (pdcp_pP->kRRCenc != NULL) {
        free(pdcp_pP->kRRCenc);
    }
    break;
gauthier's avatar
gauthier committed
1134
#if defined(Rel10)
1135 1136 1137
  case CONFIG_ACTION_MBMS_ADD:
  case CONFIG_ACTION_MBMS_MODIFY:
    if (enb_flagP == ENB_FLAG_NO) {
1138
        LOG_I(PDCP,"[UE %d] Config request for eNB %d: %s: Frame %d service_id/mch index %d, session_id/lcid %d, rbid %d configured\n",
1139
            ue_mod_idP, enb_mod_idP, actionP == CONFIG_ACTION_MBMS_ADD ? "CONFIG_ACTION_MBMS_ADD" : "CONFIG_ACTION_MBMS_MODIFY", frameP, mch_idP, lc_idP, rb_idP);
gauthier's avatar
gauthier committed
1140
    } else {
1141
        LOG_I(PDCP,"[eNB %d] Config request for UE %d: %s: Frame %d service_id/mch index %d, session_id/lcid %d, rbid %d configured\n",
1142
            enb_mod_idP, ue_mod_idP, actionP == CONFIG_ACTION_MBMS_ADD ? "CONFIG_ACTION_MBMS_ADD" : "CONFIG_ACTION_MBMS_MODIFY", frameP, mch_idP, lc_idP, rb_idP);
gauthier's avatar
gauthier committed
1143 1144
    }
    if (enb_flagP == 1) {
1145
        pdcp_mbms_array_eNB[enb_mod_idP][mch_idP][lc_idP].instanciated_instance = TRUE ;
gauthier's avatar
gauthier committed
1146
        pdcp_mbms_array_eNB[enb_mod_idP][mch_idP][lc_idP].rb_id = rb_idP;
gauthier's avatar
gauthier committed
1147
    } else {
1148 1149
        pdcp_mbms_array_ue[ue_mod_idP][mch_idP][lc_idP].instanciated_instance = TRUE ;
        pdcp_mbms_array_ue[ue_mod_idP][mch_idP][lc_idP].rb_id = rb_idP;
gauthier's avatar
gauthier committed
1150 1151
    }
    break;
gauthier's avatar
gauthier committed
1152
#endif
1153
  case CONFIG_ACTION_SET_SECURITY_MODE:
gauthier's avatar
gauthier committed
1154 1155 1156 1157 1158
    pdcp_config_set_security(pdcp_pP, enb_mod_idP, ue_mod_idP, frameP, enb_flagP, rb_idP, lc_idP, security_modeP, kRRCenc_pP, kRRCint_pP, kUPenc_pP);
    break;
  default:
    DevParam(actionP, enb_mod_idP, ue_mod_idP);
    break;
1159 1160 1161
  }
  return 0;
}
1162

gauthier's avatar
gauthier committed
1163 1164 1165 1166
void pdcp_config_set_security(pdcp_t    *pdcp_pP,
    module_id_t     enb_mod_idP,
    module_id_t     ue_mod_idP,
    frame_t    frameP,
1167
    eNB_flag_t enb_flagP,
gauthier's avatar
gauthier committed
1168
    rb_id_t    rb_idP,
1169 1170 1171 1172 1173
    uint16_t        lc_idP,
    uint8_t         security_modeP,
    uint8_t        *kRRCenc,
    uint8_t        *kRRCint,
    uint8_t        *kUPenc)
1174
{
gauthier's avatar
gauthier committed
1175
  DevAssert(pdcp_pP != NULL);
1176

gauthier's avatar
gauthier committed
1177 1178 1179
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
      pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
      pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
1180

1181 1182
      if (enb_flagP == ENB_FLAG_NO) {
          LOG_D(PDCP,"[UE %d][RB %02d] Set security mode : CONFIG_ACTION_SET_SECURITY_MODE: "
gauthier's avatar
gauthier committed
1183 1184 1185
              "Frame %d  cipheringAlgorithm %d integrityProtAlgorithm %d\n",
              ue_mod_idP, rb_idP, frameP, pdcp_pP->cipheringAlgorithm, pdcp_pP->integrityProtAlgorithm);
      } else {
1186
          LOG_D(PDCP,"[eNB %d][UE %d][RB %02d] Set security mode : CONFIG_ACTION_SET_SECURITY_MODE: "
gauthier's avatar
gauthier committed
1187 1188 1189 1190 1191 1192
              "Frame %d  cipheringAlgorithm %d integrityProtAlgorithm %d\n",
              enb_mod_idP, ue_mod_idP, rb_idP, frameP, pdcp_pP->cipheringAlgorithm, pdcp_pP->integrityProtAlgorithm);
      }
      pdcp_pP->kRRCenc = kRRCenc;
      pdcp_pP->kRRCint = kRRCint;
      pdcp_pP->kUPenc  = kUPenc;
1193

gauthier's avatar
gauthier committed
1194 1195
      /* Activate security */
      pdcp_pP->security_activated = 1;
1196
  } else {
gauthier's avatar
gauthier committed
1197
      LOG_E(PDCP,"[%s %d] bad security mode %d", security_modeP);
1198
  }
1199 1200