pdcp_fifo.c 48 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

/*! \file pdcp_fifo.c
23
 * \brief pdcp interface with linux IP interface, have a look at http://man7.org/linux/man-pages/man7/netlink.7.html for netlink
24 25
 * \author  Navid Nikaein and Lionel GAUTHIER
 * \date 2009 - 2016
26
 * \version 0.5
27
 * \email navid.nikaein@eurecom.fr
28 29 30
 * \warning This component can be runned only in user-space
 * @ingroup pdcp
 */
31 32

#define PDCP_FIFO_C
33
//#define PDCP_DEBUG 1
34
//#define DEBUG_PDCP_FIFO_FLUSH_SDU
35 36 37 38 39 40

extern int otg_enabled;

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

41
#include <pthread.h>
42 43 44 45 46 47 48 49 50
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define rtf_put write
#define rtf_get read

#include "../MAC/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
51
#include "NETWORK_DRIVER/LITE/constant.h"
52 53 54 55
#include "SIMULATION/ETH_TRANSPORT/extern.h"
#include "UTIL/OCG/OCG.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/log.h"
56
#include "UTIL/OTG/otg_tx.h"
57
#include "UTIL/FIFO/pad_list.h"
58
#include "UTIL/LOG/vcd_signal_dumper.h"
59
#include "platform_constants.h"
Lionel Gauthier's avatar
msc  
Lionel Gauthier committed
60
#include "msc.h"
61
#include "pdcp.h"
62

63
#include "assertions.h"
64

65
#ifdef PDCP_USE_NETLINK
66 67
#include <sys/socket.h>
#include <linux/netlink.h>
68
#include "NETWORK_DRIVER/UE_IP/constant.h"
69

70
extern char nl_rx_buf[NL_MAX_PAYLOAD];
71
extern struct sockaddr_nl nas_src_addr, nas_dest_addr;
72 73 74 75
extern struct nlmsghdr *nas_nlh_tx;
extern struct nlmsghdr *nas_nlh_rx;
extern struct iovec nas_iov_tx;
extern struct iovec nas_iov_rx;
76
extern int nas_sock_fd;
77 78
extern struct msghdr nas_msg_tx;
extern struct msghdr nas_msg_rx;
79

80
unsigned char pdcp_read_state_g = 0;
81 82
#endif

83
extern Packet_OTG_List_t *otg_pdcp_buffer;
84

85
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
Lionel Gauthier's avatar
 
Lionel Gauthier committed
86
#  include "gtpv1u_eNB_task.h"
Cedric Roux's avatar
Cedric Roux committed
87
#  include "gtpv1u_eNB_defs.h"
Lionel Gauthier's avatar
Lionel Gauthier committed
88 89
#endif

90 91
extern int gtpv1u_new_data_req( uint8_t  enb_module_idP, rnti_t   ue_rntiP, uint8_t  rab_idP, uint8_t *buffer_pP, uint32_t buf_lenP, uint32_t buf_offsetP);

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
/* Prevent de-queueing the same PDCP SDU from the queue twice
 * by multiple threads. This has happened in TDD when thread-odd
 * is flushing a PDCP SDU after UE_RX() processing; whereas
 * thread-even is at a special-subframe, skips the UE_RX() process
 * and goes straight to the PDCP SDU flushing. The 2nd flushing
 * dequeues the same SDU again causing unexpected behavior.
 *
 * comment out the MACRO below to disable this protection
 */
#define PDCP_SDU_FLUSH_LOCK

#ifdef PDCP_SDU_FLUSH_LOCK
static pthread_mutex_t mtex = PTHREAD_MUTEX_INITIALIZER;
#endif

107
pdcp_data_req_header_t pdcp_read_header_g;
108 109

//-----------------------------------------------------------------------------
110
int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const  ctxt_pP)
111
{
112
   //-----------------------------------------------------------------------------
113

114 115 116
   //#if defined(PDCP_USE_NETLINK) && defined(LINUX)
   int ret = 0;
   //#endif
117

118 119
#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
#define THREAD_NAME_LEN 16
120 121 122 123 124 125 126
   static char threadname[THREAD_NAME_LEN];
   ret = pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN);
   if (ret != 0)
   {
      perror("pthread_getname_np : ");
      exit_fun("Error getting thread name");
   }
127 128 129
#undef THREAD_NAME_LEN
#endif

130
#ifdef PDCP_SDU_FLUSH_LOCK
131 132
   ret = pthread_mutex_trylock(&mtex);
   if (ret == EBUSY) {
133
#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
134 135
      LOG_W(PDCP, "[%s] at SFN/SF=%d/%d wait for PDCP FIFO to be unlocked\n",
            threadname, ctxt_pP->frame, ctxt_pP->subframe);
136
#endif
137 138 139
      if (pthread_mutex_lock(&mtex)) {
         exit_fun("PDCP_SDU_FLUSH_LOCK lock error!");
      }
140
#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
141 142
      LOG_I(PDCP, "[%s] at SFN/SF=%d/%d PDCP FIFO is unlocked\n",
            threadname, ctxt_pP->frame, ctxt_pP->subframe);
143
#endif
144 145 146
   } else if (ret != 0) {
      exit_fun("PDCP_SDU_FLUSH_LOCK trylock error!");
   }
147 148 149

#endif

150 151 152 153
   mem_block_t     *sdu_p            = list_get_head (&pdcp_sdu_list);
   int              bytes_wrote      = 0;
   int              pdcp_nb_sdu_sent = 0;
   uint8_t          cont             = 1;
154
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
155
   //MessageDef      *message_p        = NULL;
156 157
#endif

158 159
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 1 );
   while (sdu_p && cont) {
160

161 162 163 164 165 166
#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU
    LOG_D(PDCP, "[%s] SFN/SF=%d/%d inst=%d size=%d\n",
        threadname, ctxt_pP->frame, ctxt_pP->subframe,
        ((pdcp_data_ind_header_t*) sdu_p->data)->inst,
        ((pdcp_data_ind_header_t *) sdu_p->data)->data_size);
#endif
167

168
#if defined(LINK_ENB_PDCP_TO_GTPV1U)
Lionel Gauthier's avatar
Lionel Gauthier committed
169

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
      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(
               ctxt_pP->module_id, //gtpv1u_data_t *gtpv1u_data_p,
               ctxt_pP->rnti,//rb_id/maxDRB, TO DO UE ID
               ((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,
               0);

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

Lionel Gauthier's avatar
Lionel Gauthier committed
190
#endif /* defined(ENABLE_USE_MME) */
191
#ifdef PDCP_DEBUG
192
      LOG_I(PDCP, "PDCP->IP TTI %d INST %d: Preparing %d Bytes of data from rab %d to Nas_mesh\n",
193 194
            ctxt_pP->frame, ((pdcp_data_ind_header_t *)(sdu_p->data))->inst,
            ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size, ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id);
195
#endif //PDCP_DEBUG
196 197 198 199 200 201
      cont = 0;

//TTN - for D2D (PC5S)
#ifdef Rel14
      sidelink_pc5s_element *sl_pc5s_msg_recv = NULL;
      char send_buf[BUFSIZE];
202
      int rb_id = ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id;
203

204
      if (rb_id >= MAX_NUM_LCID_DATA) { //hardcoded for PC5-Signaling
205
      //if ((rb_id == 28) | (rb_id == 29) | (rb_id == 30))
206 207 208 209

#ifdef PDCP_DEBUG
         sl_pc5s_msg_recv = calloc(1, sizeof(sidelink_pc5s_element));
         memcpy((void*)sl_pc5s_msg_recv, (void*)(sdu_p->data+sizeof(pdcp_data_ind_header_t)), sizeof(sidelink_pc5s_element));
210 211 212 213 214 215
         LOG_D(PDCP,"Received PC5S message, header traffic_type: %d)\n", sl_pc5s_msg_recv->pc5s_header.traffic_type);
         LOG_D(PDCP,"Received PC5S message, header rb_id: %d)\n", sl_pc5s_msg_recv->pc5s_header.rb_id);
         LOG_D(PDCP,"Received PC5S message, header data_size: %d)\n", sl_pc5s_msg_recv->pc5s_header.data_size);
         LOG_D(PDCP,"Received PC5S message, header inst: %d)\n", sl_pc5s_msg_recv->pc5s_header.inst);
         LOG_D(PDCP,"Received PC5-S message, sourceL2Id: 0x%08x\n)\n", sl_pc5s_msg_recv->pc5s_header.sourceL2Id);
         LOG_D(PDCP,"Received PC5-S message, destinationL1Id: 0x%08x\n)\n", sl_pc5s_msg_recv->pc5s_header.destinationL2Id);
216
         free(sl_pc5s_msg_recv);
217 218 219 220
#endif
         memset(send_buf, 0, BUFSIZE);
         memcpy((void *)send_buf, (void*)(sdu_p->data+sizeof(pdcp_data_ind_header_t)), sizeof(sidelink_pc5s_element));

221 222
         int prose_addr_len = sizeof(prose_pdcp_addr);
         int n = sendto(pdcp_pc5_sockfd, (char *)send_buf, sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr, prose_addr_len);
223 224 225 226
         if (n < 0) {
            LOG_E(PDCP, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }
227
      }
228 229 230 231 232 233
#endif

      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);
         }
234

235
#ifdef PDCP_USE_RT_FIFO
236 237 238
         bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO,
               &(((uint8_t *) sdu->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
               pdcp_output_header_bytes_to_write);
239 240

#else
241
#ifdef PDCP_USE_NETLINK
242
#ifdef LINUX
243 244 245
         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;
246
#endif //LINUX
247
#endif //PDCP_USE_NETLINK
248

249
         bytes_wrote = pdcp_output_header_bytes_to_write;
250
#endif //PDCP_USE_RT_FIFO
251 252

#ifdef PDCP_DEBUG
253
         LOG_I(PDCP, "Frame %d Sent %d Bytes of header to Nas_mesh\n",
254 255
               ctxt_pP->frame,
               bytes_wrote);
256 257
#endif //PDCP_DEBUG

258 259
         if (bytes_wrote > 0) {
            pdcp_output_header_bytes_to_write = pdcp_output_header_bytes_to_write - bytes_wrote;
260

261 262 263
            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;
               AssertFatal(pdcp_output_sdu_bytes_to_write >= 0, "invalid data_size!");
264

265
#ifdef PDCP_USE_RT_FIFO
266
               bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO, &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
267 268
#else

269
#ifdef PDCP_USE_NETLINK
270
#ifdef LINUX
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
               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;
               VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_SIZE, pdcp_output_sdu_bytes_to_write);
               VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 1 );
               ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
               VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH_BUFFER, 0 );
               VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE_PDCP_FLUSH_ERR, ret );

               if (ret<0) {
                  LOG_E(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
                  MSC_LOG_TX_MESSAGE_FAILED(
                        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                    NULL,
                                    0,
                                    MSC_AS_TIME_FMT" DATA-IND RNTI %"PRIx16" rb %u size %u",
                                    MSC_AS_TIME_ARGS(ctxt_pP),
                                    ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id,
                                    ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size);
                  AssertFatal(1==0,"sendmsg failed for nas_sock_fd\n");
                  break;
               } else {
                  MSC_LOG_TX_MESSAGE(
                        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                    NULL,
                                    0,
                                    MSC_AS_TIME_FMT" DATA-IND RNTI %"PRIx16" rb %u size %u",
                                    MSC_AS_TIME_ARGS(ctxt_pP),
                                    ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id,
                                    ((pdcp_data_ind_header_t *)(sdu_p->data))->data_size);
               }
303

304
#endif // LINUX
305
#endif //PDCP_USE_NETLINK
306
               bytes_wrote= pdcp_output_sdu_bytes_to_write;
307
#endif // PDCP_USE_RT_FIFO
308 309

#ifdef PDCP_DEBUG
310
               LOG_I(PDCP, "PDCP->IP Frame %d INST %d: Sent %d Bytes of data from rab %d to higher layers\n",
311 312 313 314
                     ctxt_pP->frame,
                     ((pdcp_data_ind_header_t *)(sdu_p->data))->inst,
                     bytes_wrote,
                     ((pdcp_data_ind_header_t *)(sdu_p->data))->rb_id);
315
#endif //PDCP_DEBUG
316

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
               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, __func__);
                     cont = 1;
                     pdcp_nb_sdu_sent += 1;
                     sdu_p = list_get_head (&pdcp_sdu_list);
                  } else {
                     LOG_D(PDCP, "1 skip free_mem_block: pdcp_output_sdu_bytes_to_write = %d\n", pdcp_output_sdu_bytes_to_write);
                     AssertFatal(pdcp_output_sdu_bytes_to_write > 0, "pdcp_output_sdu_bytes_to_write cannot be negative!");
                  }
               } else {
                  LOG_W(PDCP, "2: RADIO->IP SEND SDU CONGESTION!\n");
341
                  AssertFatal(1==0,"congestion, aborting\n");
342
               }
343
            } else {
344
               LOG_W(PDCP, "3: RADIO->IP SEND SDU CONGESTION!\n");
345
            }
346 347 348
         } else {
            LOG_D(PDCP, "4 skip free_mem_block: bytes_wrote = %d\n", bytes_wrote);
         }
349
      } else {
350
         // continue writing sdu
351
#ifdef PDCP_USE_RT_FIFO
352 353 354
         bytes_wrote = rtf_put (PDCP2PDCP_USE_RT_FIFO,
               (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);
355
#else  // PDCP_USE_RT_FIFO
356
         bytes_wrote = pdcp_output_sdu_bytes_to_write;
357
#endif  // PDCP_USE_RT_FIFO
358
         LOG_D(PDCP, "THINH 2 bytes_wrote = %d\n", bytes_wrote);
359

360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
         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, __func__);
               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");
            } else {
               LOG_D(PDCP, "5 skip free_mem_block: pdcp_output_sdu_bytes_to_write = %d\n", pdcp_output_sdu_bytes_to_write);
            }
         } else {
            LOG_D(PDCP, "6 skip free_mem_block: bytes_wrote = %d\n", bytes_wrote);
         }
377
      }
378 379
   }
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 0 );
380

381
#ifdef PDCP_USE_RT_FIFO
382

383 384
   if ((pdcp_nb_sdu_sent)) {
      if ((pdcp_2_nas_irq > 0)) {
385
#ifdef PDCP_DEBUG
386 387
         LOG_D(PDCP, "Frame %d : Trigger NAS RX interrupt\n",
               ctxt_pP->frame);
388
#endif //PDCP_DEBUG
389
         rt_pend_linux_srq (pdcp_2_nas_irq);
390

391 392 393 394 395 396
      } 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);
      }
   }
397

398
#endif  //PDCP_USE_RT_FIFO
399

400
#ifdef PDCP_SDU_FLUSH_LOCK
401
   if (pthread_mutex_unlock(&mtex)) exit_fun("PDCP_SDU_FLUSH_LOCK unlock error!");
402 403
#endif

404
   return pdcp_nb_sdu_sent;
405 406 407
}

//-----------------------------------------------------------------------------
408
int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
409
{
410
#ifdef PDCP_USE_NETLINK
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
   protocol_ctxt_t                ctxt_cpy = *ctxt_pP;
   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;
   /* avoid gcc warnings */
   (void)data_p;
   module_id_t                    ue_id     = 0;
   pdcp_t*                        pdcp_p    = NULL;

//TTN for D2D (PC5S)
#ifdef Rel14
   int prose_addr_len;
   char send_buf[BUFSIZE], receive_buf[BUFSIZE];
   int optval;
   int bytes_received;
   sidelink_pc5s_element *sl_pc5s_msg_recv = NULL;
   sidelink_pc5s_element *sl_pc5s_msg_send = NULL;
   uint32_t sourceL2Id;
   uint32_t groupL2Id;
   module_id_t         module_id = 0;
432
   pc5s_header_t *pc5s_header;
433
#endif
434

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
# if defined(PDCP_USE_NETLINK_QUEUES)
   rb_id_t                        rab_id    = 0;

   pdcp_transmission_mode_t       pdcp_mode = PDCP_TRANSMISSION_MODE_UNKNOWN;


   while (pdcp_netlink_dequeue_element(ctxt_pP, &data_p) != 0) {
      DevAssert(data_p != NULL);
      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;
      }
457

458
      CHECK_CTXT_ARGS(&ctxt_cpy);
Lionel Gauthier's avatar
Lionel Gauthier committed
459

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

462 463 464 465 466 467 468 469 470 471
      if (rab_id != 0) {
         LOG_I(PDCP, "[FRAME %05d][%s][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ "
               "/ %d Bytes --->][PDCP][MOD %u][RB %u]\n",
               ctxt_cpy.frame,
               (ctxt_cpy.enb_flag) ? "eNB" : "UE",
                     data_p->pdcp_read_header.inst,
                     data_p->pdcp_read_header.rb_id,
                     data_p->pdcp_read_header.data_size,
                     ctxt_cpy.module_id,
                     rab_id);
472 473
#ifdef  OAI_NW_DRIVER_TYPE_ETHERNET

474 475 476
         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 */ ) {
Cedric Roux's avatar
Cedric Roux committed
477
#if defined(Rel10) || defined(Rel14)
478
            PDCP_TRANSMISSION_MODE_TRANSPARENT;
479
#else
480
            pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
481
#endif
482 483 484 485 486 487 488
         } 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*/ ) {
            pdcp_mode=  PDCP_TRANSMISSION_MODE_DATA;
         } else {
            pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
            LOG_W(PDCP,"unknown IP traffic type \n");
         }
489

490
#else // OAI_NW_DRIVER_TYPE_ETHERNET NASMESH driver does not curreenlty support multicast traffic
491
         pdcp_mode = PDCP_TRANSMISSION_MODE_DATA;
492
#endif
493 494 495 496 497 498 499
         pdcp_data_req(&ctxt_cpy,
               SRB_FLAG_NO,
               rab_id % maxDRB,
               RLC_MUI_UNDEFINED,
               RLC_SDU_CONFIRM_NO,
               data_p->pdcp_read_header.data_size,
               data_p->data,
500 501 502 503 504
               pdcp_mode
#ifdef Rel14
               ,NULL, NULL
#endif
               );
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
      } 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++) {
            if (pdcp_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) {
               LOG_D(PDCP, "eNB Try Forcing send on DEFAULT_RAB_ID UE %d\n", ue_id);
               ctxt.module_id     = ctxt_cpy.module_id;
               ctxt.rnti          = ctxt_cpy.pdcp_module_id_to_rnti[ctxt_cpy.module_id][ue_id];
               ctxt.frame         = ctxt_cpy.frame;
               ctxt.enb_flag      = ctxt_cpy.enb_flag;

               pdcp_data_req(
                     &ctxt,
                     SRB_FLAG_NO,
                     DEFAULT_RAB_ID,
                     RLC_MUI_UNDEFINED,
                     RLC_SDU_CONFIRM_NO,
                     data_p->pdcp_read_header.data_size,
                     data_p->data,
528 529 530 531 532
                     PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
                     ,NULL, NULL
#endif
                     );
533 534 535 536 537 538 539 540 541 542 543 544
            }
         }
      } 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,
               data_p->pdcp_read_header.data_size,
               data_p->data,
545 546 547 548 549
               PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
               ,NULL, NULL
#endif
               );
550
      }
551

552 553 554 555
      free(data_p->data);
      free(data_p);
      data_p = NULL;
   }
556

557
   return 0;
558
# else /* PDCP_USE_NETLINK_QUEUES*/
559 560 561 562 563 564 565 566
   int              len = 1;
   int  msg_len;
   rb_id_t          rab_id  = 0;
   int rlc_data_req_flag = 3;


//TTN for D2D (PC5S)
#ifdef Rel14
567
   prose_addr_len = sizeof(prose_pdcp_addr);
568 569 570
   // receive a message from ProSe App
   memset(receive_buf, 0, BUFSIZE);
   bytes_received = recvfrom(pdcp_pc5_sockfd, receive_buf, BUFSIZE, 0,
571
         (struct sockaddr *) &prose_pdcp_addr, &prose_addr_len);
572 573 574 575 576
   //  if (bytes_received < 0){
   //    LOG_E(RRC, "ERROR: Failed to receive from ProSe App\n");
   //    exit(EXIT_FAILURE);
   // }
   if (bytes_received > 0) {
577 578
      pc5s_header = calloc(1, sizeof(pc5s_header_t));
      memcpy((void *)pc5s_header, (void *)receive_buf, sizeof(pc5s_header_t));
579

580
      if (pc5s_header->traffic_type == TRAFFIC_PC5S_SESSION_INIT){
581
         //send reply to ProSe app
582
         LOG_D(PDCP,"Received a request to open PDCP socket and establish a new PDCP session ... send response to ProSe App \n");
583 584
         memset(send_buf, 0, BUFSIZE);
         sl_pc5s_msg_send = calloc(1, sizeof(sidelink_pc5s_element));
585
         sl_pc5s_msg_send->pc5s_header.traffic_type = TRAFFIC_PC5S_SESSION_INIT;
586 587 588
         sl_pc5s_msg_send->pc5sPrimitive.status = 1;

         memcpy((void *)send_buf, (void *)sl_pc5s_msg_send, sizeof(sidelink_pc5s_element));
589 590
         int prose_addr_len = sizeof(prose_pdcp_addr);
         int bytes_sent = sendto(pdcp_pc5_sockfd, (char *)send_buf, sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr, prose_addr_len);
591 592 593 594
         if (bytes_sent < 0) {
            LOG_E(PDCP, "ERROR: Failed to send to ProSe App\n");
            exit(EXIT_FAILURE);
         }
595
      } else if (pc5s_header->traffic_type == TRAFFIC_PC5S_SIGNALLING) { //if containing PC5-S message -> send to other UE
596
         LOG_D(PDCP,"Received PC5-S message ... send to the other UE\n");
597
#ifdef PDCP_DEBUG
598 599 600 601 602 603
         LOG_D(PDCP,"Received PC5-S message, traffic_type: %d)\n", pc5s_header->traffic_type);
         LOG_D(PDCP,"Received PC5-S message, rbid: %d)\n", pc5s_header->rb_id);
         LOG_D(PDCP,"Received PC5-S message, data_size: %d)\n", pc5s_header->data_size);
         LOG_D(PDCP,"Received PC5-S message, inst: %d)\n", pc5s_header->inst);
         LOG_D(PDCP,"Received PC5-S message,sourceL2Id: 0x%08x\n)\n", pc5s_header->sourceL2Id);
         LOG_D(PDCP,"Received PC5-S message,destinationL1Id: 0x%08x\n)\n", pc5s_header->destinationL2Id);
604

605
#endif
606

607
         /* TODO: do we have to reset to 0 or not? not for a scenario with 1 UE at least */
608
         //          pc5s_header.inst = 0;
609 610 611 612
         //#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
         ctxt.frame         = ctxt_cpy.frame;
         ctxt.enb_flag      = ctxt_cpy.enb_flag;

613
         LOG_I(PDCP, "[PDCP] pc5s_header->rb_id = %d\n", pc5s_header->rb_id);
614 615 616

         if (ctxt_cpy.enb_flag) {
            ctxt.module_id = 0;
617
            rab_id      = pc5s_header->rb_id % maxDRB;
618 619 620
            ctxt.rnti          = pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index];
         } else {
            ctxt.module_id = 0;
621
            rab_id      = pc5s_header->rb_id % maxDRB;
622
            ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
         }

         //UE
         if (!ctxt.enb_flag) {
            if (rab_id != 0) {
               if (rab_id == UE_IP_DEFAULT_RAB_ID) {
                  LOG_I(PDCP, "PDCP_COLL_KEY_DEFAULT_DRB_VALUE(module_id=%d, rnti=%x, enb_flag=%d)\n",
                        ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
                  key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
                  h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
                  LOG_I(PDCP,"request key %x : (%d,%x,%d,%d)\n",
                        key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
               } else {
                  rab_id = rab_id % maxDRB;
                  LOG_I(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%d, SRB_FLAG=%d)\n",
                        ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
                  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);
                  LOG_I(PDCP,"request key %x : (%d,%x,%d,%d)\n",
                        key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
               }

               if (h_rc == HASH_TABLE_OK) {
                  rab_id = pdcp_p->rb_id;
#ifdef PDCP_DEBUG
                  LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d  on Rab %d \n",
                        ctxt.frame,
650
                        pc5s_header->inst,
651
                        bytes_received,
652
                        pc5s_header->rb_id);
653 654 655

                  LOG_I(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
                        ctxt.frame,
656 657 658
                        pc5s_header->inst,
                        pc5s_header->rb_id,
                        pc5s_header->data_size,
659 660 661 662 663 664 665 666 667 668 669
                        ctxt.module_id,
                        ctxt.rnti,
                        rab_id);
#endif
                  MSC_LOG_RX_MESSAGE(
                        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                    NULL,
                                    0,
                                    MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
                                    MSC_AS_TIME_ARGS(ctxt_pP),
670 671
                                    pc5s_header.inst,
                                    pc5s_header.rb_id,
672
                                    rab_id,
673
                                    pc5s_header.data_size);
674 675 676 677 678 679 680

                  pdcp_data_req(
                        &ctxt,
                        SRB_FLAG_NO,
                        rab_id,
                        RLC_MUI_UNDEFINED,
                        RLC_SDU_CONFIRM_NO,
681
                        pc5s_header->data_size,
682
                        (unsigned char *)receive_buf,
683 684
                        PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
685 686
                        ,&pc5s_header->sourceL2Id
                        ,&pc5s_header->destinationL2Id
687 688
#endif
                        );
689 690 691 692 693 694 695 696
               } else {
                  MSC_LOG_RX_DISCARDED_MESSAGE(
                        (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                    NULL,
                                    0,
                                    MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
                                    MSC_AS_TIME_ARGS(ctxt_pP),
697 698
                                    pc5s_header.inst,
                                    pc5s_header.rb_id,
699
                                    rab_id,
700
                                    pc5s_header.data_size);
701 702 703
                  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",
                        ctxt.frame,
704 705 706
                        pc5s_header->inst,
                        pc5s_header->rb_id,
                        pc5s_header->data_size,
707 708 709 710 711 712 713 714 715
                        ctxt.module_id,
                        ctxt.rnti,
                        rab_id,
                        key);
               }
            }  else { //if (rab_id == 0)
               LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
               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",
                     ctxt.frame,
716 717 718
                     pc5s_header->inst,
                     pc5s_header->rb_id,
                     pc5s_header->data_size,
719 720 721 722 723 724 725 726 727
                     ctxt.module_id,
                     ctxt.rnti,
                     DEFAULT_RAB_ID);
               MSC_LOG_RX_MESSAGE(
                     (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                           (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                 NULL,0,
                                 MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u default rab %u size %u",
                                 MSC_AS_TIME_ARGS(ctxt_pP),
728 729
                                 pc5s_header->inst,
                                 pc5s_header->rb_id,
730
                                 DEFAULT_RAB_ID,
731
                                 pc5s_header->data_size);
732 733 734 735 736 737 738

               pdcp_data_req (
                     &ctxt,
                     SRB_FLAG_NO,
                     DEFAULT_RAB_ID,
                     RLC_MUI_UNDEFINED,
                     RLC_SDU_CONFIRM_NO,
739
                     pc5s_header->data_size,
740
                     (unsigned char *)receive_buf,
741 742
                     PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
743 744
                     ,&pc5s_header->sourceL2Id
                     ,&pc5s_header->destinationL2Id
745 746
#endif
                     );
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
            }
         }
          free (sl_pc5s_msg_recv);
          free (sl_pc5s_msg_send);
      }
   }

#endif

   while ((len > 0) && (rlc_data_req_flag !=0))  {
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 1 );
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER, 1 );
      len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ_BUFFER, 0 );

      if (len<=0) {
         // nothing in pdcp NAS socket
Raymond Knopp's avatar
Raymond Knopp committed
764
         LOG_D(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
      } else {

         msg_len = len;
         for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
               NLMSG_OK (nas_nlh_rx, msg_len);
               nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, msg_len)) {

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

            if (nas_nlh_rx->nlmsg_type == NLMSG_ERROR) {
               LOG_D(PDCP, "[PDCP][NETLINK] RX NLMSG_ERROR\n");
            }

            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));
785 786
                  LOG_D(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %u data_size %d, source L2Id 0x%08x, destination L2Id 0x%08x\n",
                        pdcp_read_header_g.inst, pdcp_read_header_g.rb_id, pdcp_read_header_g.data_size,pdcp_read_header_g.sourceL2Id, pdcp_read_header_g.destinationL2Id );
787 788 789 790 791 792 793 794 795 796 797 798
               } else {
                  LOG_E(PDCP, "[PDCP][NETLINK] WRONG size %d should be sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)\n",
                        nas_nlh_rx->nlmsg_len);
               }
            } else {
               pdcp_read_state_g = 0;
               // print_active_requests()
#ifdef PDCP_DEBUG
               LOG_D(PDCP, "[PDCP][NETLINK] Something in socket, length %zu\n",
                     nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
#endif

Cedric Roux's avatar
Cedric Roux committed
799 800
          /* TODO: do we have to reset to 0 or not? not for a scenario with 1 UE at least */
//          pdcp_read_header_g.inst = 0;
Cedric Roux's avatar
Cedric Roux committed
801
//#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
802
          ctxt.frame         = ctxt_cpy.frame;
803
          ctxt.enb_flag      = ctxt_cpy.enb_flag;
804

805
#ifdef PDCP_DEBUG
806
               LOG_I(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %d, source L2Id = 0x%08x, destination L2Id = 0x%08x \n", pdcp_read_header_g.rb_id, pdcp_read_header_g.sourceL2Id, pdcp_read_header_g.destinationL2Id);
807 808
#endif

809
          if (ctxt_cpy.enb_flag) {
810
            ctxt.module_id = 0;
811
            rab_id      = pdcp_read_header_g.rb_id % maxDRB;
812
            ctxt.rnti          = pdcp_eNB_UE_instance_to_rnti[pdcp_read_header_g.rb_id / maxDRB];
813
          } else {
814
            ctxt.module_id = 0;
815
            rab_id      = pdcp_read_header_g.rb_id % maxDRB;
816
            ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
817
          }
818

819 820 821
          if (ctxt.enb_flag) {
            if (rab_id != 0) {
              rab_id = rab_id % maxDRB;
822 823
              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);
824

825
                     if (h_rc == HASH_TABLE_OK) {
826
#ifdef PDCP_DEBUG
827 828 829 830 831 832
                        LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) 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);
833 834
#endif

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
                        MSC_LOG_RX_MESSAGE(
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                                    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                          NULL,
                                          0,
                                          MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
                                          MSC_AS_TIME_ARGS(ctxt_pP),
                                          pdcp_read_header_g.inst,
                                          pdcp_read_header_g.rb_id,
                                          rab_id,
                                          pdcp_read_header_g.data_size);
                        LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u]UE %u][RB %u]\n",
                              ctxt_cpy.frame,
                              pdcp_read_header_g.inst,
                              pdcp_read_header_g.rb_id,
                              pdcp_read_header_g.data_size,
                              ctxt.module_id,
                              ctxt.rnti,
                              rab_id);

                        pdcp_data_req(&ctxt,
856 857 858 859 860 861
                              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),
862 863 864 865 866
                              PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
                              ,NULL, NULL
#endif
                              );
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
                     } else {
                        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",
                              ctxt.frame,
                              pdcp_read_header_g.inst,
                              pdcp_read_header_g.rb_id,
                              pdcp_read_header_g.data_size,
                              ctxt.module_id,
                              ctxt.rnti,
                              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
                     //#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
                     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",
                                 ctxt.frame,
                                 pdcp_read_header_g.inst,
                                 pdcp_read_header_g.rb_id,
                                 pdcp_read_header_g.data_size,
                                 ctxt.module_id,
                                 ctxt.rnti,
                                 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),
899 900 901 902 903
                                 PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
                                ,NULL, NULL
#endif
                                );
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
                        }
                     }
                  }
               } else { // enb_flag
                  if (rab_id != 0) {
                     if (rab_id == UE_IP_DEFAULT_RAB_ID) {
                        LOG_I(PDCP, "PDCP_COLL_KEY_DEFAULT_DRB_VALUE(module_id=%d, rnti=%x, enb_flag=%d)\n",
                              ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
                        key = PDCP_COLL_KEY_DEFAULT_DRB_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag);
                        h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
                        LOG_I(PDCP,"request key %x : (%d,%x,%d,%d)\n",
                              key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
                     } else {
                        rab_id = rab_id % maxDRB;
                        LOG_I(PDCP, "PDCP_COLL_KEY_VALUE(module_id=%d, rnti=%x, enb_flag=%d, rab_id=%d, SRB_FLAG=%d)\n",
                              ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
                        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);
                        LOG_I(PDCP,"request key %x : (%d,%x,%d,%d)\n",
                              key,ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id);
                     }

                     if (h_rc == HASH_TABLE_OK) {
                        rab_id = pdcp_p->rb_id;
928
#ifdef PDCP_DEBUG
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
                        LOG_I(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %zu) 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);

                        LOG_I(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
                              ctxt.frame,
                              pdcp_read_header_g.inst,
                              pdcp_read_header_g.rb_id,
                              pdcp_read_header_g.data_size,
                              ctxt.module_id,
                              ctxt.rnti,
                              rab_id);
944
#endif
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964
                        MSC_LOG_RX_MESSAGE(
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                                    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                          NULL,
                                          0,
                                          MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
                                          MSC_AS_TIME_ARGS(ctxt_pP),
                                          pdcp_read_header_g.inst,
                                          pdcp_read_header_g.rb_id,
                                          rab_id,
                                          pdcp_read_header_g.data_size);

                        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),
965 966 967 968 969 970
                              PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
                              ,&pdcp_read_header_g.sourceL2Id
                              ,&pdcp_read_header_g.destinationL2Id
#endif
                              );
971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
                     } else {
                        MSC_LOG_RX_DISCARDED_MESSAGE(
                              (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                                    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                          NULL,
                                          0,
                                          MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
                                          MSC_AS_TIME_ARGS(ctxt_pP),
                                          pdcp_read_header_g.inst,
                                          pdcp_read_header_g.rb_id,
                                          rab_id,
                                          pdcp_read_header_g.data_size);
                        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",
                              ctxt.frame,
                              pdcp_read_header_g.inst,
                              pdcp_read_header_g.rb_id,
                              pdcp_read_header_g.data_size,
                              ctxt.module_id,
                              ctxt.rnti,
                              rab_id,
                              key);
                     }
                  }  else {
                     LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
                     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",
                           ctxt.frame,
                           pdcp_read_header_g.inst,
                           pdcp_read_header_g.rb_id,
                           pdcp_read_header_g.data_size,
                           ctxt.module_id,
                           ctxt.rnti,
                           DEFAULT_RAB_ID);
                     MSC_LOG_RX_MESSAGE(
                           (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                                 (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                                       NULL,0,
                                       MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u default rab %u size %u",
                                       MSC_AS_TIME_ARGS(ctxt_pP),
                                       pdcp_read_header_g.inst,
                                       pdcp_read_header_g.rb_id,
                                       DEFAULT_RAB_ID,
                                       pdcp_read_header_g.data_size);

                     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),
1023 1024 1025 1026 1027 1028
                           PDCP_TRANSMISSION_MODE_DATA
#ifdef Rel14
                           ,&pdcp_read_header_g.sourceL2Id
                           ,&pdcp_read_header_g.destinationL2Id
#endif
                           );
1029 1030
                  }
               }
1031

1032 1033
            }
         }
1034
      }
1035 1036 1037
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_READ, 0 );
   }

1038

1039
   return len;
1040
# endif
1041
#else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO
1042
   return 0;
1043
#endif // PDCP_USE_NETLINK
1044 1045 1046
}


1047 1048
void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t* const  ctxt_pP) {

1049

1050
  module_id_t          dst_id; // dst for otg
1051 1052 1053
  protocol_ctxt_t      ctxt;
  // we need to add conditions to avoid transmitting data when the UE is not RRC connected.
  if ((otg_enabled==1) && (ctxt_pP->enb_flag == ENB_FLAG_YES)) { // generate DL traffic
1054

1055 1056 1057



1058 1059 1060 1061 1062 1063
    PROTOCOL_CTXT_SET_BY_MODULE_ID(
      &ctxt,
      ctxt_pP->module_id,
      ctxt_pP->enb_flag,
      NOT_A_RNTI,
      ctxt_pP->frame,
1064 1065
      ctxt_pP->subframe,
      ctxt_pP->module_id);
1066 1067

    for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
1068
      ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id];
1069

1070
    }
1071
  }
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112
}

//TTN for D2D (PC5S)
#ifdef Rel14

int
pdcp_pc5_socket_init() {
   pthread_attr_t     attr;
   struct sched_param sched_param;
   int optval; // flag value for setsockopt
   int n; // message byte size

   //create PDCP socket
   pdcp_pc5_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
   if (pdcp_pc5_sockfd < 0){
      LOG_E(PDCP,"[pdcp_pc5_socket_init] Error opening socket %d (%d:%s)\n",pdcp_pc5_sockfd,errno, strerror(errno));
      exit(EXIT_FAILURE);
   }

   optval = 1;
   setsockopt(pdcp_pc5_sockfd, SOL_SOCKET, SO_REUSEADDR,
         (const void *)&optval , sizeof(int));

   fcntl(pdcp_pc5_sockfd,F_SETFL,O_NONBLOCK);

   bzero((char *) &pdcp_sin, sizeof(pdcp_sin));
   pdcp_sin.sin_family = AF_INET;
   pdcp_sin.sin_addr.s_addr = htonl(INADDR_ANY);
   pdcp_sin.sin_port = htons(PDCP_SOCKET_PORT_NO);
   // associate the parent socket with a port
   if (bind(pdcp_pc5_sockfd, (struct sockaddr *) &pdcp_sin,
         sizeof(pdcp_sin)) < 0) {
      LOG_E(PDCP,"[pdcp_pc5_socket_init] ERROR: Failed on binding the socket\n");
      exit(1);
   }

}

#endif