pdcp.c 96.5 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
#include <pthread.h>
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"
Laurent Thomas's avatar
Laurent Thomas committed
64
#include <openair3/ocp-gtpu/gtp_itf.h>
Lionel Gauthier's avatar
 
Lionel Gauthier committed
65

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

68

69

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

76
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
77 78 79 80 81 82 83 84
  #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;
85 86
#endif

87 88 89 90 91 92 93 94 95 96 97 98 99
uint32_t Pdcp_stats_tx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB];
uint32_t Pdcp_stats_tx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_throughput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_tx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
100

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
uint32_t Pdcp_stats_rx_window_ms[MAX_eNB][MAX_MOBILES_PER_ENB];
uint32_t Pdcp_stats_rx[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_bytes[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_bytes_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_bytes_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_sn[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_goodput_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_aiat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_aiat_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_aiat_tmp_w[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_iat[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
uint32_t Pdcp_stats_rx_outoforder[MAX_eNB][MAX_MOBILES_PER_ENB][NB_RB_MAX];
int pdcp_pc5_sockfd;
struct sockaddr_in prose_ctrl_addr;
struct sockaddr_in prose_pdcp_addr;
struct sockaddr_in pdcp_sin;
119
/* pdcp module parameters and related functions*/
frtabu's avatar
frtabu committed
120
static pdcp_params_t pdcp_params= {0,NULL};
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
rnti_t                 pdcp_UE_UE_module_id_to_rnti[MAX_MOBILES_PER_ENB];
rnti_t                 pdcp_eNB_UE_instance_to_rnti[MAX_MOBILES_PER_ENB]; // for noS1 mode
unsigned int           pdcp_eNB_UE_instance_to_rnti_index;

signed int             pdcp_2_nas_irq;
pdcp_stats_t              UE_pdcp_stats[MAX_MOBILES_PER_ENB];
pdcp_stats_t              eNB_pdcp_stats[NUMBER_OF_eNB_MAX];

static pdcp_mbms_t               pdcp_mbms_array_ue[MAX_MOBILES_PER_ENB][LTE_maxServiceCount][LTE_maxSessionPerPMCH];   // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h
static pdcp_mbms_t               pdcp_mbms_array_eNB[NUMBER_OF_eNB_MAX][LTE_maxServiceCount][LTE_maxSessionPerPMCH]; // some constants from openair2/RRC/LTE/MESSAGES/asn1_constants.h
static sdu_size_t             pdcp_input_sdu_remaining_size_to_read;
static sdu_size_t             pdcp_output_header_bytes_to_write;
static sdu_size_t             pdcp_output_sdu_bytes_to_write;
notifiedFIFO_t         pdcp_sdu_list;

pdcp_enb_t pdcp_enb[MAX_NUM_CCs];

138

139 140 141 142 143 144 145
extern volatile int oai_exit;

pthread_t pdcp_stats_thread_desc;

void *pdcp_stats_thread(void *param) {

   FILE *fd;
146 147 148 149 150 151
   int old_byte_cnt[MAX_MOBILES_PER_ENB][NB_RB_MAX],old_byte_cnt_rx[MAX_MOBILES_PER_ENB][NB_RB_MAX];
   for (int i=0;i<MAX_MOBILES_PER_ENB;i++)
     for (int j=0;j<NB_RB_MAX;j++) {
	old_byte_cnt[i][j]=0;
	old_byte_cnt_rx[i][j]=0;
     }
152 153 154 155 156 157 158 159
   while (!oai_exit) {
     sleep(1);

     fd=fopen("PDCP_stats.log","w+");
     AssertFatal(fd!=NULL,"Cannot open MAC_stats.log\n");
     int drb_id=3;
     for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
        if (pdcp_enb[0].rnti[UE_id]>0) {
160 161
           fprintf(fd,"PDCP: CRNTI %x, DRB %d: tx_bytes %d, DL Throughput %e\n",
                   pdcp_enb[0].rnti[UE_id],drb_id,
162
                   Pdcp_stats_tx_bytes[0][UE_id][drb_id],
163 164 165 166
                   (double)((Pdcp_stats_tx_bytes[0][UE_id][drb_id]-old_byte_cnt[UE_id][drb_id])<<3));
           fprintf(fd,"                              rx_bytes %d, UL Throughput %e\n",             
                   Pdcp_stats_rx_bytes[0][UE_id][drb_id],
                   (double)((Pdcp_stats_rx_bytes[0][UE_id][drb_id]-old_byte_cnt_rx[UE_id][drb_id])<<3));
Raymond Knopp's avatar
Raymond Knopp committed
167 168
           old_byte_cnt[UE_id][drb_id]=Pdcp_stats_tx_bytes[0][UE_id][drb_id];
           old_byte_cnt_rx[UE_id][drb_id]=Pdcp_stats_rx_bytes[0][UE_id][drb_id];
169 170 171
        }
     }
     fclose(fd);
172
   }
173
   return(NULL);
174 175
}

176 177 178
uint64_t get_pdcp_optmask(void) {
  return pdcp_params.optmask;
}
179 180 181 182 183 184 185 186
//-----------------------------------------------------------------------------
/*
 * 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()
 */
187
boolean_t pdcp_data_req(
frtabu's avatar
frtabu committed
188
  protocol_ctxt_t  *ctxt_pP,
189 190 191 192 193 194
  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
195 196 197
  const pdcp_transmission_mode_t modeP,
  const uint32_t *const sourceL2Id,
  const uint32_t *const destinationL2Id
198 199
)
//-----------------------------------------------------------------------------
200
{
201
  pdcp_t            *pdcp_p          = NULL;
202 203 204 205 206
  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;
207 208
  mem_block_t       *pdcp_pdu_p      = NULL;
  rlc_op_status_t    rlc_status;
209
  boolean_t          ret             = TRUE;
210 211
  hash_key_t         key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t     h_rc;
212 213
  uint8_t            rb_offset= (srb_flagP == 0) ? DTCH -1 : 0;
  uint16_t           pdcp_uid=0;
214
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
215
  CHECK_CTXT_ARGS(ctxt_pP);
Cedric Roux's avatar
Cedric Roux committed
216
#if T_TRACER
frtabu's avatar
frtabu committed
217

Cedric Roux's avatar
Cedric Roux committed
218 219
  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
220

Cedric Roux's avatar
Cedric Roux committed
221 222
#endif

223 224 225 226 227 228 229 230
  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?
   */
231
  AssertFatal(sdu_buffer_sizeP<= MAX_IP_PACKET_SIZE,"Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
frtabu's avatar
frtabu committed
232
              sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
233

234
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
laurent's avatar
laurent committed
235
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
236
  } else {
237
    if (srb_flagP) {
laurent's avatar
laurent committed
238
      AssertError (rb_idP < 3, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
239
    } else {
laurent's avatar
laurent committed
240
      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
241
    }
242
  }
243

244
  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
245
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
246

247 248
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
laurent's avatar
laurent committed
249
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %ld Ignoring SDU...\n",
frtabu's avatar
frtabu committed
250 251
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
252
      ctxt_pP->configured=FALSE;
253
      return FALSE;
254
    }
frtabu's avatar
frtabu committed
255
  } else {
256
    // instance for a given RB is configured
257
    ctxt_pP->configured=TRUE;
258
  }
259

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

266
  // PDCP transparent mode for MBMS traffic
267

268
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
269
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
270
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
271 272 273

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

275 276 277 278
      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
279
        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %ld \n", srb_flagP, rb_idP);
280
      }
frtabu's avatar
frtabu committed
281 282 283

      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);
284 285
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
frtabu's avatar
frtabu committed
286
      LOG_E(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
287
            PROTOCOL_CTXT_ARGS(ctxt_pP));
288
    }
289
  } else {
290 291 292 293 294 295 296 297 298 299
    // 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;
300 301
    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),
302 303 304 305 306 307
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
308
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
309 310

    if (pdcp_pdu_p != NULL) {
311
      /*
312 313 314
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
315
       */
316 317 318 319 320 321
      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);
322

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

327
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
328 329 330 331
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
332

333
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
334 335 336 337 338 339 340
          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 ;
341

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

346
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
347 348 349 350
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
351

352
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
353 354
          return FALSE;
        }
355
      }
356

357
      /*
358
       * Validate incoming sequence number, there might be a problem with PDCP initialization
359
       */
360
      if (current_sn > pdcp_calculate_max_seq_num_for_given_size(pdcp_p->seq_num_size)) {
Cedric Roux's avatar
Cedric Roux committed
361
        LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Generated sequence number (%"PRIu16") is greater than a sequence number could ever be!\n"\
362 363 364
              "There must be a problem with PDCP initialization, ignoring this PDU...\n",
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              current_sn);
365
        free_mem_block(pdcp_pdu_p, __func__);
366

367
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
368 369 370 371
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
372

373
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
374 375 376 377 378 379 380 381 382 383
        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
384
      for (i=0; i<pdcp_tailer_len; i++) {
385
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
386
      }
387 388 389 390

      if ((pdcp_p->security_activated != 0) &&
          (((pdcp_p->cipheringAlgorithm) != 0) ||
           ((pdcp_p->integrityProtAlgorithm) != 0))) {
391
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
392 393 394 395
          start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].apply_security);
        } else {
          start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
        }
396 397 398 399

        pdcp_apply_security(ctxt_pP,
                            pdcp_p,
                            srb_flagP,
400
                            rb_idP % LTE_maxDRB,
401 402 403 404 405
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);

406 407 408 409 410
        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);
        }
411 412 413 414 415 416 417 418 419 420
      }

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

421 422 423 424 425
      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);
      }
426

laurent's avatar
laurent committed
427
      LOG_E(PDCP,  "[FRAME %5u][%s][PDCP][MOD %u][RB %ld] PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
428 429 430 431
            ctxt_pP->frame,
            (ctxt_pP->enb_flag) ? "eNB" : "UE",
            ctxt_pP->module_id,
            rb_idP);
432
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
433 434 435 436 437 438 439
      return FALSE;
    }

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

frtabu's avatar
frtabu committed
443
    if ((pdcp_pdu_p!=NULL) && (srb_flagP == 0) && (ctxt_pP->enb_flag == 1)) {
laurent's avatar
laurent committed
444 445
      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);
446

447
      if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_DU(RC.rrc[ctxt_pP->module_id]->node_type)) {
448 449
        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
450 451 452 453
      } 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
454
	ret=FALSE;
frtabu's avatar
frtabu committed
455 456 457 458 459
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;
460

frtabu's avatar
frtabu committed
461 462 463
          case RLC_OP_STATUS_BAD_PARAMETER:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n");
            break;
464

frtabu's avatar
frtabu committed
465 466 467
          case RLC_OP_STATUS_INTERNAL_ERROR:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n");
            break;
468

frtabu's avatar
frtabu committed
469 470 471
          case RLC_OP_STATUS_OUT_OF_RESSOURCES:
            LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n");
            break;
472

frtabu's avatar
frtabu committed
473 474 475 476 477 478 479
          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)) {
480 481 482
        // DL transfer
        MessageDef                            *message_p;
        // Note: the acyual task must be TASK_PDCP_ENB, but this task is not created
483
        message_p = itti_alloc_new_message (TASK_PDCP_ENB, 0, F1AP_DL_RRC_MESSAGE);
484 485
        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
486
        F1AP_DL_RRC_MESSAGE (message_p).gNB_CU_ue_id  = 0;
487 488 489 490 491 492 493 494 495 496
        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
497
      } else {
498 499 500 501 502 503 504 505 506 507
        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
508 509
                                 );

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
        switch (rlc_status) {
          case RLC_OP_STATUS_OK:
            LOG_D(PDCP, "Data sending request over RLC succeeded!\n");
            ret=TRUE;
            break;

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

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

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

          default:
            LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status);
            ret= FALSE;
            break;
        } // switch case
      }
537
    }
538
  }
539

540
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
541 542 543 544
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
545

546 547 548 549 550
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */

frtabu's avatar
frtabu committed
551
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
552 553 554 555
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
      break;
  }

556
  LOG_D(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, (int)(rb_idP+rb_offset), current_sn);
557
  Pdcp_stats_tx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
558
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
559
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
560
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
561
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;
562
  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]);
563
  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]);
564
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
565
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
566
  return ret;
567 568
}

569

570 571 572
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
frtabu's avatar
frtabu committed
573
  const protocol_ctxt_t *const ctxt_pP,
574 575 576 577
  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
578
  mem_block_t *const sdu_buffer_pP
579 580
)
//-----------------------------------------------------------------------------
581
{
582
  pdcp_t      *pdcp_p          = NULL;
583 584
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
585
  pdcp_sn_t    sequence_number = 0;
586
  volatile sdu_size_t   payload_offset  = 0;
587
  rb_id_t      rb_id            = rb_idP;
588
  boolean_t    packet_forwarded = FALSE;
589 590
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
591
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
592
  uint16_t     pdcp_uid=0;
593

594
  MessageDef  *message_p        = NULL;
Lionel Gauthier's avatar
 
Lionel Gauthier committed
595
  uint8_t     *gtpu_buffer_p    = NULL;
596 597 598
  uint32_t    rx_hfn_for_count;
  int         pdcp_sn_for_count;
  int         security_ok;
599
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
600
  LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
laurent's avatar
laurent committed
601
              "[MSG] PDCP UL %s PDU on rb_id %ld\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
Cedric Roux's avatar
Cedric Roux committed
602

603
  if (MBMS_flagP) {
604
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE,
laurent's avatar
laurent committed
605
                 "RB id is too high (%ld/%d) %u rnti %x!\n",
606 607 608 609
                 rb_idP,
                 NB_RB_MBMS_MAX,
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
610 611

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
612
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
laurent's avatar
laurent committed
613
            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
614 615 616 617 618
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
619
    } else {
620
      LOG_D(PDCP, "Data indication notification for PDCP entity from UE %x to eNB %u "
laurent's avatar
laurent committed
621
            "and radio bearer ID %ld rlc sdu size %d ctxt_pP->enb_flag %d\n",
622
            ctxt_pP->rnti,
623
            ctxt_pP->module_id,
624 625 626
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
Lionel Gauthier's avatar
sync  
Lionel Gauthier committed
627 628
    }
  } else {
629
    rb_id = rb_idP % LTE_maxDRB;
laurent's avatar
laurent committed
630
    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u UE %x!\n",
631
                 rb_id,
632
                 LTE_maxDRB,
633 634
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
laurent's avatar
laurent committed
635
    AssertError (rb_id > 0, return FALSE, "RB id is too low (%ld/%d) %u UE %x!\n",
636
                 rb_id,
637
                 LTE_maxDRB,
638 639 640
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_id, srb_flagP);
frtabu's avatar
frtabu committed
641
    h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
642 643 644 645 646 647

    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);
648
      free_mem_block(sdu_buffer_pP, __func__);
649
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
650
      return FALSE;
651
    }
652
  }
653

654

655
  if (sdu_buffer_sizeP == 0) {
656 657
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
658
  }
659

660 661 662 663 664
  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);
  }
665 666

  /*
667 668
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
669
   */
670

671
  if (MBMS_flagP == 0 ) {
672 673 674
    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
675
      sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char *)sdu_buffer_pP->data);
676 677
    } else { // DRB
      pdcp_tailer_len = 0;
678

679
      if (pdcp_p->seq_num_size == 7) {
680
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_SHORT_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
681
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char *)sdu_buffer_pP->data);
682
      } else if (pdcp_p->seq_num_size == 12) {
683
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
684
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char *)sdu_buffer_pP->data);
685
      } else {
686
        //sequence_number = 4095;
687 688 689 690
        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);
691
        exit(1);
692
      }
693

694 695
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
696

697 698 699 700
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
701 702 703 704
      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);
705
      free_mem_block(sdu_buffer_pP, __func__);
706

707 708 709 710 711
      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);
      }
712

713
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
714 715 716
      return FALSE;
    }

717
#if 0
718

719
    /* Removed by Cedric */
720
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
Lionel Gauthier's avatar
 
Lionel Gauthier committed
721
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
722
      /* if (dc == PDCP_DATA_PDU )
723 724 725
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
726
    } else {
frtabu's avatar
frtabu committed
727 728
      Pdcp_stats_rx_outoforder[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
      LOG_E(PDCP,
729 730 731
            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);
732
      /*
733 734
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
735
       */
bruno mongazon's avatar
bruno mongazon committed
736 737
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
738 739
      return FALSE;
    }
740

741
#endif
742 743 744

    // SRB1/2: control-plane data
    if (srb_flagP) {
745 746 747 748 749 750 751 752
      /* 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;
      }
753

754
      if (pdcp_p->security_activated == 1) {
755 756 757 758 759
        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);
        }
760

761
        security_ok = pdcp_validate_security(ctxt_pP,
frtabu's avatar
frtabu committed
762 763 764 765
                                             pdcp_p,
                                             srb_flagP,
                                             rb_idP,
                                             pdcp_header_len,
766 767
                                             rx_hfn_for_count,
                                             pdcp_sn_for_count,
frtabu's avatar
frtabu committed
768
                                             sdu_buffer_pP->data,
769
                                             sdu_buffer_sizeP - pdcp_tailer_len) == 0;
770

771 772 773 774 775
        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);
        }
776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
      } 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++;
798
      }
799

frtabu's avatar
frtabu committed
800 801 802 803 804
      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__);
805

806
      // free_mem_block(new_sdu, __func__);
807 808 809 810 811
      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);
      }
812

813
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
814
      return TRUE;
815
    } /* if (srb_flagP) */
816 817 818 819

    /*
     * DRBs
     */
820
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
821

822
    switch (pdcp_p->rlc_mode) {
frtabu's avatar
frtabu committed
823 824 825
      case RLC_MODE_AM: {
        /* process as described in 36.323 5.1.2.1.2 */
        int reordering_window;
826

frtabu's avatar
frtabu committed
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
        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) {
844
          pdcp_p->rx_hfn++;
frtabu's avatar
frtabu committed
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
          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;
863
        }
864

frtabu's avatar
frtabu committed
865 866 867 868 869 870
        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);
          }
871

frtabu's avatar
frtabu committed
872 873 874 875 876 877 878 879 880
          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;
881

frtabu's avatar
frtabu committed
882 883 884 885 886 887 888 889
          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;
        }
890

frtabu's avatar
frtabu committed
891 892 893 894 895 896 897 898 899
        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;
        }
900

frtabu's avatar
frtabu committed
901 902 903 904 905 906 907 908 909 910 911 912 913 914
        /* 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 */
915

frtabu's avatar
frtabu committed
916
      case RLC_MODE_UM:
917

frtabu's avatar
frtabu committed
918 919 920 921
        /* process as described in 36.323 5.1.2.1.3 */
        if (sequence_number < pdcp_p->next_pdcp_rx_sn) {
          pdcp_p->rx_hfn++;
        }
922

frtabu's avatar
frtabu committed
923 924 925
        rx_hfn_for_count  = pdcp_p->rx_hfn;
        pdcp_sn_for_count = sequence_number;
        pdcp_p->next_pdcp_rx_sn = sequence_number + 1;
926

frtabu's avatar
frtabu committed
927 928 929
        if (pdcp_p->next_pdcp_rx_sn > pdcp_p->maximum_pdcp_rx_sn) {
          pdcp_p->next_pdcp_rx_sn = 0;
          pdcp_p->rx_hfn++;
930 931
        }

frtabu's avatar
frtabu committed
932 933 934 935 936 937
        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);
          }
938

frtabu's avatar
frtabu committed
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953
          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);
          }
954
        } else {
frtabu's avatar
frtabu committed
955
          security_ok = 1;
956
        }
957

frtabu's avatar
frtabu committed
958 959 960 961 962 963 964 965 966
        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;
        }
967

frtabu's avatar
frtabu committed
968
        break;
969

frtabu's avatar
frtabu committed
970 971 972
      default:
        LOG_E(PDCP, "bad RLC mode, cannot happen.\n");
        exit(1);
973 974
    } /* switch (pdcp_p->rlc_mode) */
  } else { /* MBMS_flagP == 0 */
975
    payload_offset=0;
976
  }
977 978 979

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

982 983 984 985 986
    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);
    }
987

988
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
989 990 991
    return TRUE;
  }

992 993 994 995 996 997 998
  // 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)
   */
999

1000
  if (LINK_ENB_PDCP_TO_GTPV1U) {
frtabu's avatar
frtabu committed
1001
    if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
laurent's avatar
laurent committed
1002
      LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %ld len %u\n",
1003 1004 1005
            ctxt_pP->rnti,
            rb_id + 4,
            sdu_buffer_sizeP - payload_offset );
frtabu's avatar
frtabu committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
      MSC_LOG_TX_MESSAGE(
        MSC_PDCP_ENB,
        MSC_GTPU_ENB,
        NULL,0,
        "0 GTPV1U_ENB_TUNNEL_DATA_REQ  ue %x rab %u len %u",
        ctxt_pP->rnti,
        rb_id + 4,
        sdu_buffer_sizeP - payload_offset);
      //LOG_T(PDCP,"Sending to GTPV1U %d bytes\n", sdu_buffer_sizeP - payload_offset);
      gtpu_buffer_p = itti_malloc(TASK_PDCP_ENB, TASK_GTPV1_U,
                                  sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
      AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
      memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
1019
      message_p = itti_alloc_new_message(TASK_PDCP_ENB, 0, GTPV1U_ENB_TUNNEL_DATA_REQ);
frtabu's avatar
frtabu committed
1020 1021 1022 1023 1024 1025
      AssertFatal(message_p != NULL, "OUT OF MEMORY");
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).buffer       = gtpu_buffer_p;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).length       = sdu_buffer_sizeP - payload_offset;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).offset       = GTPU_HEADER_OVERHEAD_MAX;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti         = ctxt_pP->rnti;
      GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id       = rb_id + 4;
Laurent Thomas's avatar
Laurent Thomas committed
1026
      itti_send_msg_to_task(TASK_VARIABLE, INSTANCE_DEFAULT, message_p);
frtabu's avatar
frtabu committed
1027 1028
      packet_forwarded = TRUE;
    }
1029
  } else {
frtabu's avatar
frtabu committed
1030
    packet_forwarded = FALSE;
1031
  }
1032

1033
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
1034

1035
  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
1036 1037 1038 1039 1040 1041
   // 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;
1042

1043 1044
   // 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;
1045

1046
  }
frtabu's avatar
frtabu committed
1047

1048 1049
#endif

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

1053
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
1054 1055 1056 1057 1058 1059
        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
1060 1061 1062
      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;
1063
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
1064 1065 1066 1067

      // 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
1068
        pdcpHead->rb_id = rb_id;
frtabu's avatar
frtabu committed
1069

1070
        if (EPC_MODE_ENABLED) {
frtabu's avatar
frtabu committed
1071 1072 1073 1074 1075
          /* 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
1076
            pdcpHead->inst  = ctxt_pP->module_id;
frtabu's avatar
frtabu committed
1077 1078
          } else {  // nfapi_mode
            if (UE_NAS_USE_TUN) {
laurent's avatar
laurent committed
1079
              pdcpHead->inst  = ctxt_pP->module_id;
frtabu's avatar
frtabu committed
1080
            } else {
laurent's avatar
laurent committed
1081
              pdcpHead->inst  = 1;
frtabu's avatar
frtabu committed
1082
            }
frtabu's avatar
frtabu committed
1083
          } // nfapi_mode
1084
        }
1085
      } else {
laurent's avatar
laurent committed
1086 1087
        pdcpHead->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
        pdcpHead->inst  = ctxt_pP->module_id;
1088
      }
1089

1090
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
frtabu's avatar
frtabu committed
1091
        static uint32_t pdcp_inst = 0;
laurent's avatar
laurent committed
1092 1093
        pdcpHead->inst = pdcp_inst++;
        LOG_D(PDCP, "inst=%d size=%d\n", pdcpHead->inst, pdcpHead->data_size);
1094
      }
1095

laurent's avatar
laurent committed
1096
      memcpy(pdcpHead+1,
1097
             &sdu_buffer_pP->data[payload_offset],
1098
             sdu_buffer_sizeP - payload_offset);
laurent's avatar
laurent committed
1099 1100 1101 1102
      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); 
1103

frtabu's avatar
frtabu committed
1104
    /* Print octets of incoming data in hexadecimal form */
laurent's avatar
laurent committed
1105
      LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
frtabu's avatar
frtabu committed
1106 1107 1108 1109
          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);
1110
  }
1111

1112
  /* Update PDCP statistics */
frtabu's avatar
frtabu committed
1113 1114
  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 ) {
1115
      break;
1116
    }
1117 1118
  }

1119
  Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1120
  Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
1121
  Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1122
  Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
1123

1124
  Pdcp_stats_rx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=sequence_number;
1125
  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]);
1126
  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]);
1127
  Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
1128
  free_mem_block(sdu_buffer_pP, __func__);
1129

1130 1131 1132 1133 1134
  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);
  }
1135

1136
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
1137 1138 1139
  return TRUE;
}

frtabu's avatar
frtabu committed
1140
void pdcp_update_stats(const protocol_ctxt_t *const  ctxt_pP) {
1141
  uint16_t           pdcp_uid = 0;
Navid Nikaein's avatar
Navid Nikaein committed
1142
  uint8_t            rb_id     = 0;
1143

frtabu's avatar
frtabu committed
1144 1145 1146
  // 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++) {
1147 1148
      //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
1149
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
          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;
        }
1161

frtabu's avatar
frtabu committed
1162 1163 1164 1165
        // 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;
1166
      }
frtabu's avatar
frtabu committed
1167

Raymond Knopp's avatar
Raymond Knopp committed
1168
      if (Pdcp_stats_rx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
          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;
1185
      }
Navid Nikaein's avatar
Navid Nikaein committed
1186 1187 1188
    }
  }
}
1189 1190


1191
//-----------------------------------------------------------------------------
1192 1193
void
pdcp_run (
frtabu's avatar
frtabu committed
1194
  const protocol_ctxt_t *const  ctxt_pP
1195 1196
)
//-----------------------------------------------------------------------------
1197
{
1198 1199 1200 1201 1202
  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);
  }
1203

1204
  pdcp_enb[ctxt_pP->module_id].sfn++; // range: 0 to 18,446,744,073,709,551,615
1205
  pdcp_enb[ctxt_pP->module_id].frame=ctxt_pP->frame; // 1023
1206
  pdcp_enb[ctxt_pP->module_id].subframe= ctxt_pP->subframe;
Navid Nikaein's avatar
Navid Nikaein committed
1207
  pdcp_update_stats(ctxt_pP);
1208
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
1209 1210 1211
  MessageDef   *msg_p;
  int           result;
  protocol_ctxt_t  ctxt;
1212

1213 1214 1215 1216 1217 1218
  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
1219 1220 1221 1222 1223 1224 1225 1226 1227
        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);
1228
          LOG_D(PDCP, PROTOCOL_CTXT_FMT"Received %s from %s: instance %ld, rb_id %ld, muiP %d, confirmP %d, mode %d\n",
frtabu's avatar
frtabu committed
1229 1230 1231
                PROTOCOL_CTXT_ARGS(&ctxt),
                ITTI_MSG_NAME (msg_p),
                ITTI_MSG_ORIGIN_NAME(msg_p),
1232
                ITTI_MSG_DESTINATION_INSTANCE (msg_p),
frtabu's avatar
frtabu committed
1233 1234 1235 1236
                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
1237
          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
1238 1239 1240 1241 1242 1243 1244
          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
1245 1246
                                  RRC_DCCH_DATA_REQ (msg_p).mode,
                                  NULL, NULL
frtabu's avatar
frtabu committed
1247
                                 );
1248

frtabu's avatar
frtabu committed
1249 1250
          if (result != TRUE)
            LOG_E(PDCP, "PDCP data request failed!\n");
1251

frtabu's avatar
frtabu committed
1252 1253 1254 1255
          // 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;
1256

frtabu's avatar
frtabu committed
1257 1258 1259 1260 1261 1262
        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;
1263

frtabu's avatar
frtabu committed
1264 1265 1266
          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);
          }
1267

frtabu's avatar
frtabu committed
1268 1269 1270
          //paging pdcp log
          LOG_D(PDCP, "PDCP Received RRC_PCCH_DATA_REQ CC_id %d length %d \n", CC_id, sdu_buffer_sizeP);
        }
1271
        break;
frtabu's avatar
frtabu committed
1272 1273 1274 1275

        default:
          LOG_E(PDCP, "Received unexpected message %s\n", ITTI_MSG_NAME (msg_p));
          break;
1276
      }
1277 1278 1279 1280

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

1283
  // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
1284 1285
  //  if (LINK_ENB_PDCP_TO_GTPV1U && ctxt_pP->enb_flag == ENB_FLAG_NO) {
  if (!EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {
1286
    pdcp_fifo_read_input_sdus(ctxt_pP);
Lionel Gauthier's avatar
Lionel Gauthier committed
1287
  }
1288

1289
  // PDCP -> NAS/IP traffic: RX
1290 1291
  if (ctxt_pP->enb_flag) {
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
frtabu's avatar
frtabu committed
1292
  } else {
1293 1294
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].pdcp_ip);
  }
1295

1296
  pdcp_fifo_flush_sdus(ctxt_pP);
1297

1298 1299 1300 1301 1302
  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);
  }
1303

1304 1305 1306 1307 1308
  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
1309

1310
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
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
//-----------------------------------------------------------------------------
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),
1354
//                ITTI_MSG_DESTINATION_INSTANCE (msg_p),
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
//                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) {
1407 1408
  //if (EPC_MODE_ENABLED || ctxt_pP->enb_flag == ENB_FLAG_NO ) {

1409
    pdcp_fifo_read_input_mbms_sdus_fromtun(ctxt_pP);
1410
  //}
1411 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

  // 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
1439
void pdcp_init_stats_UE(module_id_t mod, uint16_t uid) {
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
  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
1472
void pdcp_add_UE(const protocol_ctxt_t *const  ctxt_pP) {
1473
  int i, ue_flag=1; //, ret=-1; to be decied later
frtabu's avatar
frtabu committed
1474 1475

  for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1476 1477 1478 1479 1480
    if (pdcp_enb[ctxt_pP->module_id].rnti[i] == ctxt_pP->rnti) {
      ue_flag=-1;
      break;
    }
  }
frtabu's avatar
frtabu committed
1481 1482 1483 1484 1485 1486 1487 1488

  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);
1489
        pdcp_init_stats_UE(ctxt_pP->module_id, i);
frtabu's avatar
frtabu committed
1490 1491
        // ret=1;
        break;
1492 1493 1494
      }
    }
  }
frtabu's avatar
frtabu committed
1495

1496 1497
  //return ret;
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1498

1499 1500 1501
//-----------------------------------------------------------------------------
boolean_t
pdcp_remove_UE(
frtabu's avatar
frtabu committed
1502
  const protocol_ctxt_t *const  ctxt_pP
1503 1504 1505
)
//-----------------------------------------------------------------------------
{
1506 1507
  LTE_DRB_Identity_t  srb_id         = 0;
  LTE_DRB_Identity_t  drb_id         = 0;
1508 1509
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1510
  int i;
frtabu's avatar
frtabu committed
1511
  // check and remove SRBs first
Raymond Knopp's avatar
 
Raymond Knopp committed
1512

frtabu's avatar
frtabu committed
1513 1514
  for(int i = 0; i<MAX_MOBILES_PER_ENB; i++) {
    if(pdcp_eNB_UE_instance_to_rnti[i] == ctxt_pP->rnti) {
1515 1516 1517 1518 1519
      pdcp_eNB_UE_instance_to_rnti[i] = NOT_A_RNTI;
      break;
    }
  }

Emad's avatar
Emad committed
1520
  for (srb_id=1; srb_id<3; srb_id++) {
1521 1522
    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
1523 1524
  }

1525
  for (drb_id=0; drb_id<LTE_maxDRB; drb_id++) {
1526 1527
    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
1528 1529
  }

1530 1531
  (void)h_rc; /* remove gcc warning "set but not used" */

1532
  // remove ue for pdcp enb inst
frtabu's avatar
frtabu committed
1533
  for (i=0; i < MAX_MOBILES_PER_ENB; i++) {
1534 1535
    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
1536 1537
            pdcp_enb[ctxt_pP->module_id].uid[i],
            pdcp_enb[ctxt_pP->module_id].rnti[i]);
1538 1539 1540 1541 1542 1543
      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;
    }
  }
1544

Raymond Knopp's avatar
 
Raymond Knopp committed
1545 1546 1547 1548
  return 1;
}


1549 1550 1551
//-----------------------------------------------------------------------------
boolean_t
rrc_pdcp_config_asn1_req (
frtabu's avatar
frtabu committed
1552
  const protocol_ctxt_t *const  ctxt_pP,
1553 1554 1555
  LTE_SRB_ToAddModList_t  *const srb2add_list_pP,
  LTE_DRB_ToAddModList_t  *const drb2add_list_pP,
  LTE_DRB_ToReleaseList_t *const drb2release_list_pP,
1556 1557 1558
  const uint8_t                   security_modeP,
  uint8_t                  *const kRRCenc_pP,
  uint8_t                  *const kRRCint_pP,
frtabu's avatar
frtabu committed
1559 1560 1561
  uint8_t                  *const kUPenc_pP,
  LTE_PMCH_InfoList_r9_t  *const pmch_InfoList_r9_pP,
  rb_id_t                 *const defaultDRB
1562
)
1563
//-----------------------------------------------------------------------------
1564
{
1565
  long int        lc_id          = 0;
1566
  LTE_DRB_Identity_t  srb_id     = 0;
1567
  long int        mch_id         = 0;
Lionel Gauthier's avatar
Lionel Gauthier committed
1568
  rlc_mode_t      rlc_type       = RLC_MODE_NONE;
1569 1570
  LTE_DRB_Identity_t  drb_id     = 0;
  LTE_DRB_Identity_t *pdrb_id_p  = NULL;
1571
  uint8_t         drb_sn         = 12;
1572 1573
  uint8_t         srb_sn         = 5; // fixed sn for SRBs
  uint8_t         drb_report     = 0;
1574
  long int        cnt            = 0;
1575 1576
  uint16_t        header_compression_profile = 0;
  config_action_t action                     = CONFIG_ACTION_ADD;
1577 1578
  LTE_SRB_ToAddMod_t *srb_toaddmod_p = NULL;
  LTE_DRB_ToAddMod_t *drb_toaddmod_p = NULL;
1579
  pdcp_t         *pdcp_p         = NULL;
1580 1581
  hash_key_t      key            = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
1582 1583
  hash_key_t      key_defaultDRB = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_defaultDRB_rc;
1584
  int i,j;
1585 1586
  LTE_MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  LTE_MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
1587 1588 1589 1590 1591 1592
  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);
1593

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

1596
  if (srb2add_list_pP != NULL) {
1597 1598 1599 1600
    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;
1601
      lc_id = srb_id;
1602
      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
1603
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1604

1605 1606 1607 1608 1609
      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);
1610
      } else {
1611 1612 1613
        action = CONFIG_ACTION_ADD;
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
1614

1615 1616 1617 1618 1619 1620
        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
1621 1622
        } else {
          LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n",
1623 1624 1625
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
                key);
        }
1626 1627 1628 1629
      }

      if (srb_toaddmod_p->rlc_Config) {
        switch (srb_toaddmod_p->rlc_Config->present) {
frtabu's avatar
frtabu committed
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656
          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;
            }
1657 1658

            break;
1659

frtabu's avatar
frtabu committed
1660
          case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue:
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676
            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
1677
            // already the default values
1678 1679
            break;

frtabu's avatar
frtabu committed
1680 1681 1682
          default:
            DevParam(srb_toaddmod_p->rlc_Config->present, ctxt_pP->module_id, ctxt_pP->rnti);
            break;
1683
        }
1684
      }
1685
    }
1686
  }
1687

1688 1689
  // reset the action

1690
  if (drb2add_list_pP != NULL) {
1691 1692 1693
    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
1694

1695 1696 1697 1698 1699 1700 1701 1702 1703
      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
1704
        LOG_E(RLC, PROTOCOL_CTXT_FMT" logicalChannelIdentity = %ld is invalid in RRC message when adding DRB!\n", PROTOCOL_CTXT_ARGS(ctxt_pP), lc_id);
1705 1706 1707
        continue;
      }

1708
      DevCheck4(drb_id < LTE_maxDRB, drb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
1709
      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
1710
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1711

1712 1713 1714 1715 1716
      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);
1717 1718
      } else {
        action = CONFIG_ACTION_ADD;
1719 1720 1721
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);

1722
        // save the first configured DRB-ID as the default DRB-ID
1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
        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;
1736
        } else if (h_rc != HASH_TABLE_OK) {
1737 1738 1739 1740 1741 1742 1743 1744 1745
          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
1746
        }
1747
      }
1748 1749 1750 1751 1752 1753 1754 1755

      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;
1756
          drb_sn = LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits; // default SN size
1757 1758 1759 1760 1761 1762 1763 1764 1765
          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
1766 1767
          case LTE_PDCP_Config__headerCompression_PR_NOTHING:
          case LTE_PDCP_Config__headerCompression_PR_notUsed:
1768
            header_compression_profile=0x0;
frtabu's avatar
frtabu committed
1769
            break;
1770

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

frtabu's avatar
frtabu committed
1800 1801 1802 1803
          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;
1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
        }

        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);
1822
      }
1823
    }
1824 1825
  }

1826
  if (drb2release_list_pP != NULL) {
1827 1828 1829
    for (cnt=0; cnt<drb2release_list_pP->list.count; cnt++) {
      pdrb_id_p = drb2release_list_pP->list.array[cnt];
      drb_id =  *pdrb_id_p;
1830
      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
1831
      h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
1832 1833

      if (h_rc != HASH_TABLE_OK) {
Cedric Roux's avatar
Cedric Roux committed
1834
        LOG_E(PDCP, PROTOCOL_CTXT_FMT" PDCP REMOVE FAILED drb_id %ld\n",
1835 1836 1837
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              drb_id);
        continue;
1838
      }
1839

frtabu's avatar
frtabu committed
1840
      lc_id = pdcp_p->lcid;
1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
      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);
1858
      h_rc = hashtable_remove(pdcp_coll_p, key);
1859 1860

      if ((defaultDRB != NULL) && (*defaultDRB == drb_id)) {
1861
        // default DRB being removed. nevertheless this shouldn't happen as removing default DRB is not allowed in standard
1862
        key_defaultDRB = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag);
frtabu's avatar
frtabu committed
1863
        h_defaultDRB_rc = hashtable_get(pdcp_coll_p, key_defaultDRB, (void **)&pdcp_p);
1864 1865 1866 1867 1868 1869 1870 1871 1872

        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
      }
1873
    }
1874 1875
  }

1876
  if (pmch_InfoList_r9_pP != NULL) {
1877 1878 1879 1880 1881
    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
1882

1883
        if (0/*MBMS_SessionInfo_p->sessionId_r9*/)
1884 1885 1886
          lc_id = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        else
          lc_id = MBMS_SessionInfo_p->logicalChannelIdentity_r9;
frtabu's avatar
frtabu committed
1887

1888
        mch_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string
frtabu's avatar
frtabu committed
1889
        //        mch_id = j;
1890 1891 1892

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

1895
          if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1896 1897 1898 1899 1900
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
          }
        } else {
1901
          drb_id =  (mch_id * LTE_maxSessionPerPMCH ) + lc_id; // + (LTE_maxDRB + 3); // 15
1902

1903
          if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) {
1904 1905 1906
            action = CONFIG_ACTION_MBMS_MODIFY;
          } else {
            action = CONFIG_ACTION_MBMS_ADD;
1907
          }
1908 1909
        }

1910
        LOG_I(PDCP, "lc_id (%02ld) mch_id(%02x,%02x,%02x) drb_id(%ld) action(%d)\n",
frtabu's avatar
frtabu committed
1911 1912 1913 1914 1915 1916
              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);
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932
        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
1933
      }
1934
    }
1935
  }
1936

1937
  return 0;
1938 1939
}

1940
//-----------------------------------------------------------------------------
1941 1942
boolean_t
pdcp_config_req_asn1 (
frtabu's avatar
frtabu committed
1943 1944
  const protocol_ctxt_t *const  ctxt_pP,
  pdcp_t          *const        pdcp_pP,
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
  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)
1958
//-----------------------------------------------------------------------------
1959
{
1960

1961
  switch (actionP) {
frtabu's avatar
frtabu committed
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977
    case CONFIG_ACTION_ADD:
      DevAssert(pdcp_pP != NULL);

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

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

            pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
1978
          }
frtabu's avatar
frtabu committed
1979

1980
          pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index] = ctxt_pP->rnti;
1981
          pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB;
frtabu's avatar
frtabu committed
1982
        }
1983

frtabu's avatar
frtabu committed
1984 1985 1986 1987
        //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;
1988
      }
1989

frtabu's avatar
frtabu committed
1990 1991 1992 1993 1994
      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;
1995

frtabu's avatar
frtabu committed
1996
      if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits) {
1997 1998
        pdcp_pP->seq_num_size = 12;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 12) - 1;
frtabu's avatar
frtabu committed
1999
      } else if (rb_snP == LTE_PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits) {
2000 2001
        pdcp_pP->seq_num_size = 7;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 7) - 1;
frtabu's avatar
frtabu committed
2002
      } else {
2003 2004
        pdcp_pP->seq_num_size = 5;
        pdcp_pP->maximum_pdcp_rx_sn = (1 << 5) - 1;
frtabu's avatar
frtabu committed
2005
      }
2006

frtabu's avatar
frtabu committed
2007 2008 2009 2010 2011 2012 2013
      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
2014
      LOG_I(PDCP, PROTOCOL_PDCP_CTXT_FMT" Action ADD  LCID %d (%s id %ld) "
2015
            "configured with SN size %d bits and RLC %s\n",
frtabu's avatar
frtabu committed
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
            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,
2028
          rb_idP,
frtabu's avatar
frtabu committed
2029 2030 2031 2032 2033 2034
          lc_idP,
          security_modeP,
          kRRCenc_pP,
          kRRCint_pP,
          kUPenc_pP);
      }
2035

frtabu's avatar
frtabu committed
2036
      break;
2037

frtabu's avatar
frtabu committed
2038 2039 2040 2041 2042
    case CONFIG_ACTION_MODIFY:
      DevAssert(pdcp_pP != NULL);
      pdcp_pP->header_compression_profile=header_compression_profileP;
      pdcp_pP->status_report = rb_reportP;
      pdcp_pP->rlc_mode = rlc_modeP;
2043

frtabu's avatar
frtabu committed
2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055
      /* 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);
      }
2056

frtabu's avatar
frtabu committed
2057 2058 2059 2060 2061 2062 2063 2064 2065
      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
2066
            "RB id %ld reconfigured with SN size %d and RLC %s \n",
frtabu's avatar
frtabu committed
2067 2068 2069 2070
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            rb_idP,
            rb_snP,
2071
            (rlc_modeP == RLC_MODE_AM) ? "AM" : (rlc_modeP == RLC_MODE_TM) ? "TM" : "UM");
frtabu's avatar
frtabu committed
2072
      break;
2073

frtabu's avatar
frtabu committed
2074 2075 2076 2077
    case CONFIG_ACTION_REMOVE:
      DevAssert(pdcp_pP != NULL);
      //#warning "TODO pdcp_module_id_to_rnti"
      //pdcp_module_id_to_rnti[ctxt_pP.module_id ][dst_id] = NOT_A_RNTI;
laurent's avatar
laurent committed
2078
      LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE LCID %d RBID %ld configured\n",
frtabu's avatar
frtabu committed
2079 2080 2081
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
            lc_idP,
            rb_idP);
2082

frtabu's avatar
frtabu committed
2083 2084 2085
      if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
        // pdcp_remove_UE(ctxt_pP);
      }
2086

frtabu's avatar
frtabu committed
2087 2088 2089 2090
      /* Security keys */
      if (pdcp_pP->kUPenc != NULL) {
        free(pdcp_pP->kUPenc);
      }
2091

frtabu's avatar
frtabu committed
2092 2093 2094
      if (pdcp_pP->kRRCint != NULL) {
        free(pdcp_pP->kRRCint);
      }
2095

frtabu's avatar
frtabu committed
2096 2097 2098
      if (pdcp_pP->kRRCenc != NULL) {
        free(pdcp_pP->kRRCenc);
      }
2099

frtabu's avatar
frtabu committed
2100 2101
      memset(pdcp_pP, 0, sizeof(pdcp_t));
      break;
2102

frtabu's avatar
frtabu committed
2103 2104
    case CONFIG_ACTION_MBMS_ADD:
    case CONFIG_ACTION_MBMS_MODIFY:
laurent's avatar
laurent committed
2105
      LOG_D(PDCP," %s service_id/mch index %d, session_id/lcid %d, rbid %ld configured\n",
frtabu's avatar
frtabu committed
2106 2107 2108 2109 2110
            //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);
2111

frtabu's avatar
frtabu committed
2112 2113 2114 2115 2116 2117 2118
      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;
      }
2119

frtabu's avatar
frtabu committed
2120
      break;
2121

frtabu's avatar
frtabu committed
2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136
    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;
2137
  }
2138

2139 2140
  return 0;
}
2141

2142 2143 2144
//-----------------------------------------------------------------------------
void
pdcp_config_set_security(
frtabu's avatar
frtabu committed
2145 2146
  const protocol_ctxt_t *const  ctxt_pP,
  pdcp_t          *const pdcp_pP,
2147 2148 2149
  const rb_id_t         rb_idP,
  const uint16_t        lc_idP,
  const uint8_t         security_modeP,
frtabu's avatar
frtabu committed
2150 2151 2152
  uint8_t         *const kRRCenc,
  uint8_t         *const kRRCint,
  uint8_t         *const  kUPenc)
2153
//-----------------------------------------------------------------------------
2154
{
2155
  DevAssert(pdcp_pP != NULL);
2156

2157
  if ((security_modeP >= 0) && (security_modeP <= 0x77)) {
2158 2159
    pdcp_pP->cipheringAlgorithm     = security_modeP & 0x0f;
    pdcp_pP->integrityProtAlgorithm = (security_modeP>>4) & 0xf;
2160 2161
    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
2162 2163
          pdcp_pP->cipheringAlgorithm,
          pdcp_pP->integrityProtAlgorithm);
2164 2165 2166 2167 2168
    pdcp_pP->kRRCenc = kRRCenc;
    pdcp_pP->kRRCint = kRRCint;
    pdcp_pP->kUPenc  = kUPenc;
    /* Activate security */
    pdcp_pP->security_activated = 1;
frtabu's avatar
frtabu committed
2169 2170 2171 2172 2173 2174
    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);
2175
  } else {
frtabu's avatar
frtabu committed
2176 2177 2178 2179 2180
    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",
2181 2182
          PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
          security_modeP);
2183
  }
2184 2185
}

2186
//-----------------------------------------------------------------------------
Mahesh's avatar
Mahesh committed
2187
void rrc_pdcp_config_req (
frtabu's avatar
frtabu committed
2188
  const protocol_ctxt_t *const  ctxt_pP,
2189 2190 2191 2192
  const srb_flag_t srb_flagP,
  const uint32_t actionP,
  const rb_id_t rb_idP,
  const uint8_t security_modeP)
2193
//-----------------------------------------------------------------------------
2194
{
2195
  pdcp_t *pdcp_p = NULL;
2196 2197
  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
2198
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
2199

2200
  if (h_rc == HASH_TABLE_OK) {
frtabu's avatar
frtabu committed
2201 2202 2203
    /*
     * Initialize sequence number state variables of relevant PDCP entity
     */
2204
    switch (actionP) {
frtabu's avatar
frtabu committed
2205
      case CONFIG_ACTION_ADD:
2206 2207 2208 2209 2210
        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
2211
          pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti;
2212 2213
        } else {
          pdcp_p->is_ue = FALSE;
frtabu's avatar
frtabu committed
2214
        }
2215

2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
        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
2230
        LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld (already added) configured\n",
2231 2232
              PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
              rb_idP);
frtabu's avatar
frtabu committed
2233
        break;
2234

frtabu's avatar
frtabu committed
2235 2236
      case CONFIG_ACTION_MODIFY:
        break;
2237

frtabu's avatar
frtabu committed
2238
      case CONFIG_ACTION_REMOVE:
laurent's avatar
laurent committed
2239
        LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_REMOVE: radio bearer id %ld configured\n",
frtabu's avatar
frtabu committed
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251
              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;
2252

frtabu's avatar
frtabu committed
2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269
      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;
2270
    }
frtabu's avatar
frtabu committed
2271 2272 2273 2274 2275
  } else {
    switch (actionP) {
      case CONFIG_ACTION_ADD:
        pdcp_p = calloc(1, sizeof(pdcp_t));
        h_rc = hashtable_insert(pdcp_coll_p, key, pdcp_p);
2276

frtabu's avatar
frtabu committed
2277 2278 2279 2280 2281 2282 2283
        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;
2284

frtabu's avatar
frtabu committed
2285 2286 2287 2288 2289 2290
          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;
          }
2291

frtabu's avatar
frtabu committed
2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303
          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;
          }
2304

frtabu's avatar
frtabu committed
2305 2306 2307
          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
2308
          LOG_D(PDCP,PROTOCOL_PDCP_CTXT_FMT" Config request : Action ADD:  radio bearer id %ld configured\n",
frtabu's avatar
frtabu committed
2309 2310 2311
                PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p),
                rb_idP);
        }
2312

frtabu's avatar
frtabu committed
2313
        break;
2314

frtabu's avatar
frtabu committed
2315 2316 2317 2318 2319 2320 2321 2322
      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));
2323
    }
2324
  }
2325
}
2326

frtabu's avatar
frtabu committed
2327 2328 2329
pdcp_data_ind_func_t get_pdcp_data_ind_func() {
  return pdcp_params.pdcp_data_ind_func;
}
2330

2331
void pdcp_set_rlc_data_req_func(send_rlc_data_req_func_t send_rlc_data_req) {
frtabu's avatar
frtabu committed
2332
  pdcp_params.send_rlc_data_req_func = send_rlc_data_req;
2333
}
2334

2335
void pdcp_set_pdcp_data_ind_func(pdcp_data_ind_func_t pdcp_data_ind) {
frtabu's avatar
frtabu committed
2336 2337
  pdcp_params.pdcp_data_ind_func = pdcp_data_ind;
}
2338

2339 2340 2341 2342 2343 2344
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 ;
2345 2346
  }

2347 2348 2349 2350
  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":""));
2351

2352
  if (PDCP_USE_NETLINK) {
2353 2354
    nas_getparams();

2355
    if(UE_NAS_USE_TUN) {
2356
      int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1;
frtabu's avatar
frtabu committed
2357
      netlink_init_tun("ue",num_if);
2358 2359
      if (IS_SOFTMODEM_NOS1)
    	  nas_config(1, 1, 2, "ue");
2360
      netlink_init_mbms_tun("uem");
2361
      nas_config_mbms(1, 2, 2, "uem");
2362 2363
      LOG_I(PDCP, "UE pdcp will use tun interface\n");
    } else if(ENB_NAS_USE_TUN) {
frtabu's avatar
frtabu committed
2364
      netlink_init_tun("enb",1);
2365
      nas_config(1, 1, 1, "enb");
2366
      if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
2367
        netlink_init_mbms_tun("enm");
2368 2369 2370
      	nas_config_mbms(1, 2, 1, "enm"); 
      	LOG_I(PDCP, "ENB pdcp will use mbms tun interface\n");
      }
2371
      LOG_I(PDCP, "ENB pdcp will use tun interface\n");
2372
    } else {
2373
      LOG_I(PDCP, "pdcp will use kernel modules\n");
2374 2375
      netlink_init();
    }
2376 2377 2378
  }else{
         if(pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT){
             LOG_W(PDCP, "ENB pdcp will use tun interface for MBMS\n");
2379
            netlink_init_mbms_tun("enm");
2380 2381 2382 2383 2384
             nas_config_mbms_s1(1, 2, 1, "enm"); 
         }else
             LOG_E(PDCP, "ENB pdcp will not use tun interface\n");
   }

2385 2386
  pthread_create(&pdcp_stats_thread_desc,NULL,pdcp_stats_thread,NULL);

2387
  return pdcp_params.optmask ;
2388 2389
}

2390

2391 2392 2393
//-----------------------------------------------------------------------------
void
pdcp_free (
frtabu's avatar
frtabu committed
2394
  void *pdcp_pP
2395 2396 2397
)
//-----------------------------------------------------------------------------
{
frtabu's avatar
frtabu committed
2398
  pdcp_t *pdcp_p = (pdcp_t *)pdcp_pP;
2399

2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415
  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);
  }
2416 2417 2418
}

//-----------------------------------------------------------------------------
2419 2420
void pdcp_module_cleanup (void)
//-----------------------------------------------------------------------------
2421 2422 2423 2424
{
}

//-----------------------------------------------------------------------------
2425
void pdcp_layer_init(void)
2426
//-----------------------------------------------------------------------------
2427
{
Lionel Gauthier's avatar
Lionel Gauthier committed
2428
  module_id_t       instance;
2429
  int i,j;
Lionel Gauthier's avatar
Lionel Gauthier committed
2430 2431
  mbms_session_id_t session_id;
  mbms_service_id_t service_id;
2432
  /*
2433 2434
   * Initialize SDU list
   */
laurent's avatar
laurent committed
2435
  initNotifiedFIFO(&pdcp_sdu_list);
2436
  pdcp_coll_p = hashtable_create ((LTE_maxDRB + 2) * NUMBER_OF_UE_MAX, NULL, pdcp_free);
2437
  AssertFatal(pdcp_coll_p != NULL, "UNRECOVERABLE error, PDCP hashtable_create failed");
2438

2439
  for (instance = 0; instance < MAX_MOBILES_PER_ENB; instance++) {
2440 2441
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2442
        memset(&pdcp_mbms_array_ue[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2443
      }
2444
    }
frtabu's avatar
frtabu committed
2445

2446
    pdcp_eNB_UE_instance_to_rnti[instance] = NOT_A_RNTI;
2447
  }
2448

frtabu's avatar
frtabu committed
2449
  pdcp_eNB_UE_instance_to_rnti_index = 0;
2450

2451
  for (instance = 0; instance < NUMBER_OF_eNB_MAX; instance++) {
2452 2453
    for (service_id = 0; service_id < LTE_maxServiceCount; service_id++) {
      for (session_id = 0; session_id < LTE_maxSessionPerPMCH; session_id++) {
2454
        memset(&pdcp_mbms_array_eNB[instance][service_id][session_id], 0, sizeof(pdcp_mbms_t));
2455
      }
2456
    }
2457
  }
2458

2459 2460
#ifdef MBMS_MULTICAST_OUT
  mbms_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
frtabu's avatar
frtabu committed
2461

2462 2463 2464
  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
2465
#endif
2466 2467 2468 2469
  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;
2470
  memset(pdcp_enb, 0, sizeof(pdcp_enb_t));
2471 2472
  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
2473

2474 2475
  for (i = 0; i < MAX_eNB; i++) {
    for (j = 0; j < MAX_MOBILES_PER_ENB; j++) {
2476 2477 2478 2479
      Pdcp_stats_tx_window_ms[i][j]=100;
      Pdcp_stats_rx_window_ms[i][j]=100;
    }
  }
2480

2481
  memset(Pdcp_stats_tx, 0, sizeof(Pdcp_stats_tx));
2482 2483
  memset(Pdcp_stats_tx_w, 0, sizeof(Pdcp_stats_tx_w));
  memset(Pdcp_stats_tx_tmp_w, 0, sizeof(Pdcp_stats_tx_tmp_w));
2484
  memset(Pdcp_stats_tx_bytes, 0, sizeof(Pdcp_stats_tx_bytes));
2485 2486
  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));
2487
  memset(Pdcp_stats_tx_sn, 0, sizeof(Pdcp_stats_tx_sn));
2488
  memset(Pdcp_stats_tx_throughput_w, 0, sizeof(Pdcp_stats_tx_throughput_w));
2489 2490
  memset(Pdcp_stats_tx_aiat, 0, sizeof(Pdcp_stats_tx_aiat));
  memset(Pdcp_stats_tx_iat, 0, sizeof(Pdcp_stats_tx_iat));
2491
  memset(Pdcp_stats_rx, 0, sizeof(Pdcp_stats_rx));
2492 2493
  memset(Pdcp_stats_rx_w, 0, sizeof(Pdcp_stats_rx_w));
  memset(Pdcp_stats_rx_tmp_w, 0, sizeof(Pdcp_stats_rx_tmp_w));
2494
  memset(Pdcp_stats_rx_bytes, 0, sizeof(Pdcp_stats_rx_bytes));
2495 2496
  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));
2497
  memset(Pdcp_stats_rx_sn, 0, sizeof(Pdcp_stats_rx_sn));
2498
  memset(Pdcp_stats_rx_goodput_w, 0, sizeof(Pdcp_stats_rx_goodput_w));
2499 2500 2501
  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));
2502 2503 2504
}

//-----------------------------------------------------------------------------
2505 2506
void pdcp_layer_cleanup (void)
//-----------------------------------------------------------------------------
2507
{
laurent's avatar
laurent committed
2508 2509
  //list_free (&pdcp_sdu_list);
  while(pollNotifiedFIFO(&pdcp_sdu_list)) {};
frtabu's avatar
frtabu committed
2510
  hashtable_destroy(&pdcp_coll_p);
2511
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
2512

2513 2514 2515 2516
  if(mbms_socket != -1) {
    close(mbms_socket);
    mbms_socket = -1;
  }
frtabu's avatar
frtabu committed
2517

2518
#endif
2519
}