pdcp.c 94.1 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
  int UE_id = -1;
129
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
130
  CHECK_CTXT_ARGS(ctxt_pP);
Cedric Roux's avatar
Cedric Roux committed
131
#if T_TRACER
frtabu's avatar
frtabu committed
132

Cedric Roux's avatar
Cedric Roux committed
133 134
  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
135

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

138 139 140 141 142 143 144 145
  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?
   */
Cai Yang's avatar
Cai Yang committed
146 147 148 149
  if(sdu_buffer_sizeP > MAX_IP_PACKET_SIZE) {
    LOG_E(PDCP,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n", sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
    return FALSE;
  }
150

151
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
Cai Yang's avatar
Cai Yang committed
152
    if(rb_idP >= NB_RB_MBMS_MAX) {
153
      LOG_E(PDCP,"RB id is too high (%ld/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
Cai Yang's avatar
Cai Yang committed
154 155
      return FALSE;
    }
156
  } else {
157
    if (srb_flagP) {
Cai Yang's avatar
Cai Yang committed
158
      if(rb_idP >= 3) {
159
        LOG_E(PDCP,"RB id is too high (%ld/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
Cai Yang's avatar
Cai Yang committed
160 161
        return FALSE;
      }
162
    } else {
Cai Yang's avatar
Cai Yang committed
163
      if(rb_idP >= LTE_maxDRB) {
164
        LOG_E(PDCP,"RB id is too high (%ld/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
Cai Yang's avatar
Cai Yang committed
165 166
        return FALSE;
      }
167
    }
168
  }
169

170
  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
171
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
172

173 174
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
laurent's avatar
laurent committed
175
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %ld Ignoring SDU...\n",
frtabu's avatar
frtabu committed
176 177
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
178
      ctxt_pP->configured=FALSE;
179
      return FALSE;
180
    }
frtabu's avatar
frtabu committed
181
  } else {
182
    // instance for a given RB is configured
183
    ctxt_pP->configured=TRUE;
184
  }
185

186
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
187 188 189 190
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
191

192
  // PDCP transparent mode for MBMS traffic
193

194
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
195
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
196
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
197 198 199

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

201 202 203 204
      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
205
        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %ld \n", srb_flagP, rb_idP);
206
      }
frtabu's avatar
frtabu committed
207 208 209

      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);
210 211
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
frtabu's avatar
frtabu committed
212
      LOG_E(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
213
            PROTOCOL_CTXT_ARGS(ctxt_pP));
214
    }
215
  } else {
216 217 218 219 220 221 222 223 224 225
    // 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;
226 227
    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),
228 229 230 231 232 233
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
234
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
235 236

    if (pdcp_pdu_p != NULL) {
237
      /*
238 239 240
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
241
       */
242 243 244 245 246 247
      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);
248

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

253
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
254 255 256 257
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
258

259
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
260 261 262 263 264 265 266
          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 ;
267

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

272
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
273 274 275 276
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
277

278
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
279 280
          return FALSE;
        }
281
      }
282

283
      /*
284
       * Validate incoming sequence number, there might be a problem with PDCP initialization
285
       */
286
      if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
Cedric Roux's avatar
Cedric Roux committed
287
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Generated sequence number (%"PRIu16") is greater than a sequence number could ever be!\n"\
288 289 290
              "There must be a problem with PDCP initialization, ignoring this PDU...\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              current_sn);
291
        free_mem_block(pdcp_pdu_p, __func__);
292

293
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
294 295 296 297
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
298

299
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
300 301 302 303 304 305 306 307 308 309
        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
310
      for (i=0; i<pdcp_tailer_len; i++) {
311
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
312
      }
313 314 315 316

      if ((pdcp_p->security_activated != 0) &&
          (((pdcp_p->cipheringAlgorithm) != 0) ||
           ((pdcp_p->integrityProtAlgorithm) != 0))) {
317
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
318 319 320 321
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
322

Cai Yang's avatar
Cai Yang committed
323
        int ret = pdcp_apply_security(ctxt_pP,
324 325
                            pdcp_p,
                            srb_flagP,
326
                            rb_idP % LTE_maxDRB,
327 328 329 330
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);
Cai Yang's avatar
Cai Yang committed
331 332 333 334 335
							
        if(ret < 0) {
          LOG_E(PDCP,"pdcp_apply_security return value is -1\n");
          return FALSE;
        }
336

337 338 339 340 341
        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);
        }
342 343 344 345 346 347 348 349 350 351
      }

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

352 353 354 355 356
      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);
      }
357

laurent's avatar
laurent committed
358
      LOG_E(PDCP,  "[FRAME %5u][%s][PDCP][MOD %u][RB %ld] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
359 360 361 362
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->module_id,
            rb_idP);
363
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
364 365 366 367 368 369 370
      return FALSE;
    }

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

frtabu's avatar
frtabu committed
374
    if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1)) {
laurent's avatar
laurent committed
375 376
      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);
377

378 379 380 381 382 383 384 385 386 387
      // 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
388 389
        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
390 391 392 393
      } 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
394
	ret=FALSE;
frtabu's avatar
frtabu committed
395 396 397 398 399
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;
400

frtabu's avatar
frtabu committed
401 402 403
          case RLC_OP_STATUS_BAD_PARAMETER:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
            break;
404

frtabu's avatar
frtabu committed
405 406 407
          case RLC_OP_STATUS_INTERNAL_ERROR:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
            break;
408

frtabu's avatar
frtabu committed
409
          case RLC_OP_STATUS_OUT_OF_RESSOURCES:
410 411 412 413 414 415 416 417

            for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
              if (RC.mac[ctxt_pP->module_id]->UE_info.active[UE_id] == TRUE) {
                if (RC.mac[ctxt_pP->module_id]->UE_info.UE_template[RC.mac[ctxt_pP->module_id]->UE_info.pCC_id[UE_id]][UE_id].rnti == ctxt_pP->rnti) {
                    RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].rlc_out_of_resources_cnt++;
                    break;
                }
              }
418 419
            }
            LOG_D(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
frtabu's avatar
frtabu committed
420 421
            ret= FALSE;
            break;
422

frtabu's avatar
frtabu committed
423 424 425 426 427 428 429
          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)) {
430 431 432 433 434 435
        // 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
436
        F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id  = 0;
437 438 439 440 441 442 443 444 445 446
        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
447
      } else {
448 449 450 451 452 453 454 455 456 457
        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
458 459
                                 );

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
        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:
477 478 479 480 481 482 483 484

            for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
              if (RC.mac[ctxt_pP->module_id]->UE_info.active[UE_id] == TRUE) {
                if (RC.mac[ctxt_pP->module_id]->UE_info.UE_template[RC.mac[ctxt_pP->module_id]->UE_info.pCC_id[UE_id]][UE_id].rnti == ctxt_pP->rnti) {
                    RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].rlc_out_of_resources_cnt++;
                    break;
                }
              }
485 486
            }
            LOG_D(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
487 488 489 490 491 492 493 494 495
            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
      }
496
    }
497
  }
498

499
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
500 501 502 503
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
504

505 506 507 508 509
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */

frtabu's avatar
frtabu committed
510
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
511 512 513 514
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
      break;
  }

515 516
  //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]++;
517
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
518
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
519
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
520
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;
521
  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]);
522
  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]);
523
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
524
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
525
  return ret;
526 527
}

528

529 530 531
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
frtabu's avatar
frtabu committed
532
  const protocol_ctxt_t *const ctxt_pP,
533 534 535 536
  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
537
  mem_block_t *const sdu_buffer_pP
538 539
)
//-----------------------------------------------------------------------------
540
{
541
  pdcp_t      *pdcp_p          = NULL;
542 543
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
544
  pdcp_sn_t    sequence_number = 0;
545
  volatile sdu_size_t   payload_offset  = 0;
546
  rb_id_t      rb_id            = rb_idP;
547
  boolean_t    packet_forwarded = FALSE;
548 549
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
550
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
551
  uint16_t     pdcp_uid=0;
552

553
  MessageDef  *message_p        = NULL;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
554
  uint8_t     *gtpu_buffer_p    = NULL;
555 556 557
  uint32_t    rx_hfn_for_count;
  int         pdcp_sn_for_count;
  int         security_ok;
558
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
559
  LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
laurent's avatar
laurent committed
560
              "[MSG] PDCP UL %s PDU on rb_id %ld\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
Cedric Roux's avatar
Cedric Roux committed
561

562
  if (MBMS_flagP) {
Cai Yang's avatar
Cai Yang committed
563
    if(rb_idP >= NB_RB_MBMS_MAX) {
564
      LOG_E(PDCP,"RB id is too high (%ld/%d) %u rnti %x!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
Cai Yang's avatar
Cai Yang committed
565 566
      return FALSE;
    }
567 568

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
569
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
laurent's avatar
laurent committed
570
            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
571 572 573 574 575
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
576
    } else {
577
      LOG_D(PDCP, "Data indication notification for PDCP entity from UE %x to eNB %u "
laurent's avatar
laurent committed
578
            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
579
            ctxt_pP->rnti,
580
            ctxt_pP->module_id,
581 582 583
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
584 585
    }
  } else {
586
    rb_id = rb_idP % LTE_maxDRB;
Cai Yang's avatar
Cai Yang committed
587
    if(rb_id >= LTE_maxDRB) {
588
      LOG_E(PDCP,"RB id is too high (%ld/%d) %u UE %x!\n", rb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
Cai Yang's avatar
Cai Yang committed
589 590 591
      return FALSE;
    }
    if(rb_id <= 0) {
592
      LOG_E(PDCP,"RB id is too low (%ld/%d) %u UE %x!\n", rb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
Cai Yang's avatar
Cai Yang committed
593 594 595
      return FALSE;
    }

596
    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
597
    h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
598 599 600 601 602 603

    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);
604
      free_mem_block(sdu_buffer_pP, __func__);
605
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
606
      return FALSE;
607
    }
608
  }
609

610

611
  if (sdu_buffer_sizeP == 0) {
612 613
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
614
  }
615

616 617 618 619 620
  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);
  }
621 622

  /*
623 624
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
625
   */
626

627
  if (MBMS_flagP == 0 ) {
628 629 630
    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
631
      sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char *)sdu_buffer_pP->data);
632 633
    } else { // DRB
      pdcp_tailer_len = 0;
634

635
      if (pdcp_p->seq_num_size == 7) {
636
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_SHORT_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
637
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char *)sdu_buffer_pP->data);
638
      } else if (pdcp_p->seq_num_size == 12) {
639
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
640
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char *)sdu_buffer_pP->data);
641
      } else {
642
        //sequence_number = 4095;
643 644 645 646
        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);
647
        exit_fun("pdcp_data_ind wrong sequence number" );
648
      }
649

650 651
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
652

653 654 655 656
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
657 658 659 660
      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);
661
      free_mem_block(sdu_buffer_pP, __func__);
662

663 664 665 666 667
      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);
      }
668

669
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
670 671 672
      return FALSE;
    }

673
#if 0
674

675
    /* Removed by Cedric */
676
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
677
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
678
      /* if (dc == PDCP_DATA_PDU )
679 680 681
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
682
    } else {
frtabu's avatar
frtabu committed
683 684
      Pdcp_stats_rx_outoforder[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
      LOG_E(PDCP,
685 686 687
            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);
688
      /*
689 690
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
691
       */
bruno mongazon's avatar
bruno mongazon committed
692 693
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
694 695
      return FALSE;
    }
696

697
#endif
698 699 700

    // SRB1/2: control-plane data
    if (srb_flagP) {
701 702 703 704 705 706 707 708
      /* 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;
      }
709

710
      if (pdcp_p->security_activated == 1) {
711 712 713 714 715
        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);
        }
716

717
        security_ok = pdcp_validate_security(ctxt_pP,
frtabu's avatar
frtabu committed
718 719 720 721
                                             pdcp_p,
                                             srb_flagP,
                                             rb_idP,
                                             pdcp_header_len,
722 723
                                             rx_hfn_for_count,
                                             pdcp_sn_for_count,
frtabu's avatar
frtabu committed
724
                                             sdu_buffer_pP->data,
725
                                             sdu_buffer_sizeP - pdcp_tailer_len) == 0;
726

727 728 729 730 731
        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);
        }
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
      } 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++;
754
      }
755

frtabu's avatar
frtabu committed
756 757 758 759 760
      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__);
761

762
      // free_mem_block(new_sdu, __func__);
763 764 765 766 767
      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);
      }
768

769
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
770
      return TRUE;
771
    } /* if (srb_flagP) */
772 773 774 775

    /*
     * DRBs
     */
776
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
777

778
    switch (pdcp_p->rlc_mode) {
frtabu's avatar
frtabu committed
779 780 781
      case RLC_MODE_AM: {
        /* process as described in 36.323 5.1.2.1.2 */
        int reordering_window;
782

frtabu's avatar
frtabu committed
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
        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) {
800
          pdcp_p->rx_hfn++;
frtabu's avatar
frtabu committed
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
          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;
819
        }
820

frtabu's avatar
frtabu committed
821 822 823 824 825 826
        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);
          }
827

frtabu's avatar
frtabu committed
828 829 830 831 832 833 834 835 836
          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;
837

frtabu's avatar
frtabu committed
838 839 840 841 842 843 844 845
          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;
        }
846

frtabu's avatar
frtabu committed
847 848 849 850 851 852 853 854 855
        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;
        }
856

frtabu's avatar
frtabu committed
857 858 859 860 861 862 863 864 865 866 867 868 869 870
        /* 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 */
871

frtabu's avatar
frtabu committed
872
      case RLC_MODE_UM:
873

frtabu's avatar
frtabu committed
874 875 876 877
        /* process as described in 36.323 5.1.2.1.3 */
        if (sequence_number < pdcp_p->next_pdcp_rx_sn) {
          pdcp_p->rx_hfn++;
        }
878

frtabu's avatar
frtabu committed
879 880 881
        rx_hfn_for_count  = pdcp_p->rx_hfn;
        pdcp_sn_for_count = sequence_number;
        pdcp_p->next_pdcp_rx_sn = sequence_number + 1;
882

frtabu's avatar
frtabu committed
883 884 885
        if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
          pdcp_p->next_pdcp_rx_sn = 0;
          pdcp_p->rx_hfn++;
886 887
        }

frtabu's avatar
frtabu committed
888 889 890 891 892 893
        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);
          }
894

frtabu's avatar
frtabu committed
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
          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);
          }
910
        } else {
frtabu's avatar
frtabu committed
911
          security_ok = 1;
912
        }
913

frtabu's avatar
frtabu committed
914 915 916 917 918 919 920 921 922
        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;
        }
923

frtabu's avatar
frtabu committed
924
        break;
925

frtabu's avatar
frtabu committed
926 927
      default:
        LOG_E(PDCP, "bad RLC mode, cannot happen.\n");
928 929
        exit_fun("pdcp_data_ind bad RLC mode, cannot happen" );
        break;
930 931
    } /* switch (pdcp_p->rlc_mode) */
  } else { /* MBMS_flagP == 0 */
932
    payload_offset=0;
933
  }
934 935 936

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

939 940 941 942 943
    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);
    }
944

945
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
946 947 948
    return TRUE;
  }

949 950 951 952 953 954 955
  // 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)
   */
956

957
  if (LINK_ENB_PDCP_TO_GTPV1U) {
frtabu's avatar
frtabu committed
958
    if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
laurent's avatar
laurent committed
959
      LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %ld len %u\n",
960 961 962
            ctxt_pP->rnti,
            rb_id + 4,
            sdu_buffer_sizeP - payload_offset );
frtabu's avatar
frtabu committed
963 964 965 966 967 968 969 970 971 972 973
      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);
Cai Yang's avatar
Cai Yang committed
974 975 976 977
      if(gtpu_buffer_p == NULL) {
        LOG_E(PDCP,"OUT OF MEMORY");
        return FALSE;
      }
frtabu's avatar
frtabu committed
978 979
      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);
Cai Yang's avatar
Cai Yang committed
980 981 982 983
      if(message_p == NULL) {
        LOG_E(PDCP,"OUT OF MEMORY");
        return FALSE;
      }
frtabu's avatar
frtabu committed
984 985 986 987 988 989 990 991
      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;
    }
992
  } else {
frtabu's avatar
frtabu committed
993
    packet_forwarded = FALSE;
994
  }
995

996
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
997

998
  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
999 1000 1001 1002 1003 1004
   // 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;
1005

1006 1007
   // 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;
1008

1009
  }
frtabu's avatar
frtabu committed
1010

1011 1012
#endif

1013
  if (FALSE == packet_forwarded) {
laurent's avatar
laurent committed
1014
    notifiedFIFO_elt_t * new_sdu_p = newNotifiedFIFO_elt(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), 0, NULL, NULL);
1015

1016
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
1017 1018 1019 1020 1021 1022
        pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
      }

      /*
       * Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
       */
laurent's avatar
laurent committed
1023 1024 1025
      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;
Cai Yang's avatar
Cai Yang committed
1026 1027 1028 1029
      if((sdu_buffer_sizeP - payload_offset) < 0) {
        LOG_E(PDCP,"invalid PDCP SDU size!");
        return FALSE;
      }
1030 1031 1032 1033

      // 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) {
laurent's avatar
laurent committed
1034
        pdcpHead->rb_id = rb_id;
frtabu's avatar
frtabu committed
1035

1036
        if (EPC_MODE_ENABLED) {
frtabu's avatar
frtabu committed
1037 1038 1039 1040 1041
          /* 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 ) {
laurent's avatar
laurent committed
1042
            pdcpHead->inst  = ctxt_pP->module_id;
frtabu's avatar
frtabu committed
1043 1044
          } else {  // nfapi_mode
            if (UE_NAS_USE_TUN) {
laurent's avatar
laurent committed
1045
              pdcpHead->inst  = ctxt_pP->module_id;
frtabu's avatar
frtabu committed
1046
            } else {
laurent's avatar
laurent committed
1047
              pdcpHead->inst  = 1;
frtabu's avatar
frtabu committed
1048
            }
frtabu's avatar
frtabu committed
1049
          } // nfapi_mode
1050
        }
1051
      } else {
laurent's avatar
laurent committed
1052 1053
        pdcpHead->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
        pdcpHead->inst  = ctxt_pP->module_id;
1054
      }
1055

1056
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
frtabu's avatar
frtabu committed
1057
        static uint32_t pdcp_inst = 0;
laurent's avatar
laurent committed
1058 1059
        pdcpHead->inst = pdcp_inst++;
        LOG_D(PDCP, "inst=%d size=%d\n", pdcpHead->inst, pdcpHead->data_size);
1060
      }
1061

laurent's avatar
laurent committed
1062
      memcpy(pdcpHead+1,
1063
             &sdu_buffer_pP->data[payload_offset],
1064
             sdu_buffer_sizeP - payload_offset);
laurent's avatar
laurent committed
1065 1066 1067 1068
      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); 
1069

frtabu's avatar
frtabu committed
1070 1071 1072 1073 1074 1075
    /* 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);
1076
  }
1077

1078
  /* Update PDCP statistics */
frtabu's avatar
frtabu committed
1079 1080
  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 ) {
1081
      break;
1082
    }
1083 1084
  }

1085
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1086
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1087
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1088
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1089

1090
  Pdcp_stats_rx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=sequence_number;
1091
  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]);
1092
  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]);
1093
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
1094
  free_mem_block(sdu_buffer_pP, __func__);
1095

1096 1097 1098 1099 1100
  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);
  }
1101

1102
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
1103 1104 1105
  return TRUE;
}

frtabu's avatar
frtabu committed
1106
void pdcp_update_stats(const protocol_ctxt_t *const  ctxt_pP) {
1107
  uint16_t           pdcp_uid = 0;
Navid Nikaein's avatar
Navid Nikaein committed
1108
  uint8_t            rb_id     = 0;
1109

frtabu's avatar
frtabu committed
1110 1111 1112
  // 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++) {
1113 1114
      //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
1115
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
          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;
        }
1127

frtabu's avatar
frtabu committed
1128 1129 1130 1131
        // 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;
1132
      }
frtabu's avatar
frtabu committed
1133

Raymond Knopp's avatar
Raymond Knopp committed
1134
      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
          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;
1151
      }
Navid Nikaein's avatar
Navid Nikaein committed
1152 1153 1154
    }
  }
}
1155 1156


1157
//-----------------------------------------------------------------------------
1158 1159
void
pdcp_run (
frtabu's avatar
frtabu committed
1160
  const protocol_ctxt_t *const  ctxt_pP
1161 1162
)
//-----------------------------------------------------------------------------
1163
{
1164 1165 1166 1167 1168
  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);
  }
1169

1170
  pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
1171
  pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023
1172
  pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
Navid Nikaein's avatar
Navid Nikaein committed
1173
  pdcp_update_stats(ctxt_pP);
1174
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
1175 1176 1177
  MessageDef   *msg_p;
  int           result;
  protocol_ctxt_t  ctxt;
1178

1179 1180 1181 1182 1183 1184
  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
1185 1186 1187 1188 1189 1190 1191 1192 1193
        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
1194
          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
1195 1196 1197 1198 1199 1200 1201 1202
                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
1203
          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
1204 1205 1206 1207 1208 1209 1210
          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
1211 1212
                                  RRC_DCCH_DATA_REQ (msg_p).mode,
                                  NULL, NULL
frtabu's avatar
frtabu committed
1213
                                 );
1214

frtabu's avatar
frtabu committed
1215 1216
          if (result != TRUE)
            LOG_E(PDCP, "PDCP data request failed!\n");
1217

frtabu's avatar
frtabu committed
1218 1219
          // 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);
Cai Yang's avatar
Cai Yang committed
1220 1221 1222 1223
          if(result != EXIT_SUCCESS) {
            LOG_E(PDCP,"Failed to free memory (%d)!\n", result);
            return;
          }
frtabu's avatar
frtabu committed
1224
          break;
1225

frtabu's avatar
frtabu committed
1226 1227 1228 1229 1230 1231
        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;
1232

frtabu's avatar
frtabu committed
1233 1234 1235
          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);
          }
1236

frtabu's avatar
frtabu committed
1237 1238 1239
          //paging pdcp log
          LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
        }
1240
        break;
frtabu's avatar
frtabu committed
1241 1242 1243 1244

        default:
          LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
          break;
1245
      }
1246 1247

      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
Cai Yang's avatar
Cai Yang committed
1248 1249 1250 1251
      if(result != EXIT_SUCCESS) {
        LOG_E(PDCP,"Failed to free memory (%d)!\n", result);
        return;
      }
1252
    }
1253
  } while(msg_p != NULL);
1254

1255
  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
1256 1257
  //  if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) {
  if (!EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {
1258
    pdcp_fifo_read_input_sdus(ctxt_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
1259
  }
1260

1261
  // PDCP -> NAS/IP traffic: RX
1262 1263
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
frtabu's avatar
frtabu committed
1264
  } else {
1265 1266
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1267

1268
  pdcp_fifo_flush_sdus(ctxt_pP);
1269

1270 1271 1272 1273 1274
  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);
  }
1275

1276 1277 1278 1279 1280
  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
1281

1282
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
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 1340 1341 1342 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 1372 1373 1374 1375 1376 1377 1378
//-----------------------------------------------------------------------------
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) {
1379 1380
  //if (EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {

1381
    pdcp_fifo_read_input_mbms_sdus_fromtun(ctxt_pP);
1382
  //}
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410

  // 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
1411
void pdcp_init_stats_UE(module_id_t mod, uint16_t uid) {
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443
  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
1444
void pdcp_add_UE(const protocol_ctxt_t *const  ctxt_pP) {
1445
  int i, ue_flag=1; //, ret=-1; to be decied later
frtabu's avatar
frtabu committed
1446 1447

  for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1448 1449 1450 1451 1452
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti) {
      ue_flag=-1;
      break;
    }
  }
frtabu's avatar
frtabu committed
1453 1454 1455 1456 1457 1458 1459 1460

  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);
1461
        pdcp_init_stats_UE(ctxt_pP->module_id, i);
frtabu's avatar
frtabu committed
1462 1463
        // ret=1;
        break;
1464 1465 1466
      }
    }
  }
frtabu's avatar
frtabu committed
1467

1468 1469
  //return ret;
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1470

1471 1472 1473
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
frtabu's avatar
frtabu committed
1474
  const protocol_ctxt_t *const  ctxt_pP
1475 1476 1477
)
//-----------------------------------------------------------------------------
{
1478 1479
  LTE_DRB_Identity_t  srb_id         = 0;
  LTE_DRB_Identity_t  drb_id         = 0;
1480 1481
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1482
  int i;
frtabu's avatar
frtabu committed
1483
  // check and remove SRBs first
Raymond Knopp's avatar
 
Raymond Knopp committed
1484

frtabu's avatar
frtabu committed
1485 1486
  for(int i = 0; i<MAX_MOBILES_PER_ENB; i++) {
    if(pdcp_eNB_UE_instance_to_rnti[i] == ctxt_pP->rnti) {
1487 1488 1489 1490 1491
      pdcp_eNB_UE_instance_to_rnti[i] = NOT_A_RNTI;
      break;
    }
  }

Emad's avatar
Emad committed
1492
  for (srb_id=1; srb_id<3; srb_id++) {
1493 1494
    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
1495 1496
  }

1497
  for (drb_id=0; drb_id<LTE_maxDRB; drb_id++) {
1498 1499
    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
1500 1501
  }

1502 1503
  (void)h_rc; /* remove gcc warning "set but not used" */

1504
  // remove ue for pdcp enb inst
frtabu's avatar
frtabu committed
1505
  for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1506 1507
    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
1508 1509
            pdcp_enb[ctxt_pP->module_id].uid[i],
            pdcp_enb[ctxt_pP->module_id].rnti[i]);
1510 1511 1512 1513 1514 1515
      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;
    }
  }
1516

Raymond Knopp's avatar
 
Raymond Knopp committed
1517 1518 1519 1520
  return 1;
}


1521 1522 1523
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
frtabu's avatar
frtabu committed
1524
  const protocol_ctxt_t *const  ctxt_pP,
1525 1526 1527
  LTE_SRB_ToAddModList_t  *const srb2add_list_pP,
  LTE_DRB_ToAddModList_t  *const drb2add_list_pP,
  LTE_DRB_ToReleaseList_t *const drb2release_list_pP,
1528 1529 1530
  const uint8_t                   security_modeP,
  uint8_t                  *const kRRCenc_pP,
  uint8_t                  *const kRRCint_pP,
frtabu's avatar
frtabu committed
1531 1532 1533
  uint8_t                  *const kUPenc_pP,
  LTE_PMCH_InfoList_r9_t  *const pmch_InfoList_r9_pP,
  rb_id_t                 *const defaultDRB
1534
)
1535
//-----------------------------------------------------------------------------
1536
{
1537
  long int        lc_id          = 0;
1538
  LTE_DRB_Identity_t  srb_id     = 0;
1539
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1540
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1541 1542
  LTE_DRB_Identity_t  drb_id     = 0;
  LTE_DRB_Identity_t *pdrb_id_p  = NULL;
1543
  uint8_t         drb_sn         = 12;
1544 1545
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1546
  long int        cnt            = 0;
1547 1548
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1549 1550
  LTE_SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  LTE_DRB_ToAddMod_t *drb_toaddmod_p = NULL;
1551
  pdcp_t         *pdcp_p         = NULL;
1552 1553
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1554 1555
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
1556
  int i,j;
1557 1558
  LTE_MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  LTE_MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1559 1560 1561 1562 1563 1564
  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);
1565

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

1568
  if (srb2add_list_pP != NULL) {
1569 1570 1571 1572
    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;
1573
      lc_id = srb_id;
1574
      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
1575
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1576

1577 1578 1579 1580 1581
      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);
1582
      } else {
1583 1584 1585
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1586

1587 1588 1589 1590 1591 1592
        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
1593 1594
        } else {
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
1595 1596 1597
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1598 1599 1600 1601
      }

      if (srb_toaddmod_p->rlc_Config) {
        switch (srb_toaddmod_p->rlc_Config->present) {
frtabu's avatar
frtabu committed
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
          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;
            }
1629 1630

            break;
1631

frtabu's avatar
frtabu committed
1632
          case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue:
1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
            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
1649
            // already the default values
1650 1651
            break;

frtabu's avatar
frtabu committed
1652 1653 1654
          default:
            DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
            break;
1655
        }
1656
      }
1657
    }
1658
  }
1659

1660 1661
  // reset the action

1662
  if (drb2add_list_pP != NULL) {
1663 1664 1665
    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
1666

1667 1668 1669 1670 1671 1672 1673 1674 1675
      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
1676
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1677 1678 1679
        continue;
      }

1680
      DevCheck4(drb_id < LTE_maxDRB, drb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
1681
      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
1682
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1683

1684 1685 1686 1687 1688
      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);
1689 1690
      } else {
        action = CONFIG_ACTION_ADD;
1691 1692 1693
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1694
        // save the first configured DRB-ID as the default DRB-ID
1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707
        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;
1708
        } else if (h_rc != HASH_TABLE_OK) {
1709 1710 1711 1712 1713 1714 1715 1716 1717
          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
1718
        }
1719
      }
1720 1721 1722 1723 1724 1725 1726 1727

      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;
1728
          drb_sn = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size
1729 1730 1731 1732 1733 1734 1735 1736 1737
          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
1738 1739
          case LTE_PDCP_Config__headerCompression_PR_NOTHING:
          case LTE_PDCP_Config__headerCompression_PR_notUsed:
1740
            header_compression_profile=0x0;
frtabu's avatar
frtabu committed
1741
            break;
1742

frtabu's avatar
frtabu committed
1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
          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;
1771

frtabu's avatar
frtabu committed
1772 1773 1774 1775
          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;
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
        }

        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);
1794
      }
1795
    }
1796 1797
  }

1798
  if (drb2release_list_pP != NULL) {
1799 1800 1801
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1802
      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
1803
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1804 1805

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1806
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1807 1808 1809
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1810
      }
1811

frtabu's avatar
frtabu committed
1812
      lc_id = pdcp_p->lcid;
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829
      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);
1830
      h_rc = hashtable_remove(pdcp_coll_p, key);
1831 1832

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1833
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1834
        key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
frtabu's avatar
frtabu committed
1835
        h_defaultDRB_rc = hashtable_get(pdcp_coll_p, key_defaultDRB, (void **)&pdcp_p);
1836 1837 1838 1839 1840 1841 1842 1843 1844

        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
      }
1845
    }
1846 1847
  }

1848
  if (pmch_InfoList_r9_pP != NULL) {
1849 1850 1851 1852 1853
    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
1854

1855
        if (0/*MBMS_SessionInfo_p->sessionId_r9*/)
1856 1857 1858
          lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        else
          lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
frtabu's avatar
frtabu committed
1859

1860
        mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
frtabu's avatar
frtabu committed
1861
        //        mch_id = j;
1862 1863 1864

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

1867
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1868 1869 1870 1871 1872
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
1873
          drb_id =  (mch_id * LTE_maxSessionPerPMCH ) + lc_id; // + (LTE_maxDRB + 3); // 15
1874

1875
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1876 1877 1878
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1879
          }
1880 1881
        }

1882
        LOG_I(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
frtabu's avatar
frtabu committed
1883 1884 1885 1886 1887 1888
              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);
1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904
        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
1905
      }
1906
    }
1907
  }
1908

1909
  return 0;
1910 1911
}

1912
//-----------------------------------------------------------------------------
1913 1914
boolean_t
pdcp_config_req_asn1 (
frtabu's avatar
frtabu committed
1915 1916
  const protocol_ctxt_t *const  ctxt_pP,
  pdcp_t          *const        pdcp_pP,
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929
  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)
1930
//-----------------------------------------------------------------------------
1931
{
1932

1933
  switch (actionP) {
frtabu's avatar
frtabu committed
1934
    case CONFIG_ACTION_ADD:
Cai Yang's avatar
Cai Yang committed
1935 1936 1937 1938
      if(pdcp_pP == NULL) {
        LOG_E(PDCP,"pdcp_pP is NULL!\n");
        return FALSE;
      }
frtabu's avatar
frtabu committed
1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952

      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;
1953
          }
frtabu's avatar
frtabu committed
1954

1955
          pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
1956
          pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
frtabu's avatar
frtabu committed
1957
        }
1958

frtabu's avatar
frtabu committed
1959 1960 1961 1962
        //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;
1963
      }
1964

frtabu's avatar
frtabu committed
1965 1966 1967 1968 1969
      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;
1970

frtabu's avatar
frtabu committed
1971
      if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1972 1973
        pdcp_pP->seq_num_size = 12;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 12) - 1;
frtabu's avatar
frtabu committed
1974
      } else if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
1975 1976
        pdcp_pP->seq_num_size = 7;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 7) - 1;
frtabu's avatar
frtabu committed
1977
      } else {
1978 1979
        pdcp_pP->seq_num_size = 5;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 5) - 1;
frtabu's avatar
frtabu committed
1980
      }
1981

frtabu's avatar
frtabu committed
1982 1983 1984 1985 1986 1987 1988
      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
1989
      LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %ld) "
1990
            "configured with SN size %d bits and RLC %s\n",
frtabu's avatar
frtabu committed
1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
            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,
2003
          rb_idP,
frtabu's avatar
frtabu committed
2004 2005 2006 2007 2008 2009
          lc_idP,
          security_modeP,
          kRRCenc_pP,
          kRRCint_pP,
          kUPenc_pP);
      }
2010

frtabu's avatar
frtabu committed
2011
      break;
2012

frtabu's avatar
frtabu committed
2013
    case CONFIG_ACTION_MODIFY:
Cai Yang's avatar
Cai Yang committed
2014 2015 2016 2017
      if(pdcp_pP == NULL) {
        LOG_E(PDCP,"pdcp_pP is NULL!\n");
        return FALSE;
      }
frtabu's avatar
frtabu committed
2018 2019 2020
      pdcp_pP->header_compression_profile=header_compression_profileP;
      pdcp_pP->status_report = rb_reportP;
      pdcp_pP->rlc_mode = rlc_modeP;
2021

frtabu's avatar
frtabu committed
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
      /* 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);
      }
2034

frtabu's avatar
frtabu committed
2035 2036 2037 2038 2039 2040 2041 2042 2043
      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
2044
            "RB id %ld reconfigured with SN size %d and RLC %s \n",
frtabu's avatar
frtabu committed
2045 2046 2047 2048
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            rb_idP,
            rb_snP,
2049
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
frtabu's avatar
frtabu committed
2050
      break;
2051

frtabu's avatar
frtabu committed
2052
    case CONFIG_ACTION_REMOVE:
Cai Yang's avatar
Cai Yang committed
2053 2054 2055 2056
      if(pdcp_pP == NULL) {
        LOG_E(PDCP,"pdcp_pP is NULL!\n");
        return FALSE;
      }
frtabu's avatar
frtabu committed
2057 2058
      //#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
2059
      LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE LCID %d RBID %ld configured\n",
frtabu's avatar
frtabu committed
2060 2061 2062
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            rb_idP);
2063

frtabu's avatar
frtabu committed
2064 2065 2066
      if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
        // pdcp_remove_UE(ctxt_pP);
      }
2067

frtabu's avatar
frtabu committed
2068 2069 2070 2071
      /* Security keys */
      if (pdcp_pP->kUPenc != NULL) {
        free(pdcp_pP->kUPenc);
      }
2072

frtabu's avatar
frtabu committed
2073 2074 2075
      if (pdcp_pP->kRRCint != NULL) {
        free(pdcp_pP->kRRCint);
      }
2076

frtabu's avatar
frtabu committed
2077 2078 2079
      if (pdcp_pP->kRRCenc != NULL) {
        free(pdcp_pP->kRRCenc);
      }
2080

frtabu's avatar
frtabu committed
2081 2082
      memset(pdcp_pP, 0, sizeof(pdcp_t));
      break;
2083

frtabu's avatar
frtabu committed
2084 2085
    case CONFIG_ACTION_MBMS_ADD:
    case CONFIG_ACTION_MBMS_MODIFY:
laurent's avatar
laurent committed
2086
      LOG_D(PDCP," %s service_id/mch index %d, session_id/lcid %d, rbid %ld configured\n",
frtabu's avatar
frtabu committed
2087 2088 2089 2090 2091
            //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);
2092

frtabu's avatar
frtabu committed
2093 2094 2095 2096 2097 2098 2099
      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;
      }
2100

frtabu's avatar
frtabu committed
2101
      break;
2102

frtabu's avatar
frtabu committed
2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117
    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;
2118
  }
2119

2120 2121
  return 0;
}
2122

2123 2124 2125
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
frtabu's avatar
frtabu committed
2126 2127
  const protocol_ctxt_t *const  ctxt_pP,
  pdcp_t          *const pdcp_pP,
2128 2129 2130
  const rb_id_t         rb_idP,
  const uint16_t        lc_idP,
  const uint8_t         security_modeP,
frtabu's avatar
frtabu committed
2131 2132 2133
  uint8_t         *const kRRCenc,
  uint8_t         *const kRRCint,
  uint8_t         *const  kUPenc)
2134
//-----------------------------------------------------------------------------
2135
{
Cai Yang's avatar
Cai Yang committed
2136 2137 2138 2139
  if(pdcp_pP == NULL) {
    LOG_E(PDCP,"pdcp_pP is NULL!\n");
    return;
  }
2140

2141
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
2142 2143
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
2144 2145
    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
2146 2147
          pdcp_pP->cipheringAlgorithm,
          pdcp_pP->integrityProtAlgorithm);
2148 2149 2150 2151 2152
    pdcp_pP->kRRCenc = kRRCenc;
    pdcp_pP->kRRCint = kRRCint;
    pdcp_pP->kUPenc  = kUPenc;
    /* Activate security */
    pdcp_pP->security_activated = 1;
frtabu's avatar
frtabu committed
2153 2154 2155 2156 2157 2158
    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);
2159
  } else {
frtabu's avatar
frtabu committed
2160 2161 2162 2163 2164
    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",
2165 2166
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
2167
  }
2168 2169
}

2170
//-----------------------------------------------------------------------------
2171 2172
void
rrc_pdcp_config_req (
frtabu's avatar
frtabu committed
2173
  const protocol_ctxt_t *const  ctxt_pP,
2174 2175 2176 2177
  const srb_flag_t srb_flagP,
  const uint32_t actionP,
  const rb_id_t rb_idP,
  const uint8_t security_modeP)
2178
//-----------------------------------------------------------------------------
2179
{
2180
  pdcp_t *pdcp_p = NULL;
2181 2182
  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
2183
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
2184

2185
  if (h_rc == HASH_TABLE_OK) {
frtabu's avatar
frtabu committed
2186 2187 2188
    /*
     * Initialize sequence number state variables of relevant PDCP entity
     */
2189
    switch (actionP) {
frtabu's avatar
frtabu committed
2190
      case CONFIG_ACTION_ADD:
2191 2192 2193 2194 2195
        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
2196
          pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
2197 2198
        } else {
          pdcp_p->is_ue = FALSE;
frtabu's avatar
frtabu committed
2199
        }
2200

2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214
        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
2215
        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld (already added) configured\n",
2216 2217
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              rb_idP);
frtabu's avatar
frtabu committed
2218
        break;
2219

frtabu's avatar
frtabu committed
2220 2221
      case CONFIG_ACTION_MODIFY:
        break;
2222

frtabu's avatar
frtabu committed
2223
      case CONFIG_ACTION_REMOVE:
laurent's avatar
laurent committed
2224
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE: radio bearer id %ld configured\n",
frtabu's avatar
frtabu committed
2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
              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;
2237

frtabu's avatar
frtabu committed
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254
      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;
2255
    }
frtabu's avatar
frtabu committed
2256 2257 2258 2259 2260
  } else {
    switch (actionP) {
      case CONFIG_ACTION_ADD:
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
2261

frtabu's avatar
frtabu committed
2262 2263 2264 2265 2266 2267 2268
        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;
2269

frtabu's avatar
frtabu committed
2270 2271 2272 2273 2274 2275
          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;
          }
2276

frtabu's avatar
frtabu committed
2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288
          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;
          }
2289

frtabu's avatar
frtabu committed
2290 2291 2292
          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
2293
          LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld configured\n",
frtabu's avatar
frtabu committed
2294 2295 2296
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
                rb_idP);
        }
2297

frtabu's avatar
frtabu committed
2298
        break;
2299

frtabu's avatar
frtabu committed
2300 2301 2302 2303 2304 2305 2306 2307
      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));
2308
    }
2309
  }
2310
}
2311

frtabu's avatar
frtabu committed
2312 2313 2314
pdcp_data_ind_func_t get_pdcp_data_ind_func() {
  return pdcp_params.pdcp_data_ind_func;
}
2315

2316
void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req) {
frtabu's avatar
frtabu committed
2317
  pdcp_params.send_rlc_data_req_func = send_rlc_data_req;
2318
}
2319

2320
void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) {
frtabu's avatar
frtabu committed
2321 2322
  pdcp_params.pdcp_data_ind_func = pdcp_data_ind;
}
2323

2324 2325 2326 2327 2328 2329
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 ;
2330 2331
  }

2332 2333 2334 2335
  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":""));
2336

2337
  if (PDCP_USE_NETLINK) {
2338 2339
    nas_getparams();

2340
    if(UE_NAS_USE_TUN) {
2341
      int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1;
frtabu's avatar
frtabu committed
2342
      netlink_init_tun("ue",num_if);
2343 2344
      if (IS_SOFTMODEM_NOS1)
    	  nas_config(1, 1, 2, "ue");
2345
      netlink_init_mbms_tun("uem");
2346
      nas_config_mbms(1, 2, 2, "uem");
2347 2348
      LOG_I(PDCP, "UE pdcp will use tun interface\n");
    } else if(ENB_NAS_USE_TUN) {
frtabu's avatar
frtabu committed
2349
      netlink_init_tun("enb",1);
2350
      nas_config(1, 1, 1, "enb");
2351
      if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
2352
        netlink_init_mbms_tun("enm");
2353 2354 2355
      	nas_config_mbms(1, 2, 1, "enm"); 
      	LOG_I(PDCP, "ENB pdcp will use mbms tun interface\n");
      }
2356
      LOG_I(PDCP, "ENB pdcp will use tun interface\n");
2357
    } else {
2358
      LOG_I(PDCP, "pdcp will use kernel modules\n");
2359 2360
      netlink_init();
    }
2361 2362 2363
  }else{
         if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
             LOG_W(PDCP, "ENB pdcp will use tun interface for MBMS\n");
2364
            netlink_init_mbms_tun("enm");
2365 2366 2367 2368 2369
             nas_config_mbms_s1(1, 2, 1, "enm"); 
         }else
             LOG_E(PDCP, "ENB pdcp will not use tun interface\n");
   }

2370
  return pdcp_params.optmask ;
2371 2372
}

2373

2374 2375 2376
//-----------------------------------------------------------------------------
void
pdcp_free (
frtabu's avatar
frtabu committed
2377
  void *pdcp_pP
2378 2379 2380
)
//-----------------------------------------------------------------------------
{
frtabu's avatar
frtabu committed
2381
  pdcp_t *pdcp_p = (pdcp_t *)pdcp_pP;
2382

2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398
  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);
  }
2399 2400 2401
}

//-----------------------------------------------------------------------------
2402 2403
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
2404 2405 2406 2407
{
}

//-----------------------------------------------------------------------------
2408
void pdcp_layer_init(void)
2409
//-----------------------------------------------------------------------------
2410
{
Lionel Gauthier's avatar
Lionel Gauthier committed
2411
  module_id_t       instance;
2412
  int i,j;
Lionel Gauthier's avatar
Lionel Gauthier committed
2413 2414
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
2415
  /*
2416 2417
   * Initialize SDU list
   */
laurent's avatar
laurent committed
2418
  initNotifiedFIFO(&pdcp_sdu_list);
2419
  pdcp_coll_p = hashtable_create ((LTE_maxDRB + 2) * NUMBER_OF_UE_MAX, NULL, pdcp_free);
Cai Yang's avatar
Cai Yang committed
2420 2421 2422 2423
  if(pdcp_coll_p == NULL) {
    LOG_E(PDCP,"UNRECOVERABLE error, PDCP hashtable_create failed");
    return;
  }
2424

2425
  for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
2426 2427
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2428
        memset(&pdcp_mbms_array_ue[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2429
      }
2430
    }
frtabu's avatar
frtabu committed
2431

2432
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
2433
  }
2434

frtabu's avatar
frtabu committed
2435
  pdcp_eNB_UE_instance_to_rnti_index = 0;
2436

2437
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
2438 2439
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2440
        memset(&pdcp_mbms_array_eNB[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2441
      }
2442
    }
2443
  }
2444

2445 2446
#ifdef MBMS_MULTICAST_OUT
  mbms_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
frtabu's avatar
frtabu committed
2447

2448 2449 2450
  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
2451
#endif
2452 2453 2454 2455
  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;
2456
  memset(pdcp_enb, 0, sizeof(pdcp_enb_t));
2457 2458
  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
2459

2460 2461
  for (i = 0; i < MAX_eNB; i++) {
    for (j = 0; j < MAX_MOBILES_PER_ENB; j++) {
2462 2463 2464 2465
      Pdcp_stats_tx_window_ms[i][j]=100;
      Pdcp_stats_rx_window_ms[i][j]=100;
    }
  }
2466

2467
  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
2468 2469
  memset(Pdcp_stats_tx_w, 0, sizeof(Pdcp_stats_tx_w));
  memset(Pdcp_stats_tx_tmp_w, 0, sizeof(Pdcp_stats_tx_tmp_w));
2470
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
2471 2472
  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));
2473
  memset(Pdcp_stats_tx_sn, 0, sizeof(Pdcp_stats_tx_sn));
2474
  memset(Pdcp_stats_tx_throughput_w, 0, sizeof(Pdcp_stats_tx_throughput_w));
2475 2476
  memset(Pdcp_stats_tx_aiat, 0, sizeof(Pdcp_stats_tx_aiat));
  memset(Pdcp_stats_tx_iat, 0, sizeof(Pdcp_stats_tx_iat));
2477
  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
2478 2479
  memset(Pdcp_stats_rx_w, 0, sizeof(Pdcp_stats_rx_w));
  memset(Pdcp_stats_rx_tmp_w, 0, sizeof(Pdcp_stats_rx_tmp_w));
2480
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
2481 2482
  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));
2483
  memset(Pdcp_stats_rx_sn, 0, sizeof(Pdcp_stats_rx_sn));
2484
  memset(Pdcp_stats_rx_goodput_w, 0, sizeof(Pdcp_stats_rx_goodput_w));
2485 2486 2487
  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));
2488 2489 2490
}

//-----------------------------------------------------------------------------
2491 2492
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
2493
{
laurent's avatar
laurent committed
2494 2495
  //list_free (&pdcp_sdu_list);
  while(pollNotifiedFIFO(&pdcp_sdu_list)) {};
frtabu's avatar
frtabu committed
2496
  hashtable_destroy(&pdcp_coll_p);
2497
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
2498

2499 2500 2501 2502
  if(mbms_socket != -1) {
    close(mbms_socket);
    mbms_socket = -1;
  }
frtabu's avatar
frtabu committed
2503

2504
#endif
2505
}