pdcp.c 92.6 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23

/*! \file pdcp.c
 * \brief pdcp interface with RLC
24
 * \author Navid Nikaein and Lionel GAUTHIER
25
 * \date 2009-2012
26
 * \email navid.nikaein@eurecom.fr
27 28 29 30
 * \version 1.0
 */

#define PDCP_C
31

32 33
#define MBMS_MULTICAST_OUT

34
#include "assertions.h"
35
#include "hashtable.h"
36 37 38 39
#include "pdcp.h"
#include "pdcp_util.h"
#include "pdcp_sequence_manager.h"
#include "LAYER2/RLC/rlc.h"
40 41
#include "LAYER2/MAC/mac_extern.h"
#include "RRC/LTE/rrc_proto.h"
42 43 44
#include "pdcp_primitives.h"
#include "OCG.h"
#include "OCG_extern.h"
45
#include "otg_rx.h"
46
#include "common/utils/LOG/log.h"
47 48
#include <inttypes.h>
#include "platform_constants.h"
frtabu's avatar
frtabu committed
49
#include "nfapi/oai_integration/vendor_ext.h"
50
#include "common/utils/LOG/vcd_signal_dumper.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
51
#include "msc.h"
52
#include "common/ngran_types.h"
Y_Tomita's avatar
Y_Tomita committed
53
#include "targets/COMMON/openairinterface5g_limits.h"
frtabu's avatar
frtabu committed
54
#include "targets/RT/USER/lte-softmodem.h"
55
#include "SIMULATION/ETH_TRANSPORT/proto.h"
56
#include "UTIL/OSA/osa_defs.h"
57
#include "openair2/RRC/NAS/nas_config.h"
58 59
#include "intertask_interface.h"
#include "openair3/S1AP/s1ap_eNB.h"
60

61

Lionel Gauthier's avatar
 
Lionel Gauthier committed
62
#  include "gtpv1u_eNB_task.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
63
#  include "gtpv1u.h"
Lionel Gauthier's avatar
 
Lionel Gauthier committed
64

65
#include "ENB_APP/enb_config.h"
frtabu's avatar
frtabu committed
66

67

68

69
extern int otg_enabled;
70
extern uint8_t nfapi_mode;
71 72
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
73
hash_table_t  *pdcp_coll_p = NULL;
74

75
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
76 77 78 79 80 81 82 83
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <netinet/ip.h>
  #include <netinet/udp.h>
  #include <unistd.h>

  static int mbms_socket = -1;
84 85
#endif

86 87

/* pdcp module parameters and related functions*/
frtabu's avatar
frtabu committed
88
static pdcp_params_t pdcp_params= {0,NULL};
89 90 91 92

uint64_t get_pdcp_optmask(void) {
  return pdcp_params.optmask;
}
93 94 95 96 97 98 99 100
//-----------------------------------------------------------------------------
/*
 * 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()
 */
101
boolean_t pdcp_data_req(
frtabu's avatar
frtabu committed
102
  protocol_ctxt_t  *ctxt_pP,
103 104 105 106 107 108
  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,
frtabu's avatar
frtabu committed
109 110 111
  const pdcp_transmission_mode_t modeP,
  const uint32_t *const sourceL2Id,
  const uint32_t *const destinationL2Id
112 113
)
//-----------------------------------------------------------------------------
114
{
115
  pdcp_t            *pdcp_p          = NULL;
116 117 118 119 120
  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;
121 122
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
123
  boolean_t          ret             = TRUE;
124 125
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
126 127
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
128
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
129
  CHECK_CTXT_ARGS(ctxt_pP);
Cedric Roux's avatar
Cedric Roux committed
130
#if T_TRACER
frtabu's avatar
frtabu committed
131

Cedric Roux's avatar
Cedric Roux committed
132 133
  if (ctxt_pP->enb_flag != ENB_FLAG_NO)
    T(T_ENB_PDCP_DL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
frtabu's avatar
frtabu committed
134

Cedric Roux's avatar
Cedric Roux committed
135 136
#endif

137 138 139 140 141 142 143 144
  if (sdu_buffer_sizeP == 0) {
    LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
    return FALSE;
  }

  /*
   * XXX MAX_IP_PACKET_SIZE is 4096, shouldn't this be MAX SDU size, which is 8188 bytes?
   */
145
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
frtabu's avatar
frtabu committed
146
              sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
147

148
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
laurent's avatar
laurent committed
149
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
150
  } else {
151
    if (srb_flagP) {
laurent's avatar
laurent committed
152
      AssertError (rb_idP < 3, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
153
    } else {
laurent's avatar
laurent committed
154
      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
155
    }
156
  }
157

158
  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
frtabu's avatar
frtabu committed
159
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
160

161 162
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
laurent's avatar
laurent committed
163
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %ld Ignoring SDU...\n",
frtabu's avatar
frtabu committed
164 165
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
166
      ctxt_pP->configured=FALSE;
167
      return FALSE;
168
    }
frtabu's avatar
frtabu committed
169
  } else {
170
    // instance for a given RB is configured
171
    ctxt_pP->configured=TRUE;
172
  }
173

174
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
175 176 177 178
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
179

180
  // PDCP transparent mode for MBMS traffic
181

182
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
183
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
184
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
185 186 187

    if (pdcp_pdu_p != NULL) {
      memcpy(&pdcp_pdu_p->data[0], sdu_buffer_pP, sdu_buffer_sizeP);
188

189 190 191 192
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
        rlc_util_print_hex_octets(PDCP,
                                  (unsigned char *)&pdcp_pdu_p->data[0],
                                  sdu_buffer_sizeP);
laurent's avatar
laurent committed
193
        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %ld \n", srb_flagP, rb_idP);
194
      }
frtabu's avatar
frtabu committed
195 196 197

      rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)?MBMS_FLAG_NO:MBMS_FLAG_YES, rb_idP, muiP,
                   confirmP, sdu_buffer_sizeP, pdcp_pdu_p,NULL,NULL);
198 199
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
frtabu's avatar
frtabu committed
200
      LOG_E(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
201
            PROTOCOL_CTXT_ARGS(ctxt_pP));
202
    }
203
  } else {
204 205 206 207 208 209 210 211 212 213
    // calculate the pdcp header and trailer size
    if (srb_flagP) {
      pdcp_header_len = PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE;
      pdcp_tailer_len = PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE;
    } else {
      pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
      pdcp_tailer_len = 0;
    }

    pdcp_pdu_size = sdu_buffer_sizeP + pdcp_header_len + pdcp_tailer_len;
214 215
    LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT"Data request notification  pdu size %d (header%d, trailer%d)\n",
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
216 217 218 219 220 221
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
222
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
223 224

    if (pdcp_pdu_p != NULL) {
225
      /*
226 227 228
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
229
       */
230 231 232 233 234 235
      if (srb_flagP) { // this Control plane PDCP Data PDU
        pdcp_control_plane_data_pdu_header pdu_header;
        pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p);
        current_sn = pdu_header.sn;
        memset(&pdu_header.mac_i[0],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
        memset(&pdcp_pdu_p->data[sdu_buffer_sizeP + pdcp_header_len],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE);
236

frtabu's avatar
frtabu committed
237
        if (pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == FALSE) {
238 239
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
240

241
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
242 243 244 245
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
246

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

frtabu's avatar
frtabu committed
256
        if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == FALSE) {
257 258
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p));
259

260
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
261 262 263 264
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
265

266
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
267 268
          return FALSE;
        }
269
      }
270

271
      /*
272
       * Validate incoming sequence number, there might be a problem with PDCP initialization
273
       */
274
      if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
Cedric Roux's avatar
Cedric Roux committed
275
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Generated sequence number (%"PRIu16") is greater than a sequence number could ever be!\n"\
276 277 278
              "There must be a problem with PDCP initialization, ignoring this PDU...\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              current_sn);
279
        free_mem_block(pdcp_pdu_p, __func__);
280

281
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
282 283 284 285
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
286

287
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
288 289 290 291 292 293 294 295 296 297
        return FALSE;
      }

      LOG_D(PDCP, "Sequence number %d is assigned to current PDU\n", current_sn);
      /* Then append data... */
      memcpy(&pdcp_pdu_p->data[pdcp_header_len], sdu_buffer_pP, sdu_buffer_sizeP);

      //For control plane data that are not integrity protected,
      // the MAC-I field is still present and should be padded with padding bits set to 0.
      // NOTE: user-plane data are never integrity protected
298
      for (i=0; i<pdcp_tailer_len; i++) {
299
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
300
      }
301 302 303 304

      if ((pdcp_p->security_activated != 0) &&
          (((pdcp_p->cipheringAlgorithm) != 0) ||
           ((pdcp_p->integrityProtAlgorithm) != 0))) {
305
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
306 307 308 309
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
310 311 312 313

        pdcp_apply_security(ctxt_pP,
                            pdcp_p,
                            srb_flagP,
314
                            rb_idP % LTE_maxDRB,
315 316 317 318 319
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);

320 321 322 323 324
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
325 326 327 328 329 330 331 332 333 334
      }

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

335 336 337 338 339
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
      }
340

laurent's avatar
laurent committed
341
      LOG_E(PDCP,  "[FRAME %5u][%s][PDCP][MOD %u][RB %ld] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
342 343 344 345
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->module_id,
            rb_idP);
346
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
347 348 349 350 351 352 353
      return FALSE;
    }

    /*
     * Ask sublayer to transmit data and check return value
     * to see if RLC succeeded
     */
354
    LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
laurent's avatar
laurent committed
355
                "[MSG] PDCP DL %s PDU on rb_id %ld\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
356

frtabu's avatar
frtabu committed
357
    if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1)) {
laurent's avatar
laurent committed
358 359
      LOG_D(PDCP, "pdcp data req on drb %ld, size %d, rnti %x, node_type %d \n",
            rb_idP, pdcp_pdu_size, ctxt_pP->rnti, RC.rrc ? RC.rrc[ctxt_pP->module_id]->node_type: -1);
360

361 362 363 364 365 366 367 368 369 370
      // The check on nos1 is done only for the use case of LTE stack running over 5g-nr PHY. This should be changed
      // before future merge of develop with develop-nr and instead of a check of IS_SOFTMODEM_NOS1, we should use a check
      // with a new execution option capturing the nr-ip-over-LTE-stack use case.
      ngran_node_t node_type;
      if (IS_SOFTMODEM_NOS1)
    	  node_type = ngran_gNB;
      else
    	  node_type = RC.rrc[ctxt_pP->module_id]->node_type;

      if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_DU(node_type)) { //RC.rrc[ctxt_pP->module_id]->node_type
371 372
        LOG_E(PDCP, "Can't be DU, bad node type %d \n", RC.rrc[ctxt_pP->module_id]->node_type);
        ret=FALSE;
frtabu's avatar
frtabu committed
373 374 375 376
      } else {
        rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP,
                     confirmP, pdcp_pdu_size, pdcp_pdu_p,sourceL2Id,
                     destinationL2Id);
laurent's avatar
laurent committed
377
	ret=FALSE;
frtabu's avatar
frtabu committed
378 379 380 381 382
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;
383

frtabu's avatar
frtabu committed
384 385 386
          case RLC_OP_STATUS_BAD_PARAMETER:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
            break;
387

frtabu's avatar
frtabu committed
388 389 390
          case RLC_OP_STATUS_INTERNAL_ERROR:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
            break;
391

frtabu's avatar
frtabu committed
392 393 394
          case RLC_OP_STATUS_OUT_OF_RESSOURCES:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
            break;
395

frtabu's avatar
frtabu committed
396 397 398 399 400 401 402
          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);
            break;
        } // switch case
      } /* end if node_type is not DU */
    } else { // SRB
      if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) {
403 404 405 406 407 408
        // DL transfer
        MessageDef                            *message_p;
        // Note: the acyual task must be TASK_PDCP_ENB, but this task is not created
        message_p = itti_alloc_new_message (TASK_PDCP_ENB, F1AP_DL_RRC_MESSAGE);
        F1AP_DL_RRC_MESSAGE (message_p).rrc_container =  &pdcp_pdu_p->data[0] ;
        F1AP_DL_RRC_MESSAGE (message_p).rrc_container_length = pdcp_pdu_size;
frtabu's avatar
frtabu committed
409
        F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id  = 0;
410 411 412 413 414 415 416 417 418 419
        F1AP_DL_RRC_MESSAGE (message_p).gNB_DU_ue_id  = 0;
        F1AP_DL_RRC_MESSAGE (message_p).old_gNB_DU_ue_id  = 0xFFFFFFFF; // unknown
        F1AP_DL_RRC_MESSAGE (message_p).rnti = ctxt_pP->rnti;
        F1AP_DL_RRC_MESSAGE (message_p).srb_id = rb_idP;
        F1AP_DL_RRC_MESSAGE (message_p).execute_duplication      = 1;
        F1AP_DL_RRC_MESSAGE (message_p).RAT_frequency_priority_information.en_dc      = 0;
        itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p);
        //CU_send_DL_RRC_MESSAGE_TRANSFER(ctxt_pP->module_id, message_p);
        LOG_I(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n");
        ret=TRUE;
frtabu's avatar
frtabu committed
420
      } else {
421 422 423 424 425 426 427 428 429 430
        rlc_status = rlc_data_req(ctxt_pP
                                  , srb_flagP
                                  , MBMS_FLAG_NO
                                  , rb_idP
                                  , muiP
                                  , confirmP
                                  , pdcp_pdu_size
                                  , pdcp_pdu_p
                                  ,NULL
                                  ,NULL
frtabu's avatar
frtabu committed
431 432
                                 );

433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;

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

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

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

          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);
            ret= FALSE;
            break;
        } // switch case
      }
460
    }
461
  }
462

463
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
464 465 466 467
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
468

469 470 471 472 473
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */

frtabu's avatar
frtabu committed
474
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
475 476 477 478
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
      break;
  }

479 480
  //LOG_I(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, rb_idP+rb_offset, current_sn);
  Pdcp_stats_tx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
481
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
482
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
483
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
484
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;
485
  Pdcp_stats_tx_aiat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+= (pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
486
  Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+= (pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
487
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
488
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
489
  return ret;
490 491
}

492

493 494 495
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
frtabu's avatar
frtabu committed
496
  const protocol_ctxt_t *const ctxt_pP,
497 498 499 500
  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,
frtabu's avatar
frtabu committed
501
  mem_block_t *const sdu_buffer_pP
502 503
)
//-----------------------------------------------------------------------------
504
{
505
  pdcp_t      *pdcp_p          = NULL;
506 507
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
508
  pdcp_sn_t    sequence_number = 0;
509
  volatile sdu_size_t   payload_offset  = 0;
510
  rb_id_t      rb_id            = rb_idP;
511
  boolean_t    packet_forwarded = FALSE;
512 513
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
514
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
515
  uint16_t     pdcp_uid=0;
516

517
  MessageDef  *message_p        = NULL;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
518
  uint8_t     *gtpu_buffer_p    = NULL;
519 520 521
  uint32_t    rx_hfn_for_count;
  int         pdcp_sn_for_count;
  int         security_ok;
522
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
523
  LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
laurent's avatar
laurent committed
524
              "[MSG] PDCP UL %s PDU on rb_id %ld\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
Cedric Roux's avatar
Cedric Roux committed
525

526
  if (MBMS_flagP) {
527
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE,
laurent's avatar
laurent committed
528
                 "RB id is too high (%ld/%d) %u rnti %x!\n",
529 530 531 532
                 rb_idP,
                 NB_RB_MBMS_MAX,
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
533 534

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
535
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
laurent's avatar
laurent committed
536
            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
537 538 539 540 541
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
542
    } else {
543
      LOG_D(PDCP, "Data indication notification for PDCP entity from UE %x to eNB %u "
laurent's avatar
laurent committed
544
            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
545
            ctxt_pP->rnti,
546
            ctxt_pP->module_id,
547 548 549
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
550 551
    }
  } else {
552
    rb_id = rb_idP % LTE_maxDRB;
laurent's avatar
laurent committed
553
    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u UE %x!\n",
554
                 rb_id,
555
                 LTE_maxDRB,
556 557
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
laurent's avatar
laurent committed
558
    AssertError (rb_id > 0, return FALSE, "RB id is too low (%ld/%d) %u UE %x!\n",
559
                 rb_id,
560
                 LTE_maxDRB,
561 562 563
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_id, srb_flagP);
frtabu's avatar
frtabu committed
564
    h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
565 566 567 568 569 570

    if (h_rc != HASH_TABLE_OK) {
      LOG_W(PDCP,
            PROTOCOL_CTXT_FMT"Could not get PDCP instance key 0x%"PRIx64"\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            key);
571
      free_mem_block(sdu_buffer_pP, __func__);
572
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
573
      return FALSE;
574
    }
575
  }
576

577

578
  if (sdu_buffer_sizeP == 0) {
579 580
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
581
  }
582

583 584 585 586 587
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
  }
588 589

  /*
590 591
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
592
   */
593

594
  if (MBMS_flagP == 0 ) {
595 596 597
    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;
frtabu's avatar
frtabu committed
598
      sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char *)sdu_buffer_pP->data);
599 600
    } else { // DRB
      pdcp_tailer_len = 0;
601

602
      if (pdcp_p->seq_num_size == 7) {
603
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_SHORT_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
604
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char *)sdu_buffer_pP->data);
605
      } else if (pdcp_p->seq_num_size == 12) {
606
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
607
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char *)sdu_buffer_pP->data);
608
      } else {
609
        //sequence_number = 4095;
610 611 612 613
        LOG_E(PDCP,
              PROTOCOL_PDCP_CTXT_FMT"wrong sequence number  (%d) for this pdcp entity \n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
              pdcp_p->seq_num_size);
614
        exit(1);
615
      }
616

617 618
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
619

620 621 622 623
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
624 625 626 627
      LOG_W(PDCP,
            PROTOCOL_PDCP_CTXT_FMT"Incoming (from RLC) SDU is short of size (size:%d)! Ignoring...\n",
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
            sdu_buffer_sizeP);
628
      free_mem_block(sdu_buffer_pP, __func__);
629

630 631 632 633 634
      if (ctxt_pP->enb_flag) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
      }
635

636
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
637 638 639
      return FALSE;
    }

640
#if 0
641

642
    /* Removed by Cedric */
643
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
644
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
645
      /* if (dc == PDCP_DATA_PDU )
646 647 648
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
649
    } else {
frtabu's avatar
frtabu committed
650 651
      Pdcp_stats_rx_outoforder[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
      LOG_E(PDCP,
652 653 654
            PROTOCOL_PDCP_CTXT_FMT"Incoming PDU has an unexpected sequence number (%d), RX window synchronisation have probably been lost!\n",
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
            sequence_number);
655
      /*
656 657
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
658
       */
bruno mongazon's avatar
bruno mongazon committed
659 660
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
661 662
      return FALSE;
    }
663

664
#endif
665 666 667

    // SRB1/2: control-plane data
    if (srb_flagP) {
668 669 670 671 672 673 674 675
      /* process as described in 36.323 5.1.2.2 */
      if (sequence_number < pdcp_p->next_pdcp_rx_sn) {
        rx_hfn_for_count  = pdcp_p->rx_hfn + 1;
        pdcp_sn_for_count = sequence_number;
      } else {
        rx_hfn_for_count  = pdcp_p->rx_hfn;
        pdcp_sn_for_count = sequence_number;
      }
676

677
      if (pdcp_p->security_activated == 1) {
678 679 680 681 682
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
        }
683

684
        security_ok = pdcp_validate_security(ctxt_pP,
frtabu's avatar
frtabu committed
685 686 687 688
                                             pdcp_p,
                                             srb_flagP,
                                             rb_idP,
                                             pdcp_header_len,
689 690
                                             rx_hfn_for_count,
                                             pdcp_sn_for_count,
frtabu's avatar
frtabu committed
691
                                             sdu_buffer_pP->data,
692
                                             sdu_buffer_sizeP - pdcp_tailer_len) == 0;
693

694 695 696 697 698
        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
        }
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
      } else {
        security_ok = 1;
      }

      if (security_ok == 0) {
        LOG_W(PDCP,
              PROTOCOL_PDCP_CTXT_FMT"security not validated for incoming PDCP SRB PDU\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
        LOG_W(PDCP, "Ignoring PDU...\n");
        free_mem_block(sdu_buffer_pP, __func__);
        /* TODO: indicate integrity verification failure to upper layer */
        return FALSE;
      }

      if (sequence_number < pdcp_p->next_pdcp_rx_sn)
        pdcp_p->rx_hfn++;

      pdcp_p->next_pdcp_rx_sn = sequence_number + 1;

      if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
        pdcp_p->next_pdcp_rx_sn = 0;
        pdcp_p->rx_hfn++;
721
      }
722

frtabu's avatar
frtabu committed
723 724 725 726 727
      rrc_data_ind(ctxt_pP,
                   rb_id,
                   sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
                   (uint8_t *)&sdu_buffer_pP->data[pdcp_header_len]);
      free_mem_block(sdu_buffer_pP, __func__);
728

729
      // free_mem_block(new_sdu, __func__);
730 731 732 733 734
      if (ctxt_pP->enb_flag) {
        stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
      } else {
        stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
      }
735

736
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
737
      return TRUE;
738
    } /* if (srb_flagP) */
739 740 741 742

    /*
     * DRBs
     */
743
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
744

745
    switch (pdcp_p->rlc_mode) {
frtabu's avatar
frtabu committed
746 747 748
      case RLC_MODE_AM: {
        /* process as described in 36.323 5.1.2.1.2 */
        int reordering_window;
749

frtabu's avatar
frtabu committed
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
        if (pdcp_p->seq_num_size == 7)
          reordering_window = REORDERING_WINDOW_SN_7BIT;
        else
          reordering_window = REORDERING_WINDOW_SN_12BIT;

        if (sequence_number - pdcp_p->last_submitted_pdcp_rx_sn > reordering_window ||
            (pdcp_p->last_submitted_pdcp_rx_sn - sequence_number >= 0 &&
             pdcp_p->last_submitted_pdcp_rx_sn - sequence_number < reordering_window)) {
          /* TODO: specs say to decipher and do header decompression */
          LOG_W(PDCP,
                PROTOCOL_PDCP_CTXT_FMT"discard PDU, out of\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          LOG_W(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer_pP, __func__);
          /* TODO: indicate integrity verification failure to upper layer */
          return FALSE;
        } else if (pdcp_p->next_pdcp_rx_sn - sequence_number > reordering_window) {
767
          pdcp_p->rx_hfn++;
frtabu's avatar
frtabu committed
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
          rx_hfn_for_count  = pdcp_p->rx_hfn;
          pdcp_sn_for_count = sequence_number;
          pdcp_p->next_pdcp_rx_sn = sequence_number + 1;
        } else if (sequence_number - pdcp_p->next_pdcp_rx_sn >= reordering_window) {
          rx_hfn_for_count  = pdcp_p->rx_hfn - 1;
          pdcp_sn_for_count = sequence_number;
        } else if (sequence_number >= pdcp_p->next_pdcp_rx_sn) {
          rx_hfn_for_count  = pdcp_p->rx_hfn;
          pdcp_sn_for_count = sequence_number;
          pdcp_p->next_pdcp_rx_sn = sequence_number + 1;

          if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
            pdcp_p->next_pdcp_rx_sn = 0;
            pdcp_p->rx_hfn++;
          }
        } else { /* sequence_number < pdcp_p->next_pdcp_rx_sn */
          rx_hfn_for_count  = pdcp_p->rx_hfn;
          pdcp_sn_for_count = sequence_number;
786
        }
787

frtabu's avatar
frtabu committed
788 789 790 791 792 793
        if (pdcp_p->security_activated == 1) {
          if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
            start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
          } else {
            start_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
          }
794

frtabu's avatar
frtabu committed
795 796 797 798 799 800 801 802 803
          security_ok = pdcp_validate_security(ctxt_pP,
                                               pdcp_p,
                                               srb_flagP,
                                               rb_idP,
                                               pdcp_header_len,
                                               rx_hfn_for_count,
                                               pdcp_sn_for_count,
                                               sdu_buffer_pP->data,
                                               sdu_buffer_sizeP - pdcp_tailer_len) == 0;
804

frtabu's avatar
frtabu committed
805 806 807 808 809 810 811 812
          if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
          }
        } else {
          security_ok = 1;
        }
813

frtabu's avatar
frtabu committed
814 815 816 817 818 819 820 821 822
        if (security_ok == 0) {
          LOG_W(PDCP,
                PROTOCOL_PDCP_CTXT_FMT"security not validated for incoming PDPC DRB RLC/AM PDU\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          LOG_W(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer_pP, __func__);
          /* TODO: indicate integrity verification failure to upper layer */
          return FALSE;
        }
823

frtabu's avatar
frtabu committed
824 825 826 827 828 829 830 831 832 833 834 835 836 837
        /* TODO: specs say we have to store this PDU in a list and then deliver
         *       stored packets to upper layers according to a well defined
         *       procedure. The code below that deals with delivery is today
         *       too complex to do this properly, so we only send the current
         *       received packet. This is not correct and has to be fixed
         *       some day.
         *       In the meantime, let's pretend the last submitted PDCP SDU
         *       is the current one.
         * TODO: we also have to deal with re-establishment PDU (control PDUs)
         *       that contain no SDU.
         */
        pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
        break;
        } /* case RLC_MODE_AM */
838

frtabu's avatar
frtabu committed
839
      case RLC_MODE_UM:
840

frtabu's avatar
frtabu committed
841 842 843 844
        /* process as described in 36.323 5.1.2.1.3 */
        if (sequence_number < pdcp_p->next_pdcp_rx_sn) {
          pdcp_p->rx_hfn++;
        }
845

frtabu's avatar
frtabu committed
846 847 848
        rx_hfn_for_count  = pdcp_p->rx_hfn;
        pdcp_sn_for_count = sequence_number;
        pdcp_p->next_pdcp_rx_sn = sequence_number + 1;
849

frtabu's avatar
frtabu committed
850 851 852
        if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
          pdcp_p->next_pdcp_rx_sn = 0;
          pdcp_p->rx_hfn++;
853 854
        }

frtabu's avatar
frtabu committed
855 856 857 858 859 860
        if (pdcp_p->security_activated == 1) {
          if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
            start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
          } else {
            start_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
          }
861

frtabu's avatar
frtabu committed
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
          security_ok = pdcp_validate_security(ctxt_pP,
                                               pdcp_p,
                                               srb_flagP,
                                               rb_idP,
                                               pdcp_header_len,
                                               rx_hfn_for_count,
                                               pdcp_sn_for_count,
                                               sdu_buffer_pP->data,
                                               sdu_buffer_sizeP - pdcp_tailer_len) == 0;

          if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].validate_security);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].validate_security);
          }
877
        } else {
frtabu's avatar
frtabu committed
878
          security_ok = 1;
879
        }
880

frtabu's avatar
frtabu committed
881 882 883 884 885 886 887 888 889
        if (security_ok == 0) {
          LOG_W(PDCP,
                PROTOCOL_PDCP_CTXT_FMT"security not validated for incoming PDPC DRB RLC/UM PDU\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          LOG_W(PDCP, "Ignoring PDU...\n");
          free_mem_block(sdu_buffer_pP, __func__);
          /* TODO: indicate integrity verification failure to upper layer */
          return FALSE;
        }
890

frtabu's avatar
frtabu committed
891
        break;
892

frtabu's avatar
frtabu committed
893 894 895
      default:
        LOG_E(PDCP, "bad RLC mode, cannot happen.\n");
        exit(1);
896 897
    } /* switch (pdcp_p->rlc_mode) */
  } else { /* MBMS_flagP == 0 */
898
    payload_offset=0;
899
  }
900 901 902

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

905 906 907 908 909
    if (ctxt_pP->enb_flag) {
      stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
    } else {
      stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
    }
910

911
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
912 913 914
    return TRUE;
  }

915 916 917 918 919 920 921
  // 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)
   */
922

923
  if (LINK_ENB_PDCP_TO_GTPV1U) {
frtabu's avatar
frtabu committed
924
    if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
laurent's avatar
laurent committed
925
      LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %ld len %u\n",
926 927 928
            ctxt_pP->rnti,
            rb_id + 4,
            sdu_buffer_sizeP - payload_offset );
frtabu's avatar
frtabu committed
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
      MSC_LOG_TX_MESSAGE(
        MSC_PDCP_ENB,
        MSC_GTPU_ENB,
        NULL,0,
        "0 GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %u len %u",
        ctxt_pP->rnti,
        rb_id + 4,
        sdu_buffer_sizeP - payload_offset);
      //LOG_T(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
      gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
                                  sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
      AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
      memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
      message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
      AssertFatal(message_p != NULL, "OUT OF MEMORY");
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer       = gtpu_buffer_p;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length       = sdu_buffer_sizeP - payload_offset;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset       = GTPU_HEADER_OVERHEAD_MAX;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
      itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
      packet_forwarded = TRUE;
    }
952
  } else {
frtabu's avatar
frtabu committed
953
    packet_forwarded = FALSE;
954
  }
955

956
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
957

958
  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
959 960 961 962 963 964
   // struct iphdr   *ip_header = (struct iphdr *)&sdu_buffer_pP->data[payload_offset];
   // struct udphdr *udp_header = (struct udphdr *)&sdu_buffer_pP->data[payload_offset + sizeof(struct iphdr)];
   // struct sockaddr_in dest_addr;
   // dest_addr.sin_family      = AF_INET;
   // dest_addr.sin_port        = udp_header->dest;
   // dest_addr.sin_addr.s_addr = ip_header->daddr;
965

966 967
   // sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
   // //packet_forwarded = TRUE;
968

969
  }
frtabu's avatar
frtabu committed
970

971 972
#endif

973
  if (FALSE == packet_forwarded) {
974
    notifiedFIFO_elt_t * new_sdu_p = newNotifiedFIFO_elt(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), 0, NULL, NULL);
975

976
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
977 978 979 980 981 982
        pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
      }

      /*
       * Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
       */
983 984 985
      pdcp_data_ind_header_t * pdcpHead=(pdcp_data_ind_header_t *)NotifiedFifoData(new_sdu_p);
      memset(pdcpHead, 0, sizeof (pdcp_data_ind_header_t));
      pdcpHead->data_size = sdu_buffer_sizeP - payload_offset;
986
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
987 988 989 990

      // Here there is no virtualization possible
      // set ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst for IP layer here
      if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
991
        pdcpHead->rb_id = rb_id;
frtabu's avatar
frtabu committed
992

993
        if (EPC_MODE_ENABLED) {
frtabu's avatar
frtabu committed
994 995 996 997 998
          /* for the UE compiled in S1 mode, we need 1 here
           * for the UE compiled in noS1 mode, we need 0
           * TODO: be sure of this
           */
          if (NFAPI_MODE == NFAPI_UE_STUB_PNF ) {
999
#ifdef UESIM_EXPANSION
1000

tomita.y's avatar
tomita.y committed
1001
            if (UE_NAS_USE_TUN) {
1002
              pdcpHead->inst  = ctxt_pP->module_id;
tomita.y's avatar
tomita.y committed
1003
            } else {
1004
              pdcpHead->inst  = 0;
tomita.y's avatar
tomita.y committed
1005
            }
1006

1007
#else
1008
            pdcpHead->inst  = ctxt_pP->module_id;
1009
#endif
frtabu's avatar
frtabu committed
1010 1011
          } else {  // nfapi_mode
            if (UE_NAS_USE_TUN) {
1012
              pdcpHead->inst  = ctxt_pP->module_id;
frtabu's avatar
frtabu committed
1013
            } else {
1014
              pdcpHead->inst  = 1;
frtabu's avatar
frtabu committed
1015
            }
frtabu's avatar
frtabu committed
1016
          } // nfapi_mode
1017
        }
1018
      } else {
1019 1020
        pdcpHead->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
        pdcpHead->inst  = ctxt_pP->module_id;
1021
      }
1022

1023
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
frtabu's avatar
frtabu committed
1024
        static uint32_t pdcp_inst = 0;
1025 1026
        pdcpHead->inst = pdcp_inst++;
        LOG_D(PDCP, "inst=%d size=%d\n", pdcpHead->inst, pdcpHead->data_size);
1027
      }
1028

1029
      memcpy(pdcpHead+1,
1030
             &sdu_buffer_pP->data[payload_offset],
1031
             sdu_buffer_sizeP - payload_offset);
1032 1033 1034 1035
      if( LOG_DEBUGFLAG(DEBUG_PDCP) )
	log_dump(PDCP, pdcpHead+1, min(sdu_buffer_sizeP - payload_offset,30) , LOG_DUMP_CHAR,
	         "Printing first bytes of PDCP SDU before adding it to the list: \n");
      pushNotifiedFIFO(&pdcp_sdu_list, new_sdu_p); 
1036

frtabu's avatar
frtabu committed
1037 1038 1039 1040 1041 1042
    /* 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 + (int)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);
1043
  }
1044

1045
  /* Update PDCP statistics */
frtabu's avatar
frtabu committed
1046 1047
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti ) {
1048
      break;
1049
    }
1050 1051
  }

1052
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1053
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1054
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1055
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1056

1057
  Pdcp_stats_rx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=sequence_number;
1058
  Pdcp_stats_rx_aiat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+= (pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
1059
  Pdcp_stats_rx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(pdcp_enb[ctxt_pP->module_id].sfn - Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]);
1060
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
1061
  free_mem_block(sdu_buffer_pP, __func__);
1062

1063 1064 1065 1066 1067
  if (ctxt_pP->enb_flag) {
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_ind);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_ind);
  }
1068

1069
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
1070 1071 1072
  return TRUE;
}

frtabu's avatar
frtabu committed
1073
void pdcp_update_stats(const protocol_ctxt_t *const  ctxt_pP) {
1074
  uint16_t           pdcp_uid = 0;
Navid Nikaein's avatar
Navid Nikaein committed
1075
  uint8_t            rb_id     = 0;
1076

frtabu's avatar
frtabu committed
1077 1078 1079
  // these stats are measured for both eNB and UE on per seond basis
  for (rb_id =0; rb_id < NB_RB_MAX; rb_id ++) {
    for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
1080 1081
      //printf("frame %d and subframe %d \n", pdcp_enb[ctxt_pP->module_id].frame, pdcp_enb[ctxt_pP->module_id].subframe);
      // tx stats
Raymond Knopp's avatar
Raymond Knopp committed
1082
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0) {
        // unit: bit/s
        Pdcp_stats_tx_throughput_w[ctxt_pP->module_id][pdcp_uid][rb_id]=Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]*8;
        Pdcp_stats_tx_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
        Pdcp_stats_tx_bytes_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];

        if (Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id] > 0) {
          Pdcp_stats_tx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]=(Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]/Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]);
        } else {
          Pdcp_stats_tx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
        }
1094

frtabu's avatar
frtabu committed
1095 1096 1097 1098
        // reset the tmp vars
        Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
        Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
        Pdcp_stats_tx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
1099
      }
frtabu's avatar
frtabu committed
1100

Raymond Knopp's avatar
Raymond Knopp committed
1101
      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
          pdcp_enb[ctxt_pP->module_id].sfn % Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] == 0) {
        // rx stats
        Pdcp_stats_rx_goodput_w[ctxt_pP->module_id][pdcp_uid][rb_id]=Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]*8;
        Pdcp_stats_rx_w[ctxt_pP->module_id][pdcp_uid][rb_id]=   Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];
        Pdcp_stats_rx_bytes_w[ctxt_pP->module_id][pdcp_uid][rb_id]= Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id];

        if(Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id] > 0) {
          Pdcp_stats_rx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]= (Pdcp_stats_rx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]/Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]);
        } else {
          Pdcp_stats_rx_aiat_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
        }

        // reset the tmp vars
        Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
        Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
        Pdcp_stats_rx_aiat_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_id]=0;
1118
      }
Navid Nikaein's avatar
Navid Nikaein committed
1119 1120 1121
    }
  }
}
1122 1123


1124
//-----------------------------------------------------------------------------
1125 1126
void
pdcp_run (
frtabu's avatar
frtabu committed
1127
  const protocol_ctxt_t *const  ctxt_pP
1128 1129
)
//-----------------------------------------------------------------------------
1130
{
1131 1132 1133 1134 1135
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  }
1136

1137
  pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
1138
  pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023
1139
  pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
Navid Nikaein's avatar
Navid Nikaein committed
1140
  pdcp_update_stats(ctxt_pP);
1141
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
1142 1143 1144
  MessageDef   *msg_p;
  int           result;
  protocol_ctxt_t  ctxt;
1145

1146 1147 1148 1149 1150 1151
  do {
    // Checks if a message has been sent to PDCP sub-task
    itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);

    if (msg_p != NULL) {
      switch (ITTI_MSG_ID(msg_p)) {
frtabu's avatar
frtabu committed
1152 1153 1154 1155 1156 1157 1158 1159 1160
        case RRC_DCCH_DATA_REQ:
          PROTOCOL_CTXT_SET_BY_MODULE_ID(
            &ctxt,
            RRC_DCCH_DATA_REQ (msg_p).module_id,
            RRC_DCCH_DATA_REQ (msg_p).enb_flag,
            RRC_DCCH_DATA_REQ (msg_p).rnti,
            RRC_DCCH_DATA_REQ (msg_p).frame,
            0,
            RRC_DCCH_DATA_REQ (msg_p).eNB_index);
laurent's avatar
laurent committed
1161
          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %ld, muiP %d, confirmP %d, mode %d\n",
frtabu's avatar
frtabu committed
1162 1163 1164 1165 1166 1167 1168 1169
                PROTOCOL_CTXT_ARGS(&ctxt),
                ITTI_MSG_NAME (msg_p),
                ITTI_MSG_ORIGIN_NAME(msg_p),
                ITTI_MSG_INSTANCE (msg_p),
                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);
laurent's avatar
laurent committed
1170
          LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %ld \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
frtabu's avatar
frtabu committed
1171 1172 1173 1174 1175 1176 1177
          result = pdcp_data_req (&ctxt,
                                  SRB_FLAG_YES,
                                  RRC_DCCH_DATA_REQ (msg_p).rb_id,
                                  RRC_DCCH_DATA_REQ (msg_p).muip,
                                  RRC_DCCH_DATA_REQ (msg_p).confirmp,
                                  RRC_DCCH_DATA_REQ (msg_p).sdu_size,
                                  RRC_DCCH_DATA_REQ (msg_p).sdu_p,
frtabu's avatar
frtabu committed
1178 1179
                                  RRC_DCCH_DATA_REQ (msg_p).mode,
                                  NULL, NULL
frtabu's avatar
frtabu committed
1180
                                 );
1181

frtabu's avatar
frtabu committed
1182 1183
          if (result != TRUE)
            LOG_E(PDCP, "PDCP data request failed!\n");
1184

frtabu's avatar
frtabu committed
1185 1186 1187 1188
          // 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;
1189

frtabu's avatar
frtabu committed
1190 1191 1192 1193 1194 1195
        case RRC_PCCH_DATA_REQ: {
          sdu_size_t     sdu_buffer_sizeP;
          sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size;
          uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id;
          uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index;
          RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP;
1196

frtabu's avatar
frtabu committed
1197 1198 1199
          if (sdu_buffer_sizeP > 0) {
            memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP);
          }
1200

frtabu's avatar
frtabu committed
1201 1202 1203
          //paging pdcp log
          LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
        }
1204
        break;
frtabu's avatar
frtabu committed
1205 1206 1207 1208

        default:
          LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
          break;
1209
      }
1210 1211 1212 1213

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

1216
  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
1217 1218
  //  if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) {
  if (!EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {
1219
    pdcp_fifo_read_input_sdus(ctxt_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
1220
  }
1221

1222
  // PDCP -> NAS/IP traffic: RX
1223 1224
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
frtabu's avatar
frtabu committed
1225
  } else {
1226 1227
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1228

1229
  pdcp_fifo_flush_sdus(ctxt_pP);
1230

1231 1232 1233 1234 1235
  if (ctxt_pP->enb_flag) {
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1236

1237 1238 1239 1240 1241
  if (ctxt_pP->enb_flag) {
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
  }
frtabu's avatar
frtabu committed
1242

1243
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
1244 1245
}

1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
//-----------------------------------------------------------------------------
void
pdcp_mbms_run (
  const protocol_ctxt_t *const  ctxt_pP
)
//-----------------------------------------------------------------------------
{
 // if (ctxt_pP->enb_flag) {
 //   start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
 // } else {
 //   start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
 // }

 // pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
 // pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023
 // pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
 // pdcp_update_stats(ctxt_pP);
 // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
 // MessageDef   *msg_p;
  //int           result;
  //protocol_ctxt_t  ctxt;

//  do {
//    // Checks if a message has been sent to PDCP sub-task
//    itti_poll_msg (ctxt_pP->enb_flag ? TASK_PDCP_ENB : TASK_PDCP_UE, &msg_p);
//
//    if (msg_p != NULL) {
//      switch (ITTI_MSG_ID(msg_p)) {
//        case RRC_DCCH_DATA_REQ:
//          PROTOCOL_CTXT_SET_BY_MODULE_ID(
//            &ctxt,
//            RRC_DCCH_DATA_REQ (msg_p).module_id,
//            RRC_DCCH_DATA_REQ (msg_p).enb_flag,
//            RRC_DCCH_DATA_REQ (msg_p).rnti,
//            RRC_DCCH_DATA_REQ (msg_p).frame,
//            0,
//            RRC_DCCH_DATA_REQ (msg_p).eNB_index);
//          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %d, rb_id %d, muiP %d, confirmP %d, mode %d\n",
//                PROTOCOL_CTXT_ARGS(&ctxt),
//                ITTI_MSG_NAME (msg_p),
//                ITTI_MSG_ORIGIN_NAME(msg_p),
//                ITTI_MSG_INSTANCE (msg_p),
//                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);
//          LOG_D(PDCP, "Before calling pdcp_data_req from pdcp_run! RRC_DCCH_DATA_REQ (msg_p).rb_id: %d \n", RRC_DCCH_DATA_REQ (msg_p).rb_id);
//          result = pdcp_data_req (&ctxt,
//                                  SRB_FLAG_YES,
//                                  RRC_DCCH_DATA_REQ (msg_p).rb_id,
//                                  RRC_DCCH_DATA_REQ (msg_p).muip,
//                                  RRC_DCCH_DATA_REQ (msg_p).confirmp,
//                                  RRC_DCCH_DATA_REQ (msg_p).sdu_size,
//                                  RRC_DCCH_DATA_REQ (msg_p).sdu_p,
//                                  RRC_DCCH_DATA_REQ (msg_p).mode,
//                                  NULL, NULL
//                                 );
//
//          if (result != TRUE)
//            LOG_E(PDCP, "PDCP data request failed!\n");
//
//          // Message buffer has been processed, free it now.
//          result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ (msg_p).sdu_p);
//          AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
//          break;
//
//        case RRC_PCCH_DATA_REQ: {
//          sdu_size_t     sdu_buffer_sizeP;
//          sdu_buffer_sizeP = RRC_PCCH_DATA_REQ(msg_p).sdu_size;
//          uint8_t CC_id = RRC_PCCH_DATA_REQ(msg_p).CC_id;
//          uint8_t ue_index = RRC_PCCH_DATA_REQ(msg_p).ue_index;
//          RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_paging[ue_index] = sdu_buffer_sizeP;
//
//          if (sdu_buffer_sizeP > 0) {
//            memcpy(RC.rrc[ctxt_pP->module_id]->carrier[CC_id].paging[ue_index], RRC_PCCH_DATA_REQ(msg_p).sdu_p, sdu_buffer_sizeP);
//          }
//
//          //paging pdcp log
//          LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
//        }
//        break;
//
//        default:
//          LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
//          break;
//      }
//
//      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
//      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
//    }
//  } while(msg_p != NULL);
//
  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
  //  if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) {
1340 1341
  //if (EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {

1342
    pdcp_fifo_read_input_mbms_sdus_fromtun(ctxt_pP);
1343
  //}
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371

  // PDCP -> NAS/IP traffic: RX
//  if (ctxt_pP->enb_flag) {
//    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
//  } else {
//    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
//  }
//

    //pdcp_fifo_flush_mbms_sdus(ctxt_pP);

//  if (ctxt_pP->enb_flag) {
//    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
//  } else {
//    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
//  }
//
//  if (ctxt_pP->enb_flag) {
//    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_run);
//  } else {
//    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_run);
//  }
//
//  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
}



frtabu's avatar
frtabu committed
1372
void pdcp_init_stats_UE(module_id_t mod, uint16_t uid) {
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404
  Pdcp_stats_tx_window_ms[mod][uid] = 100;
  Pdcp_stats_rx_window_ms[mod][uid] = 100;

  for (int i = 0; i < NB_RB_MAX; ++i) {
    Pdcp_stats_tx_bytes[mod][uid][i] = 0;
    Pdcp_stats_tx_bytes_w[mod][uid][i] = 0;
    Pdcp_stats_tx_bytes_tmp_w[mod][uid][i] = 0;
    Pdcp_stats_tx[mod][uid][i] = 0;
    Pdcp_stats_tx_w[mod][uid][i] = 0;
    Pdcp_stats_tx_tmp_w[mod][uid][i] = 0;
    Pdcp_stats_tx_sn[mod][uid][i] = 0;
    Pdcp_stats_tx_throughput_w[mod][uid][i] = 0;
    Pdcp_stats_tx_aiat[mod][uid][i] = 0;
    Pdcp_stats_tx_aiat_w[mod][uid][i] = 0;
    Pdcp_stats_tx_aiat_tmp_w[mod][uid][i] = 0;
    Pdcp_stats_tx_iat[mod][uid][i] = 0;
    Pdcp_stats_rx[mod][uid][i] = 0;
    Pdcp_stats_rx_w[mod][uid][i] = 0;
    Pdcp_stats_rx_tmp_w[mod][uid][i] = 0;
    Pdcp_stats_rx_bytes[mod][uid][i] = 0;
    Pdcp_stats_rx_bytes_w[mod][uid][i] = 0;
    Pdcp_stats_rx_bytes_tmp_w[mod][uid][i] = 0;
    Pdcp_stats_rx_sn[mod][uid][i] = 0;
    Pdcp_stats_rx_goodput_w[mod][uid][i] = 0;
    Pdcp_stats_rx_aiat[mod][uid][i] = 0;
    Pdcp_stats_rx_aiat_w[mod][uid][i] = 0;
    Pdcp_stats_rx_aiat_tmp_w[mod][uid][i] = 0;
    Pdcp_stats_rx_iat[mod][uid][i] = 0;
    Pdcp_stats_rx_outoforder[mod][uid][i] = 0;
  }
}

frtabu's avatar
frtabu committed
1405
void pdcp_add_UE(const protocol_ctxt_t *const  ctxt_pP) {
1406
  int i, ue_flag=1; //, ret=-1; to be decied later
frtabu's avatar
frtabu committed
1407 1408

  for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1409 1410 1411 1412 1413
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti) {
      ue_flag=-1;
      break;
    }
  }
frtabu's avatar
frtabu committed
1414 1415 1416 1417 1418 1419 1420 1421

  if (ue_flag == 1 ) {
    for (i=0; i < MAX_MOBILES_PER_ENB ; i++) {
      if (pdcp_enb[ctxt_pP->module_id].rnti[i] == 0 ) {
        pdcp_enb[ctxt_pP->module_id].rnti[i]=ctxt_pP->rnti;
        pdcp_enb[ctxt_pP->module_id].uid[i]=i;
        pdcp_enb[ctxt_pP->module_id].num_ues++;
        printf("add new uid is %d %x\n\n", i, ctxt_pP->rnti);
1422
        pdcp_init_stats_UE(ctxt_pP->module_id, i);
frtabu's avatar
frtabu committed
1423 1424
        // ret=1;
        break;
1425 1426 1427
      }
    }
  }
frtabu's avatar
frtabu committed
1428

1429 1430
  //return ret;
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1431

1432 1433 1434
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
frtabu's avatar
frtabu committed
1435
  const protocol_ctxt_t *const  ctxt_pP
1436 1437 1438
)
//-----------------------------------------------------------------------------
{
1439 1440
  LTE_DRB_Identity_t  srb_id         = 0;
  LTE_DRB_Identity_t  drb_id         = 0;
1441 1442
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1443
  int i;
frtabu's avatar
frtabu committed
1444
  // check and remove SRBs first
Raymond Knopp's avatar
 
Raymond Knopp committed
1445

frtabu's avatar
frtabu committed
1446 1447
  for(int i = 0; i<MAX_MOBILES_PER_ENB; i++) {
    if(pdcp_eNB_UE_instance_to_rnti[i] == ctxt_pP->rnti) {
1448 1449 1450 1451 1452
      pdcp_eNB_UE_instance_to_rnti[i] = NOT_A_RNTI;
      break;
    }
  }

Emad's avatar
Emad committed
1453
  for (srb_id=1; srb_id<3; srb_id++) {
1454 1455
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES);
    h_rc = hashtable_remove(pdcp_coll_p, key);
Raymond Knopp's avatar
 
Raymond Knopp committed
1456 1457
  }

1458
  for (drb_id=0; drb_id<LTE_maxDRB; drb_id++) {
1459 1460
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
    h_rc = hashtable_remove(pdcp_coll_p, key);
Raymond Knopp's avatar
 
Raymond Knopp committed
1461 1462
  }

1463 1464
  (void)h_rc; /* remove gcc warning "set but not used" */

1465
  // remove ue for pdcp enb inst
frtabu's avatar
frtabu committed
1466
  for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1467 1468
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti ) {
      LOG_I(PDCP, "remove uid is %d/%d %x\n", i,
frtabu's avatar
frtabu committed
1469 1470
            pdcp_enb[ctxt_pP->module_id].uid[i],
            pdcp_enb[ctxt_pP->module_id].rnti[i]);
1471 1472 1473 1474 1475 1476
      pdcp_enb[ctxt_pP->module_id].uid[i]=0;
      pdcp_enb[ctxt_pP->module_id].rnti[i]=0;
      pdcp_enb[ctxt_pP->module_id].num_ues--;
      break;
    }
  }
1477

Raymond Knopp's avatar
 
Raymond Knopp committed
1478 1479 1480 1481
  return 1;
}


1482 1483 1484
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
frtabu's avatar
frtabu committed
1485
  const protocol_ctxt_t *const  ctxt_pP,
1486 1487 1488
  LTE_SRB_ToAddModList_t  *const srb2add_list_pP,
  LTE_DRB_ToAddModList_t  *const drb2add_list_pP,
  LTE_DRB_ToReleaseList_t *const drb2release_list_pP,
1489 1490 1491
  const uint8_t                   security_modeP,
  uint8_t                  *const kRRCenc_pP,
  uint8_t                  *const kRRCint_pP,
frtabu's avatar
frtabu committed
1492 1493 1494
  uint8_t                  *const kUPenc_pP,
  LTE_PMCH_InfoList_r9_t  *const pmch_InfoList_r9_pP,
  rb_id_t                 *const defaultDRB
1495
)
1496
//-----------------------------------------------------------------------------
1497
{
1498
  long int        lc_id          = 0;
1499
  LTE_DRB_Identity_t  srb_id     = 0;
1500
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1501
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1502 1503
  LTE_DRB_Identity_t  drb_id     = 0;
  LTE_DRB_Identity_t *pdrb_id_p  = NULL;
1504
  uint8_t         drb_sn         = 12;
1505 1506
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1507
  long int        cnt            = 0;
1508 1509
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1510 1511
  LTE_SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  LTE_DRB_ToAddMod_t *drb_toaddmod_p = NULL;
1512
  pdcp_t         *pdcp_p         = NULL;
1513 1514
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1515 1516
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
1517
  int i,j;
1518 1519
  LTE_MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  LTE_MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1520 1521 1522 1523 1524 1525
  LOG_T(PDCP, PROTOCOL_CTXT_FMT" %s() SRB2ADD %p DRB2ADD %p DRB2RELEASE %p\n",
        PROTOCOL_CTXT_ARGS(ctxt_pP),
        __FUNCTION__,
        srb2add_list_pP,
        drb2add_list_pP,
        drb2release_list_pP);
1526

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

1529
  if (srb2add_list_pP != NULL) {
1530 1531 1532 1533
    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;
1534
      lc_id = srb_id;
1535
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, srb_id, SRB_FLAG_YES);
frtabu's avatar
frtabu committed
1536
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1537

1538 1539 1540 1541 1542
      if (h_rc == HASH_TABLE_OK) {
        action = CONFIG_ACTION_MODIFY;
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_MODIFY key 0x%"PRIx64"\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
              key);
1543
      } else {
1544 1545 1546
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1547

1548 1549 1550 1551 1552 1553
        if (h_rc != HASH_TABLE_OK) {
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64" FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
          free(pdcp_p);
          return TRUE;
frtabu's avatar
frtabu committed
1554 1555
        } else {
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
1556 1557 1558
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1559 1560 1561 1562
      }

      if (srb_toaddmod_p->rlc_Config) {
        switch (srb_toaddmod_p->rlc_Config->present) {
frtabu's avatar
frtabu committed
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
          case LTE_SRB_ToAddMod__rlc_Config_PR_NOTHING:
            break;

          case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue:
            switch (srb_toaddmod_p->rlc_Config->choice.explicitValue.present) {
              case LTE_RLC_Config_PR_NOTHING:
                break;

              default:
                pdcp_config_req_asn1 (
                  ctxt_pP,
                  pdcp_p,
                  SRB_FLAG_YES,
                  rlc_type,
                  action,
                  lc_id,
                  mch_id,
                  srb_id,
                  srb_sn,
                  0, // drb_report
                  0, // header compression
                  security_modeP,
                  kRRCenc_pP,
                  kRRCint_pP,
                  kUPenc_pP);
                break;
            }
1590 1591

            break;
1592

frtabu's avatar
frtabu committed
1593
          case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue:
1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
            pdcp_config_req_asn1 (
              ctxt_pP,
              pdcp_p,
              SRB_FLAG_YES,
              rlc_type,
              action,
              lc_id,
              mch_id,
              srb_id,
              srb_sn,
              0, // drb_report
              0, // header compression
              security_modeP,
              kRRCenc_pP,
              kRRCint_pP,
              kUPenc_pP);
frtabu's avatar
frtabu committed
1610
            // already the default values
1611 1612
            break;

frtabu's avatar
frtabu committed
1613 1614 1615
          default:
            DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
            break;
1616
        }
1617
      }
1618
    }
1619
  }
1620

1621 1622
  // reset the action

1623
  if (drb2add_list_pP != NULL) {
1624 1625 1626
    for (cnt=0; cnt<drb2add_list_pP->list.count; cnt++) {
      drb_toaddmod_p = drb2add_list_pP->list.array[cnt];
      drb_id = drb_toaddmod_p->drb_Identity;// + drb_id_offset;
frtabu's avatar
frtabu committed
1627

1628 1629 1630 1631 1632 1633 1634 1635 1636
      if (drb_toaddmod_p->logicalChannelIdentity) {
        lc_id = *(drb_toaddmod_p->logicalChannelIdentity);
      } else {
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" logicalChannelIdentity is missing in DRB-ToAddMod information element!\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
        continue;
      }

      if (lc_id == 1 || lc_id == 2) {
Cedric Roux's avatar
Cedric Roux committed
1637
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1638 1639 1640
        continue;
      }

1641
      DevCheck4(drb_id < LTE_maxDRB, drb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
1642
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
frtabu's avatar
frtabu committed
1643
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1644

1645 1646 1647 1648 1649
      if (h_rc == HASH_TABLE_OK) {
        action = CONFIG_ACTION_MODIFY;
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_MODIFY key 0x%"PRIx64"\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
              key);
1650 1651
      } else {
        action = CONFIG_ACTION_ADD;
1652 1653 1654
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1655
        // save the first configured DRB-ID as the default DRB-ID
1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668
        if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
          key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
          h_defaultDRB_rc = hashtable_insert(pdcp_coll_p, key_defaultDRB, pdcp_p);
        } else {
          h_defaultDRB_rc = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
        }

        if (h_defaultDRB_rc != HASH_TABLE_OK) {
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD default DRB key 0x%"PRIx64" FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key_defaultDRB);
          free(pdcp_p);
          return TRUE;
1669
        } else if (h_rc != HASH_TABLE_OK) {
1670 1671 1672 1673 1674 1675 1676 1677 1678
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64" FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
          free(pdcp_p);
          return TRUE;
        } else {
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64"\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
frtabu's avatar
frtabu committed
1679
        }
1680
      }
1681 1682 1683 1684 1685 1686 1687 1688

      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;
1689
          drb_sn = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size
1690 1691 1692 1693 1694 1695 1696 1697 1698
          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) {
frtabu's avatar
frtabu committed
1699 1700
          case LTE_PDCP_Config__headerCompression_PR_NOTHING:
          case LTE_PDCP_Config__headerCompression_PR_notUsed:
1701
            header_compression_profile=0x0;
frtabu's avatar
frtabu committed
1702
            break;
1703

frtabu's avatar
frtabu committed
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731
          case LTE_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;
1732

frtabu's avatar
frtabu committed
1733 1734 1735 1736
          default:
            LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT"[RB %ld] unknown drb_toaddmod->PDCP_Config->headerCompression->present \n",
                  PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), drb_id);
            break;
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
        }

        pdcp_config_req_asn1 (
          ctxt_pP,
          pdcp_p,
          SRB_FLAG_NO,
          rlc_type,
          action,
          lc_id,
          mch_id,
          drb_id,
          drb_sn,
          drb_report,
          header_compression_profile,
          security_modeP,
          kRRCenc_pP,
          kRRCint_pP,
          kUPenc_pP);
1755
      }
1756
    }
1757 1758
  }

1759
  if (drb2release_list_pP != NULL) {
1760 1761 1762
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1763
      key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, drb_id, SRB_FLAG_NO);
frtabu's avatar
frtabu committed
1764
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1765 1766

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1767
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1768 1769 1770
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1771
      }
1772

frtabu's avatar
frtabu committed
1773
      lc_id = pdcp_p->lcid;
1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790
      action = CONFIG_ACTION_REMOVE;
      pdcp_config_req_asn1 (
        ctxt_pP,
        pdcp_p,
        SRB_FLAG_NO,
        rlc_type,
        action,
        lc_id,
        mch_id,
        drb_id,
        0,
        0,
        0,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
1791
      h_rc = hashtable_remove(pdcp_coll_p, key);
1792 1793

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1794
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1795
        key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
frtabu's avatar
frtabu committed
1796
        h_defaultDRB_rc = hashtable_get(pdcp_coll_p, key_defaultDRB, (void **)&pdcp_p);
1797 1798 1799 1800 1801 1802 1803 1804 1805

        if (h_defaultDRB_rc == HASH_TABLE_OK) {
          h_defaultDRB_rc = hashtable_remove(pdcp_coll_p, key_defaultDRB);
        } else {
          LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED default DRB\n", PROTOCOL_CTXT_ARGS(ctxt_pP));
        }
      } else {
        key_defaultDRB = HASH_TABLE_OK; // do not trigger any error handling if this is not a default DRB
      }
1806
    }
1807 1808
  }

1809
  if (pmch_InfoList_r9_pP != NULL) {
1810 1811 1812 1813 1814
    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];
frtabu's avatar
frtabu committed
1815

1816
        if (0/*MBMS_SessionInfo_p->sessionId_r9*/)
1817 1818 1819
          lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        else
          lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
frtabu's avatar
frtabu committed
1820

1821
        mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
frtabu's avatar
frtabu committed
1822
        //        mch_id = j;
1823 1824 1825

        // can set the mch_id = i
        if (ctxt_pP->enb_flag) {
1826
          drb_id =  (mch_id * LTE_maxSessionPerPMCH ) + lc_id ;//+ (LTE_maxDRB + 3)*MAX_MOBILES_PER_ENB; // 1
1827

1828
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1829 1830 1831 1832 1833
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
1834
          drb_id =  (mch_id * LTE_maxSessionPerPMCH ) + lc_id; // + (LTE_maxDRB + 3); // 15
1835

1836
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1837 1838 1839
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1840
          }
1841 1842
        }

1843
        LOG_I(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
frtabu's avatar
frtabu committed
1844 1845 1846 1847 1848 1849
              lc_id,
              MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[0],
              MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[1],
              MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2],
              drb_id,
              action);
1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865
        pdcp_config_req_asn1 (
          ctxt_pP,
          NULL,  // unused for MBMS
          SRB_FLAG_NO,
          RLC_MODE_NONE,
          action,
          lc_id,
          mch_id,
          drb_id,
          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
1866
      }
1867
    }
1868
  }
1869

1870
  return 0;
1871 1872
}

1873
//-----------------------------------------------------------------------------
1874 1875
boolean_t
pdcp_config_req_asn1 (
frtabu's avatar
frtabu committed
1876 1877
  const protocol_ctxt_t *const  ctxt_pP,
  pdcp_t          *const        pdcp_pP,
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890
  const srb_flag_t              srb_flagP,
  const rlc_mode_t              rlc_modeP,
  const config_action_t         actionP,
  const uint16_t                lc_idP,
  const uint16_t                mch_idP,
  const rb_id_t                 rb_idP,
  const uint8_t                 rb_snP,
  const uint8_t                 rb_reportP,
  const uint16_t                header_compression_profileP,
  const uint8_t                 security_modeP,
  uint8_t         *const        kRRCenc_pP,
  uint8_t         *const        kRRCint_pP,
  uint8_t         *const        kUPenc_pP)
1891
//-----------------------------------------------------------------------------
1892
{
1893

1894
  switch (actionP) {
frtabu's avatar
frtabu committed
1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910
    case CONFIG_ACTION_ADD:
      DevAssert(pdcp_pP != NULL);

      if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
        pdcp_pP->is_ue = FALSE;
        pdcp_add_UE(ctxt_pP);

        //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti;
        //      pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
        if( srb_flagP == SRB_FLAG_NO ) {
          for(int i = 0; i<MAX_MOBILES_PER_ENB; i++) {
            if(pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] == NOT_A_RNTI) {
              break;
            }

            pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1911
          }
frtabu's avatar
frtabu committed
1912

1913
          pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
1914
          pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
frtabu's avatar
frtabu committed
1915
        }
1916

frtabu's avatar
frtabu committed
1917 1918 1919 1920
        //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
      } else {
        pdcp_pP->is_ue = TRUE;
        pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
1921
      }
1922

frtabu's avatar
frtabu committed
1923 1924 1925 1926 1927
      pdcp_pP->is_srb                     = (srb_flagP == SRB_FLAG_YES) ? TRUE : FALSE;
      pdcp_pP->lcid                       = lc_idP;
      pdcp_pP->rb_id                      = rb_idP;
      pdcp_pP->header_compression_profile = header_compression_profileP;
      pdcp_pP->status_report              = rb_reportP;
1928

frtabu's avatar
frtabu committed
1929
      if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1930 1931
        pdcp_pP->seq_num_size = 12;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 12) - 1;
frtabu's avatar
frtabu committed
1932
      } else if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1933 1934
        pdcp_pP->seq_num_size = 7;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 7) - 1;
frtabu's avatar
frtabu committed
1935
      } else {
1936 1937
        pdcp_pP->seq_num_size = 5;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 5) - 1;
frtabu's avatar
frtabu committed
1938
      }
1939

frtabu's avatar
frtabu committed
1940 1941 1942 1943 1944 1945 1946
      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;
      pdcp_pP->last_submitted_pdcp_rx_sn        = 4095;
      pdcp_pP->first_missing_pdu                = -1;
laurent's avatar
laurent committed
1947
      LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %ld) "
1948
            "configured with SN size %d bits and RLC %s\n",
frtabu's avatar
frtabu committed
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            (srb_flagP == SRB_FLAG_YES) ? "SRB" : "DRB",
            rb_idP,
            pdcp_pP->seq_num_size,
            (rlc_modeP == RLC_MODE_AM ) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");

      /* Setup security */
      if (security_modeP != 0xff) {
        pdcp_config_set_security(
          ctxt_pP,
          pdcp_pP,
1961
          rb_idP,
frtabu's avatar
frtabu committed
1962 1963 1964 1965 1966 1967
          lc_idP,
          security_modeP,
          kRRCenc_pP,
          kRRCint_pP,
          kUPenc_pP);
      }
1968

frtabu's avatar
frtabu committed
1969
      break;
1970

frtabu's avatar
frtabu committed
1971 1972 1973 1974 1975
    case CONFIG_ACTION_MODIFY:
      DevAssert(pdcp_pP != NULL);
      pdcp_pP->header_compression_profile=header_compression_profileP;
      pdcp_pP->status_report = rb_reportP;
      pdcp_pP->rlc_mode = rlc_modeP;
1976

frtabu's avatar
frtabu committed
1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988
      /* Setup security */
      if (security_modeP != 0xff) {
        pdcp_config_set_security(
          ctxt_pP,
          pdcp_pP,
          rb_idP,
          lc_idP,
          security_modeP,
          kRRCenc_pP,
          kRRCint_pP,
          kUPenc_pP);
      }
1989

frtabu's avatar
frtabu committed
1990 1991 1992 1993 1994 1995 1996 1997 1998
      if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
        pdcp_pP->seq_num_size = 7;
      } else if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
        pdcp_pP->seq_num_size = 12;
      } else {
        pdcp_pP->seq_num_size=5;
      }

      LOG_I(PDCP,PROTOCOL_PDCP_CTXT_FMT" Action MODIFY LCID %d "
laurent's avatar
laurent committed
1999
            "RB id %ld reconfigured with SN size %d and RLC %s \n",
frtabu's avatar
frtabu committed
2000 2001 2002 2003
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            rb_idP,
            rb_snP,
2004
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
frtabu's avatar
frtabu committed
2005
      break;
2006

frtabu's avatar
frtabu committed
2007 2008 2009 2010
    case CONFIG_ACTION_REMOVE:
      DevAssert(pdcp_pP != NULL);
      //#warning "TODO pdcp_module_id_to_rnti"
      //pdcp_module_id_to_rnti[ctxt_pP.module_id ][dst_id] = NOT_A_RNTI;
laurent's avatar
laurent committed
2011
      LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE LCID %d RBID %ld configured\n",
frtabu's avatar
frtabu committed
2012 2013 2014
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            rb_idP);
2015

frtabu's avatar
frtabu committed
2016 2017 2018
      if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
        // pdcp_remove_UE(ctxt_pP);
      }
2019

frtabu's avatar
frtabu committed
2020 2021 2022 2023
      /* Security keys */
      if (pdcp_pP->kUPenc != NULL) {
        free(pdcp_pP->kUPenc);
      }
2024

frtabu's avatar
frtabu committed
2025 2026 2027
      if (pdcp_pP->kRRCint != NULL) {
        free(pdcp_pP->kRRCint);
      }
2028

frtabu's avatar
frtabu committed
2029 2030 2031
      if (pdcp_pP->kRRCenc != NULL) {
        free(pdcp_pP->kRRCenc);
      }
2032

frtabu's avatar
frtabu committed
2033 2034
      memset(pdcp_pP, 0, sizeof(pdcp_t));
      break;
2035

frtabu's avatar
frtabu committed
2036 2037
    case CONFIG_ACTION_MBMS_ADD:
    case CONFIG_ACTION_MBMS_MODIFY:
laurent's avatar
laurent committed
2038
      LOG_D(PDCP," %s service_id/mch index %d, session_id/lcid %d, rbid %ld configured\n",
frtabu's avatar
frtabu committed
2039 2040 2041 2042 2043
            //PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            actionP == CONFIG_ACTION_MBMS_ADD ? "CONFIG_ACTION_MBMS_ADD" : "CONFIG_ACTION_MBMS_MODIFY",
            mch_idP,
            lc_idP,
            rb_idP);
2044

frtabu's avatar
frtabu committed
2045 2046 2047 2048 2049 2050 2051
      if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
        pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = TRUE ;
        pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].rb_id = rb_idP;
      } else {
        pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = TRUE ;
        pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].rb_id = rb_idP;
      }
2052

frtabu's avatar
frtabu committed
2053
      break;
2054

frtabu's avatar
frtabu committed
2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069
    case CONFIG_ACTION_SET_SECURITY_MODE:
      pdcp_config_set_security(
        ctxt_pP,
        pdcp_pP,
        rb_idP,
        lc_idP,
        security_modeP,
        kRRCenc_pP,
        kRRCint_pP,
        kUPenc_pP);
      break;

    default:
      DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
      break;
2070
  }
2071

2072 2073
  return 0;
}
2074

2075 2076 2077
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
frtabu's avatar
frtabu committed
2078 2079
  const protocol_ctxt_t *const  ctxt_pP,
  pdcp_t          *const pdcp_pP,
2080 2081 2082
  const rb_id_t         rb_idP,
  const uint16_t        lc_idP,
  const uint8_t         security_modeP,
frtabu's avatar
frtabu committed
2083 2084 2085
  uint8_t         *const kRRCenc,
  uint8_t         *const kRRCint,
  uint8_t         *const  kUPenc)
2086
//-----------------------------------------------------------------------------
2087
{
2088
  DevAssert(pdcp_pP != NULL);
2089

2090
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
2091 2092
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
2093 2094
    LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_SET_SECURITY_MODE: cipheringAlgorithm %d integrityProtAlgorithm %d\n",
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
frtabu's avatar
frtabu committed
2095 2096
          pdcp_pP->cipheringAlgorithm,
          pdcp_pP->integrityProtAlgorithm);
2097 2098 2099 2100 2101
    pdcp_pP->kRRCenc = kRRCenc;
    pdcp_pP->kRRCint = kRRCint;
    pdcp_pP->kUPenc  = kUPenc;
    /* Activate security */
    pdcp_pP->security_activated = 1;
frtabu's avatar
frtabu committed
2102 2103 2104 2105 2106 2107
    MSC_LOG_EVENT(
      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
      "0 Set security ciph %X integ %x UE %"PRIx16" ",
      pdcp_pP->cipheringAlgorithm,
      pdcp_pP->integrityProtAlgorithm,
      ctxt_pP->rnti);
2108
  } else {
frtabu's avatar
frtabu committed
2109 2110 2111 2112 2113
    MSC_LOG_EVENT(
      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
      "0 Set security failed UE %"PRIx16" ",
      ctxt_pP->rnti);
    LOG_E(PDCP,PROTOCOL_PDCP_CTXT_FMT"  bad security mode %d",
2114 2115
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
2116
  }
2117 2118
}

2119
//-----------------------------------------------------------------------------
2120 2121
void
rrc_pdcp_config_req (
frtabu's avatar
frtabu committed
2122
  const protocol_ctxt_t *const  ctxt_pP,
2123 2124 2125 2126
  const srb_flag_t srb_flagP,
  const uint32_t actionP,
  const rb_id_t rb_idP,
  const uint8_t security_modeP)
2127
//-----------------------------------------------------------------------------
2128
{
2129
  pdcp_t *pdcp_p = NULL;
2130 2131
  hash_key_t       key           = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
  hashtable_rc_t   h_rc;
frtabu's avatar
frtabu committed
2132
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
2133

2134
  if (h_rc == HASH_TABLE_OK) {
frtabu's avatar
frtabu committed
2135 2136 2137
    /*
     * Initialize sequence number state variables of relevant PDCP entity
     */
2138
    switch (actionP) {
frtabu's avatar
frtabu committed
2139
      case CONFIG_ACTION_ADD:
2140 2141 2142 2143 2144
        pdcp_p->is_srb = srb_flagP;
        pdcp_p->rb_id  = rb_idP;

        if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
          pdcp_p->is_ue = TRUE;
frtabu's avatar
frtabu committed
2145
          pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
2146 2147
        } else {
          pdcp_p->is_ue = FALSE;
frtabu's avatar
frtabu committed
2148
        }
2149

2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163
        pdcp_p->next_pdcp_tx_sn = 0;
        pdcp_p->next_pdcp_rx_sn = 0;
        pdcp_p->tx_hfn = 0;
        pdcp_p->rx_hfn = 0;
        /* SN of the last PDCP SDU delivered to upper layers */
        pdcp_p->last_submitted_pdcp_rx_sn = 4095;

        if (rb_idP < DTCH) { // SRB
          pdcp_p->seq_num_size = 5;
        } else { // DRB
          pdcp_p->seq_num_size = 12;
        }

        pdcp_p->first_missing_pdu = -1;
laurent's avatar
laurent committed
2164
        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld (already added) configured\n",
2165 2166
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              rb_idP);
frtabu's avatar
frtabu committed
2167
        break;
2168

frtabu's avatar
frtabu committed
2169 2170
      case CONFIG_ACTION_MODIFY:
        break;
2171

frtabu's avatar
frtabu committed
2172
      case CONFIG_ACTION_REMOVE:
laurent's avatar
laurent committed
2173
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE: radio bearer id %ld configured\n",
frtabu's avatar
frtabu committed
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              rb_idP);
        pdcp_p->next_pdcp_tx_sn = 0;
        pdcp_p->next_pdcp_rx_sn = 0;
        pdcp_p->tx_hfn = 0;
        pdcp_p->rx_hfn = 0;
        pdcp_p->last_submitted_pdcp_rx_sn = 4095;
        pdcp_p->seq_num_size = 0;
        pdcp_p->first_missing_pdu = -1;
        pdcp_p->security_activated = 0;
        h_rc = hashtable_remove(pdcp_coll_p, key);
        break;
2186

frtabu's avatar
frtabu committed
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203
      case CONFIG_ACTION_SET_SECURITY_MODE:
        if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
          pdcp_p->cipheringAlgorithm= security_modeP & 0x0f;
          pdcp_p->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_SET_SECURITY_MODE: cipheringAlgorithm %d integrityProtAlgorithm %d\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
                pdcp_p->cipheringAlgorithm,
                pdcp_p->integrityProtAlgorithm );
        } else {
          LOG_W(PDCP,PROTOCOL_PDCP_CTXT_FMT" bad security mode %d", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), security_modeP);
        }

        break;

      default:
        DevParam(actionP, ctxt_pP->module_id, ctxt_pP->rnti);
        break;
2204
    }
frtabu's avatar
frtabu committed
2205 2206 2207 2208 2209
  } else {
    switch (actionP) {
      case CONFIG_ACTION_ADD:
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
2210

frtabu's avatar
frtabu committed
2211 2212 2213 2214 2215 2216 2217
        if (h_rc != HASH_TABLE_OK) {
          LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" PDCP ADD FAILED\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
          free(pdcp_p);
        } else {
          pdcp_p->is_srb = srb_flagP;
          pdcp_p->rb_id  = rb_idP;
2218

frtabu's avatar
frtabu committed
2219 2220 2221 2222 2223 2224
          if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
            pdcp_p->is_ue = TRUE;
            pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
          } else {
            pdcp_p->is_ue = FALSE;
          }
2225

frtabu's avatar
frtabu committed
2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237
          pdcp_p->next_pdcp_tx_sn = 0;
          pdcp_p->next_pdcp_rx_sn = 0;
          pdcp_p->tx_hfn = 0;
          pdcp_p->rx_hfn = 0;
          /* SN of the last PDCP SDU delivered to upper layers */
          pdcp_p->last_submitted_pdcp_rx_sn = 4095;

          if (rb_idP < DTCH) { // SRB
            pdcp_p->seq_num_size = 5;
          } else { // DRB
            pdcp_p->seq_num_size = 12;
          }
2238

frtabu's avatar
frtabu committed
2239 2240 2241
          pdcp_p->first_missing_pdu = -1;
          LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Inserting PDCP instance in collection key 0x%"PRIx64"\n",
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p), key);
laurent's avatar
laurent committed
2242
          LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld configured\n",
frtabu's avatar
frtabu committed
2243 2244 2245
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
                rb_idP);
        }
2246

frtabu's avatar
frtabu committed
2247
        break;
2248

frtabu's avatar
frtabu committed
2249 2250 2251 2252 2253 2254 2255 2256
      case CONFIG_ACTION_REMOVE:
        LOG_D(PDCP, PROTOCOL_CTXT_FMT" CONFIG_REQ PDCP CONFIG_ACTION_REMOVE PDCP instance not found\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP));
        break;

      default:
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" CONFIG_REQ PDCP NOT FOUND\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP));
2257
    }
2258
  }
2259
}
2260

frtabu's avatar
frtabu committed
2261 2262 2263
pdcp_data_ind_func_t get_pdcp_data_ind_func() {
  return pdcp_params.pdcp_data_ind_func;
}
2264

2265
void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req) {
frtabu's avatar
frtabu committed
2266
  pdcp_params.send_rlc_data_req_func = send_rlc_data_req;
2267
}
2268

2269
void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) {
frtabu's avatar
frtabu committed
2270 2271
  pdcp_params.pdcp_data_ind_func = pdcp_data_ind;
}
2272

2273 2274 2275 2276 2277 2278
uint64_t pdcp_module_init( uint64_t pdcp_optmask ) {
  /* temporary enforce netlink when UE_NAS_USE_TUN is set,
     this is while switching from noS1 as build option
     to noS1 as config option                               */
  if ( pdcp_optmask & UE_NAS_USE_TUN_BIT) {
    pdcp_params.optmask = pdcp_params.optmask | PDCP_USE_NETLINK_BIT ;
2279 2280
  }

2281 2282 2283 2284
  pdcp_params.optmask = pdcp_params.optmask | pdcp_optmask ;
  LOG_I(PDCP, "pdcp init,%s %s\n",
        ((LINK_ENB_PDCP_TO_GTPV1U)?"usegtp":""),
        ((PDCP_USE_NETLINK)?"usenetlink":""));
2285

2286
  if (PDCP_USE_NETLINK) {
2287 2288
    nas_getparams();

2289
    if(UE_NAS_USE_TUN) {
frtabu's avatar
frtabu committed
2290 2291
      int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1;
      netlink_init_tun("ue",num_if);
2292 2293
      if (IS_SOFTMODEM_NOS1)
    	  nas_config(1, 1, 2, "ue");
2294
      netlink_init_mbms_tun("uem");
2295
      nas_config_mbms(1, 2, 2, "uem");
2296 2297
      LOG_I(PDCP, "UE pdcp will use tun interface\n");
    } else if(ENB_NAS_USE_TUN) {
frtabu's avatar
frtabu committed
2298
      netlink_init_tun("enb",1);
2299
      nas_config(1, 1, 1, "enb");
2300
      if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
2301
        netlink_init_mbms_tun("enm");
2302 2303 2304
      	nas_config_mbms(1, 2, 1, "enm"); 
      	LOG_I(PDCP, "ENB pdcp will use mbms tun interface\n");
      }
2305
      LOG_I(PDCP, "ENB pdcp will use tun interface\n");
2306
    } else {
2307
      LOG_I(PDCP, "pdcp will use kernel modules\n");
2308 2309
      netlink_init();
    }
2310 2311 2312
  }else{
         if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
             LOG_W(PDCP, "ENB pdcp will use tun interface for MBMS\n");
2313
            netlink_init_mbms_tun("enm");
2314 2315 2316 2317 2318
             nas_config_mbms_s1(1, 2, 1, "enm"); 
         }else
             LOG_E(PDCP, "ENB pdcp will not use tun interface\n");
   }

2319
  return pdcp_params.optmask ;
2320 2321
}

2322

2323 2324 2325
//-----------------------------------------------------------------------------
void
pdcp_free (
frtabu's avatar
frtabu committed
2326
  void *pdcp_pP
2327 2328 2329
)
//-----------------------------------------------------------------------------
{
frtabu's avatar
frtabu committed
2330
  pdcp_t *pdcp_p = (pdcp_t *)pdcp_pP;
2331

2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347
  if (pdcp_p != NULL) {
    if (pdcp_p->kUPenc != NULL) {
      free(pdcp_p->kUPenc);
    }

    if (pdcp_p->kRRCint != NULL) {
      free(pdcp_p->kRRCint);
    }

    if (pdcp_p->kRRCenc != NULL) {
      free(pdcp_p->kRRCenc);
    }

    memset(pdcp_pP, 0, sizeof(pdcp_t));
    free(pdcp_pP);
  }
2348 2349 2350
}

//-----------------------------------------------------------------------------
2351 2352
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
2353 2354 2355 2356
{
}

//-----------------------------------------------------------------------------
2357
void pdcp_layer_init(void)
2358
//-----------------------------------------------------------------------------
2359
{
Lionel Gauthier's avatar
Lionel Gauthier committed
2360
  module_id_t       instance;
2361
  int i,j;
Lionel Gauthier's avatar
Lionel Gauthier committed
2362 2363
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
2364
  /*
2365 2366
   * Initialize SDU list
   */
2367
  initNotifiedFIFO(&pdcp_sdu_list);
2368
  pdcp_coll_p = hashtable_create ((LTE_maxDRB + 2) * NUMBER_OF_UE_MAX, NULL, pdcp_free);
2369
  AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
2370

2371
  for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
2372 2373
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2374
        memset(&pdcp_mbms_array_ue[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2375
      }
2376
    }
frtabu's avatar
frtabu committed
2377

2378
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
2379
  }
2380

frtabu's avatar
frtabu committed
2381
  pdcp_eNB_UE_instance_to_rnti_index = 0;
2382

2383
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
2384 2385
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2386
        memset(&pdcp_mbms_array_eNB[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2387
      }
2388
    }
2389
  }
2390

2391 2392
#ifdef MBMS_MULTICAST_OUT
  mbms_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
frtabu's avatar
frtabu committed
2393

2394 2395 2396
  if (mbms_socket == -1)
    LOG_W(PDCP, "Could not create RAW socket, MBMS packets will not be put to the network\n");

frtabu's avatar
frtabu committed
2397
#endif
2398 2399 2400 2401
  LOG_I(PDCP, "PDCP layer has been initialized\n");
  pdcp_output_sdu_bytes_to_write=0;
  pdcp_output_header_bytes_to_write=0;
  pdcp_input_sdu_remaining_size_to_read=0;
2402
  memset(pdcp_enb, 0, sizeof(pdcp_enb_t));
2403 2404
  memset(Pdcp_stats_tx_window_ms, 0, sizeof(Pdcp_stats_tx_window_ms));
  memset(Pdcp_stats_rx_window_ms, 0, sizeof(Pdcp_stats_rx_window_ms));
frtabu's avatar
frtabu committed
2405

2406 2407
  for (i = 0; i < MAX_eNB; i++) {
    for (j = 0; j < MAX_MOBILES_PER_ENB; j++) {
2408 2409 2410 2411
      Pdcp_stats_tx_window_ms[i][j]=100;
      Pdcp_stats_rx_window_ms[i][j]=100;
    }
  }
2412

2413
  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
2414 2415
  memset(Pdcp_stats_tx_w, 0, sizeof(Pdcp_stats_tx_w));
  memset(Pdcp_stats_tx_tmp_w, 0, sizeof(Pdcp_stats_tx_tmp_w));
2416
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
2417 2418
  memset(Pdcp_stats_tx_bytes_w, 0, sizeof(Pdcp_stats_tx_bytes_w));
  memset(Pdcp_stats_tx_bytes_tmp_w, 0, sizeof(Pdcp_stats_tx_bytes_tmp_w));
2419
  memset(Pdcp_stats_tx_sn, 0, sizeof(Pdcp_stats_tx_sn));
2420
  memset(Pdcp_stats_tx_throughput_w, 0, sizeof(Pdcp_stats_tx_throughput_w));
2421 2422
  memset(Pdcp_stats_tx_aiat, 0, sizeof(Pdcp_stats_tx_aiat));
  memset(Pdcp_stats_tx_iat, 0, sizeof(Pdcp_stats_tx_iat));
2423
  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
2424 2425
  memset(Pdcp_stats_rx_w, 0, sizeof(Pdcp_stats_rx_w));
  memset(Pdcp_stats_rx_tmp_w, 0, sizeof(Pdcp_stats_rx_tmp_w));
2426
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
2427 2428
  memset(Pdcp_stats_rx_bytes_w, 0, sizeof(Pdcp_stats_rx_bytes_w));
  memset(Pdcp_stats_rx_bytes_tmp_w, 0, sizeof(Pdcp_stats_rx_bytes_tmp_w));
2429
  memset(Pdcp_stats_rx_sn, 0, sizeof(Pdcp_stats_rx_sn));
2430
  memset(Pdcp_stats_rx_goodput_w, 0, sizeof(Pdcp_stats_rx_goodput_w));
2431 2432 2433
  memset(Pdcp_stats_rx_aiat, 0, sizeof(Pdcp_stats_rx_aiat));
  memset(Pdcp_stats_rx_iat, 0, sizeof(Pdcp_stats_rx_iat));
  memset(Pdcp_stats_rx_outoforder, 0, sizeof(Pdcp_stats_rx_outoforder));
2434 2435 2436
}

//-----------------------------------------------------------------------------
2437 2438
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
2439
{
2440 2441
  //list_free (&pdcp_sdu_list);
  while(pollNotifiedFIFO(&pdcp_sdu_list)) {};
frtabu's avatar
frtabu committed
2442
  hashtable_destroy(&pdcp_coll_p);
2443
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
2444

2445 2446 2447 2448
  if(mbms_socket != -1) {
    close(mbms_socket);
    mbms_socket = -1;
  }
frtabu's avatar
frtabu committed
2449

2450
#endif
2451
}