pdcp.c 75.1 KB
Newer Older
1 2 3 4 5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
Cedric Roux's avatar
Cedric Roux committed
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

Thomas Schlichter's avatar
Thomas Schlichter committed
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"
49
#include "common/utils/LOG/vcd_signal_dumper.h"
gauthier's avatar
gauthier committed
50
#include "msc.h"
Yoshihiro Tomita's avatar
Yoshihiro Tomita committed
51
#include "targets/COMMON/openairinterface5g_limits.h"
52
#include "SIMULATION/ETH_TRANSPORT/proto.h"
53
#if defined(ENABLE_SECURITY)
frtabu's avatar
frtabu committed
54
  #include "UTIL/OSA/osa_defs.h"
55 56
#endif

57
# include "intertask_interface.h"
58

59 60 61

#  include "gtpv1u_eNB_task.h"
#  include "gtpv1u.h"
gauthier's avatar
 
gauthier committed
62

63
extern int otg_enabled;
64
extern uint8_t nfapi_mode;
65 66
#include "common/ran_context.h"
extern RAN_CONTEXT_t RC;
67
hash_table_t  *pdcp_coll_p = NULL;
68

Thomas Schlichter's avatar
Thomas Schlichter committed
69
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
70 71 72 73 74 75 76 77
  #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;
Thomas Schlichter's avatar
Thomas Schlichter committed
78 79
#endif

80 81 82 83 84 85 86

/* pdcp module parameters and related functions*/
static pdcp_params_t pdcp_params= {0};

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

Cedric Roux's avatar
Cedric Roux committed
126 127
  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
128

Cedric Roux's avatar
Cedric Roux committed
129 130
#endif

131 132 133 134 135 136 137 138
  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?
   */
139
  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
140 141
              sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);

142
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
143
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
144
  } else {
145
    if (srb_flagP) {
nikaeinn's avatar
nikaeinn committed
146
      AssertError (rb_idP < 3, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
147
    } else {
148
      AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
149
    }
150
  }
gauthier's avatar
gauthier committed
151

152
  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
153
  h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
154

155 156
  if (h_rc != HASH_TABLE_OK) {
    if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
157
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
frtabu's avatar
frtabu committed
158 159
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
160
      ctxt_pP->configured=FALSE;
161
      return FALSE;
162
    }
frtabu's avatar
frtabu committed
163
  } else {
164
    // instance for a given RB is configured
165
    ctxt_pP->configured=TRUE;
166
  }
frtabu's avatar
frtabu committed
167

168
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
169 170 171 172
    start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
173

174
  // PDCP transparent mode for MBMS traffic
175

gauthier's avatar
gauthier committed
176
  if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
177
    LOG_D(PDCP, " [TM] Asking for a new mem_block of size %d\n",sdu_buffer_sizeP);
178
    pdcp_pdu_p = get_free_mem_block(sdu_buffer_sizeP, __func__);
179 180 181

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

183 184 185 186 187 188
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
        rlc_util_print_hex_octets(PDCP,
                                  (unsigned char *)&pdcp_pdu_p->data[0],
                                  sdu_buffer_sizeP);
        LOG_UI(PDCP, "Before rlc_data_req 1, srb_flagP: %d, rb_idP: %d \n", srb_flagP, rb_idP);
      }
189

190 191
      rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_YES, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p
                                ,NULL, NULL
frtabu's avatar
frtabu committed
192
                               );
193 194
    } else {
      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
frtabu's avatar
frtabu committed
195
      LOG_E(PDCP,PROTOCOL_CTXT_FMT" PDCP_DATA_REQ SDU DROPPED, OUT OF MEMORY \n",
196
            PROTOCOL_CTXT_ARGS(ctxt_pP));
197
    }
198
  } else {
199 200 201 202 203 204 205 206 207 208
    // 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;
209 210
    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),
211 212 213 214 215 216
          pdcp_pdu_size,
          pdcp_header_len,
          pdcp_tailer_len);
    /*
     * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
     */
217
    pdcp_pdu_p = get_free_mem_block(pdcp_pdu_size, __func__);
218 219

    if (pdcp_pdu_p != NULL) {
220
      /*
221 222 223
       * Create a Data PDU with header and append data
       *
       * Place User Plane PDCP Data PDU header first
224
       */
225 226 227 228 229 230
      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);
231

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

236
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
237 238 239 240
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
241

gauthier's avatar
gauthier committed
242
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
243 244 245 246 247 248 249
          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 ;
250

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

frtabu's avatar
frtabu committed
255
          if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
256 257 258 259
            stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
          } else {
            stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
          }
260

gauthier's avatar
gauthier committed
261
          VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
262 263
          return FALSE;
        }
gauthier's avatar
gauthier committed
264
      }
265

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

276
        if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
277 278 279 280
          stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
        } else {
          stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
        }
281

gauthier's avatar
gauthier committed
282
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
283 284 285 286 287 288 289 290 291 292
        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
293
      for (i=0; i<pdcp_tailer_len; i++) {
294
        pdcp_pdu_p->data[pdcp_header_len + sdu_buffer_sizeP + i] = 0x00;// pdu_header.mac_i[i];
295
      }
296 297 298 299 300 301

#if defined(ENABLE_SECURITY)

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

        pdcp_apply_security(ctxt_pP,
                            pdcp_p,
                            srb_flagP,
311
                            rb_idP % LTE_maxDRB,
312 313 314 315 316
                            pdcp_header_len,
                            current_sn,
                            pdcp_pdu_p->data,
                            sdu_buffer_sizeP);

317 318 319 320 321
        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);
        }
322 323 324 325 326 327 328 329 330 331 332
      }

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

333 334 335 336 337
      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);
      }
338

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

    /*
     * Ask sublayer to transmit data and check return value
     * to see if RLC succeeded
     */
352 353
    LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)pdcp_pdu_p->data,pdcp_pdu_size,
                "[MSG] PDCP DL %s PDU on rb_id %d\n",(srb_flagP)? "CONTROL" : "DATA", rb_idP);
354
    LOG_D(PDCP, "Before rlc_data_req 2, srb_flagP: %d, rb_idP: %d \n", srb_flagP, rb_idP);
355
    rlc_status = rlc_data_req(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p
frtabu's avatar
frtabu committed
356 357
                              ,sourceL2Id
                              ,destinationL2Id
358
                             );
359
  }
360

361
  switch (rlc_status) {
frtabu's avatar
frtabu committed
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    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;
386
  }
387

388
  if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
389 390 391 392
    stop_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
  } else {
    stop_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
  }
393

394 395 396 397 398
  /*
   * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK
   * so we return TRUE afterwards
   */

frtabu's avatar
frtabu committed
399
  for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) {
400 401 402 403
    if (pdcp_enb[ctxt_pP->module_id].rnti[pdcp_uid] == ctxt_pP->rnti )
      break;
  }

404 405
  //LOG_I(PDCP,"ueid %d lcid %d tx seq num %d\n", pdcp_uid, rb_idP+rb_offset, current_sn);
  Pdcp_stats_tx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
406
  Pdcp_stats_tx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
407
  Pdcp_stats_tx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
408
  Pdcp_stats_tx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=sdu_buffer_sizeP;
409
  Pdcp_stats_tx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=current_sn;
410
  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]);
frtabu's avatar
frtabu committed
411
  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]);
412
  Pdcp_stats_tx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
gauthier's avatar
gauthier committed
413
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT);
414
  return ret;
415 416
}

gauthier's avatar
gauthier committed
417

418 419 420
//-----------------------------------------------------------------------------
boolean_t
pdcp_data_ind(
frtabu's avatar
frtabu committed
421
  const protocol_ctxt_t *const ctxt_pP,
422 423 424 425
  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
426
  mem_block_t *const sdu_buffer_pP
427 428
)
//-----------------------------------------------------------------------------
429
{
gauthier's avatar
gauthier committed
430 431 432
  pdcp_t      *pdcp_p          = NULL;
  list_t      *sdu_list_p      = NULL;
  mem_block_t *new_sdu_p       = NULL;
433 434
  uint8_t      pdcp_header_len = 0;
  uint8_t      pdcp_tailer_len = 0;
gauthier's avatar
gauthier committed
435
  pdcp_sn_t    sequence_number = 0;
436
  volatile sdu_size_t   payload_offset  = 0;
437
  rb_id_t      rb_id            = rb_idP;
438
  boolean_t    packet_forwarded = FALSE;
439 440
  hash_key_t      key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t  h_rc;
441
  uint8_t      rb_offset= (srb_flagP == 0) ? DTCH -1 :0;
frtabu's avatar
frtabu committed
442
  uint16_t     pdcp_uid=0;
443
  uint8_t      oo_flag=0;
444
  MessageDef  *message_p        = NULL;
gauthier's avatar
 
gauthier committed
445
  uint8_t     *gtpu_buffer_p    = NULL;
gauthier's avatar
gauthier committed
446
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_IN);
447 448
  LOG_DUMPMSG(PDCP,DEBUG_PDCP,(char *)sdu_buffer_pP->data,sdu_buffer_sizeP,
              "[MSG] PDCP UL %s PDU on rb_id %d\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP);
Cedric Roux's avatar
Cedric Roux committed
449
#if T_TRACER
frtabu's avatar
frtabu committed
450

Cedric Roux's avatar
Cedric Roux committed
451 452
  if (ctxt_pP->enb_flag != ENB_FLAG_NO)
    T(T_ENB_PDCP_UL, 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
453

Cedric Roux's avatar
Cedric Roux committed
454 455
#endif

456
  if (MBMS_flagP) {
457 458 459 460 461 462
    AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE,
                 "RB id is too high (%u/%d) %u rnti %x!\n",
                 rb_idP,
                 NB_RB_MBMS_MAX,
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
463 464

    if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
465
      LOG_D(PDCP, "e-MBMS Data indication notification for PDCP entity from eNB %u to UE %x "
466
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
467 468 469 470 471
            ctxt_pP->module_id,
            ctxt_pP->rnti,
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
gauthier's avatar
sync  
gauthier committed
472
    } else {
473 474 475
      LOG_D(PDCP, "Data indication notification for PDCP entity from UE %x to eNB %u "
            "and radio bearer ID %d rlc sdu size %d ctxt_pP->enb_flag %d\n",
            ctxt_pP->rnti,
476
            ctxt_pP->module_id,
477 478 479
            rb_idP,
            sdu_buffer_sizeP,
            ctxt_pP->enb_flag);
gauthier's avatar
sync  
gauthier committed
480 481
    }
  } else {
482 483
    rb_id = rb_idP % LTE_maxDRB;
    AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%u/%d) %u UE %x!\n",
484
                 rb_id,
485
                 LTE_maxDRB,
486 487 488 489
                 ctxt_pP->module_id,
                 ctxt_pP->rnti);
    AssertError (rb_id > 0, return FALSE, "RB id is too low (%u/%d) %u UE %x!\n",
                 rb_id,
490
                 LTE_maxDRB,
491 492 493
                 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
494
    h_rc = hashtable_get(pdcp_coll_p, key, (void **)&pdcp_p);
495 496 497 498 499 500

    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);
501
      free_mem_block(sdu_buffer_pP, __func__);
gauthier's avatar
gauthier committed
502
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
503
      return FALSE;
504
    }
505
  }
506

gauthier's avatar
gauthier committed
507
  sdu_list_p = &pdcp_sdu_list;
508

gauthier's avatar
gauthier committed
509
  if (sdu_buffer_sizeP == 0) {
510 511
    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
    return FALSE;
512
  }
513

514 515 516 517 518
  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);
  }
519 520

  /*
521 522
   * Parse the PDU placed at the beginning of SDU to check
   * if incoming SN is in line with RX window
gauthier's avatar
gauthier committed
523
   */
524

525
  if (MBMS_flagP == 0 ) {
526 527 528
    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
529
      sequence_number =   pdcp_get_sequence_number_of_pdu_with_SRB_sn((unsigned char *)sdu_buffer_pP->data);
530 531
    } else { // DRB
      pdcp_tailer_len = 0;
532 533 534

      if (pdcp_p->seq_num_size == PDCP_SN_7BIT) {
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_SHORT_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
535
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_short_sn((unsigned char *)sdu_buffer_pP->data);
536 537
      } else if (pdcp_p->seq_num_size == PDCP_SN_12BIT) {
        pdcp_header_len = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
frtabu's avatar
frtabu committed
538
        sequence_number =     pdcp_get_sequence_number_of_pdu_with_long_sn((unsigned char *)sdu_buffer_pP->data);
gauthier's avatar
gauthier committed
539
      } else {
540
        //sequence_number = 4095;
541 542 543 544
        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);
gauthier's avatar
gauthier committed
545
      }
546

547 548
      //uint8_t dc = pdcp_get_dc_filed((unsigned char*)sdu_buffer_pP->data);
    }
549

550 551 552 553
    /*
     * Check if incoming SDU is long enough to carry a PDU header
     */
    if (sdu_buffer_sizeP < pdcp_header_len + pdcp_tailer_len ) {
554 555 556 557
      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);
558
      free_mem_block(sdu_buffer_pP, __func__);
559

560 561 562 563 564
      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);
      }
565

gauthier's avatar
gauthier committed
566
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
567 568 569
      return FALSE;
    }

570
    if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) {
gauthier's avatar
 
gauthier committed
571
      LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number);
572
      /* if (dc == PDCP_DATA_PDU )
573 574 575
      LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n");
      else
      LOG_D(PDCP, "Passing piggybacked SDU to RRC ...\n");*/
576
    } else {
577
      oo_flag=1;
578 579 580 581
      LOG_W(PDCP,
            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);
gauthier's avatar
gauthier committed
582
      /*
583 584
       * XXX Till we implement in-sequence delivery and duplicate discarding
       * mechanism all out-of-order packets will be delivered to RRC/IP
585
       */
Mongazon's avatar
Mongazon committed
586 587
      LOG_W(PDCP, "Ignoring PDU...\n");
      free_mem_block(sdu_buffer_pP, __func__);
588 589
      return FALSE;
    }
590 591 592

    // SRB1/2: control-plane data
    if (srb_flagP) {
593
#if defined(ENABLE_SECURITY)
594

595
      if (pdcp_p->security_activated == 1) {
596 597 598 599 600
        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);
        }
601 602 603 604 605 606 607 608 609 610

        pdcp_validate_security(ctxt_pP,
                               pdcp_p,
                               srb_flagP,
                               rb_idP,
                               pdcp_header_len,
                               sequence_number,
                               sdu_buffer_pP->data,
                               sdu_buffer_sizeP - pdcp_tailer_len);

611 612 613 614 615
        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);
        }
gauthier's avatar
gauthier committed
616
      }
617

618 619
#endif
      //rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
frtabu's avatar
frtabu committed
620 621
      MSC_LOG_TX_MESSAGE(
        (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_PDCP_UE:MSC_PDCP_ENB,
622 623 624 625 626
        (ctxt_pP->enb_flag == ENB_FLAG_NO)? MSC_RRC_UE:MSC_RRC_ENB,
        NULL,0,
        PROTOCOL_PDCP_CTXT_FMT" DATA-IND len %u",
        PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
        sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len);
frtabu's avatar
frtabu committed
627 628 629 630 631
      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__);
632

633
      // free_mem_block(new_sdu, __func__);
634 635 636 637 638
      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);
      }
639

gauthier's avatar
gauthier committed
640
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
641 642
      return TRUE;
    }
643 644 645 646

    /*
     * DRBs
     */
647 648
    payload_offset=pdcp_header_len;// PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
#if defined(ENABLE_SECURITY)
649

650
    if (pdcp_p->security_activated == 1) {
651 652 653 654 655
      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);
      }
656

657
      pdcp_validate_security(
658 659 660 661 662 663 664 665 666
        ctxt_pP,
        pdcp_p,
        srb_flagP,
        rb_idP,
        pdcp_header_len,
        sequence_number,
        sdu_buffer_pP->data,
        sdu_buffer_sizeP - pdcp_tailer_len);

667 668 669 670 671
      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);
      }
672
    }
673

674
#endif
675
  } else {
676
    payload_offset=0;
677
  }
678 679 680

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

683 684 685 686 687
    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);
    }
688

gauthier's avatar
gauthier committed
689
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
690 691 692
    return TRUE;
  }

693 694 695 696 697 698 699
  // 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)
   */
700 701 702 703

  if (LINK_ENB_PDCP_TO_GTPV1U) {
    if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) {
      MSC_LOG_TX_MESSAGE(
704 705 706 707 708 709 710
        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);
711 712
      //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,
713
                                  sdu_buffer_sizeP - payload_offset + GTPU_HEADER_OVERHEAD_MAX);
714 715 716 717
      AssertFatal(gtpu_buffer_p != NULL, "OUT OF MEMORY");
      memcpy(&gtpu_buffer_p[GTPU_HEADER_OVERHEAD_MAX], &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset);
      message_p = itti_alloc_new_message(TASK_PDCP_ENB, GTPV1U_ENB_TUNNEL_DATA_REQ);
      AssertFatal(message_p != NULL, "OUT OF MEMORY");
718 719 720 721 722
      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;
723 724 725 726 727
      itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p);
      packet_forwarded = TRUE;
    }
  } else {
    packet_forwarded = FALSE;
728
  }
frtabu's avatar
frtabu committed
729

Thomas Schlichter's avatar
Thomas Schlichter committed
730
#ifdef MBMS_MULTICAST_OUT
frtabu's avatar
frtabu committed
731

Thomas Schlichter's avatar
Thomas Schlichter committed
732
  if ((MBMS_flagP != 0) && (mbms_socket != -1)) {
frtabu's avatar
frtabu committed
733 734
    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)];
Thomas Schlichter's avatar
Thomas Schlichter committed
735 736 737 738
    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;
frtabu's avatar
frtabu committed
739
    sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
Thomas Schlichter's avatar
Thomas Schlichter committed
740 741
    packet_forwarded = TRUE;
  }
frtabu's avatar
frtabu committed
742

Thomas Schlichter's avatar
Thomas Schlichter committed
743 744
#endif

745
  if (FALSE == packet_forwarded) {
746
    new_sdu_p = get_free_mem_block(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), __func__);
747

748
    if (new_sdu_p) {
Thomas Schlichter's avatar
Thomas Schlichter committed
749
      if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) {
750 751 752 753 754 755 756 757
        pdcp_p->last_submitted_pdcp_rx_sn = sequence_number;
      }

      /*
       * Prepend PDCP indication header which is going to be removed at pdcp_fifo_flush_sdus()
       */
      memset(new_sdu_p->data, 0, sizeof (pdcp_data_ind_header_t));
      ((pdcp_data_ind_header_t *) new_sdu_p->data)->data_size = sdu_buffer_sizeP - payload_offset;
758
      AssertFatal((sdu_buffer_sizeP - payload_offset >= 0), "invalid PDCP SDU size!");
759 760 761 762 763

      // 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) {
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id;
764

765
        if (EPC_MODE_ENABLED) {
766 767 768 769
          /* 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
           */
770
          if (nfapi_mode == 3) {
771
#ifdef UESIM_EXPANSION
772

773
            if (UE_NAS_USE_TUN) {
774
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
775
            } else {
776
              ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = 0;
777
            }
778

779
#else
780
            ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
781
#endif
782
          } else {
783
            ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = 1;
784
          }
785
        }
786
      } else {
frtabu's avatar
frtabu committed
787 788
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->rb_id = rb_id + (ctxt_pP->module_id * LTE_maxDRB);
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst  = ctxt_pP->module_id;
789
      }
frtabu's avatar
frtabu committed
790

791 792 793 794 795 796 797 798
      if( LOG_DEBUGFLAG(DEBUG_PDCP) ) {
        static uint32_t pdcp_inst = 0;
        ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst = pdcp_inst++;
        LOG_D(PDCP, "inst=%d size=%d\n", ((pdcp_data_ind_header_t *) new_sdu_p->data)->inst, ((pdcp_data_ind_header_t *) new_sdu_p->data)->data_size);
      }

      memcpy(&new_sdu_p->data[sizeof (pdcp_data_ind_header_t)],
             &sdu_buffer_pP->data[payload_offset],
799 800 801 802
             sdu_buffer_sizeP - payload_offset);
      list_add_tail_eurecom (new_sdu_p, sdu_list_p);
    }

frtabu's avatar
frtabu committed
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
    /* Print octets of incoming data in hexadecimal form */
    LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
          sdu_buffer_sizeP  - payload_offset + (int)sizeof(pdcp_data_ind_header_t),
          sdu_buffer_sizeP  - payload_offset);
    //util_print_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset);
    //util_flush_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset);

    /*
       * Update PDCP statistics
     * XXX Following two actions are identical, is there a merge error?
     */

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

    Pdcp_stats_rx[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
    Pdcp_stats_rx_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
    Pdcp_stats_rx_bytes[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
    Pdcp_stats_rx_bytes_tmp_w[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]+=(sdu_buffer_sizeP  - payload_offset);
    Pdcp_stats_rx_sn[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=sequence_number;

827
    if (oo_flag == 1 ) {
frtabu's avatar
frtabu committed
828
      Pdcp_stats_rx_outoforder[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]++;
frtabu's avatar
frtabu committed
829 830
    } else {
      LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" PDCP_DATA_IND SDU DROPPED, OUT OF ORDER \n",
831
            PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p));
frtabu's avatar
frtabu committed
832
    }
833

frtabu's avatar
frtabu committed
834 835 836
    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]);
    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]);
    Pdcp_stats_rx_iat[ctxt_pP->module_id][pdcp_uid][rb_idP+rb_offset]=pdcp_enb[ctxt_pP->module_id].sfn;
Thomas Schlichter's avatar
Thomas Schlichter committed
837 838
  }

839
  free_mem_block(sdu_buffer_pP, __func__);
840

841 842 843 844 845
  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);
  }
846

gauthier's avatar
gauthier committed
847
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
848 849 850
  return TRUE;
}

frtabu's avatar
frtabu committed
851
void pdcp_update_stats(const protocol_ctxt_t *const  ctxt_pP) {
852
  uint16_t           pdcp_uid = 0;
nikaeinn's avatar
nikaeinn committed
853
  uint8_t            rb_id     = 0;
frtabu's avatar
frtabu committed
854 855 856 857

  // 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++) {
858 859
      //printf("frame %d and subframe %d \n", pdcp_enb[ctxt_pP->module_id].frame, pdcp_enb[ctxt_pP->module_id].subframe);
      // tx stats
knopp's avatar
knopp committed
860
      if (Pdcp_stats_tx_window_ms[ctxt_pP->module_id][pdcp_uid] > 0 &&
frtabu's avatar
frtabu committed
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
          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