From 8fa560227832d8582e5c0d04bcc64bfff27662c0 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Fri, 11 Oct 2013 14:45:30 +0000
Subject: [PATCH] - Added thread that fetch netlink packets and place them in a
 FIFO (option enabled by default) to reduce pdcp_run execution time - Fix some
 debug formats

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4187 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair1/PHY/LTE_TRANSPORT/dlsch_coding.c     |   3 +-
 openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c   |   2 +-
 .../SIMULATION/ETH_TRANSPORT/netlink_init.c   |   2 +
 openair2/LAYER2/Makefile.inc                  |   1 +
 openair2/LAYER2/PDCP_v10.1.0/pdcp.c           |  53 ++--
 openair2/LAYER2/PDCP_v10.1.0/pdcp.h           |  11 +-
 openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c      |  88 ++++++-
 openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c   | 238 ++++++++++++++++++
 .../LAYER2/PDCP_v10.1.0/pdcp_primitives.h     |   3 +
 openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c    |   2 +
 openair2/UTIL/FIFO/types.h                    |   6 +-
 openair2/UTIL/OSA/osa_internal.h              |   2 +-
 openair2/UTIL/OSA/osa_key_deriver.c           |   9 +-
 openair2/UTIL/OTG/otg_models.c                |  22 +-
 targets/SIMU/USER/Makefile                    |   1 +
 targets/SIMU/USER/oaisim_functions.c          |   5 +-
 16 files changed, 382 insertions(+), 66 deletions(-)
 create mode 100644 openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c

diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index 90926004cd..feb30915c6 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -169,7 +169,8 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigne
       return(dlsch);
     }
   }
-  msg("new_eNB_dlsch exit flag %d, size of  %d\n",exit_flag, sizeof(LTE_eNB_DLSCH_t));
+  LOG_D(PHY, "new_eNB_dlsch exit flag %d, size of  %ld\n",
+        exit_flag, sizeof(LTE_eNB_DLSCH_t));
   free_eNB_dlsch(dlsch);
   return(NULL);
   
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
index be0cbe12d9..5f62d2d2ee 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
@@ -120,7 +120,7 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_ite
     if (exit_flag==0)
       return(dlsch);
   }
-  msg("new_ue_dlsch with size %d: exit_flag = %d\n",sizeof(LTE_DL_UE_HARQ_t), exit_flag);
+  msg("new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(LTE_DL_UE_HARQ_t), exit_flag);
   free_ue_dlsch(dlsch);
 
   return(NULL);
diff --git a/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c b/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
index c1395c4637..691744ffb0 100644
--- a/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
+++ b/openair1/SIMULATION/ETH_TRANSPORT/netlink_init.c
@@ -43,11 +43,13 @@ int netlink_init(void)
     }
     printf("[NETLINK]Opened socket with fd %d\n",nas_sock_fd);
 
+#if !defined(ENABLE_PDCP_NETLINK_FIFO)
     ret = fcntl(nas_sock_fd,F_SETFL,O_NONBLOCK);
     if (ret == -1) {
       printf("[NETLINK] Error fcntl (%d:%s)\n",errno, strerror(errno));
 //      exit(1);
     }
+#endif
 
     memset(&nas_src_addr, 0, sizeof(nas_src_addr));
     nas_src_addr.nl_family = AF_NETLINK;
diff --git a/openair2/LAYER2/Makefile.inc b/openair2/LAYER2/Makefile.inc
index 41cac88a1e..9cc4055597 100644
--- a/openair2/LAYER2/Makefile.inc
+++ b/openair2/LAYER2/Makefile.inc
@@ -27,6 +27,7 @@ SOURCES_L2 +=  $(PDCP_DIR)/pdcp_sequence_manager.c
 SOURCES_L2 +=  $(PDCP_DIR)/pdcp_primitives.c
 SOURCES_L2 +=  $(PDCP_DIR)/pdcp_util.c
 SOURCES_L2 +=  $(PDCP_DIR)/pdcp_security.c
+SOURCES_L2 +=  $(PDCP_DIR)/pdcp_netlink.c
 
 SOURCES_L2 +=  $(RLC_AM_DIR)/rlc_am.c
 SOURCES_L2 +=  $(RLC_AM_DIR)/rlc_am_init.c
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index 0ced904b73..bd14ff4e9e 100755
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -82,8 +82,8 @@ extern int otg_rx_pkt( int src, int dst, int ctime, char *buffer_tx, unsigned in
 BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb_id, sdu_size_t sdu_buffer_size, \
                    unsigned char* sdu_buffer, pdcp_t* test_pdcp_entity, list_t* test_list)
 #else
-    BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb_id, u32 muiP, u32 confirmP, \
-                       sdu_size_t sdu_buffer_size, unsigned char* sdu_buffer, u8 mode)
+BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb_id, u32 muiP, u32 confirmP, \
+                   sdu_size_t sdu_buffer_size, unsigned char* sdu_buffer, u8 mode)
 #endif
 {
   //-----------------------------------------------------------------------------
@@ -126,7 +126,7 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
       memcpy(&pdcp_pdu->data[0], sdu_buffer, sdu_buffer_size); 
       rlc_status = rlc_data_req(module_id, frame, eNB_flag, RLC_MBMS_YES, rb_id, muiP, confirmP, sdu_buffer_size, pdcp_pdu);
     } else
-      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;    
+      rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
   } else {
     // calculate the pdcp header and trailer size
     if ((rb_id % NB_RB_MAX) < DTCH) {
@@ -137,15 +137,15 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
       pdcp_tailer_len = 0;
     }
     pdcp_pdu_size= sdu_buffer_size + pdcp_header_len + pdcp_tailer_len;
-    
+
     LOG_I(PDCP, "Data request notification for PDCP entity with module ID %d and radio bearer ID %d pdu size %d (header%d, trailer%d)\n", module_id, rb_id,pdcp_pdu_size, pdcp_header_len,pdcp_tailer_len);
-    
+
     /*
      * Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
      */
     LOG_D(PDCP, "Asking for a new mem_block of size %d\n", pdcp_pdu_size);
     pdcp_pdu = get_free_mem_block(pdcp_pdu_size);
-    
+
     if (pdcp_pdu != NULL) {
       /*
        * Create a Data PDU with header and append data
@@ -295,7 +295,7 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
   "ID %d and radio bearer ID %d rlc sdu size %d eNB_flag %d\n", module_id, rb_id, sdu_buffer_size, eNB_flag);
 
   if (sdu_buffer_size == 0) {
-    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!");
+    LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
     return FALSE;
   }
 
@@ -469,14 +469,13 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
 }
 
 //-----------------------------------------------------------------------------
-void
-    pdcp_run (u32_t frame, u8 eNB_flag, u8 UE_index, u8 eNB_index) {
+void pdcp_run (u32_t frame, u8 eNB_flag, u8 UE_index, u8 eNB_index) {
   //-----------------------------------------------------------------------------
 
 #ifndef NAS_NETLINK
 #ifdef USER_MODE
 #define PDCP_DUMMY_BUFFER_SIZE 38
-    unsigned char pdcp_dummy_buffer[PDCP_DUMMY_BUFFER_SIZE];
+  unsigned char pdcp_dummy_buffer[PDCP_DUMMY_BUFFER_SIZE];
 #endif
 #endif
 //     unsigned int diff, i, k, j;
@@ -487,7 +486,7 @@ void
 //     int pkt_size=0;
 //     unsigned int ctime=0;
 
-    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
+  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
 
     /*
       if ((frame % 128) == 0) {
@@ -510,10 +509,10 @@ void
   pdcp_fifo_read_input_sdus_from_otg(frame, eNB_flag, UE_index, eNB_index);
 
   // IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
-  pdcp_fifo_read_input_sdus(frame,eNB_flag);
+  pdcp_fifo_read_input_sdus(frame, eNB_flag, UE_index, eNB_index);
 
   // PDCP -> NAS/IP traffic: RX
-  pdcp_fifo_flush_sdus(frame,eNB_flag);
+  pdcp_fifo_flush_sdus(frame, eNB_flag);
 
   vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
 }
@@ -531,21 +530,21 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
 #endif
                                ){
 
-  long int        rb_id        = 0;
-  long int        lc_id        = 0;
-  long int        srb_id        = 0;
+  long int        rb_id          = 0;
+  long int        lc_id          = 0;
+  long int        srb_id         = 0;
   long int        mch_id         = 0;
-  rlc_mode_t      rlc_type    = RLC_NONE;
-  DRB_Identity_t  drb_id       = 0;
-  DRB_Identity_t* pdrb_id      = NULL;
-  u8              drb_sn       = 0;
-  u8              srb_sn       = 5; // fixed sn for SRBs
-  u8              drb_report   = 0;
-  long int        cnt          = 0;
+  rlc_mode_t      rlc_type       = RLC_NONE;
+  DRB_Identity_t  drb_id         = 0;
+  DRB_Identity_t* pdrb_id        = NULL;
+  u8              drb_sn         = 0;
+  u8              srb_sn         = 5; // fixed sn for SRBs
+  u8              drb_report     = 0;
+  long int        cnt            = 0;
   u16 header_compression_profile = 0;
-  u32 action                   = ACTION_ADD;
-  SRB_ToAddMod_t* srb_toaddmod = NULL;
-  DRB_ToAddMod_t* drb_toaddmod = NULL;
+  u32 action                     = ACTION_ADD;
+  SRB_ToAddMod_t* srb_toaddmod   = NULL;
+  DRB_ToAddMod_t* drb_toaddmod   = NULL;
 
 #ifdef Rel10
   int i,j;
@@ -692,7 +691,7 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
   if (drb2release_list != NULL) {
     for (cnt=0;cnt<drb2add_list->list.count;cnt++) {
       pdrb_id = drb2release_list->list.array[cnt];
-      rb_id =  (index * NB_RB_MAX) + pdrb_id;
+      rb_id =  (index * NB_RB_MAX) + *pdrb_id;
       action = ACTION_REMOVE;
       pdcp_config_req_asn1 (module_id,
                             frame,
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 13be1f28aa..0332e513f6 100755
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -91,7 +91,6 @@ extern pthread_mutex_t pdcp_mutex;
 extern pthread_cond_t pdcp_cond;
 extern int pdcp_instance_cnt;
 
-static void *pdcp_thread_main(void* param);
 int init_pdcp_thread(void);
 void cleanup_pdcp_thread(void);
 
@@ -343,13 +342,14 @@ public_pdcp(int pdcp_module_init ();)
 public_pdcp(void pdcp_module_cleanup ();)
 public_pdcp(void pdcp_layer_init ();)
 public_pdcp(void pdcp_layer_cleanup ();)
+public_pdcp(int pdcp_netlink_init(void);)
 
 #define PDCP2NAS_FIFO 21
 #define NAS2PDCP_FIFO 22
 
 protected_pdcp_fifo(int pdcp_fifo_flush_sdus (u32_t,u8_t);)
 protected_pdcp_fifo(int pdcp_fifo_read_input_sdus_remaining_bytes (u32_t,u8_t);)
-protected_pdcp_fifo(int pdcp_fifo_read_input_sdus(u32_t,u8_t);)
+protected_pdcp_fifo(int pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag, u8_t UE_index, u8_t eNB_index);)
 protected_pdcp_fifo(void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index, u8 eNB_index);)
 
 //-----------------------------------------------------------------------------
@@ -368,6 +368,13 @@ typedef struct pdcp_data_ind_header_t {
   int       inst;
 } pdcp_data_ind_header_t;
 
+struct pdcp_netlink_element_s {
+    pdcp_data_req_header_t pdcp_read_header;
+
+    /* Data part of the message */
+    uint8_t *data;
+};
+
 #if 0
 /*
  * Missing PDU information struct, a copy of this will be enqueued
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index a938813f16..a7c36709d6 100755
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -93,8 +93,7 @@ extern Packet_OTG_List *otg_pdcp_buffer;
 pdcp_data_req_header_t pdcp_read_header;
 
 //-----------------------------------------------------------------------------
-int
-    pdcp_fifo_flush_sdus (u32_t frame,u8 eNB_flag)
+int pdcp_fifo_flush_sdus (u32_t frame,u8 eNB_flag)
 {
   //-----------------------------------------------------------------------------
 
@@ -170,7 +169,7 @@ int
           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("");
+            mac_xface->macphy_exit("sendmsg failed for nas_sock_fd\n");
             break;
           }
 #endif // LINUX
@@ -350,8 +349,7 @@ int
 }
 
 //-----------------------------------------------------------------------------
-int
-    pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag)
+int pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag, u8_t UE_index, u8_t eNB_index)
 {
   //-----------------------------------------------------------------------------
 //#ifdef NAS_FIFO
@@ -426,11 +424,11 @@ int
 //          } else {
 //#ifdef PDCP_DEBUG
 //#ifdef LINUX
-//              LOG_I(PDCP, "[PDCP][NETLINK] Received socket with length %d (nlmsg_len = %d)\n", \
+//              LOG_I(PDCP, "[PDCP][NETLINK] Received socket with length %d (nlmsg_len = %d)\n",
 //                      len, nas_nlh->nlmsg_len-sizeof(struct nlmsghdr));
 //#else
-//              LOG_I(PDCP, "[PDCP][NETLINK] nlmsg_len = %d (%d,%d)\n", \
-//                       nas_nlh->nlmsg_len, sizeof(pdcp_data_req_header_t), \
+//              LOG_I(PDCP, "[PDCP][NETLINK] nlmsg_len = %d (%d,%d)\n",
+//                       nas_nlh->nlmsg_len, sizeof(pdcp_data_req_header_t),
 //                       sizeof(struct nlmsghdr));
 //#endif
 //#endif
@@ -465,7 +463,7 @@ int
 //#endif
 //
 //#ifdef OAI_EMU
-//              pdcp_read_header.inst = (pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) ? \
+//              pdcp_read_header.inst = (pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) ?
 //                                pdcp_read_header.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local :
 //                                pdcp_read_header.inst +  oai_emulation.info.first_enb_local;
 //#else
@@ -475,7 +473,7 @@ int
 //              if (pdcp_read_header.rb_id != 0) {
 //                  if (pdcp_array[pdcp_read_header.inst][pdcp_read_header.rb_id].instanciated_instance) {
 //#ifdef PDCP_DEBUG
-//                      LOG_I(PDCP, "[PDCP][NETLINK][IP->PDCP] TTI %d, INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n", \
+//                      LOG_I(PDCP, "[PDCP][NETLINK][IP->PDCP] TTI %d, INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
 //                        frame, pdcp_read_header.inst, len, nas_nlh->nlmsg_len-sizeof(struct nlmsghdr), pdcp_read_header.rb_id);
 //                      LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
 //                        frame, pdcp_read_header.inst,  pdcp_read_header.data_size, pdcp_read_header.inst, pdcp_read_header.rb_id);
@@ -527,8 +525,72 @@ int
 //#else // neither NAS_NETLINK nor NAS_FIFO
 //  return 0;
 //#endif // NAS_NETLINK
-//#endif // NAS_FIFO
 #ifdef NAS_NETLINK
+# if defined(ENABLE_PDCP_NETLINK_FIFO)
+    rb_id_t rab_id;
+
+    struct pdcp_netlink_element_s *data = NULL;
+
+    while (pdcp_netlink_dequeue_element(eNB_flag, UE_index, eNB_index, &data) != 0) {
+        if (data->pdcp_read_header.rb_id != 0) {
+            if (pdcp_array[data->pdcp_read_header.inst][data->pdcp_read_header.rb_id%NB_RB_MAX].instanciated_instance) {
+#ifdef PDCP_DEBUG
+                LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ "
+                      "/ %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
+                      frame, data->pdcp_read_header.inst, data->pdcp_read_header.data_size,
+                      data->pdcp_read_header.inst, data->pdcp_read_header.rb_id);
+#endif
+
+                pdcp_data_req(data->pdcp_read_header.inst,
+                              frame,
+                              eNB_flag,
+                              data->pdcp_read_header.rb_id,
+                              RLC_MUI_UNDEFINED,
+                              RLC_SDU_CONFIRM_NO,
+                              data->pdcp_read_header.data_size,
+                              data->data,
+                              PDCP_DATA_PDU);
+            } else {
+                LOG_E(PDCP, "Received packet for non-instanciated instance %u with rb_id %u\n",
+                      data->pdcp_read_header.inst, data->pdcp_read_header.rb_id);
+            }
+        } else if (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
+             */
+#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
+            for (rab_id = DEFAULT_RAB_ID; rab_id < MAX_RB; rab_id = rab_id + NB_RB_MAX) {
+                if (pdcp_array[pdcp_input_header.inst][rab_id%NB_RB_MAX].instanciated_instance == (pdcp_input_header.inst + 1)) {
+                    pdcp_data_req(data->pdcp_read_header.inst,
+                                  frame,
+                                  eNB_flag,
+                                  rab_id,
+                                  RLC_MUI_UNDEFINED,
+                                  RLC_SDU_CONFIRM_NO,
+                                  data->pdcp_read_header.data_size,
+                                  data->data,
+                                  PDCP_DATA_PDU);
+                }
+            }
+        } else {
+            LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
+            pdcp_data_req(data->pdcp_read_header.inst,
+                          frame, eNB_flag,
+                          DEFAULT_RAB_ID,
+                          RLC_MUI_UNDEFINED,
+                          RLC_SDU_CONFIRM_NO,
+                          data->pdcp_read_header.data_size,
+                          data->data,
+                          PDCP_DATA_PDU);
+        }
+
+        free(data->data);
+        free(data);
+        data = NULL;
+    }
+    return 0;
+# else
   int              len = 1;
   rb_id_t          rab_id  = 0;
 
@@ -546,7 +608,7 @@ int
                   if (nas_nlh_rx->nlmsg_type == NLMSG_DONE) {
                       LOG_I(PDCP, "[PDCP][NETLINK] RX NLMSG_DONE\n");
                       //return;
-                  };
+                  }
 
                   if (nas_nlh_rx->nlmsg_type == NLMSG_ERROR) {
                       LOG_I(PDCP, "[PDCP][NETLINK] RX NLMSG_ERROR\n");
@@ -624,7 +686,7 @@ int
           }
   }
   return len;
-
+# endif
 #else // neither NAS_NETLINK nor NAS_FIFO
   return 0;
 #endif // NAS_NETLINK
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
new file mode 100644
index 0000000000..37bda5c3a6
--- /dev/null
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_netlink.c
@@ -0,0 +1,238 @@
+/*******************************************************************************
+
+  Eurecom OpenAirInterface
+  Copyright(c) 1999 - 2013 Eurecom
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms and conditions of the GNU General Public License,
+  version 2, as published by the Free Software Foundation.
+
+  This program is distributed in the hope 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.
+
+  You should have received a copy of the GNU General Public License along with
+  this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+  The full GNU General Public License is included in this distribution in
+  the file called "COPYING".
+
+  Contact Information
+  Openair Admin: openair_admin@eurecom.fr
+  Openair Tech : openair_tech@eurecom.fr
+  Forums       : http://forums.eurecom.fsr/openairinterface
+  Address      : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
+
+*******************************************************************************/
+
+/*! \file pdcp_netlink.c
+* \brief pdcp communication with linux IP interface,
+* have a look at http://man7.org/linux/man-pages/man7/netlink.7.html for netlink.
+* Read operation from netlink should be achieved in an asynchronous way to avoid
+* subframe overload, netlink congestion...
+* \author Sebastien ROUX
+* \date 2013
+* \version 0.1
+* @ingroup pdcp
+*/
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <error.h>
+#include <unistd.h>
+
+#include <linux/netlink.h>
+
+#include "assertions.h"
+#include "queue.h"
+#include "liblfds611.h"
+
+#include "UTIL/LOG/log.h"
+#include "UTIL/OCG/OCG.h"
+#include "UTIL/OCG/OCG_extern.h"
+#include "LAYER2/MAC/extern.h"
+
+#include "pdcp.h"
+#include "pdcp_primitives.h"
+
+#define PDCP_QUEUE_NB_ELEMENTS 200
+
+extern char nl_rx_buf[NL_MAX_PAYLOAD];
+extern struct nlmsghdr *nas_nlh_rx;
+extern struct iovec nas_iov_rx;
+extern int nas_sock_fd;
+extern struct msghdr nas_msg_rx;
+
+static pthread_t pdcp_netlink_thread;
+
+/* We use lock-free queues between the User-plane driver running in kernel-space
+ * and the corresponding entity in User-space.
+ * one queue for eNBs (index 0)/one queue for UEs (index 1)
+ */
+static struct lfds611_queue_state **pdcp_netlink_queue = NULL;
+static uint32_t *pdcp_netlink_nb_element = NULL;
+
+static void *pdcp_netlink_thread_fct(void *arg);
+
+int pdcp_netlink_init(void) {
+
+    int i, nb_modules;
+    pthread_attr_t attr;
+    struct sched_param sched_param;
+
+#if defined(USER_MODE) && defined(OAI_EMU)
+    nb_modules = NB_eNB_INST + NB_UE_INST;
+#else
+    nb_modules = 1;
+#endif
+
+    pdcp_netlink_queue = calloc(nb_modules, sizeof(struct lfds611_queue_state*));
+    pdcp_netlink_nb_element = malloc(nb_modules * sizeof(uint32_t));
+
+    LOG_I(PDCP, "Creating %d queues for Netlink -> PDCP communication\n",
+          nb_modules);
+
+    for (i = 0; i < nb_modules; i++) {
+        pdcp_netlink_nb_element[i] = 0;
+        if (lfds611_queue_new(&pdcp_netlink_queue[i], PDCP_QUEUE_NB_ELEMENTS) < 0) {
+            LOG_E(PDCP, "Failed to create new FIFO for Netlink -> PDCP communcation instance %d\n", i);
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (pthread_attr_init(&attr) != 0) {
+        LOG_E(PDCP, "Failed to initialize pthread attribute for Netlink -> PDCP communication (%d:%s)\n",
+              errno, strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    sched_param.sched_priority = 10;
+
+    pthread_attr_setschedpolicy(&attr, SCHED_RR);
+    pthread_attr_setschedparam(&attr, &sched_param);
+
+    /* Create one thread that fetchs packets from the netlink.
+     * When the netlink fifo is full, packets are silently dropped, this behaviour
+     * should be avoided if we want a reliable link.
+     */
+    if (pthread_create(&pdcp_netlink_thread, &attr, pdcp_netlink_thread_fct, NULL) != 0) {
+        LOG_E(PDCP, "Failed to create new thread for Netlink/PDCP communcation (%d:%s)\n",
+              errno, strerror(errno));
+        exit(EXIT_FAILURE);
+    }
+
+    return 0;
+}
+
+int pdcp_netlink_dequeue_element(uint8_t eNB_flag, uint8_t UE_index, uint8_t eNB_index,
+                                 struct pdcp_netlink_element_s **data)
+{
+    int ret = 0;
+    module_id_t module_id;
+
+#if defined(USER_MODE) && defined(OAI_EMU)
+    module_id = (eNB_flag != 0) ? eNB_index : NB_eNB_INST + UE_index;
+#else
+    module_id = 0;
+#endif
+
+    ret = lfds611_queue_dequeue(pdcp_netlink_queue[module_id], (void **)data);
+
+    if (ret != 0) {
+        LOG_D(PDCP, "De-queueing packet for module %d\n", module_id);
+    }
+    return ret;
+}
+
+static
+void *pdcp_netlink_thread_fct(void *arg) {
+    int len;
+    struct pdcp_netlink_element_s *new_data = NULL;
+    uint8_t pdcp_read_state;
+
+    pdcp_read_state = 0;
+    memset(nl_rx_buf, 0, NL_MAX_PAYLOAD);
+
+    while (1) {
+
+        len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);
+
+        if (len == 0) {
+            /* Other peer (kernel) has performed an orderly shutdown
+             */
+            LOG_E(PDCP, "Kernel module has closed the netlink\n");
+            exit(EXIT_FAILURE);
+        } else if (len < 0) {
+            /* There was an error */
+            LOG_E(PDCP, "An error occured while reading netlink (%d:%s)\n",
+                  errno, strerror(errno));
+            exit(EXIT_FAILURE);
+        } else {
+            /* Normal read.
+             * NOTE: netlink messages can be assembled to form a multipart message
+             */
+            for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
+                 NLMSG_OK(nas_nlh_rx, len);
+                 nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {
+
+                /* There is no need to check for nlmsg_type because
+                 * the header is not set in our drivers.
+                 */
+                if (pdcp_read_state == 0) {
+                    new_data = malloc(sizeof(struct pdcp_netlink_element_s));
+
+                    if (nas_nlh_rx->nlmsg_len == sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)) {
+                        pdcp_read_state = 1;
+                        memcpy((void *)&new_data->pdcp_read_header, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
+                        LOG_I(PDCP, "[NETLINK] RX pdcp_data_req_header_t inst %u, "
+                              "rb_id %u data_size %d\n",
+                              new_data->pdcp_read_header.inst, new_data->pdcp_read_header.rb_id,
+                              new_data->pdcp_read_header.data_size);
+                    } else {
+                        LOG_E(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 = 0;
+
+#ifdef OAI_EMU
+                    if (new_data->pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) {
+                        new_data->pdcp_read_header.inst = new_data->pdcp_read_header.inst
+                        - oai_emulation.info.nb_enb_local + NB_eNB_INST
+                        + oai_emulation.info.first_ue_local;
+                    } else {
+                        new_data->pdcp_read_header.inst = new_data->pdcp_read_header.inst
+                        + oai_emulation.info.first_enb_local;
+                    }
+#else
+                    new_data->pdcp_read_header.inst = 0;
+#endif
+                    new_data->data = malloc(sizeof(uint8_t) * new_data->pdcp_read_header.data_size);
+                    /* Copy the data */
+                    memcpy(new_data->data, NLMSG_DATA(nas_nlh_rx), new_data->pdcp_read_header.data_size);
+
+                    if (pdcp_netlink_nb_element[new_data->pdcp_read_header.inst]
+                        > PDCP_QUEUE_NB_ELEMENTS) {
+                        LOG_E(PDCP, "[Mod %02x] We reached maximum number of elements in pdcp queue (%d)\n",
+                              new_data->pdcp_read_header.inst, pdcp_netlink_nb_element);
+                    }
+
+                    LOG_D(PDCP, "En-queueing packet for module %d\n", new_data->pdcp_read_header.inst);
+
+                    /* Enqueue the element in the right queue */
+//                     lfds611_queue_enqueue(pdcp_netlink_queue[new_data->pdcp_read_header.inst], new_data);
+                    lfds611_queue_guaranteed_enqueue(pdcp_netlink_queue[new_data->pdcp_read_header.inst], new_data);
+                }
+            }
+        }
+    }
+    return NULL;
+}
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h
index 10b868bc08..16bedd27ba 100755
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h
@@ -153,6 +153,9 @@ BOOL pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_b
 BOOL pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, \
      u8 bitmap[512], pdcp_control_pdu_for_pdcp_status_report* pdu);
 
+int pdcp_netlink_dequeue_element(uint8_t eNB_flag, uint8_t UE_index, uint8_t eNB_index,
+                                 struct pdcp_netlink_element_s **data);
+
 void pdcp_config_set_security(module_id_t module_id, u32 frame, u8 eNB_flag, rb_id_t rb_id,
                               u16 lc_id, u8 security_mode, u8 *kRRCenc, u8 *kRRCint, u8 *kUPenc);
 
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c
index 9aff9de7d3..3cc41a16a3 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_thread.c
@@ -57,6 +57,8 @@ pthread_mutex_t pdcp_mutex;
 pthread_cond_t pdcp_cond;
 int pdcp_instance_cnt;
 
+static void *pdcp_thread_main(void* param);
+
 static void *pdcp_thread_main(void* param) {
 
   //u8 eNB_flag = *((u8*)param);
diff --git a/openair2/UTIL/FIFO/types.h b/openair2/UTIL/FIFO/types.h
index 0c630d4c22..74dfe1f01e 100644
--- a/openair2/UTIL/FIFO/types.h
+++ b/openair2/UTIL/FIFO/types.h
@@ -69,12 +69,12 @@ typedef struct Packet_otg_elt {
 } Packet_otg_elt;
 
 typedef struct Job_element {
-  struct Job_elt *next;
+  struct Job_element *next;
   Job job;
 } Job_elt;
 
 typedef struct Event_element {
-  struct Event_elt *next;
-  struct Event_elt *previous;
+  struct Event_element *next;
+  struct Event_element *previous;
   Event event;
 } Event_elt;
diff --git a/openair2/UTIL/OSA/osa_internal.h b/openair2/UTIL/OSA/osa_internal.h
index 318549b2f7..3f0116017d 100644
--- a/openair2/UTIL/OSA/osa_internal.h
+++ b/openair2/UTIL/OSA/osa_internal.h
@@ -21,6 +21,6 @@
 ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
 #endif
 
-#define SECU_DEBUG
+// #define SECU_DEBUG
 
 #endif /* OSA_INTERNAL_H_ */
diff --git a/openair2/UTIL/OSA/osa_key_deriver.c b/openair2/UTIL/OSA/osa_key_deriver.c
index 625fe0e403..b05bbc226f 100644
--- a/openair2/UTIL/OSA/osa_key_deriver.c
+++ b/openair2/UTIL/OSA/osa_key_deriver.c
@@ -24,7 +24,7 @@ void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key,
 }
 
 /*!
- * @brief Derive the keys from kasme and perform truncate on the generated key to
+ * @brief Derive the keys from key and perform truncate on the generated key to
  * reduce his size to 128 bits. Definition of the derivation function can
  * be found in 3GPP TS.33401 #A.7
  * @param[in] alg_type Algorithm distinguisher
@@ -41,9 +41,6 @@ int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
                const uint8_t key[32], uint8_t **out)
 {
     uint8_t string[7];
-#if defined(SECU_DEBUG)
-    int i;
-#endif
 
     /* FC */
     string[0] = FC_ALG_KEY_DER;
@@ -79,7 +76,7 @@ int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
     return 0;
 }
 
-int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB)
+int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB)
 {
     uint8_t string[7];
 
@@ -107,7 +104,7 @@ int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keN
     }
 #endif
 
-    kdf(string, 7, kasme, 32, keNB, 32);
+    kdf(string, 7, key, 32, keNB, 32);
 
     return 0;
 }
diff --git a/openair2/UTIL/OTG/otg_models.c b/openair2/UTIL/OTG/otg_models.c
index 19dbe763cf..6324cfbd87 100644
--- a/openair2/UTIL/OTG/otg_models.c
+++ b/openair2/UTIL/OTG/otg_models.c
@@ -111,7 +111,7 @@ double tarmaCalculateSample( double inputSamples[], tarmaProcess_t *proc){
  */
 void tarmaUpdateInputSample (tarmaStream_t *stream){
   int cnt;
-  LOG_T(OTG,"TARMA_DEBUG: tarmaUpdateInputSample(%d)\n",(int)stream);
+  LOG_T(OTG,"TARMA_DEBUG: tarmaUpdateInputSample(%p)\n", stream);
   if(stream){
 	for(cnt=0; cnt<TARMA_NUM_PROCESSES; cnt++){
 	  stream->tarma_input_samples[cnt]=gaussian_dist(10000,1)-10000;
@@ -153,7 +153,7 @@ tarmaStream_t *tarmaInitStream(tarmaStream_t *stream){
 	  proc->polyWeight[cntpy]=0;
 	}
   }
-  LOG_D(OTG,"TARMA_DEBUG: tarmaInitStream(%d) called\n",(int)stream);
+  LOG_D(OTG,"TARMA_DEBUG: tarmaInitStream(%p) called\n", stream);
   return stream;
 }
 
@@ -188,7 +188,7 @@ void tarmaPrintProc(tarmaProcess_t *proc){
   char prefix[]="OTG TARMA DEBUG: ";
   int cntma, cntar;
 
-  printf("%s tarmaPrintProc(%d) called\n",prefix,(int)proc);
+  printf("%s tarmaPrintProc(%p) called\n", prefix, proc);
   printf("%s     ma history:\n",prefix);
   for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++){
 	printf("%s       ma[%d]: %f\n",prefix,cntma,proc->maHist[cntma]);
@@ -209,7 +209,7 @@ void tarmaPrintStreamInit(tarmaStream_t *stream){
   tarmaProcess_t *proc;
   int cntvar, cntp, cntma, cntar, cntpy;
 
-  printf("%s tarmaPrintStreamInit(%d) called\n",prefix,(int)stream);
+  printf("%s tarmaPrintStreamInit(%p) called\n", prefix, stream);
   for(cntvar=0; cntvar<2; cntvar++){
 	if(cntvar==0){
 	  proc=&(stream->tarma_idt);
@@ -258,7 +258,7 @@ double tarmaCalculateVideoSample(tarmaVideo_t *video){
   if(video){
 	proc=&(video->tarma_size);
 	frameidx=video->tarmaVideoGopStructure[video->tarmaVideoFrameNumber];
-  LOG_D(OTG,"TARMA_DEBUG: tarmaCalculateVideoSample(%d) called\n",(int)video);
+  LOG_D(OTG,"TARMA_DEBUG: tarmaCalculateVideoSample(%p) called\n", video);
   LOG_D(OTG,"TARMA_DEBUG:     frameidx=%d\n",frameidx);
 	if(frameidx>=0 && frameidx<=TARMA_NUM_FRAME_TYPES){
 	  for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++){
@@ -291,7 +291,7 @@ tarmaVideo_t *tarmaInitVideo(tarmaVideo_t *video){
   tarmaProcess_t *proc;
   int cntp, cntma, cntar, cntpy, cntgop, cnttype;
 
-  LOG_D(OTG,"TARMA_DEBUG: tarmaInitVideo(%d) called\n",(int)video);
+  LOG_D(OTG,"TARMA_DEBUG: tarmaInitVideo(%p) called\n", video);
   if(video==0){
 	video=(tarmaVideo_t*) malloc(sizeof(tarmaVideo_t));
   }
@@ -382,7 +382,7 @@ void tarmaPrintVideoInit(tarmaVideo_t *video){
   tarmaProcess_t *proc;
   int cntp, cntma, cntar, cntpy, cntgop, cnttype;
 
-  printf("%s tarmaPrintVideoInit(%d) called\n",prefix,(int)video);
+  printf("%s tarmaPrintVideoInit(%p) called\n", prefix, video);
   proc=&(video->tarma_size);
   printf("%s      input process weights\n",prefix);
   for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++){
@@ -482,7 +482,7 @@ backgroundStream_t *backgroundStreamInit(backgroundStream_t *stream, double lamb
 	}
   }
 
-  LOG_D(OTG,"BACKGROUND_USERS DEBUG: backgroundStreamInit(%d) called\n",(int)stream);
+  LOG_D(OTG,"BACKGROUND_USERS DEBUG: backgroundStreamInit(%p) called\n", stream);
   backgroundPrintStream (stream);
   return stream;
 }
@@ -496,7 +496,7 @@ backgroundStream_t *backgroundStreamInit(backgroundStream_t *stream, double lamb
 void backgroundUpdateStream(backgroundStream_t *stream, int ctime){
   int numNewSessions, cnts, period;
 
-  LOG_D(OTG,"BACKGROUND DEBUG: backgroundUpdateStream(stream*=%d,ctime=%d,period=%d) called\n",(int)stream, ctime);
+  LOG_D(OTG,"BACKGROUND DEBUG: backgroundUpdateStream(stream*=%p,ctime=%d) called\n", stream, ctime);
   if(stream){
 	period=ctime-stream->lastUpdateTime;
 	numNewSessions=poisson_dist(stream->meanNumSessions/5710*period);
@@ -532,7 +532,7 @@ double backgroundCalculateSize(backgroundStream_t *stream, int ctime, int idt){
   double mrate=0;
 
   backgroundUpdateStream(stream, ctime);
-  LOG_D(OTG,"BACKGROUND DEBUG: backgroundCalculateSize(stream*=%d,idt=%d,ctime=%d) called\n",(int)stream, idt, ctime);
+  LOG_D(OTG,"BACKGROUND DEBUG: backgroundCalculateSize(stream*=%p,idt=%d,ctime=%d) called\n", stream, idt, ctime);
   if(stream){
 	for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++){
 	  if(stream->activeSessions[cnts].endTime>ctime){
@@ -554,7 +554,7 @@ double backgroundCalculateSize(backgroundStream_t *stream, int ctime, int idt){
 void backgroundPrintStream(backgroundStream_t *stream){
   int cnts;
   
-  LOG_D(OTG,"BACKGROUND DEBUG: backgroundPrintStream(%d)\n",(int)stream);
+  LOG_D(OTG,"BACKGROUND DEBUG: backgroundPrintStream(%p)\n", stream);
   if(stream){
     LOG_D(OTG,"BACKGROUND DEBUG:     meanNumSessions(lambda_n)=%f\n",stream->meanNumSessions);
 	for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++){
diff --git a/targets/SIMU/USER/Makefile b/targets/SIMU/USER/Makefile
index 4227e7fa93..b46ca33c2f 100644
--- a/targets/SIMU/USER/Makefile
+++ b/targets/SIMU/USER/Makefile
@@ -247,6 +247,7 @@ endif
 
 CFLAGS += -DENABLE_VCD_FIFO
 CFLAGS += -DENABLE_NEW_MULTICAST
+CFLAGS += -DENABLE_PDCP_NETLINK_FIFO
 # CFLAGS += -DENABLE_LOG_FIFO
 
 # Check if libpgm is installed and use it if found instead of the unreliable
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index 7354c2d274..8a8aacce06 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -405,7 +405,6 @@ void check_and_adjust_params() {
   if (ret < 0)
     LOG_E(EMU,"[INIT] Netlink not available, careful ...\n");
 
-  
   if (ethernet_flag == 1) {
     oai_emulation.info.master[oai_emulation.info.master_id].nb_ue = oai_emulation.info.nb_ue_local + oai_emulation.info.nb_rn_local;
     oai_emulation.info.master[oai_emulation.info.master_id].nb_enb = oai_emulation.info.nb_enb_local + oai_emulation.info.nb_rn_local;
@@ -434,6 +433,10 @@ void check_and_adjust_params() {
   NB_eNB_INST = oai_emulation.info.nb_enb_local + oai_emulation.info.nb_enb_remote;
   NB_RN_INST = oai_emulation.info.nb_rn_local + oai_emulation.info.nb_rn_remote;
 
+#if defined(ENABLE_PDCP_NETLINK_FIFO)
+  pdcp_netlink_init();
+#endif
+
   if (NB_RN_INST > 0 ) {
     LOG_N(EMU,"Total number of RN %d (local %d, remote %d) mobility (the same as eNB) %s  \n", NB_RN_INST,oai_emulation.info.nb_rn_local,oai_emulation.info.nb_rn_remote, oai_emulation.topology_config.mobility.eNB_mobility.eNB_mobility_type.selected_option);
     
-- 
GitLab