pdcp_fifo.c 30.4 KB
Newer Older
1
/*******************************************************************************
gauthier's avatar
gauthier committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

gauthier's avatar
gauthier committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


gauthier's avatar
gauthier committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

gauthier's avatar
gauthier committed
16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
gauthier's avatar
gauthier committed
22 23 24 25
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

gauthier's avatar
gauthier committed
28
 *******************************************************************************/
29 30

/*! \file pdcp_fifo.c
gauthier's avatar
gauthier committed
31 32 33 34 35 36 37
 * \brief pdcp interface with linux IP interface, have a look at http://man7.org/linux/man-pages/man7/netlink.7.html for netlink
 * \author  Lionel GAUTHIER and Navid Nikaein
 * \date 2009
 * \version 0.5
 * \warning This component can be runned only in user-space
 * @ingroup pdcp
 */
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

#define PDCP_FIFO_C
#define PDCP_DEBUG 1

#ifndef OAI_EMU
extern int otg_enabled;
#endif

#include "pdcp.h"
#include "pdcp_primitives.h"

#ifdef USER_MODE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define rtf_put write
#define rtf_get read
#else
#include <rtai_fifos.h>
#endif //USER_MODE

#include "../MAC/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
62
#include "NAS/DRIVER/LITE/constant.h"
63 64 65 66
#include "SIMULATION/ETH_TRANSPORT/extern.h"
#include "UTIL/OCG/OCG.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/log.h"
67
#include "UTIL/OTG/otg_tx.h"
68
#include "UTIL/FIFO/pad_list.h"
69 70
#include "platform_constants.h"

71
#include "assertions.h"
72

73
#ifdef PDCP_USE_NETLINK
74 75 76
#include <sys/socket.h>
#include <linux/netlink.h>

77
extern char nl_rx_buf[NL_MAX_PAYLOAD];
78
extern struct sockaddr_nl nas_src_addr, nas_dest_addr;
79 80 81 82
extern struct nlmsghdr *nas_nlh_tx;
extern struct nlmsghdr *nas_nlh_rx;
extern struct iovec nas_iov_tx;
extern struct iovec nas_iov_rx;
83
extern int nas_sock_fd;
84 85
extern struct msghdr nas_msg_tx;
extern struct msghdr nas_msg_rx;
86

gauthier's avatar
gauthier committed
87
unsigned char pdcp_read_state_g = 0;
88 89
#endif

90
extern Packet_OTG_List_t *otg_pdcp_buffer;
91

92
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
93
#  include "gtpv1u_eNB_task.h"
gauthier's avatar
gauthier committed
94 95
#endif

gauthier's avatar
gauthier committed
96
pdcp_data_req_header_t pdcp_read_header_g;
97 98

//-----------------------------------------------------------------------------
99
int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
100 101 102
{
  //-----------------------------------------------------------------------------

gauthier's avatar
gauthier committed
103 104 105
  mem_block_t     *sdu_p            = list_get_head (&pdcp_sdu_list);
  int              bytes_wrote      = 0;
  int              pdcp_nb_sdu_sent = 0;
gauthier's avatar
gauthier committed
106
  uint8_t          cont             = 1;
107
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
108
  //MessageDef      *message_p        = NULL;
gauthier's avatar
gauthier committed
109
#endif
110

111
#if defined(PDCP_USE_NETLINK) && defined(LINUX)
112 113 114
  int ret = 0;
#endif

gauthier's avatar
gauthier committed
115
  while (sdu_p && cont) {
116

gauthier's avatar
gauthier committed
117
#if ! defined(OAI_EMU)
118
    ((pdcp_data_ind_header_t *)(sdu_p->data))->inst = 0;
119 120
#endif

121
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
gauthier's avatar
gauthier committed
122

123 124 125 126
    if (ctxt_pP->enb_flag) {
      AssertFatal(0, "Now execution should not go here");
      LOG_D(PDCP,"Sending to GTPV1U %d bytes\n", ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size);
      gtpv1u_new_data_req(
127 128
        ctxt_pP->module_id, //gtpv1u_data_t *gtpv1u_data_p,
        ctxt_pP->rnti,//rb_id/maxDRB, TO DO UE ID
129 130 131 132 133 134 135 136 137 138 139 140 141
        ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id + 4,
        &(((uint8_t *) sdu_p->data)[sizeof (pdcp_data_ind_header_t)]),
        ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size);

      list_remove_head (&pdcp_sdu_list);
      free_mem_block (sdu_p);
      cont = 1;
      pdcp_nb_sdu_sent += 1;
      sdu_p = list_get_head (&pdcp_sdu_list);
      LOG_D(OTG,"After  GTPV1U\n");
      continue; // loop again
    }

gauthier's avatar
gauthier committed
142
#endif /* defined(ENABLE_USE_MME) */
143
#ifdef PDCP_DEBUG
144
    LOG_D(PDCP, "PDCP->IP TTI %d INST %d: Preparing %d Bytes of data from rab %d to Nas_mesh\n",
145
          ctxt_pP->frame, ((pdcp_data_ind_header_t *)(sdu_p->data))->inst,
gauthier's avatar
gauthier committed
146
          ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size, ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id);
147
#endif //PDCP_DEBUG
148
    cont = 0;
149

150 151 152 153
    if (!pdcp_output_sdu_bytes_to_write) {
      if (!pdcp_output_header_bytes_to_write) {
        pdcp_output_header_bytes_to_write = sizeof (pdcp_data_ind_header_t);
      }
154

155 156
#ifdef PDCP_USE_RT_FIFO
      bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO,
157 158
                             &(((uint8_t *) sdu->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
                             pdcp_output_header_bytes_to_write);
159 160

#else
161
#ifdef PDCP_USE_NETLINK
162
#ifdef LINUX
163 164 165
      memcpy(NLMSG_DATA(nas_nlh_tx), &(((uint8_t *) sdu_p->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
             pdcp_output_header_bytes_to_write);
      nas_nlh_tx->nlmsg_len = pdcp_output_header_bytes_to_write;
166
#endif //LINUX
167
#endif //PDCP_USE_NETLINK
168

169
      bytes_wrote = pdcp_output_header_bytes_to_write;
170
#endif //PDCP_USE_RT_FIFO
171 172

#ifdef PDCP_DEBUG
173
      LOG_D(PDCP, "Frame %d Sent %d Bytes of header to Nas_mesh\n",
174 175
            ctxt_pP->frame,
            bytes_wrote);
176 177
#endif //PDCP_DEBUG

178 179
      if (bytes_wrote > 0) {
        pdcp_output_header_bytes_to_write = pdcp_output_header_bytes_to_write - bytes_wrote;
180

181 182
        if (!pdcp_output_header_bytes_to_write) { // continue with sdu
          pdcp_output_sdu_bytes_to_write = ((pdcp_data_ind_header_t *) sdu_p->data)->data_size;
183

184 185
#ifdef PDCP_USE_RT_FIFO
          bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO, &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
186 187
#else

188
#ifdef PDCP_USE_NETLINK
189
#ifdef LINUX
190 191 192 193 194 195 196 197 198 199
          memcpy(NLMSG_DATA(nas_nlh_tx)+sizeof(pdcp_data_ind_header_t), &(sdu_p->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
          nas_nlh_tx->nlmsg_len += pdcp_output_sdu_bytes_to_write;
          ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);

          if (ret<0) {
            LOG_D(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
            mac_xface->macphy_exit("sendmsg failed for nas_sock_fd\n");
            break;
          }

200
#endif // LINUX
201
#endif //PDCP_USE_NETLINK
202
          bytes_wrote= pdcp_output_sdu_bytes_to_write;
203
#endif // PDCP_USE_RT_FIFO
204 205

#ifdef PDCP_DEBUG
206 207 208 209 210
          LOG_D(PDCP, "PDCP->IP Frame %d INST %d: Sent %d Bytes of data from rab %d to higher layers\n",
                ctxt_pP->frame,
                ((pdcp_data_ind_header_t *)(sdu_p->data))->inst,
                bytes_wrote,
                ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id);
211
#endif //PDCP_DEBUG
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233

          if (bytes_wrote > 0) {
            pdcp_output_sdu_bytes_to_write -= bytes_wrote;

            if (!pdcp_output_sdu_bytes_to_write) { // OK finish with this SDU
              // LOG_D(PDCP, "rb sent a sdu qos_sap %d\n", sapiP);
              LOG_D(PDCP,
                    "[FRAME %05d][xxx][PDCP][MOD xx/xx][RB %u][--- PDCP_DATA_IND / %d Bytes --->][IP][INSTANCE %u][RB %u]\n",
                    ctxt_pP->frame,
                    ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id,
                    ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size,
                    ((pdcp_data_ind_header_t *)(sdu_p->data))->inst,
                    ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id);

              list_remove_head (&pdcp_sdu_list);
              free_mem_block (sdu_p);
              cont = 1;
              pdcp_nb_sdu_sent += 1;
              sdu_p = list_get_head (&pdcp_sdu_list);
            }
          } else {
            LOG_W(PDCP, "RADIO->IP SEND SDU CONGESTION!\n");
234
          }
235 236 237 238 239 240
        } else {
          LOG_W(PDCP, "RADIO->IP SEND SDU CONGESTION!\n");
        }
      }
    } else {
      // continue writing sdu
241 242
#ifdef PDCP_USE_RT_FIFO
      bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO,
243 244
                             (uint8_t *) (&(sdu_p->data[sizeof (pdcp_data_ind_header_t) + ((pdcp_data_ind_header_t *) sdu_p->data)->data_size - pdcp_output_sdu_bytes_to_write])),
                             pdcp_output_sdu_bytes_to_write);
245
#else  // PDCP_USE_RT_FIFO
246
      bytes_wrote = pdcp_output_sdu_bytes_to_write;
247
#endif  // PDCP_USE_RT_FIFO
248

249 250 251 252 253 254 255 256 257 258 259 260
      if (bytes_wrote > 0) {
        pdcp_output_sdu_bytes_to_write -= bytes_wrote;

        if (!pdcp_output_sdu_bytes_to_write) {     // OK finish with this SDU
          //PRINT_RB_SEND_OUTPUT_SDU ("[PDCP] RADIO->IP SEND SDU\n");
          list_remove_head (&pdcp_sdu_list);
          free_mem_block (sdu_p);
          cont = 1;
          pdcp_nb_sdu_sent += 1;
          sdu_p = list_get_head (&pdcp_sdu_list);
          // LOG_D(PDCP, "rb sent a sdu from rab\n");
        }
261
      }
262
    }
263
  }
264

265
#ifdef PDCP_USE_RT_FIFO
266

267
  if ((pdcp_nb_sdu_sent)) {
268
    if ((pdcp_2_nas_irq > 0)) {
269
#ifdef PDCP_DEBUG
270
      LOG_D(PDCP, "Frame %d : Trigger NAS RX interrupt\n",
271
            ctxt_pP->frame);
272
#endif //PDCP_DEBUG
273
      rt_pend_linux_srq (pdcp_2_nas_irq);
274

275 276 277 278 279
    } else {
      LOG_E(PDCP, "Frame %d: ERROR IF IP STACK WANTED : NOTIF PACKET(S) pdcp_2_nas_irq not initialized : %d\n",
            ctxt_pP->frame,
            pdcp_2_nas_irq);
    }
280
  }
281

282
#endif  //PDCP_USE_RT_FIFO
283 284 285 286 287

  return pdcp_nb_sdu_sent;
}

//-----------------------------------------------------------------------------
288
int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
289
{
290 291 292 293 294 295
#ifdef PDCP_USE_NETLINK
  protocol_ctxt_t                ctxt_cpy;
  protocol_ctxt_t                ctxt;
  hash_key_t                     key       = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t                 h_rc;
  struct pdcp_netlink_element_s* data_p    = NULL;
gauthier's avatar
gauthier committed
296
  module_id_t                    ue_id     = 0;
297 298
  pdcp_t*                        pdcp_p    = NULL;
# if defined(USE_PDCP_NETLINK_QUEUES)
gauthier's avatar
gauthier committed
299
  rb_id_t                        rab_id    = 0;
300

301
  pdcp_transmission_mode_t       pdcp_mode = PDCP_TRANSMISSION_MODE_UNKNOWN;
gauthier's avatar
gauthier committed
302

gauthier's avatar
gauthier committed
303 304

  ctxt_cpy = *ctxt_pP;
305

306
  while (pdcp_netlink_dequeue_element(ctxt_pP, &data_p) != 0) {
307
    DevAssert(data != NULL);
308 309 310 311 312 313 314 315 316 317 318 319 320
    rab_id = data_p->pdcp_read_header.rb_id % maxDRB;
    // ctxt_pP->rnti is NOT_A_RNTI
    ctxt_cpy.rnti = pdcp_module_id_to_rnti[ctxt_cpy.module_id][data_p->pdcp_read_header.inst];
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_cpy.rnti, ctxt_pP->enb_flag, rab_id, SRB_FLAG_NO);
    h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

    if (h_rc != HASH_TABLE_OK) {
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Dropped IP PACKET cause no PDCP instanciated\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
      free(data_p->data);
      free(data_p);
      data_p = NULL;
      continue;
321 322
    }

323
    CHECK_CTXT_ARGS(&ctxt_cpy);
324 325 326 327 328

    AssertFatal (rab_id    < maxDRB,                       "RB id is too high (%u/%d)!\n", rab_id, maxDRB);

    if (rab_id != 0) {
        LOG_D(PDCP, "[FRAME %05d][%s][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ "
329
            "/ %d Bytes --->][PDCP][MOD %u][RB %u]\n",
330 331
              ctxt_cpy.frame,
              (ctxt_cpy.enb_flag) ? "eNB" : "UE",
332 333 334 335
            data_p->pdcp_read_header.inst,
            data_p->pdcp_read_header.rb_id,
            data_p->pdcp_read_header.data_size,
            ctxt_cpy.module_id,
336 337 338
              rab_id);
#ifdef  OAI_NW_DRIVER_TYPE_ETHERNET

339 340 341
      if ((data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV6_TYPE_MULTICAST) /*TRAFFIC_IPV6_TYPE_MULTICAST */ ||
          (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_MULTICAST) /*TRAFFIC_IPV4_TYPE_MULTICAST */ ||
          (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_BROADCAST) /*TRAFFIC_IPV4_TYPE_BROADCAST */ ) {
342
#if defined (Rel10)
343
          PDCP_TRANSMISSION_MODE_TRANSPARENT;
344
#else
345
          pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
346
#endif
347 348
      } else if ((data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV6_TYPE_UNICAST) /* TRAFFIC_IPV6_TYPE_UNICAST */ ||
                 (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_UNICAST) /*TRAFFIC_IPV4_TYPE_UNICAST*/ ) {
349 350 351 352 353 354
          pdcp_mode=  PDCP_TRANSMISSION_MODE_DATA;
        } else {
          pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
          LOG_W(PDCP,"unknown IP traffic type \n");
        }

355
#else // OAI_NW_DRIVER_TYPE_ETHERNET NASMESH driver does not curreenlty support multicast traffic
356
        pdcp_mode = PDCP_TRANSMISSION_MODE_DATA;
357
#endif
358
      pdcp_data_req(&ctxt_cpy,
359
                      SRB_FLAG_NO,
360
                      rab_id % maxDRB,
gauthier's avatar
gauthier committed
361 362
                      RLC_MUI_UNDEFINED,
                      RLC_SDU_CONFIRM_NO,
363 364
                    data_p->pdcp_read_header.data_size,
                    data_p->data,
365 366 367 368 369 370 371 372 373
                      pdcp_mode);
    } else if (ctxt_cpy.enb_flag) {
      /* rb_id = 0, thus interpreated as broadcast and transported as
       * multiple unicast is a broadcast packet, we have to send this
       * packet on all default RABS of all connected UEs
       */
      LOG_D(PDCP, "eNB Try Forcing send on DEFAULT_RAB_ID first_ue_local %u nb_ue_local %u\n", oai_emulation.info.first_ue_local, oai_emulation.info.nb_ue_local);

      for (ue_id = 0; ue_id < NB_UE_INST; ue_id++) {
374
        if (pdcp_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) {
375
          LOG_D(PDCP, "eNB Try Forcing send on DEFAULT_RAB_ID UE %d\n", ue_id);
376 377
          ctxt.module_id     = ctxt_cpy.module_id;
          ctxt.rnti          = ctxt_cpy.pdcp_module_id_to_rnti[ctxt_cpy.module_id][ue_id];
378 379 380
          ctxt.frame         = ctxt_cpy.frame;
          ctxt.enb_flag      = ctxt_cpy.enb_flag;

gauthier's avatar
gauthier committed
381
          pdcp_data_req(
382 383 384 385 386
            &ctxt,
            SRB_FLAG_NO,
            DEFAULT_RAB_ID,
            RLC_MUI_UNDEFINED,
            RLC_SDU_CONFIRM_NO,
387 388
            data_p->pdcp_read_header.data_size,
            data_p->data,
389 390
            PDCP_TRANSMISSION_MODE_DATA);
        }
gauthier's avatar
gauthier committed
391
      }
392 393 394 395 396 397 398 399
    } else {
      LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
      pdcp_data_req(
        &ctxt_cpy,
        SRB_FLAG_NO,
        DEFAULT_RAB_ID,
        RLC_MUI_UNDEFINED,
        RLC_SDU_CONFIRM_NO,
400 401
        data_p->pdcp_read_header.data_size,
        data_p->data,
402 403 404
        PDCP_TRANSMISSION_MODE_DATA);
    }

405 406 407
    free(data_p->data);
    free(data_p);
    data_p = NULL;
gauthier's avatar
gauthier committed
408
  }
409

gauthier's avatar
gauthier committed
410
  return 0;
411
# else /* USE_PDCP_NETLINK_QUEUES*/
412 413 414
  int              len = 1;
  rb_id_t          rab_id  = 0;

415 416 417 418 419
  while (len > 0) {
    len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);

    if (len<=0) {
      // nothing in pdcp NAS socket
420
      //LOG_D(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
421 422 423 424 425 426
    } else {
      for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
           NLMSG_OK (nas_nlh_rx, len);
           nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {

        if (nas_nlh_rx->nlmsg_type == NLMSG_DONE) {
427
          LOG_D(PDCP, "[PDCP][NETLINK] RX NLMSG_DONE\n");
428 429 430 431
          //return;
        }

        if (nas_nlh_rx->nlmsg_type == NLMSG_ERROR) {
432
          LOG_D(PDCP, "[PDCP][NETLINK] RX NLMSG_ERROR\n");
433 434 435 436 437 438
        }

        if (pdcp_read_state_g == 0) {
          if (nas_nlh_rx->nlmsg_len == sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)) {
            pdcp_read_state_g = 1;  //get
            memcpy((void *)&pdcp_read_header_g, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
439
            LOG_D(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %u data_size %d\n",
440 441
                  pdcp_read_header_g.inst, pdcp_read_header_g.rb_id, pdcp_read_header_g.data_size);
          } else {
442
            LOG_E(PDCP, "[PDCP][NETLINK] WRONG size %d should be sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)\n",
443 444 445 446 447
                  nas_nlh_rx->nlmsg_len);
          }
        } else {
          pdcp_read_state_g = 0;
          // print_active_requests()
448
#ifdef PDCP_DEBUG
449
          LOG_D(PDCP, "[PDCP][NETLINK] Something in socket, length %d \n",
450
                nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
451
#endif
gauthier's avatar
gauthier committed
452

453
#ifdef OAI_EMU
454 455 456 457 458

          // overwrite function input parameters, because only one netlink socket for all instances
          if (pdcp_read_header_g.inst < oai_emulation.info.nb_enb_local) {
            ctxt.frame         = ctxt_cpy.frame;
            ctxt.enb_flag      = ENB_FLAG_YES;
459 460
            ctxt.module_id     = pdcp_read_header_g.inst  +  oai_emulation.info.first_enb_local;
            ctxt.rnti          = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id ][pdcp_read_header_g.rb_id / maxDRB + oai_emulation.info.first_ue_local];
461 462 463 464
            rab_id    = pdcp_read_header_g.rb_id % maxDRB;
          } else {
            ctxt.frame         = ctxt_cpy.frame;
            ctxt.enb_flag      = ENB_FLAG_NO;
465 466
            ctxt.module_id     = pdcp_read_header_g.inst - oai_emulation.info.nb_enb_local + oai_emulation.info.first_ue_local;
            ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
467 468 469
            rab_id    = pdcp_read_header_g.rb_id;
          }

470
          CHECK_CTXT_ARGS(&ctxt);
471 472 473 474
          AssertFatal (rab_id    < maxDRB,                       "RB id is too high (%u/%d)!\n", rab_id, maxDRB);
          /*LGpdcp_read_header.inst = (pdcp_read_header_g.inst >= oai_emulation.info.nb_enb_local) ? \
                  pdcp_read_header_g.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local :
                  pdcp_read_header_g.inst +  oai_emulation.info.first_enb_local;*/
475
#else // OAI_EMU
476
          pdcp_read_header_g.inst = 0;
477
#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
478
          ctxt.frame         = ctxt_cpy.frame;
479
          ctxt.enb_flag      = ctxt_cpy.enb_flag;
480 481

          if (ctxt_cpy.enb_flag) {
482
            ctxt.module_id = 0;
483 484
            rab_id      = pdcp_read_header_g.rb_id % maxDRB;
          } else {
485
            ctxt.module_id = 0;
486 487 488
            rab_id      = pdcp_read_header_g.rb_id % maxDRB;
          }

gauthier's avatar
gauthier committed
489 490
#endif

491 492 493
          if (ctxt.enb_flag) {
            if (rab_id != 0) {
              rab_id = rab_id % maxDRB;
494 495
              key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
              h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
496

497
              if (h_rc == HASH_TABLE_OK) {
498
#ifdef PDCP_DEBUG
499 500 501 502 503 504
                LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      len,
                      nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr),
                      pdcp_read_header_g.rb_id);
505 506
#endif

507
                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u]UE %u][RB %u]\n",
508 509 510 511
                      ctxt_cpy.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
512 513
                      ctxt.module_id,
                      ctxt.rnti,
514 515 516 517 518 519 520 521 522 523 524
                      rab_id);

                pdcp_data_req(&ctxt,
                              SRB_FLAG_NO,
                              rab_id,
                              RLC_MUI_UNDEFINED,
                              RLC_SDU_CONFIRM_NO,
                              pdcp_read_header_g.data_size,
                              (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                              PDCP_TRANSMISSION_MODE_DATA);
              } else {
525
                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE, DROPPED\n",
526 527 528 529
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
530 531
                      ctxt.module_id,
                      ctxt.rnti,
532 533 534 535
                      rab_id);
              }
            } else  { // rb_id =0, thus interpreated as broadcast and transported as multiple unicast
              // is a broadcast packet, we have to send this packet on all default RABS of all connected UEs
gauthier's avatar
gauthier committed
536
#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
537 538 539 540
              for (ue_id = 0; ue_id < NB_UE_INST; ue_id++) {
                if (oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) {
                  ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id];
                  LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
541 542 543 544
                        ctxt.frame,
                        pdcp_read_header_g.inst,
                        pdcp_read_header_g.rb_id,
                        pdcp_read_header_g.data_size,
545 546
                        ctxt.module_id,
                        ctxt.rnti,
547 548 549 550 551 552 553 554 555 556 557 558 559
                        DEFAULT_RAB_ID);
                  pdcp_data_req (
                    &ctxt,
                    SRB_FLAG_NO,
                    DEFAULT_RAB_ID,
                    RLC_MUI_UNDEFINED,
                    RLC_SDU_CONFIRM_NO,
                    pdcp_read_header_g.data_size,
                    (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                    PDCP_TRANSMISSION_MODE_DATA);
                }
              }
            }
560
          } else { // enb_flag
561
            if (rab_id != 0) {
562 563 564 565 566
              rab_id = rab_id % maxDRB;
              key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
              h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

              if (h_rc == HASH_TABLE_OK) {
gauthier's avatar
gauthier committed
567
#ifdef PDCP_DEBUG
568 569 570 571 572 573
                LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      len,
                      nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr),
                      pdcp_read_header_g.rb_id);
574

575
                LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
576 577 578 579
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
580 581
                      ctxt.module_id,
                      ctxt.rnti,
582 583
                      rab_id);
#endif
gauthier's avatar
gauthier committed
584

585 586 587 588 589 590 591 592 593 594
                pdcp_data_req(
                  &ctxt,
                  SRB_FLAG_NO,
                  rab_id,
                  RLC_MUI_UNDEFINED,
                  RLC_SDU_CONFIRM_NO,
                  pdcp_read_header_g.data_size,
                  (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                  PDCP_TRANSMISSION_MODE_DATA);
              } else {
595 596
                LOG_D(PDCP,
                      "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
597 598 599 600
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
601 602 603 604
                      ctxt.module_id,
                      ctxt.rnti,
                      rab_id,
                      key);
605
              }
606 607
            }  else {
              LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
608
              LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
609 610 611 612
                    ctxt.frame,
                    pdcp_read_header_g.inst,
                    pdcp_read_header_g.rb_id,
                    pdcp_read_header_g.data_size,
613 614
                    ctxt.module_id,
                    ctxt.rnti,
615 616 617 618 619 620 621 622 623 624 625
                    DEFAULT_RAB_ID);
              pdcp_data_req (
                &ctxt,
                SRB_FLAG_NO,
                DEFAULT_RAB_ID,
                RLC_MUI_UNDEFINED,
                RLC_SDU_CONFIRM_NO,
                pdcp_read_header_g.data_size,
                (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                PDCP_TRANSMISSION_MODE_DATA);
            }
626
          }
627 628

        }
gauthier's avatar
gauthier committed
629
      }
630
    }
631
  }
632

633
  return len;
634
# endif
635
#else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO
636
  return 0;
637
#endif // PDCP_USE_NETLINK
638 639 640
}


641 642
void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t* const  ctxt_pP)
{
643 644 645
  unsigned char       *otg_pkt=NULL;
  module_id_t          dst_id; // dst for otg
  rb_id_t              rb_id;
646
  unsigned int         pkt_size=0;
647
#if defined(USER_MODE) && defined(OAI_EMU)
648
  module_id_t          src_id;
649
  static unsigned int  pkt_cnt_enb=0, pkt_cnt_ue=0;
650

651 652
  Packet_otg_elt_t    *otg_pkt_info=NULL;
  int                  result;
653 654 655 656 657
  uint8_t              pdcp_mode, is_ue=0;
#endif
  protocol_ctxt_t      ctxt;
  // we need to add conditions to avoid transmitting data when the UE is not RRC connected.
#if defined(USER_MODE) && defined(OAI_EMU)
658

659
  if (oai_emulation.info.otg_enabled ==1 ) {
660 661 662 663 664 665 666 667 668
    // module_id is source id
    while ((otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[ctxt_pP->instance]))) != NULL) {
      LOG_I(OTG,"Mod_id %d Frame %d Got a packet (%p), HEAD of otg_pdcp_buffer[%d] is %p and Nb elements is %d\n",
            ctxt_pP->module_id,
            ctxt_pP->frame,
            otg_pkt_info,
            ctxt_pP->instance,
            pkt_list_get_head(&(otg_pdcp_buffer[ctxt_pP->instance])),
            otg_pdcp_buffer[ctxt_pP->instance].nb_elements);
669
      //otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[module_id]));
670 671
      dst_id    = (otg_pkt_info->otg_pkt).dst_id; // type is module_id_t
      src_id    = (otg_pkt_info->otg_pkt).module_id; // type is module_id_t
672 673 674 675 676 677 678 679 680 681 682 683
      rb_id     = (otg_pkt_info->otg_pkt).rb_id;
      is_ue     = (otg_pkt_info->otg_pkt).is_ue;
      pdcp_mode = (otg_pkt_info->otg_pkt).mode;
      //    LOG_I(PDCP,"pdcp_fifo, pdcp mode is= %d\n",pdcp_mode);

      // generate traffic if the ue is rrc reconfigured state
      // if (mac_get_rrc_status(module_id, ctxt_pP->enb_flag, dst_id ) > 2 /*RRC_CONNECTED*/) { // not needed: this test is already done in update_otg_enb
      otg_pkt = (unsigned char*) (otg_pkt_info->otg_pkt).sdu_buffer;
      pkt_size = (otg_pkt_info->otg_pkt).sdu_buffer_size;

      if (otg_pkt != NULL) {
        if (is_ue == 0 ) {
684 685 686 687 688 689 690
          PROTOCOL_CTXT_SET_BY_MODULE_ID(
            &ctxt,
            src_id,
            ENB_FLAG_YES,
            oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id],
            ctxt_pP->frame,
            ctxt_pP->subframe);
691 692

          LOG_D(OTG,"[eNB %d] Frame %d sending packet %d from module %d on rab id %d (src %d, dst %d) pkt size %d for pdcp mode %d\n",
693 694 695 696 697 698 699 700 701
                ctxt.module_id,
                ctxt.frame,
                pkt_cnt_enb++,
                src_id,
                rb_id,
                src_id,
                dst_id,
                pkt_size,
                pdcp_mode);
702 703 704 705 706 707 708 709
          result = pdcp_data_req(&ctxt,
                                 SRB_FLAG_NO,
                                 rb_id,
                                 RLC_MUI_UNDEFINED,
                                 RLC_SDU_CONFIRM_NO,
                                 pkt_size,
                                 otg_pkt,
                                 pdcp_mode);
710 711 712
          if (result != TRUE) {
            LOG_W(OTG,"PDCP data request failed!\n");
          }
713 714 715 716 717
        } else {
          //rb_id= eNB_index * MAX_NUM_RB + DTCH;


          LOG_D(OTG,"[UE %d] Frame %d: sending packet %d from module %d on rab id %d (src %d, dst %d) pkt size %d\n",
718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
                ctxt_pP->module_id,
                ctxt_pP->frame,
                pkt_cnt_ue++,
                ctxt_pP->module_id,
                rb_id,
                ctxt_pP->module_id,
                dst_id,
                pkt_size);
          PROTOCOL_CTXT_SET_BY_MODULE_ID(
            &ctxt,
            src_id,
            ENB_FLAG_NO,
            pdcp_UE_UE_module_id_to_rnti[src_id],
            ctxt_pP->frame,
            ctxt_pP->subframe);
733 734 735 736 737 738 739 740 741

          result = pdcp_data_req( &ctxt,
                                  SRB_FLAG_NO,
                                  rb_id,
                                  RLC_MUI_UNDEFINED,
                                  RLC_SDU_CONFIRM_NO,
                                  pkt_size,
                                  otg_pkt,
                                  PDCP_TRANSMISSION_MODE_DATA);
742 743 744
          if (result != TRUE) {
            LOG_W(OTG,"PDCP data request failed!\n");
          }
745 746 747 748
        }

        free(otg_pkt);
        otg_pkt = NULL;
749
      }
750 751 752 753

      // } //else LOG_D(OTG,"ctxt_pP->frame %d enb %d-> ue %d link not yet established state %d  \n", ctxt_pP->frame, eNB_index,dst_id - NB_eNB_INST, mac_get_rrc_status(module_id, ctxt_pP->enb_flag, dst_id - NB_eNB_INST));

    }
754
  }
755

756
#else
757

758
  if ((otg_enabled==1) && (ctxt_pP->enb_flag == ENB_FLAG_YES)) { // generate DL traffic
759 760 761 762 763
    unsigned int ctime=0;
    ctime = ctxt_pP->frame * 100;

    /*if  ((mac_get_rrc_status(eNB_index, ctxt_pP->enb_flag, 0 ) > 2) &&
    (mac_get_rrc_status(eNB_index, ctxt_pP->enb_flag, 1 ) > 2)) { */
764 765 766 767 768 769 770
    PROTOCOL_CTXT_SET_BY_MODULE_ID(
      &ctxt,
      ctxt_pP->module_id,
      ctxt_pP->enb_flag,
      NOT_A_RNTI,
      ctxt_pP->frame,
      ctxt_pP->subframe);
771 772

    for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
773 774 775 776
      ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id];

      if (ctxt.rnti != NOT_A_RNTI) {
        if (mac_eNB_get_rrc_status(ctxt.module_id, ctxt.rnti ) > 2 /*RRC_SI_RECEIVED*/) {
777
        unsigned int temp = 0;
778 779 780 781 782 783
          otg_pkt=packet_gen(
                    ENB_MODULE_ID_TO_INSTANCE(ctxt.module_id),
                    UE_MODULE_ID_TO_INSTANCE(dst_id),
                    0,
                    ctime,
                    &temp);
784 785 786 787 788 789 790 791 792 793 794 795
        pkt_size = temp;

        if (otg_pkt != NULL) {
          rb_id = dst_id * maxDRB + DTCH;
          pdcp_data_req(&ctxt,
                        SRB_FLAG_NO,
                        rb_id,
                        RLC_MUI_UNDEFINED,
                        RLC_SDU_CONFIRM_NO,
                        pkt_size,
                        otg_pkt,
                        PDCP_TRANSMISSION_MODE_DATA);
796 797 798 799 800
            LOG_I(OTG,
                  "send packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n",
                  ctxt_pP->module_id, rb_id, ctxt_pP->module_id, dst_id, pkt_size);
            free(otg_pkt);
          }
801
        }
gauthier's avatar
gauthier committed
802
      }
803
    }
804
  }
805

806 807
#endif
}